mirror of https://github.com/sfeakes/AqualinkD.git
parent
295f267d93
commit
60d0a41aef
|
|
@ -1,5 +1,6 @@
|
|||
# Aqualinkd
|
||||
Linux daemon to control Aqualink RS pool controllers. Provides web UI, MQTT client & HTTP API endpoints. Control your pool equipment from any phone/tablet or computer. Is also compatible with most Home control systems including Apple HomeKit, Home Assistant, Samsung, Alexa, Google, etc.
|
||||
|
||||
<br>
|
||||
Binaries are supplied for Raspberry Pi both 32 & 64 bit OS, Has been, and can be compiled for many different SBC's, and a Docker is also available.
|
||||
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -499,14 +499,14 @@ void *set_allbutton_light_colormode( void *ptr )
|
|||
use_current_mode = true;
|
||||
LOG(ALLB_LOG, LOG_INFO, "Light Programming #: %d, on button: %s, color light type: %d, using current mode\n", val, button->label, ((clight_detail *)button->special_mask_ptr)->lightType);
|
||||
} else {
|
||||
mode_name = light_mode_name(((clight_detail *)button->special_mask_ptr)->lightType, val-1, ALLBUTTON);
|
||||
mode_name = light_mode_name(((clight_detail *)button->special_mask_ptr)->lightType, val, ALLBUTTON); // NSF DO NOT -1 from value (check WS logic if you do)
|
||||
use_current_mode = false;
|
||||
if (mode_name == NULL) {
|
||||
LOG(ALLB_LOG, LOG_ERR, "Light Programming #: %d, on button: %s, color light type: %d, couldn't find mode name '%s'\n", val, button->label, ((clight_detail *)button->special_mask_ptr)->lightType, mode_name);
|
||||
cleanAndTerminateThread(threadCtrl);
|
||||
return ptr;
|
||||
} else {
|
||||
LOG(ALLB_LOG, LOG_INFO, "Light Programming #: %d, on button: %s, color light type: %d, name '%s'\n", val, button->label, ((clight_detail *)button->special_mask_ptr)->lightType, mode_name);
|
||||
LOG(ALLB_LOG, LOG_INFO, "Light Programming #: %d, on button: %s, color light type: %d, color name '%s'\n", val, button->label, ((clight_detail *)button->special_mask_ptr)->lightType, mode_name);
|
||||
}
|
||||
}
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -28,10 +28,17 @@
|
|||
#include "allbutton_aq_programmer.h"
|
||||
#include "rs_msg_utils.h"
|
||||
#include "iaqualink.h"
|
||||
#include "color_lights.h"
|
||||
|
||||
|
||||
#define USE_LAST_VALUE 101
|
||||
|
||||
void initPanelButtons(struct aqualinkdata *aqdata, bool rspda, int size, bool combo, bool dual);
|
||||
void programDeviceLightMode(struct aqualinkdata *aqdata, int value, int button);
|
||||
|
||||
void programDeviceLightMode(struct aqualinkdata *aqdata, int value, int button, bool expectMultiple, request_source source);
|
||||
void programDeviceLightBrightness(struct aqualinkdata *aqdata, int value, int deviceIndex, bool expectMultiple, request_source source);
|
||||
|
||||
|
||||
void printPanelSupport(struct aqualinkdata *aqdata);
|
||||
uint16_t setPanelSupport(struct aqualinkdata *aqdata);
|
||||
uint16_t getPanelBitmaskFromName(const char *str);
|
||||
|
|
@ -458,6 +465,9 @@ uint16_t setPanelSupport(struct aqualinkdata *aqdata)
|
|||
if (aqdata->panel_rev[0] >= 82) // R in ascii
|
||||
aqdata->panel_support_options |= RSP_SUP_IAQL;
|
||||
|
||||
if (aqdata->panel_rev[0] >= 84) // T in ascii
|
||||
aqdata->panel_support_options |= RSP_SUP_CLIT_RSSA;
|
||||
|
||||
if (aqdata->panel_rev[0] >= 87) {// W in ascii
|
||||
aqdata->panel_support_options |= RSP_SUP_PLAB;
|
||||
aqdata->panel_support_options |= RSP_SUP_IAQL3;
|
||||
|
|
@ -1363,152 +1373,10 @@ int getWaterTemp(struct aqualinkdata *aqdata)
|
|||
|
||||
|
||||
|
||||
//bool setDeviceState(aqkey *button, bool isON)
|
||||
bool setDeviceState(struct aqualinkdata *aqdata, int deviceIndex, bool isON, request_source source)
|
||||
{
|
||||
aqkey *button = &aqdata->aqbuttons[deviceIndex];
|
||||
bool set_pre_state = true;
|
||||
|
||||
//if ( button->special_mask & VIRTUAL_BUTTON && button->special_mask & VS_PUMP) {
|
||||
if ( isVS_PUMP(button->special_mask) && isVBUTTON(button->special_mask)) {
|
||||
// Virtual Button with VSP is always on.
|
||||
LOG(PANL_LOG, LOG_INFO, "received '%s' for '%s', virtual pump is always on, ignoring", (isON == false ? "OFF" : "ON"), button->name);
|
||||
button->led->state = ON;
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((button->led->state == OFF && isON == false) ||
|
||||
(isON > 0 && (button->led->state == ON || button->led->state == FLASH ||
|
||||
button->led->state == ENABLE))) {
|
||||
LOG(PANL_LOG, LOG_INFO, "received '%s' for '%s', already '%s', Ignoring\n", (isON == false ? "OFF" : "ON"), button->name, (isON == false ? "OFF" : "ON"));
|
||||
//return false;
|
||||
} else {
|
||||
LOG(PANL_LOG, LOG_INFO, "received '%s' for '%s', turning '%s'\n", (isON == false ? "OFF" : "ON"), button->name, (isON == false ? "OFF" : "ON"));
|
||||
#ifdef AQ_PDA
|
||||
if (isPDA_PANEL) {
|
||||
if (button->special_mask & PROGRAM_LIGHT && isPDA_IAQT) {
|
||||
// AqualinkTouch in PDA mode, we can program light. (if turing off, use standard AQ_PDA_DEVICE_ON_OFF below)
|
||||
programDeviceLightMode(aqdata, (isON?0:-1), deviceIndex); // -1 means off 0 means use current light mode
|
||||
} else {
|
||||
// If we are using AqualinkTouch with iAqualink enabled, we can send button on/off much faster using that.
|
||||
if ( isPDA_IAQT && isIAQL_ACTIVE) {
|
||||
set_iaqualink_aux_state(button, isON);
|
||||
} else {
|
||||
#ifdef NEW_AQ_PROGRAMMER
|
||||
aq_programmer(AQ_PDA_DEVICE_ON_OFF, button, (isON == false ? OFF : ON), deviceIndex, aqdata);
|
||||
#else
|
||||
char msg[PTHREAD_ARG];
|
||||
sprintf(msg, "%-5d%-5d", deviceIndex, (isON == false ? OFF : ON));
|
||||
aq_programmer(AQ_PDA_DEVICE_ON_OFF, msg, aqdata);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
// Check for panel programmable light. if so simple ON isn't going to work well
|
||||
// Could also add "light mode" check, as this is only valid for panel configured light not aqualinkd configured light.
|
||||
if (isPLIGHT(button->special_mask) && isVBUTTON(button->special_mask)) {
|
||||
programDeviceLightMode(aqdata, (isON?0:-1), deviceIndex); // -1 means off 0 means use current light mode
|
||||
//aq_program(AQ_SET_IAQTOUCH_LIGHTCOLOR_MODE, button, (isON?0:-1), 0, aqdata); // should use this in teh furuter, or get programDeviceLightMode to call it.
|
||||
} else if (isPLIGHT(button->special_mask) && button->led->state == OFF) {
|
||||
// Full range dimmer can get stuck off on rev T.2 (maybe others), to overcome use allbutton with any % other than 0
|
||||
if ( ((clight_detail *)button->special_mask_ptr)->lightType == LC_DIMMER2 ||
|
||||
((clight_detail *)button->special_mask_ptr)->lightType == LC_DIMMER ) // NSF should remove this once figured out Line #1354 programDeviceLightBrightness()
|
||||
{
|
||||
// programLightBrightness has appropiate code to call allbutton programmer.
|
||||
/*
|
||||
int val = ((clight_detail *)button->special_mask_ptr)->lastValue>0?((clight_detail *)button->special_mask_ptr)->lastValue:100;
|
||||
programDeviceLightBrightness(aqdata, val, deviceIndex, (source==NET_MQTT?true:false), source);
|
||||
*/
|
||||
programDeviceLightBrightness(aqdata, 101, deviceIndex, (source==NET_MQTT?true:false), source);
|
||||
set_pre_state = false;
|
||||
}
|
||||
// OK Programable light, and no light mode selected. Now let's work out best way to turn it on. serial_adapter protocol will to it without questions,
|
||||
// all other will require programmig.
|
||||
else if (isRSSA_ENABLED) {
|
||||
set_aqualink_rssadapter_aux_state(button, true);
|
||||
} else {
|
||||
//set_light_mode("0", deviceIndex); // 0 means use current light mode
|
||||
programDeviceLightMode(aqdata, 0, deviceIndex); // 0 means use current light mode
|
||||
set_pre_state = false;
|
||||
}
|
||||
|
||||
// If aqualinkd programmable light, it will come on at last state, so set that.
|
||||
if ( ((clight_detail *)button->special_mask_ptr)->lightType == LC_PROGRAMABLE ) {
|
||||
((clight_detail *)button->special_mask_ptr)->currentValue = ((clight_detail *)button->special_mask_ptr)->lastValue;
|
||||
}
|
||||
} else if (isVBUTTON(button->special_mask)) {
|
||||
// Virtual buttons only supported with Aqualink Touch
|
||||
LOG(PANL_LOG, LOG_INFO, "Set state for Virtual Button %s code=0x%02hhx iAqualink2 enabled=%s\n",button->name, button->rssd_code, isIAQT_ENABLED?"Yes":"No");
|
||||
if (isIAQT_ENABLED) {
|
||||
// If it's one of the pre-defined onces & iaqualink is enabled, we can set it easile with button.
|
||||
|
||||
if ( isIAQL_ACTIVE && button->rssd_code && button->rssd_code != NUL)
|
||||
{
|
||||
//LOG(PANL_LOG, LOG_NOTICE, "********** USE iaqualink2 ********\n");
|
||||
set_iaqualink_aux_state(button, isON);
|
||||
} else {
|
||||
#ifdef NEW_AQ_PROGRAMMER
|
||||
aq_programmer(AQ_SET_IAQTOUCH_DEVICE_ON_OFF, button, (isON == false ? OFF : ON), deviceIndex, aqdata);
|
||||
#else
|
||||
char msg[PTHREAD_ARG];
|
||||
sprintf(msg, "%-5d%-5d", deviceIndex, (isON == false ? OFF : ON));
|
||||
aq_programmer(AQ_SET_IAQTOUCH_DEVICE_ON_OFF, msg, aqdata);
|
||||
#endif
|
||||
set_pre_state = false;
|
||||
//} else if (button->rssd_code != VBUTTON_ONETOUCH_RSSD) {
|
||||
// LOG(PANL_LOG, LOG_NOTICE, "********** USE AQ_SET_IAQTOUCH_ONETOUCH_ON_OFF ********\n");
|
||||
// aq_programmer(AQ_SET_IAQTOUCH_ONETOUCH_ON_OFF, msg, aqdata);
|
||||
//} else {
|
||||
// LOG(PANL_LOG, LOG_ERR, "Configuration! do not understand code for Virtual Buttons");
|
||||
//}
|
||||
}
|
||||
} else {
|
||||
LOG(PANL_LOG, LOG_ERR, "Can only use Aqualink Touch protocol for Virtual Buttons");
|
||||
}
|
||||
} else if (isPLIGHT(button->special_mask) && isRSSA_ENABLED) {
|
||||
// If off and program light, use the RS serial adapter since that is overiding the state now.
|
||||
set_aqualink_rssadapter_aux_state(button, isON);
|
||||
} else {
|
||||
//set_iaqualink_aux_state(button, isON);
|
||||
//set_aqualink_rssadapter_aux_state(button, isON);
|
||||
aq_send_allb_cmd(button->code);
|
||||
}
|
||||
|
||||
|
||||
// If we turned off a aqualinkd programmable light, set the mode to 0
|
||||
if (isPLIGHT(button->special_mask) && ! isON && ((clight_detail *)button->special_mask_ptr)->lightType == LC_PROGRAMABLE ) {
|
||||
updateButtonLightProgram(aqdata, 0, deviceIndex);
|
||||
}
|
||||
|
||||
#ifdef CLIGHT_PANEL_FIX
|
||||
if (isPLIGHT(button->special_mask) && isRSSA_ENABLED) {
|
||||
get_aqualink_rssadapter_button_status(button);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Pre set device to state, next status will correct if state didn't take, but this will stop multiple ON messages setting on/off
|
||||
//#ifdef PRESTATE_ONOFF
|
||||
if (_aqconfig_.device_pre_state && set_pre_state) {
|
||||
if ((button->code == KEY_POOL_HTR || button->code == KEY_SPA_HTR ||
|
||||
button->code == KEY_EXT_AUX) &&
|
||||
isON > 0) {
|
||||
button->led->state = ENABLE; // if heater and set to on, set pre-status to enable.
|
||||
LOG(PANL_LOG, LOG_INFO, "Pre-set state of %s to enable\n",button->label);
|
||||
//_aqualink_data->updated = true;
|
||||
} else if (isRSSA_ENABLED || ((button->special_mask & PROGRAM_LIGHT) != PROGRAM_LIGHT)) {
|
||||
button->led->state = (isON == false ? OFF : ON); // as long as it's not programmable light , pre-set to on/off
|
||||
LOG(PANL_LOG, LOG_INFO, "Pre-set state of %s to %s\n",button->label,(isON == false ? "Off" : "On"));
|
||||
//_aqualink_data->updated = true;
|
||||
}
|
||||
}
|
||||
//#endif
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
Basic programming that are not too involved, ie no Jandy bugs to overcome or aq_programmer can make decision on protocol to use.
|
||||
Simply set them all as unactioned, and let the delayed_request code pick them up and pass to aq_programmer
|
||||
*/
|
||||
bool programDeviceValue(struct aqualinkdata *aqdata, action_type type, int value, int id, bool expectMultiple) // id is only valid for PUMP RPM
|
||||
{
|
||||
if (aqdata->unactioned.type != NO_ACTION && type != aqdata->unactioned.type)
|
||||
|
|
@ -1562,224 +1430,359 @@ bool programDeviceValue(struct aqualinkdata *aqdata, action_type type, int value
|
|||
}
|
||||
|
||||
|
||||
void programDeviceLightBrightness(struct aqualinkdata *aqdata, int value, int deviceIndex, bool expectMultiple, request_source source)
|
||||
bool setDeviceState(struct aqualinkdata *aqdata, int deviceIndex, bool isON, request_source source)
|
||||
{
|
||||
// If Value is 101
|
||||
aqkey *button = &aqdata->aqbuttons[deviceIndex];
|
||||
bool set_pre_state = true;
|
||||
|
||||
//if ( button->special_mask & VIRTUAL_BUTTON && button->special_mask & VS_PUMP) {
|
||||
if ( isVS_PUMP(button->special_mask) && isVBUTTON(button->special_mask)) {
|
||||
// Virtual Button with VSP is always on.
|
||||
LOG(PANL_LOG, LOG_INFO, "received '%s' for '%s', virtual pump is always on, ignoring", (isON == false ? "OFF" : "ON"), button->name);
|
||||
button->led->state = ON;
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((button->led->state == OFF && isON == false) ||
|
||||
(isON > 0 && (button->led->state == ON || button->led->state == FLASH ||
|
||||
button->led->state == ENABLE))) {
|
||||
LOG(PANL_LOG, LOG_INFO, "received '%s' for '%s', already '%s', Ignoring\n", (isON == false ? "OFF" : "ON"), button->name, (isON == false ? "OFF" : "ON"));
|
||||
return false;
|
||||
}
|
||||
|
||||
LOG(PANL_LOG, LOG_INFO, "received '%s' for '%s', turning '%s'\n", (isON == false ? "OFF" : "ON"), button->name, (isON == false ? "OFF" : "ON"));
|
||||
#ifdef AQ_PDA
|
||||
if (isPDA_PANEL) {
|
||||
if (button->special_mask & PROGRAM_LIGHT && isPDA_IAQT) {
|
||||
// AqualinkTouch in PDA mode, we can program light. (if turing off, use standard AQ_PDA_DEVICE_ON_OFF below)
|
||||
programDeviceLightMode(aqdata, (isON?USE_LAST_VALUE:0), deviceIndex, (source==NET_MQTT?true:false), source);
|
||||
} else {
|
||||
// If we are using AqualinkTouch with iAqualink enabled, we can send button on/off much faster using that.
|
||||
if ( isPDA_IAQT && isIAQL_ACTIVE) {
|
||||
set_iaqualink_aux_state(button, isON);
|
||||
} else {
|
||||
aq_programmer(AQ_PDA_DEVICE_ON_OFF, button, (isON == false ? OFF : ON), deviceIndex, aqdata);
|
||||
}
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
if (isPLIGHT(button->special_mask)) {
|
||||
//programDeviceLightMode_(aqdata, (isON?USE_LAST_VALUE:0), deviceIndex ,(source==NET_MQTT?true:false), source);
|
||||
// NSF we could let programDeviceLightMode() handle ALL these cases.
|
||||
|
||||
if (isMASK_SET(button->special_mask, VIRTUAL_BUTTON)) {
|
||||
// No quick way to turn on or off and virtual button light.
|
||||
programDeviceLightMode(aqdata, (isON?USE_LAST_VALUE:0), deviceIndex ,(source==NET_MQTT?true:false), source);
|
||||
}
|
||||
else if ( ((clight_detail *)button->special_mask_ptr)->lightType == LC_PROGRAMABLE ) {
|
||||
LOG(PANL_LOG,LOG_DEBUG, "Turning light %s %s with allbutton key\n", button->label, isON?"On":"Off");
|
||||
aq_send_allb_cmd(button->code);
|
||||
if (isON) { // Will come back on in old state.
|
||||
updateButtonLightProgram(aqdata, ((clight_detail *)button->special_mask_ptr)->lastValue, deviceIndex);
|
||||
} else {
|
||||
updateButtonLightProgram(aqdata, 0, deviceIndex);
|
||||
}
|
||||
set_pre_state = false;
|
||||
} else if ( ((clight_detail *)button->special_mask_ptr)->lightType == LC_DIMMER2 ||
|
||||
((clight_detail *)button->special_mask_ptr)->lightType == LC_DIMMER) {
|
||||
if (isON) { // Dimmer light can get stuck turning on from RSSA, so use allbutton
|
||||
LOG(PANL_LOG,LOG_DEBUG, "Turning light %s On with allbutton dimmer program\n", button->label);
|
||||
aq_program(AQ_SET_ALLB_LIGHTDIMMER, button, 4, true, aqdata); // 4 = 100% since it uses light mode name
|
||||
set_pre_state = false;
|
||||
} else {
|
||||
LOG(PANL_LOG,LOG_DEBUG, "Turning light %s Off with allbutton key\n", button->label);
|
||||
aq_send_allb_cmd(button->code);
|
||||
}
|
||||
} else if (isRSSA_ENABLED) {
|
||||
LOG(PANL_LOG,LOG_DEBUG, "Turning light %s %s with all RS serial on/off key\n", button->label, isON?"On":"Off");
|
||||
set_aqualink_rssadapter_aux_state(button, isON);
|
||||
} else {
|
||||
if (isON) {
|
||||
LOG(PANL_LOG,LOG_DEBUG, "Turning light %s On with allbutton light mode program\n", button->label);
|
||||
aq_programmer(AQ_SET_LIGHTCOLOR_MODE, button, 1, true, aqdata);
|
||||
set_pre_state = false;
|
||||
} else {
|
||||
LOG(PANL_LOG,LOG_DEBUG, "Turning light %s Off with allbutton key\n", button->label);
|
||||
aq_send_allb_cmd(button->code);
|
||||
}
|
||||
}
|
||||
|
||||
} else if (isVBUTTON(button->special_mask)) {
|
||||
// Virtual buttons only supported with Aqualink Touch
|
||||
LOG(PANL_LOG, LOG_INFO, "Set state for Virtual Button %s code=0x%02hhx iAqualink2 enabled=%s\n",button->name, button->rssd_code, isIAQT_ENABLED?"Yes":"No");
|
||||
if (isIAQT_ENABLED) {
|
||||
// If it's one of the pre-defined onces & iaqualink is enabled, we can set it easile with button.
|
||||
|
||||
if ( isIAQL_ACTIVE && button->rssd_code && button->rssd_code != NUL)
|
||||
{
|
||||
//LOG(PANL_LOG, LOG_NOTICE, "********** USE iaqualink2 ********\n");
|
||||
set_iaqualink_aux_state(button, isON);
|
||||
} else {
|
||||
aq_programmer(AQ_SET_IAQTOUCH_DEVICE_ON_OFF, button, (isON == false ? OFF : ON), deviceIndex, aqdata);
|
||||
set_pre_state = false;
|
||||
}
|
||||
} else {
|
||||
LOG(PANL_LOG, LOG_ERR, "Can only use Aqualink Touch protocol for Virtual Buttons");
|
||||
}
|
||||
} else {
|
||||
// Everything else, simply send the button code.
|
||||
//set_iaqualink_aux_state(button, isON);
|
||||
//set_aqualink_rssadapter_aux_state(button, isON);
|
||||
aq_send_allb_cmd(button->code);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CLIGHT_PANEL_FIX
|
||||
if (isPLIGHT(button->special_mask) && isRSSA_ENABLED) {
|
||||
get_aqualink_rssadapter_button_status(button);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Pre set device to state, next status will correct if state didn't take, but this will stop multiple ON messages setting on/off
|
||||
//#ifdef PRESTATE_ONOFF
|
||||
if (_aqconfig_.device_pre_state && set_pre_state) {
|
||||
if ((button->code == KEY_POOL_HTR || button->code == KEY_SPA_HTR ||
|
||||
button->code == KEY_EXT_AUX) &&
|
||||
isON > 0) {
|
||||
button->led->state = ENABLE; // if heater and set to on, set pre-status to enable.
|
||||
LOG(PANL_LOG, LOG_INFO, "Pre-set state of %s to enable\n",button->label);
|
||||
//_aqualink_data->updated = true;
|
||||
//} else if (isRSSA_ENABLED || ((button->special_mask & PROGRAM_LIGHT) != PROGRAM_LIGHT)) {
|
||||
} else if (isRSSA_ENABLED || !isPLIGHT(button->special_mask)) {
|
||||
button->led->state = (isON == false ? OFF : ON); // as long as it's not programmable light , pre-set to on/off
|
||||
LOG(PANL_LOG, LOG_INFO, "Pre-set state of %s to %s\n",button->label,(isON == false ? "Off" : "On"));
|
||||
//_aqualink_data->updated = true;
|
||||
}
|
||||
}
|
||||
//#endif
|
||||
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
value 0 = off
|
||||
value 101/USE_LAST_VALUE = On use default mode if you can
|
||||
value is % for LC_DIMMER and LC_DIMMER2
|
||||
*/
|
||||
void programDeviceLightBrightness(struct aqualinkdata *aqdata, int value, int deviceIndex, bool expectMultiple, request_source source)
|
||||
{
|
||||
//int extra_value = false;
|
||||
|
||||
if (value < 0 || value > 100) {
|
||||
LOG(PANL_LOG,LOG_ERR, "Dimmer value %d is not valid, using %d\n",value,AQ_CLAMP(value,0,100));
|
||||
value = AQ_CLAMP(value,0,100);
|
||||
}
|
||||
|
||||
if (expectMultiple) {
|
||||
// Queue up a request, this will call us back through with expectMultiple=false
|
||||
time(&aqdata->unactioned.requested);
|
||||
aqdata->unactioned.value = value;
|
||||
aqdata->unactioned.type = LIGHT_BRIGHTNESS;
|
||||
aqdata->unactioned.id = deviceIndex;
|
||||
return;
|
||||
}
|
||||
|
||||
clight_detail *light = getProgramableLight(aqdata, deviceIndex);
|
||||
// Light mode 10
|
||||
|
||||
//printf("******* Light Brightness *** value=%d device=%d multiple=%d\n",value,deviceIndex,expectMultiple);
|
||||
//printf("****** Light %s on/off=%d %s\n",aqdata->aqbuttons[deviceIndex].label, aqdata->aqbuttons[deviceIndex].led->state, aqdata->aqbuttons[deviceIndex].led->state==ON?"on":"off");
|
||||
|
||||
// With changes to fix LC_DIMMER2, LC_DIMMER has now started having similar issues.
|
||||
// Need to come back and look at why, LC_DIMMER should be removed from below IF once sorted./
|
||||
if ( (light->lightType == LC_DIMMER2 || light->lightType == LC_DIMMER) && aqdata->aqbuttons[deviceIndex].led->state == OFF ) {
|
||||
// Light is off, we will turn in on but due to Jandy bug on rev T, have to use all button so values of 25/50/75/100.
|
||||
// value = 101, means use default (if if it comes on at 33% leave that, if not 100%).
|
||||
// value != 25/50/75/100 use all button to turn on, then reset with rssserial adapter.
|
||||
LOG(PANL_LOG,LOG_DEBUG, "Using allbutton programmer to set light dimmer\n");
|
||||
|
||||
if (value == 101) {
|
||||
//Should probably try to get the last value in this case, and use the closest 25% rather than default to 100. (ie 4)
|
||||
//int val = ((clight_detail *)button->special_mask_ptr)->lastValue>0?((clight_detail *)button->special_mask_ptr)->lastValue:100;
|
||||
aq_program(AQ_SET_LIGHTDIMMER, &aqdata->aqbuttons[deviceIndex], 4, true, aqdata); // 4 = 100% since it uses light mode name
|
||||
} else {
|
||||
int calVal = round( (value+12) / 25); // Round up/down
|
||||
if (calVal > 4 ) {calVal=4;}
|
||||
LOG(PANL_LOG,LOG_INFO, "Rounded dimmer value to %d for on command\n",calVal * 25);
|
||||
aq_program(AQ_SET_LIGHTDIMMER, &aqdata->aqbuttons[deviceIndex], calVal, false, aqdata);
|
||||
|
||||
if (light->lightType == LC_DIMMER2 ) {
|
||||
if (value != 25 && value !=50 && value !=75 && value != 100) {
|
||||
// Setup the rssd to set the light to the right value.
|
||||
//printf("Second programming for %%%d\n",value);
|
||||
time(&aqdata->unactioned.requested);
|
||||
aqdata->unactioned.requested += 5;
|
||||
aqdata->unactioned.value = value;
|
||||
aqdata->unactioned.type = LIGHT_MODE;
|
||||
aqdata->unactioned.id = deviceIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
int calVal = round(value / 25);
|
||||
LOG(PANL_LOG,LOG_DEBUG, "Using allbutton programmer to set light\n");
|
||||
if (calVal > 4 ) {calVal=4;}
|
||||
LOG(PANL_LOG,LOG_INFO, "Rounded dimmer value to %d for on command\n",calVal * 25);
|
||||
if (value != 25 && value !=50 && value !=75 && value != 100) {
|
||||
aq_program(AQ_SET_LIGHTDIMMER, &aqdata->aqbuttons[deviceIndex], calVal, false, aqdata);
|
||||
} else {
|
||||
aq_program(AQ_SET_LIGHTDIMMER, &aqdata->aqbuttons[deviceIndex], calVal, true, aqdata);
|
||||
}*/
|
||||
/*
|
||||
if (value != 25 && value !=50 && value !=75 && value != 100) {
|
||||
printf("Second programming for %%%d\n",value);
|
||||
time(&aqdata->unactioned.requested);
|
||||
aqdata->unactioned.requested += 5;
|
||||
aqdata->unactioned.value = value;
|
||||
aqdata->unactioned.type = LIGHT_MODE;
|
||||
aqdata->unactioned.id = deviceIndex;
|
||||
}
|
||||
*/
|
||||
if (light == NULL || (light->lightType != LC_DIMMER2 && light->lightType != LC_DIMMER)) {
|
||||
LOG(PANL_LOG,LOG_ERR, "Can not set light brightness on device '%s'\n",aqdata->aqbuttons[deviceIndex].label);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isRSSA_ENABLED && light->lightType == LC_DIMMER2) {
|
||||
LOG(PANL_LOG,LOG_ERR, "Light mode brightness 11 is only supported when `rssa_device_id` is set\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (value == 0) {
|
||||
// We simply need to turn the light off at this point, so use allbutton key as it's the quickest.
|
||||
// but can't turn off a virtual light.
|
||||
if (light->button->led->state == ON && !isMASK_SET(light->button->special_mask, VIRTUAL_BUTTON)) {
|
||||
LOG(PANL_LOG,LOG_DEBUG, "Turning light %s Off with allbutton key\n", light->button->label);
|
||||
aq_send_allb_cmd(light->button->code);
|
||||
// Could also check isRSSA_ENABLED and use set_aqualink_rssadapter_aux_state(light->button, FALSE);
|
||||
return;
|
||||
} else if (light->button->led->state != ON ) {
|
||||
LOG(PANL_LOG,LOG_WARNING, "Request to turn Light brightness '%s' to 0, already off, ignoring!\n",light->button->label);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
logic.
|
||||
set brightness through RSSA. (RSSA only protocol supports full dimmer range)
|
||||
RSSA has bug / issue. Sometimes panel will lock device forcing a panel delete/re-add of light.
|
||||
to overcome this seems to be turn it on with allbutton, if it's on then use RSSA to set the %.
|
||||
|
||||
if off turn on with allbutton.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
if (!isRSSA_ENABLED) {
|
||||
LOG(PANL_LOG,LOG_ERR, "Light mode brightness is only supported with `rssa_device_id` set\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (light == NULL) {
|
||||
LOG(PANL_LOG,LOG_ERR, "Light mode control not configured for button %d\n",deviceIndex);
|
||||
return;
|
||||
}
|
||||
|
||||
// DIMMER is 0,25,50,100 DIMMER2 is range
|
||||
if (light->lightType == LC_DIMMER) {
|
||||
value = round(value / 25);
|
||||
if (value > 4 ) {value=4;}
|
||||
LOG(PANL_LOG,LOG_INFO, "Rounded dimmer value to %d\n",value * 25);
|
||||
} else {
|
||||
|
||||
}
|
||||
|
||||
if (!expectMultiple) {
|
||||
if (value <= 0) {
|
||||
// Consider this a bad/malformed request to turn the light off.
|
||||
panel_device_request(aqdata, ON_OFF, deviceIndex, 0, source);
|
||||
if (aqdata->aqbuttons[deviceIndex].led->state == ON) {
|
||||
// Light is on, Simple set brightness through RSSD if we can
|
||||
if (isRSSA_ENABLED) {
|
||||
LOG(PANL_LOG,LOG_DEBUG, "Turning light %s to %d with RS Serial extended state\n", light->button->label, value);
|
||||
set_aqualink_rssadapter_aux_extended_state(light->button, value + RSSD_COLOR_LIGHT_OFFSET_WRITE);
|
||||
} else {
|
||||
programDeviceLightMode(aqdata, value, deviceIndex);
|
||||
LOG(PANL_LOG,LOG_DEBUG, "Turning light %s to %d with allbutton dimmer program\n", light->button->label, value);
|
||||
aq_program(AQ_SET_ALLB_LIGHTDIMMER, &aqdata->aqbuttons[deviceIndex], dimmer_percent_to_mode_index(value), false, aqdata);
|
||||
}
|
||||
} else {
|
||||
// Light is off, turn on with allbutton then reset the %.
|
||||
if (value == USE_LAST_VALUE) {
|
||||
// 101 is used last value, param #4 of true in ap_program means use default value if can, otherwise use param #3 = 4 = 100%
|
||||
LOG(PANL_LOG,LOG_DEBUG, "Turning light %s to Last mode with allbutton dimmer program\n", light->button->label);
|
||||
aq_program(AQ_SET_ALLB_LIGHTDIMMER, &aqdata->aqbuttons[deviceIndex], 4, true, aqdata); // 4 = 100% since it uses light mode name
|
||||
} else {
|
||||
int calVal = dimmer_percent_to_mode_index(value);
|
||||
LOG(PANL_LOG,LOG_INFO, "Rounded dimmer value to %d for on command\n",calVal * 25);
|
||||
LOG(PANL_LOG,LOG_DEBUG, "Turning light %s to %d with allbutton dimmer program\n", light->button->label, calVal);
|
||||
aq_program(AQ_SET_ALLB_LIGHTDIMMER, &aqdata->aqbuttons[deviceIndex], calVal, false, aqdata);
|
||||
if (value != 25 && value !=50 && value !=75 && value != 100 && isRSSA_ENABLED) {
|
||||
// Setup the rssd to set the light to the right value.
|
||||
time(&aqdata->unactioned.requested);
|
||||
aqdata->unactioned.requested += 5; // This should give enough time for the allbutton to finish
|
||||
aqdata->unactioned.value = value;
|
||||
aqdata->unactioned.type = LIGHT_BRIGHTNESS;
|
||||
aqdata->unactioned.id = deviceIndex;
|
||||
}
|
||||
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
time(&aqdata->unactioned.requested);
|
||||
aqdata->unactioned.value = value;
|
||||
aqdata->unactioned.type = LIGHT_MODE;
|
||||
aqdata->unactioned.id = deviceIndex;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
//void programDeviceLightMode(struct aqualinkdata *aqdata, char *value, int button)
|
||||
//void programDeviceLightMode(struct aqualinkdata *aqdata, int value, int button)
|
||||
void programDeviceLightMode(struct aqualinkdata *aqdata, int value, int deviceIndex)
|
||||
/*
|
||||
value 0 = off
|
||||
value 101/USE_LAST_VALUE = On use default mode if you can
|
||||
*/
|
||||
void programDeviceLightMode(struct aqualinkdata *aqdata, int value, int deviceIndex, bool expectMultiple, request_source source)
|
||||
{
|
||||
|
||||
#ifdef AQ_PDA
|
||||
if (isPDA_PANEL && !isPDA_IAQT) {
|
||||
LOG(PANL_LOG,LOG_ERR, "Light mode control not supported in PDA mode\n");
|
||||
int extra_value=false;
|
||||
/*. We should never get multiple requests for mode, only brightness uses slider. But leave here incase we need it in the future
|
||||
if (expectMultiple) {
|
||||
// Queue up a request, this will call us back through with expectMultiple=false
|
||||
time(&aqdata->unactioned.requested);
|
||||
aqdata->unactioned.value = value;
|
||||
aqdata->unactioned.type = LIGHT_MODE;
|
||||
aqdata->unactioned.id = deviceIndex;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
int i;
|
||||
clight_detail *light = NULL;
|
||||
for (i=0; i < aqdata->num_lights; i++) {
|
||||
if (&aqdata->aqbuttons[button] == aqdata->lights[i].button) {
|
||||
// Found the programmable light
|
||||
light = &aqdata->lights[i];
|
||||
break;
|
||||
}
|
||||
}*/
|
||||
*/
|
||||
|
||||
clight_detail *light = getProgramableLight(aqdata, deviceIndex);
|
||||
|
||||
if (light == NULL) {
|
||||
LOG(PANL_LOG,LOG_ERR, "Light mode control not configured for button %d\n",deviceIndex);
|
||||
LOG(PANL_LOG,LOG_ERR, "Light mode control not configured for button %d\n", deviceIndex);
|
||||
return;
|
||||
}
|
||||
|
||||
if (isMASK_SET(light->button->special_mask, VIRTUAL_BUTTON)) {
|
||||
// We can only program a light on virtual button on iaqtouch or onetouch
|
||||
if (isIAQT_ENABLED ) {
|
||||
#ifdef NEW_AQ_PROGRAMMER
|
||||
aq_programmer(AQ_SET_IAQTOUCH_LIGHTCOLOR_MODE, light->button, value, AQP_NULL, aqdata);
|
||||
#else
|
||||
char buf[LIGHT_MODE_BUFER];
|
||||
sprintf(buf, "%-5d%-5d%-5d",value, deviceIndex, light->lightType);
|
||||
aq_programmer(AQ_SET_IAQTOUCH_LIGHTCOLOR_MODE, buf, aqdata);
|
||||
#endif
|
||||
} else if (isONET_ENABLED ) {
|
||||
LOG(PANL_LOG,LOG_ERR, "Light mode on virtual button not implimented on OneTouch protocol (needs AqualinkTouch)\n");
|
||||
} else {
|
||||
LOG(PANL_LOG,LOG_ERR, "Light mode on virtual button needs AqualinkTouch protocol\n");
|
||||
}
|
||||
} else if (light->lightType == LC_PROGRAMABLE ) {
|
||||
#ifdef NEW_AQ_PROGRAMMER
|
||||
aq_programmer(AQ_SET_LIGHTPROGRAM_MODE, light->button, value, AQP_NULL, aqdata);
|
||||
#else
|
||||
char buf[LIGHT_MODE_BUFER];
|
||||
sprintf(buf, "%-5d%-5d%-5d%-5d%.2f",value,
|
||||
deviceIndex,
|
||||
_aqconfig_.light_programming_initial_on,
|
||||
_aqconfig_.light_programming_initial_off,
|
||||
_aqconfig_.light_programming_mode );
|
||||
aq_programmer(AQ_SET_LIGHTPROGRAM_MODE, buf, aqdata);
|
||||
#endif
|
||||
} else if (isRSSA_ENABLED ) {
|
||||
// If we are using rs-serial then turn light on first.
|
||||
if (light->button->led->state != ON) {
|
||||
set_aqualink_rssadapter_aux_state(light->button, TRUE);
|
||||
//set_aqualink_rssadapter_aux_extended_state(light->button, RS_SA_ON);
|
||||
//set_aqualink_rssadapter_aux_extended_state(light->button, 100);
|
||||
// Add a few delays to slow it down. 0 is get status
|
||||
//set_aqualink_rssadapter_aux_extended_state(light->button, 0);
|
||||
//set_aqualink_rssadapter_aux_extended_state(light->button, 0);
|
||||
}
|
||||
if (light->lightType == LC_DIMMER) {
|
||||
// Value 1 = 25, 2 = 50, 3 = 75, 4 = 100 (need to convert value into binary)
|
||||
if (value >= 1 && value <= 4) {
|
||||
unsigned char rssd_value = value * 25;
|
||||
//rssd_value +=128;
|
||||
set_aqualink_rssadapter_aux_extended_state(light->button, rssd_value);
|
||||
} else {
|
||||
LOG(PANL_LOG,LOG_ERR, "Light mode %d is not valid for '%s'\n",value, light->button->label);
|
||||
set_aqualink_rssadapter_aux_extended_state(light->button, 100);
|
||||
}
|
||||
} else {
|
||||
// Dimmer or any color light can simply be set with value
|
||||
set_aqualink_rssadapter_aux_extended_state(light->button, value + 128);
|
||||
}
|
||||
/*
|
||||
} else if (isRSSA_ENABLED && light->lightType == LC_DIMMER2) {
|
||||
// Dimmer needs to be turned on before you set dimmer level
|
||||
if (light->button->led->state != ON) {
|
||||
set_aqualink_rssadapter_aux_extended_state(light->button, RS_SA_ON);
|
||||
}
|
||||
set_aqualink_rssadapter_aux_extended_state(light->button, value);
|
||||
} else if (isRSSA_ENABLED && light->lightType == LC_DIMMER) {
|
||||
// Dimmer needs to be turned on first
|
||||
if (light->button->led->state != ON) {
|
||||
set_aqualink_rssadapter_aux_extended_state(light->button, RS_SA_ON);
|
||||
}
|
||||
// Value 1 = 25, 2 = 50, 3 = 75, 4 = 100 (need to convert value into binary)
|
||||
if (value >= 1 && value <= 4) {
|
||||
// If value is not on of those vales, then ignore
|
||||
unsigned char rssd_value = value * 25;
|
||||
set_aqualink_rssadapter_aux_extended_state(light->button, rssd_value);
|
||||
} else {
|
||||
LOG(PANL_LOG,LOG_ERR, "Light mode %d is not valid for '%s'\n",value, light->button->label);
|
||||
}
|
||||
} else if (isRSSA_ENABLED && light->lightType != LC_PROGRAMABLE) {
|
||||
// Any programmable COLOR light (that's programmed by panel)
|
||||
set_aqualink_rssadapter_aux_extended_state(light->button, value);*/
|
||||
} else {
|
||||
#ifdef NEW_AQ_PROGRAMMER
|
||||
aq_programmer(AQ_SET_LIGHTCOLOR_MODE, light->button, value, AQP_NULL, aqdata);
|
||||
#else
|
||||
char buf[LIGHT_MODE_BUFER];
|
||||
sprintf(buf, "%-5d%-5d%-5d",value, deviceIndex, light->lightType);
|
||||
aq_programmer(AQ_SET_LIGHTCOLOR_MODE, buf, aqdata);
|
||||
#endif
|
||||
if (! is_valid_light_mode(light->lightType, value)) {
|
||||
LOG(PANL_LOG,LOG_ERR, "Light mode '%d' is not valid for light '%s', %s\n", value, lightTypeName(light->lightType), light->button->label);
|
||||
return;
|
||||
}
|
||||
|
||||
if (light->lightType == LC_DIMMER2 || light->lightType == LC_DIMMER) {// DIMMER
|
||||
programDeviceLightBrightness(aqdata, (light->lightType== LC_DIMMER?dimmer_mode_to_percent(value):value), deviceIndex, expectMultiple, source);
|
||||
return;
|
||||
}
|
||||
|
||||
// Turn on a light with no mode set.
|
||||
if (value == USE_LAST_VALUE) {
|
||||
extra_value = true;
|
||||
value = 1; // Do we need to reset this?
|
||||
// Anything but VIRTUAL_BUTTON we can turn on with no mode simply.
|
||||
if (!isMASK_SET(light->button->special_mask, VIRTUAL_BUTTON)) {
|
||||
// for LC_PROGRAMMABLE is a simple ON command, so send it and be done.
|
||||
if (light->lightType == LC_PROGRAMABLE) {
|
||||
aq_send_allb_cmd(light->button->code);
|
||||
light->currentValue = light->lastValue; // will come back on in last mode, so set that.
|
||||
// easiest way is to turn on with RSSA then no questions asked.
|
||||
} else if (isRSSA_ENABLED) {
|
||||
set_aqualink_rssadapter_aux_state(light->button, true);
|
||||
} else {
|
||||
aq_programmer(AQ_SET_LIGHTCOLOR_MODE, light->button, 1, extra_value, aqdata);
|
||||
}
|
||||
return;
|
||||
}
|
||||
} else if (value == 0) {
|
||||
// We simply need to turn the light off at this point, so use allbutton key as it's the quickest.
|
||||
// but can't turn off a virtual light.
|
||||
if (light->button->led->state == ON && !isMASK_SET(light->button->special_mask, VIRTUAL_BUTTON)) {
|
||||
//DPRINTF("allbutton off");
|
||||
aq_send_allb_cmd(light->button->code);
|
||||
// Could also check isRSSA_ENABLED and use set_aqualink_rssadapter_aux_state(light->button, FALSE);
|
||||
return;
|
||||
} else if (light->button->led->state != ON ) {
|
||||
LOG(PANL_LOG,LOG_WARNING, "Request to turn off Light mode '%s' to off, already off, ignoring!\n",light->button->label);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Logic, select one of 3 programming options, RSSD / AllButton / AqualinkTouch
|
||||
// virtual button light can only be done with AqualinkTouch
|
||||
// LC_PROGRAMABLE can only be done with AllButton
|
||||
// user can set a default
|
||||
// dimmer light NEEDS to be turned on with allbutton.
|
||||
|
||||
// Check Virtual Button requires IAQT protocol
|
||||
if (isMASK_SET(light->button->special_mask, VIRTUAL_BUTTON) && !isIAQT_ENABLED)
|
||||
{
|
||||
// Log an error and stop execution if a Virtual Button is used without IAQT.
|
||||
LOG(PANL_LOG, LOG_ERR, "Light mode on virtual button needs AqualinkTouch protocol\n");
|
||||
return;
|
||||
}
|
||||
// Use allbutton if LC_PROGRAMABLE light, or no other protocol options
|
||||
else if (light->lightType == LC_PROGRAMABLE)
|
||||
{
|
||||
//DPRINTF("AQ_SET_LIGHTPROGRAM_MODE");
|
||||
aq_programmer(AQ_SET_LIGHTPROGRAM_MODE, light->button, value, extra_value, aqdata);
|
||||
}
|
||||
// Use allbutton if explicitly set, or no other protocol options
|
||||
else if ((!isRSSA_ENABLED && !isIAQT_ENABLED) ||
|
||||
(_aqconfig_.light_programming_interface == LIGHT_PROTOCOL_ALLB))
|
||||
{
|
||||
//DPRINTF("AQ_SET_ALLB_LIGHTCOLOR_MODE");
|
||||
aq_programmer(AQ_SET_ALLB_LIGHTCOLOR_MODE, light->button, value, extra_value, aqdata);
|
||||
}
|
||||
// Use AqualinkTouch if explicitly set or virtual button.
|
||||
else if (isIAQT_ENABLED &&
|
||||
(_aqconfig_.light_programming_interface == LIGHT_PROTOCOL_AQLT ||
|
||||
isMASK_SET(light->button->special_mask, VIRTUAL_BUTTON)))
|
||||
{
|
||||
//DPRINTF("AQ_SET_IAQTOUCH_LIGHTCOLOR_MODE");
|
||||
// This depends on the button label being accurate with panel.
|
||||
aq_programmer(AQ_SET_IAQTOUCH_LIGHTCOLOR_MODE, light->button, value, extra_value, aqdata);
|
||||
}
|
||||
// Use RS-Serial Adapter protocol
|
||||
else if (isRSSA_ENABLED)
|
||||
{
|
||||
//DPRINTF("set_aqualink_rssadapter_aux_state");
|
||||
unsigned char rssd_value = value + RSSD_COLOR_LIGHT_OFFSET_WRITE;
|
||||
// If light is off, turn it on first
|
||||
if (light->button->led->state != ON)
|
||||
{
|
||||
set_aqualink_rssadapter_aux_state(light->button, TRUE);
|
||||
}
|
||||
// Adjust the value for Dimmer lights (map color index to full range %).
|
||||
if (light->lightType == LC_DIMMER || light->lightType == LC_DIMMER2)
|
||||
{
|
||||
rssd_value = value * 25; // Dimmer is full range % on RSSD
|
||||
}
|
||||
set_aqualink_rssadapter_aux_extended_state(light->button, rssd_value);
|
||||
}
|
||||
// Default Fallback (Should rarely be reached)
|
||||
else {
|
||||
//DPRINTF("AQ_SET_LIGHTCOLOR_MODE");
|
||||
aq_programmer(AQ_SET_LIGHTCOLOR_MODE, light->button, value, extra_value, aqdata);
|
||||
}
|
||||
|
||||
|
||||
// Use function so can be called from programming thread if we decide to in future.
|
||||
if (light->lightType != LC_PROGRAMABLE ) {
|
||||
// Only update if a panel programed light. If AqualinkD programs, the programmer needs to know the last mode.
|
||||
|
|
@ -1787,6 +1790,7 @@ void programDeviceLightMode(struct aqualinkdata *aqdata, int value, int deviceIn
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
deviceIndex = button index on button list (or pumpIndex for VSP action_types)
|
||||
value = value to set (0=off 1=on, or value for setpoints / rpm / timer) action_type will depend on this value
|
||||
|
|
@ -1833,6 +1837,7 @@ bool panel_device_request(struct aqualinkdata *aqdata, action_type type, int dev
|
|||
start_timer(aqdata, deviceIndex, value);
|
||||
break;
|
||||
case LIGHT_BRIGHTNESS:
|
||||
// Allow value=0 here (unlike LIGHT_MODE) since we could get multiple requests from a slider. (aka HomeKit)
|
||||
programDeviceLightBrightness(aqdata, value, deviceIndex, (source==NET_MQTT?true:false), source);
|
||||
break;
|
||||
case LIGHT_MODE:
|
||||
|
|
@ -1840,7 +1845,7 @@ bool panel_device_request(struct aqualinkdata *aqdata, action_type type, int dev
|
|||
// Consider this a bad/malformed request to turn the light off.
|
||||
panel_device_request(aqdata, ON_OFF, deviceIndex, 0, source);
|
||||
} else {
|
||||
programDeviceLightMode(aqdata, value, deviceIndex);
|
||||
programDeviceLightMode(aqdata, value, deviceIndex, (source==NET_MQTT?true:false), source);
|
||||
}
|
||||
break;
|
||||
case POOL_HTR_SETPOINT:
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ const uint32_t PANEL_COMPARISON_MASK = (1U << 12) - 1; // We only care about bi
|
|||
#define RSP_SUP_PLAB (1 << 11) // Pump VSP by Label and not number
|
||||
#define RSP_SUP_HPCHIL (1 << 12) // Heat Pump chiller
|
||||
#define RSP_SUP_PCDOC (1 << 13) // PC Dock
|
||||
|
||||
#define RSP_SUP_CLIT_RSSA (1 << 14) // Color Lights can be set over serial adapter.
|
||||
|
||||
#define PANEL_CPU (1 << 0)
|
||||
#define PANEL_REV (1 << 1)
|
||||
|
|
|
|||
|
|
@ -73,6 +73,10 @@ const func_ptr _prog_functions[AQP_RSSADAPTER_MAX] = {
|
|||
[AQ_SET_SWG_PERCENT] = set_allbutton_SWG,
|
||||
[AQ_GET_AUX_LABELS] = get_allbutton_aux_labels,
|
||||
[AQ_SET_BOOST] = set_allbutton_boost,
|
||||
// Specific one to force all button for light programming
|
||||
[AQ_SET_ALLB_LIGHTCOLOR_MODE] = set_allbutton_light_colormode,
|
||||
[AQ_SET_ALLB_LIGHTDIMMER] = set_allbutton_light_dimmer,
|
||||
|
||||
[AQ_SET_ONETOUCH_PUMP_RPM] = set_aqualink_onetouch_pump_rpm,
|
||||
[AQ_GET_ONETOUCH_FREEZEPROTECT] = get_aqualink_onetouch_freezeprotect,
|
||||
[AQ_GET_ONETOUCH_SETPOINTS] = get_aqualink_onetouch_setpoints,
|
||||
|
|
@ -909,9 +913,11 @@ const char *ptypeName(program_type type)
|
|||
return "Set light color (using AqualinkD)";
|
||||
break;
|
||||
case AQ_SET_LIGHTCOLOR_MODE:
|
||||
return "Set light color (using Panel)";
|
||||
case AQ_SET_ALLB_LIGHTCOLOR_MODE:
|
||||
return "Set light color";
|
||||
break;
|
||||
case AQ_SET_LIGHTDIMMER:
|
||||
case AQ_SET_ALLB_LIGHTDIMMER:
|
||||
return "Set light dimmer";
|
||||
break;
|
||||
case AQ_SET_SWG_PERCENT:
|
||||
|
|
@ -1004,7 +1010,7 @@ const char *ptypeName(program_type type)
|
|||
return "Set AqualinkTouch OneTouch On/Off";
|
||||
break;
|
||||
case AQ_SET_IAQTOUCH_LIGHTCOLOR_MODE:
|
||||
return "Set AqualinkTouch Light Color (using panel)";
|
||||
return "Set AqualinkTouch Light Mode";
|
||||
break;
|
||||
case AQ_SET_IAQTOUCH_SWG_BOOST:
|
||||
return "Set AqualinkTouch Boost";
|
||||
|
|
@ -1123,6 +1129,8 @@ const char *programtypeDisplayName(program_type type)
|
|||
case AQ_SET_LIGHTCOLOR_MODE:
|
||||
case AQ_SET_IAQTOUCH_LIGHTCOLOR_MODE:
|
||||
case AQ_SET_LIGHTDIMMER:
|
||||
case AQ_SET_ALLB_LIGHTDIMMER:
|
||||
case AQ_SET_ALLB_LIGHTCOLOR_MODE:
|
||||
return "Programming: setting light mode";
|
||||
break;
|
||||
case AQ_SET_SWG_PERCENT:
|
||||
|
|
|
|||
|
|
@ -68,6 +68,9 @@ typedef enum {
|
|||
AQ_SET_PUMP_RPM,
|
||||
AQ_SET_PUMP_VS_PROGRAM,
|
||||
AQ_SET_CHILLER_TEMP,
|
||||
// **** Specific allputon light program. (maybe create all all button in future)
|
||||
AQ_SET_ALLB_LIGHTCOLOR_MODE,
|
||||
AQ_SET_ALLB_LIGHTDIMMER,
|
||||
// ******** PDA Delimiter make sure to change MAX/MIN below
|
||||
AQ_PDA_INIT,
|
||||
AQ_PDA_WAKE_INIT,
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@
|
|||
#include "sensors.h"
|
||||
//#include "aq_panel.h" // Moved to later in file to overcome circular dependancy. (crappy I know)
|
||||
|
||||
//#define PRINTF(format, ...) printf("%s:%d: " format, __FILE__, __LINE__, ##__VA_ARGS__)
|
||||
#define PRINTF(format, ...)
|
||||
//#define DPRINTF(format, ...) printf("%s:%d: " format, __FILE__, __LINE__, ##__VA_ARGS__)
|
||||
//#define DPRINTF(format, ...)
|
||||
|
||||
#define isMASK_SET(bitmask, mask) ((bitmask & mask) == mask)
|
||||
#define setMASK(bitmask, mask) (bitmask |= mask)
|
||||
|
|
|
|||
|
|
@ -434,6 +434,9 @@ void action_delayed_request()
|
|||
else if (_aqualink_data.unactioned.type == LIGHT_MODE) {
|
||||
panel_device_request(&_aqualink_data, LIGHT_MODE, _aqualink_data.unactioned.id, _aqualink_data.unactioned.value, UNACTION_TIMER);
|
||||
}
|
||||
else if (_aqualink_data.unactioned.type == LIGHT_BRIGHTNESS) {
|
||||
panel_device_request(&_aqualink_data, LIGHT_BRIGHTNESS, _aqualink_data.unactioned.id, _aqualink_data.unactioned.value, UNACTION_TIMER);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(AQUA_LOG,LOG_ERR, "Unknown request of type %d\n", _aqualink_data.unactioned.type);
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ char *_color_light_options[NUMBER_LIGHT_COLOR_TYPES][LIGHT_COLOR_OPTIONS] =
|
|||
"Magenta",
|
||||
"Garnet Red",
|
||||
"Violet",
|
||||
"Color Splash"
|
||||
"Color Splash" // 0x4b
|
||||
},
|
||||
{ // 2 = Jandy LED
|
||||
"Off",
|
||||
|
|
@ -182,6 +182,28 @@ void setColorLightsPanelVersion(uint8_t supported)
|
|||
set = true;
|
||||
}
|
||||
*/
|
||||
|
||||
bool is_valid_light_mode(clight_type type, int index)
|
||||
{
|
||||
printf("Checking _color_light_options[%d][%d]\n",type,index);
|
||||
|
||||
if (type == LC_DIMMER2) {
|
||||
if (index >= 0 && index <=100) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (index < 0 || index > LIGHT_COLOR_OPTIONS || _color_light_options[type][index] == NULL ){
|
||||
return false;
|
||||
}
|
||||
|
||||
printf("result = %s\n", _color_light_options[type][index]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void clear_aqualinkd_light_modes()
|
||||
{
|
||||
//_color_light_options[0] = _aqualinkd_custom_colors;
|
||||
|
|
@ -271,6 +293,8 @@ const char *get_currentlight_mode_name(clight_detail light, emulation_type proto
|
|||
return _color_light_options[light.lightType][light.currentValue];
|
||||
}
|
||||
|
||||
|
||||
|
||||
// This should not be uses for getting current lightmode name since it doesn;t have full logic
|
||||
|
||||
const char *light_mode_name(clight_type type, int index, emulation_type protocol)
|
||||
|
|
@ -346,6 +370,68 @@ bool set_currentlight_value(clight_detail *light, int index)
|
|||
return rtn;
|
||||
}
|
||||
|
||||
// Take a % and return 0,1,2,3,4 for 0=0, 1=25, 2=50, 3=75, 4=100, ie the index of _color_light_options[10][??]
|
||||
int dimmer_percent_to_mode_index(int value)
|
||||
{
|
||||
/*
|
||||
value = round(value / 25);
|
||||
if (value > 4 ) {value=4;}
|
||||
*/
|
||||
value = round( (value+12) / 25); // Round up/down
|
||||
if (value > 4 ) {value=4;}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
int dimmer_mode_to_percent(int value)
|
||||
{
|
||||
return value * 25;
|
||||
}
|
||||
|
||||
|
||||
const char* lightTypeName(clight_type type)
|
||||
{
|
||||
switch (type) {
|
||||
case LC_PROGRAMABLE:
|
||||
return "AqualinkD Programmable";
|
||||
break;
|
||||
case LC_JANDY:
|
||||
return "Jandy Color";
|
||||
break;
|
||||
case LC_JANDYLED:
|
||||
return "Jandy LED";
|
||||
break;
|
||||
case LC_SAL:
|
||||
return "SAm/SAL";
|
||||
break;
|
||||
case LC_CLOGIG:
|
||||
return "Color Logic";
|
||||
break;
|
||||
case LC_INTELLIB:
|
||||
return "Intelibrite";
|
||||
break;
|
||||
case LC_HAYWCL:
|
||||
return "Haywood Universal";
|
||||
break;
|
||||
case LC_JANDYINFINATE:
|
||||
return "Jandy Infinite";
|
||||
break;
|
||||
case LC_DIMMER:
|
||||
return "Dimmer";
|
||||
break;
|
||||
case LC_DIMMER2:
|
||||
return "Dimmer (full range)";
|
||||
break;
|
||||
|
||||
default:
|
||||
case LC_SPARE_2:
|
||||
case LC_SPARE_3:
|
||||
return "unknown";
|
||||
break;
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
// Used for dynamic config JS
|
||||
int build_color_lights_js(struct aqualinkdata *aqdata, char* buffer, int size)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -11,9 +11,13 @@
|
|||
//#define LIGHT_COLOR_TYPES LC_DIMMER+1
|
||||
|
||||
// The status returned from RS Serial Adapter has this added as a base.
|
||||
#define RSSD_COLOR_LIGHT_OFFSET 64
|
||||
#define RSSD_COLOR_LIGHT_OFFSET_WRITE 128 // when writing its 128
|
||||
#define RSSD_COLOR_LIGHT_OFFSET_READ 64 // when reading is 64
|
||||
#define RSSD_DIMMER_LIGHT_OFFSET 128
|
||||
|
||||
// When selecting a color light, the Button press keycode add this offset.
|
||||
#define IAQ_COLOR_LIGHT_OFFSET 16
|
||||
|
||||
//#define DIMMER_LIGHT_TYPE_INDEX 10
|
||||
|
||||
/*
|
||||
|
|
@ -24,7 +28,7 @@ typedef enum clight_type {
|
|||
LC_JANDYLED,
|
||||
LC_SAL,
|
||||
LC_CLOGIG,
|
||||
LC_INTELLIB
|
||||
LC_INTELLIB,
|
||||
} clight_type;
|
||||
*/
|
||||
//const char *light_mode_name(clight_type type, int index);
|
||||
|
|
@ -32,9 +36,12 @@ const char *get_currentlight_mode_name(clight_detail light, emulation_type proto
|
|||
const char *light_mode_name(clight_type type, int index, emulation_type protocol);
|
||||
int build_color_lights_js(struct aqualinkdata *aqdata, char* buffer, int size);
|
||||
int build_color_light_jsonarray(int index, char* buffer, int size);
|
||||
|
||||
int dimmer_percent_to_mode_index(int value);
|
||||
int dimmer_mode_to_percent(int value);
|
||||
void clear_aqualinkd_light_modes();
|
||||
bool set_currentlight_value(clight_detail *light, int index);
|
||||
bool is_valid_light_mode(clight_type type, int index);
|
||||
const char* lightTypeName(clight_type type);
|
||||
|
||||
bool set_aqualinkd_light_mode_name(char *name, int index, bool isShow);
|
||||
const char *get_aqualinkd_light_mode_name(int index, bool *isShow);
|
||||
|
|
|
|||
|
|
@ -264,6 +264,7 @@ void init_parameters (struct aqconfig * parms)
|
|||
_cfgParams[_numCfgParams].name = CFG_N_rssa_device_id;
|
||||
_cfgParams[_numCfgParams].valid_values = CFG_V_rssa_device_id;
|
||||
_cfgParams[_numCfgParams].default_value = (void *)&_dcfg_unknownHex;
|
||||
_cfgParams[_numCfgParams].config_mask |= CFG_FORCE_RESTART;
|
||||
|
||||
_numCfgParams++;
|
||||
_cfgParams[_numCfgParams].value_ptr = &_aqconfig_.extended_device_id_programming;
|
||||
|
|
@ -279,6 +280,7 @@ void init_parameters (struct aqconfig * parms)
|
|||
_cfgParams[_numCfgParams].name = CFG_N_extended_device_id;
|
||||
_cfgParams[_numCfgParams].valid_values = CFG_V_extended_device_id;
|
||||
_cfgParams[_numCfgParams].default_value = (void *)&_dcfg_unknownHex;
|
||||
_cfgParams[_numCfgParams].config_mask |= CFG_FORCE_RESTART;
|
||||
|
||||
_numCfgParams++;
|
||||
_cfgParams[_numCfgParams].value_ptr = &_aqconfig_.enable_iaqualink;
|
||||
|
|
@ -286,6 +288,7 @@ void init_parameters (struct aqconfig * parms)
|
|||
_cfgParams[_numCfgParams].name = CFG_N_enable_iaqualink;
|
||||
_cfgParams[_numCfgParams].valid_values = CFG_V_BOOL;
|
||||
_cfgParams[_numCfgParams].default_value = (void *)&_dcfg_false;
|
||||
_cfgParams[_numCfgParams].config_mask |= CFG_FORCE_RESTART;
|
||||
|
||||
#ifndef AQ_MANAGER
|
||||
_numCfgParams++;
|
||||
|
|
@ -311,6 +314,7 @@ void init_parameters (struct aqconfig * parms)
|
|||
_cfgParams[_numCfgParams].name = CFG_N_mqtt_user;
|
||||
_cfgParams[_numCfgParams].default_value = (void *)NULL;
|
||||
_cfgParams[_numCfgParams].config_mask |= CFG_ALLOW_BLANK;
|
||||
_cfgParams[_numCfgParams].config_mask |= CFG_FORCE_RESTART;
|
||||
|
||||
_numCfgParams++;
|
||||
_cfgParams[_numCfgParams].value_ptr = &_aqconfig_.mqtt_passwd;
|
||||
|
|
@ -319,6 +323,7 @@ void init_parameters (struct aqconfig * parms)
|
|||
_cfgParams[_numCfgParams].config_mask |= CFG_PASSWD_MASK;
|
||||
_cfgParams[_numCfgParams].default_value = (void *)NULL;
|
||||
_cfgParams[_numCfgParams].config_mask |= CFG_ALLOW_BLANK;
|
||||
_cfgParams[_numCfgParams].config_mask |= CFG_FORCE_RESTART;
|
||||
|
||||
_numCfgParams++;
|
||||
_cfgParams[_numCfgParams].value_ptr = &_aqconfig_.mqtt_aq_topic;
|
||||
|
|
@ -326,6 +331,7 @@ void init_parameters (struct aqconfig * parms)
|
|||
_cfgParams[_numCfgParams].name = CFG_N_mqtt_aq_topic;
|
||||
_cfgParams[_numCfgParams].default_value = (void *)_dcfg_mqtt_aq_tp;
|
||||
_cfgParams[_numCfgParams].config_mask |= CFG_ALLOW_BLANK;
|
||||
_cfgParams[_numCfgParams].config_mask |= CFG_FORCE_RESTART;
|
||||
|
||||
_numCfgParams++;
|
||||
_cfgParams[_numCfgParams].value_ptr = &_aqconfig_.mqtt_discovery_topic;
|
||||
|
|
@ -333,12 +339,14 @@ void init_parameters (struct aqconfig * parms)
|
|||
_cfgParams[_numCfgParams].name = CFG_N_mqtt_discovery_topic;
|
||||
_cfgParams[_numCfgParams].default_value = (void *)_dcfg_mqtt_discovery;
|
||||
_cfgParams[_numCfgParams].config_mask |= CFG_ALLOW_BLANK;
|
||||
_cfgParams[_numCfgParams].config_mask |= CFG_FORCE_RESTART;
|
||||
|
||||
_numCfgParams++;
|
||||
_cfgParams[_numCfgParams].value_ptr = &_aqconfig_.mqtt_discovery_use_mac;
|
||||
_cfgParams[_numCfgParams].value_type = CFG_BOOL;
|
||||
_cfgParams[_numCfgParams].name = CFG_N_mqtt_discovery_use_mac;
|
||||
_cfgParams[_numCfgParams].default_value = (void *)&_dcfg_true;
|
||||
_cfgParams[_numCfgParams].config_mask |= CFG_FORCE_RESTART;
|
||||
|
||||
|
||||
#if MG_TLS > 0
|
||||
|
|
@ -372,6 +380,14 @@ void init_parameters (struct aqconfig * parms)
|
|||
_cfgParams[_numCfgParams].config_mask |= CFG_GRP_ADVANCED;
|
||||
_cfgParams[_numCfgParams].default_value = (void *)&_dcfg_light_programming_mode;
|
||||
|
||||
_numCfgParams++;
|
||||
_cfgParams[_numCfgParams].value_ptr = &_aqconfig_.light_programming_interface;
|
||||
_cfgParams[_numCfgParams].value_type = CFG_INT;
|
||||
_cfgParams[_numCfgParams].name = CFG_N_light_programming_interface;
|
||||
_cfgParams[_numCfgParams].config_mask |= CFG_GRP_ADVANCED;
|
||||
_cfgParams[_numCfgParams].config_mask |= CFG_READONLY;
|
||||
_cfgParams[_numCfgParams].default_value = (void *)&_dcfg_zero;
|
||||
|
||||
_numCfgParams++;
|
||||
_cfgParams[_numCfgParams].value_ptr = &_aqconfig_.light_programming_initial_on;
|
||||
_cfgParams[_numCfgParams].value_type = CFG_INT;
|
||||
|
|
@ -1751,6 +1767,39 @@ void check_print_config (struct aqualinkdata *aqdata)
|
|||
}
|
||||
}
|
||||
|
||||
// Color lights check infinate water color (RS485, is set as vbutton)
|
||||
for (i=1; i < aqdata->num_lights; i++) {
|
||||
if (aqdata->lights[i].lightType == LC_JANDYINFINATE) {
|
||||
// Check we have a virtual light button
|
||||
if ( !isMASK_SET(aqdata->lights[i].button->special_mask, VIRTUAL_BUTTON)) {
|
||||
LOG(AQUA_LOG,LOG_WARNING, "Config error, Light mode %d is only valid for a virtual button\n",LC_JANDYINFINATE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check valid setting
|
||||
if (_aqconfig_.light_programming_interface > LIGHT_PROTOCOL_AQLD) {
|
||||
if (_aqconfig_.device_id == 0x60) {
|
||||
LOG(AQUA_LOG,LOG_WARNING, "Config error, %s set to %d, not supported in PDA mode",CFG_N_light_programming_interface,_aqconfig_.light_programming_interface);
|
||||
_aqconfig_.light_programming_interface = LIGHT_PROTOCOL_AQLD;
|
||||
}
|
||||
|
||||
if(_aqconfig_.light_programming_interface == LIGHT_PROTOCOL_AQLT) {
|
||||
if (! is_aqualink_touch_id(_aqconfig_.extended_device_id)) {
|
||||
LOG(AQUA_LOG,LOG_WARNING, "Config error, %s set to AqualinkTouch, %s is not set for AqualinkTouch ID",CFG_N_light_programming_interface,CFG_N_extended_device_id);
|
||||
_aqconfig_.light_programming_interface = LIGHT_PROTOCOL_AQLD;
|
||||
}
|
||||
// Below not supported yet
|
||||
//} else if(_aqconfig_.light_programming_interface == LIGHT_PROTOCOL_ONET) {
|
||||
// if (! is_onetouch_id(_aqconfig_.extended_device_id)) {
|
||||
// LOG(AQUA_LOG,LOG_WARNING, "Config error, %s set to OneTouch, %s is not set for OneTouch ID",CFG_N_light_programming_interface,CFG_N_extended_device_id);
|
||||
// _aqconfig_.light_programming_interface = LIGHT_PROTOCOL_AQLD;
|
||||
// }
|
||||
} else if ( _aqconfig_.light_programming_interface > LIGHT_PROTOCOL_ALLB ) {
|
||||
LOG(AQUA_LOG,LOG_WARNING, "Config error, %s set to %d, not supported",CFG_N_light_programming_interface,_aqconfig_.light_programming_interface);
|
||||
_aqconfig_.light_programming_interface = LIGHT_PROTOCOL_AQLD;
|
||||
}
|
||||
}
|
||||
/*
|
||||
PDA Mode
|
||||
|
||||
|
|
|
|||
|
|
@ -40,6 +40,22 @@
|
|||
|
||||
#define MAX_RSSD_LOG_FILTERS 4
|
||||
|
||||
/*
|
||||
#define LIGHT_PROGRAM_INTERFACE_AQLD 0
|
||||
#define LIGHT_PROGRAM_INTERFACE_ALLB 1
|
||||
#define LIGHT_PROGRAM_INTERFACE_ONET 2
|
||||
#define LIGHT_PROGRAM_INTERFACE_AQLT 3
|
||||
#define LIGHT_PROGRAM_INTERFACE_IAQL 4
|
||||
*/
|
||||
// Going to explicitly set these numbers since they come from config file
|
||||
typedef enum {
|
||||
LIGHT_PROTOCOL_AQLD = 0,
|
||||
LIGHT_PROTOCOL_ALLB = 1,
|
||||
LIGHT_PROTOCOL_ONET = 2,
|
||||
LIGHT_PROTOCOL_AQLT = 3,
|
||||
LIGHT_PROTOCOL_IAQL = 4
|
||||
} light_program_interface;
|
||||
|
||||
struct aqconfig
|
||||
{
|
||||
#if MG_TLS > 0
|
||||
|
|
@ -77,6 +93,7 @@ struct aqconfig
|
|||
int light_programming_initial_on;
|
||||
int light_programming_initial_off;
|
||||
bool light_programming_advance_mode;
|
||||
light_program_interface light_programming_interface; // 0=let AqualinkD decide, 1=allbutton, 2=onetouch(N/A), 3=AqualinkTouch, 4=iaqualink(N/A)
|
||||
bool override_freeze_protect;
|
||||
#ifdef AQ_PDA
|
||||
bool pda_sleep_mode;
|
||||
|
|
@ -277,11 +294,12 @@ int _numCfgParams;
|
|||
#define CFG_N_override_freeze_protect "override_freeze_protect"
|
||||
#define CFG_N_pda_sleep_mode "pda_sleep_mode"
|
||||
#define CFG_N_convert_mqtt_temp "mqtt_convert_temp_to_c"
|
||||
#define CFG_N_light_programming_interface "light_programming_interface"
|
||||
|
||||
#define CFG_N_report_zero_spa_temp "report_zero_spa_temp"
|
||||
#define CFG_N_report_zero_pool_temp "report_zero_pool_temp"
|
||||
#define CFG_N_read_RS485_devmask "read_RS485_devmask"
|
||||
#define CFG_N_use_panel_aux_labels "use_panel_aux_labels"
|
||||
//#define CFG_N_use_panel_aux_labels "use_panel_aux_labels"
|
||||
#define CFG_N_force_swg "force_swg"
|
||||
#define CFG_N_force_ps_setpoints "force_ps_setpoints"
|
||||
#define CFG_N_force_frzprotect_setpoints "force_frzprotect_setpoints"
|
||||
|
|
@ -308,7 +326,7 @@ int _numCfgParams;
|
|||
#define CFG_N_event_check_freezeprotectoff "event_freezeprotectoff_check_pump"
|
||||
#define CFG_N_event_check_boostoff "event_boostoff_check_pump"
|
||||
#define CFG_N_event_check_pumpon_hour "event_check_pumpon_hour"
|
||||
#define CFG_N_event_check_pumpoff_hour "event_check_pumpoff_hour"
|
||||
#define CFG_N_event_check_pumpoff_hour "event_check_pumpoff_hour"
|
||||
#define CFG_N_event_check_usecron "event_check_use_scheduler_times"
|
||||
|
||||
#define CFG_N_event_check_booston_device "event_booston_check_device"
|
||||
|
|
|
|||
|
|
@ -53,11 +53,19 @@ typedef enum heatpumpmsgfrom{
|
|||
|
||||
void updateHeatPumpLed(heatpumpstate state, aqledstate ledstate, struct aqualinkdata *aqdata, heatpumpmsgfrom from);
|
||||
|
||||
bool shouldPrintJAndyDebugPacket()
|
||||
{
|
||||
if (getLogLevel(DJAN_LOG) == LOG_DEBUG && getLogLevel(RSSD_LOG) < LOG_DEBUG ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
void printJandyDebugPacket (const char *msg, const unsigned char *packet, int packet_length)
|
||||
{
|
||||
// Only log if we are jandy debug mode and not serial debug (otherwise it'll print twice)
|
||||
if (getLogLevel(DJAN_LOG) == LOG_DEBUG && getLogLevel(RSSD_LOG) < LOG_DEBUG ) {
|
||||
//if (getLogLevel(DJAN_LOG) == LOG_DEBUG && getLogLevel(RSSD_LOG) < LOG_DEBUG ) {
|
||||
if (shouldPrintJAndyDebugPacket()) {
|
||||
char frame[1024];
|
||||
//beautifyPacket(frame, 1024, packet, packet_length, true);
|
||||
|
||||
|
|
@ -914,28 +922,40 @@ bool processPacketFromJandyLXHeater(unsigned char *packet_buffer, int packet_len
|
|||
|
||||
bool processPacketToJandyChemFeeder(unsigned char *packet_buffer, int packet_length, struct aqualinkdata *aqdata)
|
||||
{
|
||||
/*
|
||||
char msg[1024];
|
||||
int length = 0;
|
||||
|
||||
length += sprintf(msg+length, "Last panel info ");
|
||||
|
||||
length += sprintf(msg+length, ", pH=%f, ORP=%d",aqdata->ph, aqdata->orp);
|
||||
|
||||
LOG(DJAN_LOG, LOG_INFO, "%s\n", msg);
|
||||
*/
|
||||
LOG(DJAN_LOG, LOG_INFO, "Last panel info : pH=%f, ORP=%d",aqdata->ph, aqdata->orp);
|
||||
|
||||
if (!shouldPrintJAndyDebugPacket()) {
|
||||
// if we are not going to print the packet as debug, print it here
|
||||
logPacket(DJAN_LOG, LOG_INFO, packet_buffer, packet_length, true);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool processPacketFromJandyChemFeeder(unsigned char *packet_buffer, int packet_length, struct aqualinkdata *aqdata, const unsigned char previous_packet_to){
|
||||
/*
|
||||
char msg[1024];
|
||||
int length = 0;
|
||||
|
||||
length += sprintf(msg+length, "Last panel info ");
|
||||
|
||||
length += sprintf(msg+length, ", pH=%f, ORP=%d",aqdata->ph, aqdata->orp);
|
||||
|
||||
LOG(DJAN_LOG, LOG_INFO, "%s\n", msg);
|
||||
|
||||
*/
|
||||
LOG(DJAN_LOG, LOG_INFO, "Last panel info : pH=%f, ORP=%d",aqdata->ph, aqdata->orp);
|
||||
|
||||
if (!shouldPrintJAndyDebugPacket()) {
|
||||
// if we are not going to print the packet as debug, print it here
|
||||
logPacket(DJAN_LOG, LOG_INFO, packet_buffer, packet_length, true);
|
||||
}
|
||||
|
||||
/*
|
||||
I think the below may be accurate
|
||||
ph_setpoint = float(raw_data[8]) / 10
|
||||
|
|
@ -1214,7 +1234,10 @@ bool processPacketToJandyLight(unsigned char *packet_buffer, int packet_length,
|
|||
LOG(DJAN_LOG, LOG_INFO, "Request to set Jandy Light RGB to %d:%d:%d\n", packet_buffer[6],packet_buffer[7],packet_buffer[8]);
|
||||
}
|
||||
|
||||
logPacket(DJAN_LOG, LOG_INFO, packet_buffer, packet_length, true);
|
||||
if (!shouldPrintJAndyDebugPacket()) {
|
||||
// if we are not going to print the packet as debug, print it here
|
||||
logPacket(DJAN_LOG, LOG_INFO, packet_buffer, packet_length, true);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1226,7 +1249,10 @@ bool processPacketFromJandyLight(unsigned char *packet_buffer, int packet_length
|
|||
LOG(DJAN_LOG, LOG_INFO, "Light brightness=%d\n", packet_buffer[38]);
|
||||
}
|
||||
|
||||
logPacket(DJAN_LOG, LOG_INFO, packet_buffer, packet_length, true);
|
||||
if (!shouldPrintJAndyDebugPacket()) {
|
||||
// if we are not going to print the packet as debug, print it here
|
||||
logPacket(DJAN_LOG, LOG_INFO, packet_buffer, packet_length, true);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -356,6 +356,8 @@ void updateAQButtonFromPageButton(struct aqualinkdata *aqdata, struct iaqt_page_
|
|||
break;
|
||||
case 0x01:
|
||||
SET_IF_CHANGED(aqdata->aqbuttons[i].led->state, ON, aqdata->is_dirty);
|
||||
//NSF might want to check virtual light here, if so remove the color mode name, since
|
||||
// we didnt turn the light on, we cant state the color mode
|
||||
break;
|
||||
case 0x02:
|
||||
SET_IF_CHANGED(aqdata->aqbuttons[i].led->state, FLASH, aqdata->is_dirty);
|
||||
|
|
@ -976,7 +978,7 @@ bool process_iaqtouch_packet(unsigned char *packet, int length, struct aqualinkd
|
|||
// Set disply message if PDA panel
|
||||
memset(_popupMsg, 0, AQ_MSGLONGLEN + 1);
|
||||
rsm_strncpy(_popupMsg, packet + 6, AQ_MSGLONGLEN, length-9);
|
||||
LOG(IAQT_LOG,LOG_NOTICE, "Popup message '%s'\n",_popupMsg);
|
||||
LOG(IAQT_LOG,LOG_INFO, "Popup message '%s'\n",_popupMsg);
|
||||
|
||||
// Change this message, since you can't press OK. 'Light will turn off in 5 seconds. To change colors press Ok now.'
|
||||
if ((sp = rsm_strncasestr(_popupMsg, "To change colors press Ok now", strlen(_popupMsg))) != NULL)
|
||||
|
|
|
|||
|
|
@ -771,7 +771,7 @@ void *set_aqualink_iaqtouch_light_colormode( void *ptr )
|
|||
// See if it's on the current page
|
||||
pButton = iaqtFindButtonByLabel(key->label);
|
||||
|
||||
PRINTF("First button find = %s\n",pButton==NULL?"null":pButton->name);
|
||||
//DPRINTF("First button find = %s\n",pButton==NULL?"null":pButton->name);
|
||||
|
||||
if (pButton == NULL) {
|
||||
// No luck, go to the device page
|
||||
|
|
@ -780,22 +780,24 @@ PRINTF("First button find = %s\n",pButton==NULL?"null":pButton->name);
|
|||
|
||||
pButton = iaqtFindButtonByLabel(key->label);
|
||||
|
||||
PRINTF("Second button find = %s\n",pButton==NULL?"null":pButton->name);
|
||||
//DPRINTF("Second button find = %s\n",pButton==NULL?"null":pButton->name);
|
||||
// If not found see if page has next
|
||||
if (pButton == NULL && iaqtFindButtonByIndex(16)->type == 0x03 ) {
|
||||
iaqt_queue_cmd(KEY_IAQTCH_NEXT_PAGE);
|
||||
waitfor_iaqt_nextPage(aqdata);
|
||||
// This will fail, since not looking at device page 2 buttons
|
||||
pButton = iaqtFindButtonByLabel(key->label);
|
||||
PRINTF("Third button find = %s\n",pButton==NULL?"null":pButton->name);
|
||||
//DPRINTF("Third button find = %s\n",pButton==NULL?"null":pButton->name);
|
||||
}
|
||||
}
|
||||
|
||||
if (pButton == NULL) {
|
||||
LOG(IAQT_LOG, LOG_ERR, "IAQ Touch did not find '%s' button on device list\n", key->label);
|
||||
LOG(IAQT_LOG, LOG_ERR, "IAQ Touch did not find '%s' button on device list, please check your config line '%s'\n",
|
||||
key->label,
|
||||
isMASK_SET(key->special_mask, VIRTUAL_BUTTON)?"virtual_button_??_label":"button_??_label" );
|
||||
goto f_end;
|
||||
}
|
||||
PRINTF("FOUND button = %s\n",pButton==NULL?"null":pButton->name);
|
||||
//DPRINTF("FOUND button = %s\n",pButton==NULL?"null":pButton->name);
|
||||
// WE have a iaqualink button, press it.
|
||||
LOG(IAQT_LOG, LOG_DEBUG, "IAQ Touch found '%s' sending keycode '0x%02hhx'\n", key->label, pButton->keycode);
|
||||
send_aqt_cmd(pButton->keycode);
|
||||
|
|
@ -805,18 +807,23 @@ PRINTF("FOUND button = %s\n",pButton==NULL?"null":pButton->name);
|
|||
// After pressing the button, Just need to wait for 5 seconds and it will :-
|
||||
// a) if off turn on and default to last color.
|
||||
// b) if on, turn off. (pain that we need to wait 5 seconds.)
|
||||
PRINTF("******** WAIT for next page\n");
|
||||
//DPRINTF("******** WAIT for next page\n");
|
||||
waitfor_iaqt_queue2empty();
|
||||
waitfor_iaqt_nextPage(aqdata);
|
||||
if (use_current_mode) {
|
||||
// Their is no message for this, so give one.
|
||||
sprintf(aqdata->last_display_message, "Light will turn on in 5 seconds");
|
||||
sprintf(aqdata->last_display_message, "Light will turn %s in 5 seconds", turn_off?"off":"on");
|
||||
aqdata->is_display_message_programming = true;
|
||||
SET_DIRTY(aqdata->is_dirty);
|
||||
}
|
||||
// Wait for next page maybe?
|
||||
// Below needs a timeout.
|
||||
while (waitfor_iaqt_nextPage(aqdata) == IAQ_PAGE_COLOR_LIGHT);
|
||||
|
||||
// Pre set key to off since it'll take ages
|
||||
if (turn_off)
|
||||
key->led->state = OFF;
|
||||
|
||||
goto f_end;
|
||||
}
|
||||
|
||||
|
|
@ -841,22 +848,26 @@ PRINTF("******** WAIT for next page\n");
|
|||
}
|
||||
|
||||
LOG(IAQT_LOG, LOG_DEBUG, "IAQ Touch found '%s' sending keycode '0x%02hhx' = '0x%02hhx' for light selection\n", mode_name, pButton->keycode, pButton->keycode+16);
|
||||
PRINTF("******** current page is '0x%02hhx'\n",iaqtCurrentPage());
|
||||
//DPRINTF("******** current page is '0x%02hhx'\n",iaqtCurrentPage());
|
||||
// NSF Key code is +16 for some reason. ie key 0x07=(send 0x17). 0x0a=(send 0x1a)
|
||||
send_aqt_cmd(pButton->keycode + 16);
|
||||
send_aqt_cmd(pButton->keycode + IAQ_COLOR_LIGHT_OFFSET);
|
||||
waitfor_iaqt_queue2empty();
|
||||
// Wait for popup message to disapera
|
||||
// This is iAq Popup messag | HEX: 0x10|0x02|0x33|0x2c|0x00|0x01|0x50|0x6c|0x65|0x61|0x73|0x65|0x20|0x77|0x61|0x69|0x74|0x2e|0x2e|0x2e|0x0a|0x20|0x43|0x79|0x63|0x6c|0x69|0x6e|0x67|0x20|0x74|0x6f|0x20|0x63|0x68|0x6f|0x73|0x65|0x6e|0x20|0x63|0x6f|0x6c|0x6f|0x72|0x2e|0x00|0x00|0x00|0x00|0x2e|0x10|0x03|
|
||||
// This is popup message clear | HEX: 0x10|0x02|0x33|0x2c|0x00|0x00|0x20|0x00|0x00|0x00|0x00|0x91|0x10|0x03|
|
||||
// 5th bit 0x00 = clear. (anything else message)
|
||||
|
||||
// Pre set light to on, since it'll take ages after this finished.
|
||||
if (!turn_off)
|
||||
key->led->state = ON;
|
||||
|
||||
unsigned char msg;
|
||||
int i=0;
|
||||
while ( (msg = waitfor_iaqt_nextMessage(aqdata, CMD_IAQ_MSG_LONG)) != NUL) {
|
||||
const char *pmsg = iaqtPopupMsg();
|
||||
PRINTF("******** popupMsg = %s ********\n",pmsg);
|
||||
//DPRINTF("******** popupMsg = %s ********\n",pmsg);
|
||||
if (pmsg[0] == ' ') {
|
||||
PRINTF("******** popupMsg clear ********\n");
|
||||
//DPRINTF("******** popupMsg clear ********\n");
|
||||
break;
|
||||
}
|
||||
if (++i > 5) {
|
||||
|
|
@ -866,9 +877,9 @@ PRINTF("******** WAIT for next page\n");
|
|||
}
|
||||
/*
|
||||
unsigned char page;
|
||||
PRINTF("******** current page is '0x%02hhx'\n",iaqtCurrentPage());
|
||||
DPRINTF("******** current page is '0x%02hhx'\n",iaqtCurrentPage());
|
||||
while ( (page = waitfor_iaqt_nextPage(aqdata)) != NUL) {
|
||||
PRINTF("******** next page is '0x%02hhx'\n",page); // page = 0x48 IAQ_PAGE_COLOR_LIGHT
|
||||
DPRINTF("******** next page is '0x%02hhx'\n",page); // page = 0x48 IAQ_PAGE_COLOR_LIGHT
|
||||
}
|
||||
*/
|
||||
//LOG(IAQT_LOG, LOG_ERR, "IAQ Touch WAIYING FOR 1 MESSAGES\n");
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
#define IAQ_TOUCH_PROGRAMMER_H_
|
||||
|
||||
|
||||
|
||||
unsigned char pop_iaqt_cmd(unsigned char receive_type);
|
||||
|
||||
void set_iaq_cansend(bool cansend);
|
||||
|
|
|
|||
|
|
@ -1077,6 +1077,7 @@ bool parseJSONrequest(char *buffer, struct JSONkvptr *request)
|
|||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
bool parseJSONwebrequest(char *buffer, struct JSONwebrequest *request)
|
||||
{
|
||||
int i=0;
|
||||
|
|
@ -1148,7 +1149,7 @@ bool parseJSONwebrequest(char *buffer, struct JSONwebrequest *request)
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
*/
|
||||
/*
|
||||
int json_cfg_element_OLD(char* buffer, int size, const char *name, const void *value, cfg_value_type type, char *valid_val) {
|
||||
int result = 0;
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ const char* getAqualinkDStatusMessage(struct aqualinkdata *aqdata);
|
|||
|
||||
int build_aqualink_status_JSON(struct aqualinkdata *aqdata, char* buffer, int size);
|
||||
int build_aux_labels_JSON(struct aqualinkdata *aqdata, char* buffer, int size);
|
||||
bool parseJSONwebrequest(char *buffer, struct JSONwebrequest *request);
|
||||
//bool parseJSONwebrequest(char *buffer, struct JSONwebrequest *request);
|
||||
bool parseJSONrequest(char *buffer, struct JSONkvptr *request);
|
||||
int build_logmsg_JSON(char *dest, int loglevel, const char *src, int dest_len, int src_len);
|
||||
int build_mqtt_status_JSON(char* buffer, int size, int idx, int nvalue, float setpoint/*char *svalue*/);
|
||||
|
|
|
|||
|
|
@ -65,6 +65,14 @@ struct mg_connection *mg_next(struct mg_mgr *s, struct mg_connection *conn) {
|
|||
tolower((unsigned char)(str)[(len)-1]) == tolower((unsigned char)(SUFFIX)[2]) \
|
||||
)
|
||||
|
||||
#define FAST_SUFFIX_4_CI(str, len, SUFFIX) ( \
|
||||
(len) >= 4 && \
|
||||
tolower((unsigned char)(str)[(len)-4]) == tolower((unsigned char)(SUFFIX)[0]) && \
|
||||
tolower((unsigned char)(str)[(len)-3]) == tolower((unsigned char)(SUFFIX)[1]) && \
|
||||
tolower((unsigned char)(str)[(len)-2]) == tolower((unsigned char)(SUFFIX)[2]) && \
|
||||
tolower((unsigned char)(str)[(len)-1]) == tolower((unsigned char)(SUFFIX)[3]) \
|
||||
)
|
||||
|
||||
|
||||
/*
|
||||
#if defined AQ_DEBUG || defined AQ_TM_DEBUG
|
||||
|
|
@ -1611,7 +1619,8 @@ void action_web_request(struct mg_connection *nc, struct mg_http_message *http_m
|
|||
// If we have a get request, pass it
|
||||
if (strncmp(http_msg->uri.buf, "/api", 4 ) != 0) {
|
||||
DEBUG_TIMER_START(&tid);
|
||||
if ( FAST_SUFFIX_3_CI(http_msg->uri.buf, http_msg->uri.len, ".js") ) {
|
||||
//if ( FAST_SUFFIX_3_CI(http_msg->uri.buf, http_msg->uri.len, ".js") ) {
|
||||
if ( FAST_SUFFIX_4_CI(http_msg->uri.buf, http_msg->uri.len, "json") ) {
|
||||
mg_http_serve_dir(nc, http_msg, &_http_server_opts_nocache);
|
||||
} else {
|
||||
mg_http_serve_dir(nc, http_msg, &_http_server_opts);
|
||||
|
|
@ -1754,6 +1763,8 @@ void action_websocket_request(struct mg_connection *nc, struct mg_ws_message *wm
|
|||
int i;
|
||||
char *uri = NULL;
|
||||
char *value = NULL;
|
||||
//char *id = NULL;
|
||||
//char *text_value = NULL;
|
||||
char *msg = NULL;
|
||||
#ifdef AQ_TM_DEBUG
|
||||
int tid;
|
||||
|
|
@ -1775,8 +1786,12 @@ void action_websocket_request(struct mg_connection *nc, struct mg_ws_message *wm
|
|||
|
||||
if (jsonkv.kv[i].key != NULL && strncmp(jsonkv.kv[i].key, "uri", 3) == 0)
|
||||
uri = jsonkv.kv[i].value;
|
||||
else if (jsonkv.kv[i].key != NULL && strncmp(jsonkv.kv[i].key, "value", 4) == 0)
|
||||
else if (jsonkv.kv[i].key != NULL && strncmp(jsonkv.kv[i].key, "value", 5) == 0)
|
||||
value = jsonkv.kv[i].value;
|
||||
//else if (jsonkv.kv[i].key != NULL && strncmp(jsonkv.kv[i].key, "button", 6) == 0)
|
||||
// id = jsonkv.kv[i].value;
|
||||
//else if (jsonkv.kv[i].key != NULL && strncmp(jsonkv.kv[i].key, "text_value", 10) == 0)
|
||||
// text_value = jsonkv.kv[i].value;
|
||||
}
|
||||
|
||||
if (uri == NULL) {
|
||||
|
|
@ -1784,6 +1799,7 @@ void action_websocket_request(struct mg_connection *nc, struct mg_ws_message *wm
|
|||
return;
|
||||
}
|
||||
|
||||
// NSF in future change action_URI to accept button and text_value
|
||||
switch ( action_URI(NET_WS, uri, strlen(uri), (value!=NULL?atof(value):TEMP_UNKNOWN), false, &msg)) {
|
||||
case uActioned:
|
||||
sprintf(buffer, "{\"message\":\"ok\"}");
|
||||
|
|
|
|||
|
|
@ -372,7 +372,7 @@ bool process_rssadapter_packet(unsigned char *packet, int length, struct aqualin
|
|||
aqdata->lights[i].button->label,
|
||||
packet[6]==0x00?"OFF":"ON",
|
||||
packet[6],
|
||||
packet[6]==0x00?"--":light_mode_name( aqdata->lights[i].lightType,(packet[6] - RSSD_COLOR_LIGHT_OFFSET), RSSADAPTER) );
|
||||
packet[6]==0x00?"--":light_mode_name( aqdata->lights[i].lightType,(packet[6] - RSSD_COLOR_LIGHT_OFFSET_READ), RSSADAPTER) );
|
||||
}
|
||||
|
||||
SET_IF_CHANGED(aqdata->lights[i].RSSDstate, (packet[6]==0x00?OFF:ON), aqdata->is_dirty);
|
||||
|
|
@ -395,7 +395,7 @@ bool process_rssadapter_packet(unsigned char *packet, int length, struct aqualin
|
|||
rtn |= set_currentlight_value(&aqdata->lights[i], (packet[6] - RSSD_DIMMER_LIGHT_OFFSET));
|
||||
break;
|
||||
default:
|
||||
rtn |= set_currentlight_value(&aqdata->lights[i], (packet[6] - RSSD_COLOR_LIGHT_OFFSET));
|
||||
rtn |= set_currentlight_value(&aqdata->lights[i], (packet[6] - RSSD_COLOR_LIGHT_OFFSET_READ));
|
||||
break;
|
||||
}
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -73,6 +73,7 @@ typedef int32_t logmask_t;
|
|||
|
||||
#define AQ_MAX(x, y) (((x) > (y)) ? (x) : (y))
|
||||
#define AQ_MIN(x, y) (((x) < (y)) ? (x) : (y))
|
||||
#define AQ_CLAMP(value, min_val, max_val) ((value) > (max_val) ? (max_val) : ((value) < (min_val) ? (min_val) : (value)))
|
||||
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -4,5 +4,5 @@
|
|||
#define AQUALINKD_SHORT_NAME "AqualinkD"
|
||||
|
||||
// Use Magor . Minor . Patch
|
||||
#define AQUALINKD_VERSION "3.0.0 (beta 2)"
|
||||
#define AQUALINKD_VERSION "3.0.0 (beta 3)"
|
||||
|
||||
|
|
@ -518,24 +518,27 @@
|
|||
</style>
|
||||
|
||||
<script type='text/javascript'>
|
||||
'use strict';
|
||||
|
||||
var _panel_size = 6;
|
||||
var _panel_set = 0;
|
||||
var _currentVersion = 0;
|
||||
var _latestVersionAvailable = 0;
|
||||
var _latestDevVersionAvailable = 0;
|
||||
//var _latestDevVersionAvailable = 0;
|
||||
var _rssd_logmask = 0;
|
||||
const RSSD_MASK_ID = 512; // Must match RSSD_LOG in utils.c
|
||||
|
||||
_addedBlankLightProgram = false;
|
||||
_addedBlankSensor = false;
|
||||
_addedBlankVirtualButton = false;
|
||||
var _addedBlankLightProgram = false;
|
||||
var _addedBlankSensor = false;
|
||||
var _addedBlankVirtualButton = false;
|
||||
|
||||
const _webConfigFile = "/config.json";
|
||||
|
||||
//var _cfgRestartAlertShown = false;
|
||||
let _AlertsShown = {};
|
||||
|
||||
var _config = {};
|
||||
|
||||
const VERSION_URL = "https://api.github.com/repos/aqualinkd/AqualinkD/releases"
|
||||
let _aqualinkVersions = {};
|
||||
|
||||
const _urlParams = new URLSearchParams(window.location.search);
|
||||
|
||||
|
||||
|
|
@ -587,6 +590,13 @@
|
|||
button.classList.remove("disablebutton");
|
||||
}
|
||||
}
|
||||
function setbuttontext(id, text) {
|
||||
//console.log("enable " + id);
|
||||
var button = document.getElementById(id);
|
||||
if (button) {
|
||||
button.value = text;
|
||||
}
|
||||
}
|
||||
function disabletoggle(id) {
|
||||
disablebutton(id);
|
||||
try {
|
||||
|
|
@ -894,7 +904,7 @@
|
|||
//console.log(data[obj]["valid values"]);
|
||||
//const
|
||||
input = document.createElement("select");
|
||||
array = data[obj]["valid values"];
|
||||
const array = data[obj]["valid values"];
|
||||
for (var i = 0; i < array.length; i++) {
|
||||
var option = document.createElement("option");
|
||||
option.value = array[i];
|
||||
|
|
@ -994,7 +1004,7 @@
|
|||
//}
|
||||
|
||||
const buttonTypelist = ["pumpIndex", "pumpID", "pumpType", "pumpName", "pumpMaxSpeed", "pumpMinSpeed", "lightMode"];
|
||||
const virtButtonTypelist = ["pumpIndex", "pumpID", "pumpType", "pumpName", "pumpMaxSpeed", "pumpMinSpeed", "onetouchID", "altLabel"];
|
||||
const virtButtonTypelist = ["pumpIndex", "pumpID", "pumpType", "pumpName", "pumpMaxSpeed", "pumpMinSpeed", "lightMode", "onetouchID", "altLabel"];
|
||||
|
||||
const configtable = document.getElementById("config_table");
|
||||
const newRow = configtable.insertRow();
|
||||
|
|
@ -1060,7 +1070,7 @@
|
|||
var cell3 = newRow.insertCell();
|
||||
|
||||
cell1.style.paddingLeft = "20px";
|
||||
key = 'light_program_'+String(num+1).padStart(2, '0')
|
||||
const key = 'light_program_'+String(num+1).padStart(2, '0')
|
||||
cell1.innerHTML = 'Add '+key;
|
||||
cell1.setAttribute('label', key);
|
||||
|
||||
|
|
@ -1093,14 +1103,14 @@
|
|||
return;
|
||||
}
|
||||
|
||||
const virtButtonTypelist = ["pumpIndex", "pumpID", "pumpType", "pumpName", "pumpMaxSpeed", "pumpMinSpeed", "onetouchID", "altLabel"];
|
||||
const virtButtonTypelist = ["pumpIndex", "pumpID", "pumpType", "pumpName", "pumpMaxSpeed", "pumpMinSpeed", "lightMode", "onetouchID", "altLabel"];
|
||||
|
||||
const configtable = document.getElementById("config_table");
|
||||
|
||||
vbname="virtual_button_"+String(num).padStart(2, '0');
|
||||
vblabel=vbname+"_label";
|
||||
const vbname="virtual_button_"+String(num).padStart(2, '0');
|
||||
const vblabel=vbname+"_label";
|
||||
|
||||
newRow = configtable.insertRow();
|
||||
var newRow = configtable.insertRow();
|
||||
var cell1 = newRow.insertCell();
|
||||
cell1.colSpan = 3;
|
||||
cell1.style.fontSize = "small";
|
||||
|
|
@ -1273,7 +1283,7 @@
|
|||
newRow.style.borderTop = "1px solid black";
|
||||
}
|
||||
|
||||
key = 'sensor_'+String(num+1).padStart(2, '0');
|
||||
const key = 'sensor_'+String(num+1).padStart(2, '0');
|
||||
|
||||
// Add sensor_xx_path row
|
||||
var cell1 = newRow.insertCell();
|
||||
|
|
@ -1496,7 +1506,7 @@
|
|||
|
||||
const configtable = document.getElementById("config_table");
|
||||
|
||||
showAdvanced = document.getElementById("show_advanced").checked;
|
||||
var showAdvanced = document.getElementById("show_advanced").checked;
|
||||
//console.log (data);
|
||||
if (data != null)
|
||||
_config = data;
|
||||
|
|
@ -1620,9 +1630,11 @@
|
|||
|
||||
|
||||
function cfgAlertForceRestart(event) {
|
||||
var key = event.srcElement.getAttribute('key');
|
||||
var value = event.srcElement.value;
|
||||
//console.log( _AlertsShown[key]);
|
||||
var key = event.srcElement.getAttribute('key');
|
||||
if (key === undefined || key === null) {
|
||||
key = event.srcElement.parentNode.getAttribute('key');
|
||||
}
|
||||
if ( _AlertsShown[key] == undefined || _AlertsShown[key] == false) {
|
||||
_AlertsShown[key] = true;
|
||||
if ("force_restart_msg" in _config[key]) {
|
||||
|
|
@ -1938,16 +1950,14 @@
|
|||
}, 100);
|
||||
} else {
|
||||
//console.log("VERSION call="+call+" - "+currentVersion+". latest "+_latestVersionAvailable);
|
||||
|
||||
if ( isNewerVersion(_latestVersionAvailable, currentVersion ) || _urlParams.get('upgrade') != null) {
|
||||
enablebutton("upgrade");
|
||||
setbuttontext("upgrade", "Update AqualinkD");
|
||||
} else {
|
||||
disablebutton("upgrade");
|
||||
}
|
||||
|
||||
if (_urlParams.get('devupgrade') != null) {
|
||||
//disablebutton("upgrade");
|
||||
enablebutton("upgrade");
|
||||
var button = document.getElementById("upgrade");
|
||||
button.setAttribute("upgrade_type", "dev")
|
||||
setbuttontext("upgrade", "Check for Updates");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1970,6 +1980,7 @@
|
|||
enablebutton("restart");
|
||||
|
||||
if (data['aqualinkd_version']) {
|
||||
_currentVersion = data['aqualinkd_version'];
|
||||
//document.getElementById("aqualinkdversion").innerHTML = data['aqualinkd_version'];
|
||||
if (data['aqualinkd_version'] == _latestVersionAvailable ) {
|
||||
document.getElementById("latesversionavailable").classList.add("hidden");
|
||||
|
|
@ -1978,11 +1989,11 @@
|
|||
}
|
||||
|
||||
delayedVersionCheck(data['aqualinkd_version']);
|
||||
/*
|
||||
|
||||
if (_urlParams.get('upgrade') != null) {
|
||||
enablebutton("upgrade");
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2177,19 +2188,20 @@
|
|||
|
||||
if (patch1 === undefined) { patch1 = 0; }
|
||||
if (patch2 === undefined) { patch2 = 0; }
|
||||
|
||||
//console.log(version1+" major="+major1+", "+version2+" major="+major2);
|
||||
if (major1 > major2) return true;
|
||||
if (major1 < major2) return false;
|
||||
|
||||
//console.log(version1+" minor="+minor1+", "+version2+" minor="+minor2);
|
||||
if (minor1 > minor2) return true;
|
||||
if (minor1 < minor2) return false;
|
||||
|
||||
//Look for any strings that might be a pre-release
|
||||
if ( version2.toLowerCase().includes("dev") ||
|
||||
version2.toLowerCase().includes("pre") ) {
|
||||
version2.toLowerCase().includes("dev") ||
|
||||
version2.toLowerCase().includes("beta") ) {
|
||||
patch2--;
|
||||
}
|
||||
|
||||
//console.log(version1+" patch="+patch1+", "+version2+" patch="+patch2);
|
||||
return patch1 > patch2;
|
||||
} catch (e) {
|
||||
return false;
|
||||
|
|
@ -2240,7 +2252,7 @@
|
|||
|
||||
startWebsockets();
|
||||
getLatestVersion();
|
||||
getLatestDevVersion();
|
||||
//getLatestDevVersion();
|
||||
}
|
||||
|
||||
function set_unavailable(message) {
|
||||
|
|
@ -2278,35 +2290,15 @@
|
|||
switch (source.id) {
|
||||
case "upgrade":
|
||||
getVersions();
|
||||
aqdAlert("Loading");
|
||||
aqdAlert("Searching release versions");
|
||||
//let dlg = document.getElementById("alertDialogHeader");
|
||||
//dlg.innerHTML='<input type="list"
|
||||
return;
|
||||
/*
|
||||
if (source.getAttribute("upgrade_type") == "dev") {
|
||||
if (confirm("Are you sure you want to proceed installing AqualinkD to Dev version '"+_latestDevVersionAvailable+"'' ?")) {
|
||||
//console.log("Upgrading to dev release");
|
||||
update_log_message("***** AqualinkD upgrade in progress *****");
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
cmd.uri = "installdevrelease"
|
||||
} else {
|
||||
if (confirm("Are you sure you want to proceed upgrading AqualinkD to '"+_latestVersionAvailable+"'' ?")) {
|
||||
console.log("Upgrading");
|
||||
update_log_message("***** AqualinkD upgrade in progress *****");
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
cmd.uri = "upgrade"
|
||||
}
|
||||
*/
|
||||
// NEED TO REGET aqmanager after restart.
|
||||
break;
|
||||
case "installVersion":
|
||||
let version = document.getElementById("selectedrelease").value;
|
||||
cmd.uri = "installrelease/"+version
|
||||
cmd.value = version;
|
||||
cmd.text_value = version;
|
||||
update_log_message("***** AqualinkD upgrade in progress *****");
|
||||
break;
|
||||
case "restart":
|
||||
|
|
@ -2350,72 +2342,100 @@
|
|||
send_command(cmd);
|
||||
}
|
||||
|
||||
const VERSION_URL = "https://api.github.com/repos/aqualinkd/AqualinkD/releases"
|
||||
let _aqualinkVersions = {};
|
||||
|
||||
function populateVersionSelection(caller=null) {
|
||||
if (caller && caller.checked)
|
||||
pre = true;
|
||||
else
|
||||
pre = false;
|
||||
|
||||
try {
|
||||
let dlg_head = document.getElementById("alertDialogHeader");
|
||||
let dlg_msg = document.getElementById("alertDialogMessage");
|
||||
|
||||
let dropdown = '<select id="selectedrelease" name="version selection">';
|
||||
//for (const versionNumber of _aqualinkVersions) {
|
||||
for (const [versionNumber, details] of Object.entries(_aqualinkVersions)) {
|
||||
//alert(versionNumber);
|
||||
if (pre || _aqualinkVersions[versionNumber].prerelease === false) {
|
||||
dropdown += '<option value="'+versionNumber+'">'+versionNumber+'</option>';
|
||||
}
|
||||
}
|
||||
dropdown += '</select>';
|
||||
dropdown += ' Include Dev Releases<input type="checkbox" onchange="populateVersionSelection(this)" name="prerelease" value="PreRelease" '+(pre==true?"checked":"")+'/>';
|
||||
dropdown += '<br><input type="button" id="installVersion" onclick="send(this);aqdAlertClose();" value="Install"/>';
|
||||
dlg_head.innerHTML = dropdown;
|
||||
dlg_msg.innerText = "Select a version to install"
|
||||
|
||||
} catch (e){
|
||||
alert("load error "+e);
|
||||
|
||||
function populateVersionSelection(caller = null) {
|
||||
let prerelease = false;
|
||||
let showversionwarning=false
|
||||
|
||||
if (caller && caller.id == "useprerelease" && caller.checked){
|
||||
prerelease = true;
|
||||
} else if (caller && caller.id == "selectedrelease" && caller.value) {
|
||||
if (isNewerVersion(_currentVersion, caller.value.replace(/[^\d.-]/g, '')))
|
||||
showversionwarning=true;
|
||||
|
||||
prerelease = document.getElementById("useprerelease")?.checked?true:false;
|
||||
}
|
||||
|
||||
try {
|
||||
let dlg_head = document.getElementById("alertDialogHeader");
|
||||
let dlg_msg = document.getElementById("alertDialogMessage");
|
||||
|
||||
let dropdown = '<select id="selectedrelease" name="version selection" onchange="populateVersionSelection(this)">';
|
||||
//for (const versionNumber of _aqualinkVersions) {
|
||||
for (const [versionNumber, details] of Object.entries(_aqualinkVersions)) {
|
||||
//alert(versionNumber);
|
||||
if (prerelease || _aqualinkVersions[versionNumber].prerelease === false) {
|
||||
let exttext='';
|
||||
let selected='';
|
||||
|
||||
if (versionNumber.replace(/[^\d.-]/g, '') == _latestVersionAvailable) {
|
||||
exttext = ' (latest)';
|
||||
}
|
||||
if (versionNumber === caller?.value) {
|
||||
selected = 'selected';
|
||||
}
|
||||
|
||||
//alert("loaded");
|
||||
dropdown += '<option value="' + versionNumber + '"'+selected+'>' + versionNumber + exttext +'</option>';
|
||||
}
|
||||
}
|
||||
dropdown += '</select>';
|
||||
dropdown += ' Include Dev Releases<input id="useprerelease" type="checkbox" onchange="populateVersionSelection(this)" name="prerelease" value="PreRelease" ' + (prerelease == true ? "checked" : "") + '/>';
|
||||
dropdown += '<br>'
|
||||
if (_latestVersionAvailable == _currentVersion) {
|
||||
dropdown += '<br>latest Release version already installed';
|
||||
}
|
||||
dropdown += '<br><input type="button" id="installVersion" onclick="send(this);aqdAlertClose();" value="Install"/>';
|
||||
dlg_head.innerHTML = dropdown;
|
||||
|
||||
if (showversionwarning) {
|
||||
dlg_msg.innerHTML = 'Warning:<p style="font-size: small;">Config files are not always backward compatible when downgrading.<br>'+
|
||||
'You may need to manually update <b>aqualinkd.conf & config.json</b>.</p>';
|
||||
} else {
|
||||
dlg_msg.innerText = "";
|
||||
}
|
||||
} catch (e) {
|
||||
alert("load error " + e);
|
||||
}
|
||||
|
||||
//alert("loaded");
|
||||
}
|
||||
|
||||
async function getVersions() {
|
||||
|
||||
async function getVersions() {
|
||||
|
||||
try {
|
||||
// Fetch the file from the specified path (make sure config.json exists)
|
||||
const response = await fetch(VERSION_URL, { cache: 'no-store' });
|
||||
// Fetch the file from the specified path (make sure config.json exists)
|
||||
const response = await fetch(VERSION_URL, { cache: 'no-store' });
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
|
||||
// Get the response as plain text
|
||||
const versions = await response.text();
|
||||
const versionObject = JSON.parse(versions);
|
||||
|
||||
for (const release of versionObject) {
|
||||
if (!release.assets || release.prerelease == "true" || release.assets.length === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get the response as plain text
|
||||
const versions = await response.text();
|
||||
const versionObject = JSON.parse(versions);
|
||||
|
||||
for (const release of versionObject) {
|
||||
if (!release.assets || release.prerelease == "true" || release.assets.length === 0) {
|
||||
continue;
|
||||
}
|
||||
const downloadUrl = release.assets[0].browser_download_url;
|
||||
if (downloadUrl) {
|
||||
_aqualinkVersions[release.tag_name] = {};
|
||||
_aqualinkVersions[release.tag_name].url = downloadUrl;
|
||||
_aqualinkVersions[release.tag_name].prerelease = release.prerelease;
|
||||
}
|
||||
const downloadUrl = release.assets[0].browser_download_url;
|
||||
if (downloadUrl) {
|
||||
_aqualinkVersions[release.tag_name] = {};
|
||||
_aqualinkVersions[release.tag_name].url = downloadUrl;
|
||||
_aqualinkVersions[release.tag_name].prerelease = release.prerelease;
|
||||
}
|
||||
}
|
||||
|
||||
populateVersionSelection();
|
||||
populateVersionSelection();
|
||||
|
||||
} catch (error) {
|
||||
console.error('There was a problem fetching the config file:', error);
|
||||
console.error('There was a problem fetching the config file:', error);
|
||||
let dlg_msg = document.getElementById("alertDialogMessage");
|
||||
//dlg_msg.innerText = "Error connecting to github, please check connection!\n\n"+VERSION_URL;
|
||||
dlg_msg.innerHTML = '<p>Error connecting to github, please check connection</p<<hr><p style="font-size: small;">'+VERSION_URL+'</p>';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getLatestVersion(url="https://api.github.com/repos/AqualinkD/AqualinkD/releases/latest", tryagain=true) {
|
||||
var xmlhttp = new XMLHttpRequest();
|
||||
|
|
@ -2435,7 +2455,7 @@ let _aqualinkVersions = {};
|
|||
xmlhttp.open("GET", url);
|
||||
xmlhttp.send();
|
||||
}
|
||||
|
||||
/*
|
||||
function getLatestDevVersion(url="https://api.github.com/repos/AqualinkD/AqualinkD/contents/source/version.h", tryagain=true) {
|
||||
var xmlhttp = new XMLHttpRequest();
|
||||
xmlhttp.onreadystatechange = function () {
|
||||
|
|
@ -2453,7 +2473,7 @@ let _aqualinkVersions = {};
|
|||
xmlhttp.setRequestHeader("Accept","application/vnd.github.raw");
|
||||
xmlhttp.send();
|
||||
}
|
||||
|
||||
*/
|
||||
function aqdAlert(message) {
|
||||
document.getElementById("alertDialogHeader").innerText = '';
|
||||
document.getElementById('alertDialogMessage').innerText = message;
|
||||
|
|
@ -2496,7 +2516,7 @@ let _aqualinkVersions = {};
|
|||
</tr>
|
||||
<tr>
|
||||
<td colspan="1" align="center"><input id="restart" type="button" onclick="send(this);" value="Restart AqualinkD"></td>
|
||||
<td colspan="1" align="center"><input id="upgrade" type="button" onclick="send(this);" value="Upgrade AqualinkD"></td>
|
||||
<td colspan="1" align="center"><input id="upgrade" type="button" onclick="send(this);" value="Update AqualinkD"></td>
|
||||
</tr>
|
||||
<!--
|
||||
<tr>
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@
|
|||
"tile_on_text": "#000000",
|
||||
"tile_status_text": "#575757",
|
||||
"value_tile_normal_color": "#049FF8",
|
||||
"value_tile_normal_color_": "#4ec400ff",
|
||||
"value_tile_attention_color": "#FF8000",
|
||||
"value_tile_outofrange_color": "#FF6400",
|
||||
"options_radio_highlight": "#2196F3",
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ _confighelp["https_cert_dir"]="For two way auth only. Directory where crt.pem, k
|
|||
_confighelp["serial_port"]="Device of your RS465 adapter, examples /dev/ttyUSB1, /dev/ttyS2, /dev/serial0"
|
||||
_confighelp["panel_type"]="Your RS panel type & size. ie 4, 6, 8, 12 or 16 relates to RS4, RS6, RS8, RS12 or RS16. Must be in format XX-N ZZZZ (XX=RS or PD, N=Circuits, ZZZ=Combo or Only or Dual)";
|
||||
_confighelp["device_id"]="The id of the AqualinkD to use, use serial_logger to find ID's. If your panel is a PDA only model then PDA device ID is 0x60. set to device_id to 0xFF for to autoconfigure all this section";
|
||||
_confighelp["mqtt_address"]="MQTT address has to be set to ip:port enable MQTT ig mqtt://192.168.1.99:1883"
|
||||
_confighelp["mqtt_address"]="MQTT address has to be set to protocol://ip:port enable MQTT eg mqtt://192.168.1.99:1883"
|
||||
_confighelp["read_RS485_swg"]="Read device information directly from RS485 bus"
|
||||
_confighelp["force_swg"]="Force any devices to be active at startup. Must set these for Home Assistant integration"
|
||||
_confighelp["enable_scheduler"]="AqualinkD's internal scheduler"
|
||||
|
|
|
|||
|
|
@ -268,7 +268,7 @@
|
|||
}
|
||||
50% {
|
||||
background-color: var(--tile_background);
|
||||
opacity: 0.9;
|
||||
opacity: 0.8; /* 0.9 */
|
||||
}
|
||||
100% {
|
||||
background-color: var(--tile_on_background);
|
||||
|
|
@ -285,13 +285,36 @@
|
|||
}
|
||||
50% {
|
||||
background-color: var(--tile_background);
|
||||
opacity: 0.9;
|
||||
opacity: 0.8; /* 0.9 */
|
||||
}
|
||||
100% {
|
||||
background-color: var(--tile_on_background);
|
||||
opacity: 1.0;
|
||||
}
|
||||
}
|
||||
/*
|
||||
.flash-icon {
|
||||
color: var(--tile_on_text);
|
||||
filter: alpha(opacity=100);
|
||||
opacity: 0.9;
|
||||
-webkit-animation-name: tile-icon-flash;
|
||||
-webkit-animation-duration: 2s;
|
||||
animation-name: tile-icon-flash;
|
||||
animation-duration: 2s;
|
||||
animation-iteration-count: infinite;
|
||||
}
|
||||
@keyframes tile-icon-flash {
|
||||
0% {
|
||||
opacity: 1.0;
|
||||
}
|
||||
50% {
|
||||
opacity: 0.7;
|
||||
}
|
||||
100% {
|
||||
opacity: 1.0;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
.off {
|
||||
|
|
@ -869,9 +892,11 @@
|
|||
if (window.self !== window.top) {
|
||||
//console.log("The code is running inside an iframe.");
|
||||
// Change the link under the cog/hamburger icon
|
||||
ele = document.getElementById('cog_link');
|
||||
ele.setAttribute("href", "/");
|
||||
ele.setAttribute("target", "_parent");
|
||||
const ele = document.getElementById('cog_link');
|
||||
if (ele) {
|
||||
ele.setAttribute("href", "/");
|
||||
ele.setAttribute("target", "_parent");
|
||||
}
|
||||
} else {
|
||||
//console.log("The code is not running inside an iframe.");
|
||||
}
|
||||
|
|
@ -1140,6 +1165,7 @@
|
|||
//console.log(name+" = "+type+" "+subtype);
|
||||
|
||||
if (type.startsWith("switch")) { // Use default SVG for icon images
|
||||
|
||||
if (off_imgurl == null) {
|
||||
var valdiv = document.createElement('div');
|
||||
if (_DisableOffIconCircle) {
|
||||
|
|
@ -1271,13 +1297,14 @@
|
|||
try {
|
||||
if (state == (document.getElementById(id).getAttribute('status') == 'off')) {
|
||||
send_command(id, (state==true?1:0) );
|
||||
//console.log("Switch state "+id+" to "+(state)?"on":"off");
|
||||
} else {
|
||||
//console.log("state "+id+" to "+(state)?"on":"off")
|
||||
}
|
||||
|
||||
setTileOn(id, ((state) ? "on" : "off"));
|
||||
} catch(exception) {}
|
||||
} catch(exception) {
|
||||
console.error("setTileState() :-" + exception);
|
||||
}
|
||||
}
|
||||
|
||||
function setThermostatSetpoint(id, sp_value) {
|
||||
|
|
@ -1290,37 +1317,7 @@
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
function setTileValue(id, value) {
|
||||
var ext = '';
|
||||
var type;
|
||||
if (value == undefined || value.startsWith("-999") || value.startsWith(" "))
|
||||
value = '--';
|
||||
else {
|
||||
try {
|
||||
if ((type = document.getElementById(id).getAttribute('type')) != null) {
|
||||
if (type == 'temperature' || type == 'setpoint_thermo' || type == 'setpoint_freeze')
|
||||
ext = '°';
|
||||
else if (type == 'setpoint_swg')
|
||||
ext = '%';
|
||||
|
||||
if ((type == 'temperature' || type == 'value') && turn_on_sensortiles == true) {
|
||||
if (value == 0 || value == '--')
|
||||
setTileOn(id, 'off');
|
||||
else
|
||||
setTileOn(id, 'on');
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
//console.log('ERROR id=' + id + ' Line 764 | element = '+document.getElementById(id));
|
||||
}
|
||||
}
|
||||
//document.getElementById(id + '_tile_icon_value').textContent = value;
|
||||
var tile;
|
||||
if ((tile = document.getElementById(id + '_tile_icon_value')) != null)
|
||||
tile.innerHTML = value + ext;
|
||||
}
|
||||
*/
|
||||
function setTileValue(id, value) {
|
||||
var ext = '';
|
||||
var type = null;
|
||||
|
|
@ -1331,6 +1328,7 @@
|
|||
if (value == undefined || value.startsWith("-999") || value.startsWith(" ")) {
|
||||
value = '--';
|
||||
} else {
|
||||
let uom;
|
||||
if ((uom = document.getElementById(id).getAttribute('UOM')) != null) {
|
||||
ext = uom;
|
||||
} else if ((type = document.getElementById(id).getAttribute('type')) != null) {
|
||||
|
|
@ -1364,7 +1362,7 @@
|
|||
}
|
||||
} catch (e) {
|
||||
// Devices that are hidden are not found
|
||||
//console.log('ERROR id=' + id + ' Line '+new Error().lineNumber+' | element = '+document.getElementById(id));
|
||||
//console.log('ERROR id=' + id + ' Line '+new Error().lineNumber+' | element = '+document.getElementById(id)+"\n"+e);
|
||||
}
|
||||
//document.getElementById(id + '_tile_icon_value').textContent = value;
|
||||
var tile;
|
||||
|
|
@ -1518,7 +1516,6 @@
|
|||
//console.log("Error unknown ID '"+id+"' can't set to '"+status+"'");
|
||||
return;
|
||||
}
|
||||
|
||||
// Display is a special status to "brighten up" sensor values.
|
||||
if (status != "on" && status != "off" && status != "enabled" && status != "flash"
|
||||
&& status != "rangecritical" && status != "rangewarning" && status != "rangeoptimal") {
|
||||
|
|
@ -1535,13 +1532,17 @@
|
|||
tile.classList.add("flash");
|
||||
tile.classList.remove("on");
|
||||
text = "Delay";
|
||||
//const tile_icon = document.getElementById(id + "_tile_icon_value");
|
||||
//if (tile_icon) {tile_icon.classList.add("flash-icon");}
|
||||
} else {
|
||||
tile.classList.add("on");
|
||||
tile.classList.remove("flash");
|
||||
text = "On";
|
||||
//const tile_icon = document.getElementById(id + "_tile_icon_value");
|
||||
//if (tile_icon) {tile_icon.classList.remove("flash-icon");}
|
||||
}
|
||||
try{
|
||||
if (tile.getAttribute('type').startsWith("switch")) {
|
||||
if (tile.getAttribute('type').startsWith("switch") || tile.getAttribute('type').startsWith("light")) {
|
||||
var el = document.getElementById(id + '_tile_icon_value');
|
||||
if (el) { // standard SVG icon
|
||||
el.classList.add('switch-on');
|
||||
|
|
@ -1603,7 +1604,7 @@
|
|||
/*
|
||||
*/
|
||||
try {
|
||||
if (tile.getAttribute('type').startsWith("switch")) {
|
||||
if (tile.getAttribute('type').startsWith("switch") || tile.getAttribute('type').startsWith("light")) {
|
||||
var el = document.getElementById(id + '_tile_icon_value');
|
||||
if (el) { // standard SVG icon
|
||||
el.classList.add('switch-off');
|
||||
|
|
@ -1723,6 +1724,7 @@
|
|||
const tile_icon_classes = [
|
||||
"enabled",
|
||||
//"flash",
|
||||
//"flash-icon",
|
||||
"disabled",
|
||||
"cool",
|
||||
"heat",
|
||||
|
|
@ -1740,7 +1742,7 @@
|
|||
|
||||
if (_DisableOffIconCircle) {
|
||||
try{
|
||||
if (document.getElementById(id).getAttribute('type').startsWith("switch")) {
|
||||
if (document.getElementById(id).getAttribute('type').startsWith("switch") || document.getElementById(id).getAttribute('type').startsWith("light")) {
|
||||
allowed.delete("disabled");
|
||||
}
|
||||
} catch (e){console.log(e)}
|
||||
|
|
@ -3166,7 +3168,7 @@
|
|||
//console.trace("Tracing");
|
||||
socket_di.send(JSON.stringify(_cmd));
|
||||
|
||||
if ( _link_spa_and_heater && cmd == "Spa_Mode" ) {
|
||||
if ( _config.tile_settings.link_spa_and_spa_heater && cmd == "Spa_Mode" ) {
|
||||
var ncmd = {};
|
||||
ncmd.command = "Spa_Heater";
|
||||
ncmd.uri = "Spa_Heater/set";
|
||||
|
|
|
|||
Loading…
Reference in New Issue