Version 2.6.10

pull/456/head v2.6.10
sfeakes 2025-08-31 17:10:09 -05:00
parent be9a518ffa
commit fcfa203df3
21 changed files with 437 additions and 33 deletions

View File

@ -124,7 +124,6 @@ NEED TO FIX FOR THIS RELEASE.
* Heat Pump / Chiller for OneTouch
* Try an auto-update
* Update Mongoose
* PDA Crap.
@ -133,8 +132,15 @@ NEED TO FIX FOR THIS RELEASE.
* FIX Panel name in config to accept output from panel actual name
* Move all programming threads over to using struct programmerArgs.
* Use set_allbutton_light_dimmer for all lights (ie color lights)
-->
# Updates in 2.6.10 (DEV)
* UI now supports UOM for external sensors
* Updates to VSP status
* Fix for Jandy Panel Rev T dimmer lights bug.
* Autoconfig changes for older panels.
# Updates in 2.6.9 (July 26 2025)
* Config fixes for 0x33 ID / PDA

Binary file not shown.

Binary file not shown.

View File

@ -298,13 +298,23 @@ report_zero_pool_temp = yes
# These will depend a lot on the board & OS you are running.
# the "factor" is the number the sensor is multiplied by to get an accurate result. example below is (millidegrees Celsius to Celsius)
# Poll tile in seconds
#sensor_poll_time=30
#sensor_01_path = /sys/class/thermal/thermal_zone0/temp
#sensor_01_label = CPU
#sensor_01_factor = 0.001
#sensor_01_uom=°C
# Boards like Radxa Zero3 have others sensors like below.
#sensor_02_path = /sys/class/thermal/thermal_zone1/temp
#sensor_02_label = GPU
#sensor_02_factor = 0.001
#sensor_02_uom=°C
# Linux load average
#sensor_03_path = /proc/loadavg
#sensor_03_label = CPU load
#sensor_03_factor = 100
#sensor_03_uom = %
#sensor_03_regexp = ([0-9|\.]*)\s

Binary file not shown.

Binary file not shown.

View File

@ -13,6 +13,8 @@
#include "color_lights.h"
#include "devices_jandy.h"
bool waitForButtonState(struct aqualinkdata *aq_data, aqkey* button, aqledstate state, int numMessageReceived);
bool waitForMessage(struct aqualinkdata *aq_data, char* message, int numMessageReceived);
bool waitForEitherMessage(struct aqualinkdata *aq_data, char* message1, char* message2, int numMessageReceived);
@ -638,6 +640,153 @@ void *set_allbutton_light_programmode( void *ptr )
// just stop compiler error, ptr is not valid as it's just been freed
return ptr;
}
void *set_allbutton_light_dimmer( void *ptr )
{
int i;
struct programmingThreadCtrl *threadCtrl;
threadCtrl = (struct programmingThreadCtrl *) ptr;
struct aqualinkdata *aq_data = threadCtrl->aq_data;
waitForSingleThreadOrTerminate(threadCtrl, AQ_SET_LIGHTDIMMER);
/*
char *buf = (char*)threadCtrl->thread_args;
const char *mode_name;
int val = atoi(&buf[0]);
int btn = atoi(&buf[5]);
int typ = atoi(&buf[10]);
bool use_current_mode = false;
if (btn < 0 || btn >= aq_data->total_buttons ) {
LOG(ALLB_LOG, LOG_ERR, "Can't program light dimmer on button %d\n", btn);
cleanAndTerminateThread(threadCtrl);
return ptr;
}
aqkey *button = &aq_data->aqbuttons[btn];
unsigned char code = button->code;
*/
struct programmerArgs *pargs = &threadCtrl->pArgs;
//unsigned char code = threadCtrl->pArgs.button.code;
//aqkey *button2 = pargs->button;
aqkey *button = threadCtrl->pArgs.button;
//unsigned char code = pargs->button->code;
int val = pargs->value;
bool useDefaultIfValid = pargs->alt_value;
bool use_current_mode = false;
const char *mode_name;
//printf("****** set_allbutton_light_dimmer Light %s on/off=%s use-current-state=%s\n",button->label, button->led->state==ON?"on":"off", use_current_mode==false?"no":"yes");
if (!isPLIGHT(button->special_mask)) {
LOG(ALLB_LOG, LOG_ERR, "Can't program light for button '%d', configuration is incorrect\n", button->label);
cleanAndTerminateThread(threadCtrl);
return ptr;
}
clight_detail *light = (clight_detail *)button->special_mask_ptr;
if (pargs->value <= 0) {
use_current_mode = true;
LOG(ALLB_LOG, LOG_INFO, "Light Dimmer Programming #: %d, on button: %s, using current mode\n", val, button->label);
} else {
//mode_name = light_mode_name(typ, val-1, ALLBUTTON);
//mode_name = light_mode_name(((clight_detail *)button->special_mask_ptr)->lightType, val, ALLBUTTON);
mode_name = light_mode_name(LC_DIMMER, val, ALLBUTTON);
use_current_mode = false;
if (mode_name == NULL) {
LOG(ALLB_LOG, LOG_ERR, "Light Dimmer Programming #: %d, on button: %s, couldn't find mode name '%s'\n", val, button->label, mode_name);
cleanAndTerminateThread(threadCtrl);
return ptr;
} else {
LOG(ALLB_LOG, LOG_INFO, "Light Dimmer Programming #: %d, on button: %s, name '%s'\n", val, button->label, mode_name);
}
}
//printf("****** set_allbutton_light_dimmer Light %s on/off=%d %s\n",button->label, pargs->button->led->state, button->led->state==ON?"on":"off");
// Needs to start programming sequence with light off
if ( button->led->state == ON ) {
LOG(ALLB_LOG, LOG_INFO, "Light Programming Initial state on, turning off\n");
send_cmd(button->code);
waitfor_queue2empty();
if ( !waitForMessage(threadCtrl->aq_data, "OFF", 5)) // Message like 'Aux3 Off'
LOG(ALLB_LOG, LOG_ERR, "Light Programming didn't receive OFF message\n");
}
// Look for <>*
// Now turn on and wait for the message "color mode name<>*"
send_cmd(button->code);
waitfor_queue2empty();
i=0;
int waitCounter=12;
do{
LOG(ALLB_LOG, LOG_INFO,"Light program wait for message\n");
if ( !waitForMessage(threadCtrl->aq_data, "~*", waitCounter))
LOG(ALLB_LOG, LOG_ERR, "Light Programming didn't receive light mode message\n");
// Wait for less messages after first try. We get a lot of repeat messages before the one we need.
waitCounter = 3;
if (useDefaultIfValid) {
// If 0 in last message then it's NOT valid and we will change to 100% (5 char =0, 6 char=%)
if (aq_data->last_message[0] == '0' && aq_data->last_message[1] == '%' ) {
//printf("******** Light stuck ************\n");
LOG(ALLB_LOG, LOG_WARNING, "Light Programming detected Jandy panel light%% bug, re-setting to %d%%\n",val * 25);
useDefaultIfValid=false;
} else {
// printf("******** Light good ************ '%c' '%c'\n",aq_data->last_message[0],aq_data->last_message[1]);
send_cmd(KEY_ENTER);
waitfor_queue2empty();
break;
}
} else if (use_current_mode) {
LOG(ALLB_LOG, LOG_INFO, "Light Programming using mode %s\n",aq_data->last_message);
send_cmd(KEY_ENTER);
waitfor_queue2empty();
break;
} else if (strncasecmp(aq_data->last_message, mode_name, strlen(mode_name)) == 0) {
LOG(ALLB_LOG, LOG_INFO, "Light Programming found mode %s\n",mode_name);
send_cmd(KEY_ENTER);
waitfor_queue2empty();
break;
}
send_cmd(KEY_RIGHT);
waitfor_queue2empty();
// Just clear current message before waiting for next, since the test in the do can't distinguish
// as both messages end in "~*"
waitForMessage(threadCtrl->aq_data, NULL, 1);
i++;
} while (i <= 8);
if (i == 8) {
LOG(ALLB_LOG, LOG_ERR, "Light Programming didn't receive light mode message for '%s'\n",use_current_mode?"light program":mode_name);
} else {
// update status before we are exit.
if (light->lightType == LC_DIMMER2 ) {
// value or Dimmer2 is the actual %, while Dimmer & colorlight is an index into an array
updateLightProgram(aq_data, val * 25, light);
} else {
updateLightProgram(aq_data, val, light);
}
}
cleanAndTerminateThread(threadCtrl);
// just stop compiler error, ptr is not valid as it's just been freed
return ptr;
}
void *set_allbutton_pool_heater_temps( void *ptr )
{
struct programmingThreadCtrl *threadCtrl;

View File

@ -14,6 +14,7 @@ void *get_allbutton_aux_labels( void *ptr );
//void *threadded_send_cmd( void *ptr );
void *set_allbutton_light_programmode( void *ptr );
void *set_allbutton_light_colormode( void *ptr );
void *set_allbutton_light_dimmer( void *ptr );
void *set_allbutton_SWG( void *ptr );
void *set_allbutton_boost( void *ptr );

View File

@ -30,6 +30,7 @@
void initPanelButtons(struct aqualinkdata *aqdata, bool rspda, int size, bool combo, bool dual);
void programDeviceLightMode(struct aqualinkdata *aqdata, int value, int button);
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);
@ -185,7 +186,7 @@ pull board CPU, revision & panel string from strings like
uint8_t setPanelInformationFromPanelMsg(struct aqualinkdata *aqdata, const char *input, uint8_t type, emulation_type source) {
const char *rev_pos = NULL;
uint8_t rtn = 0;
printf("Calculate panel from %s\n",input);
//printf("Calculate panel from %s\n",input);
//const char *rev_pos = strstr(input, "REV"); // Find the position of "REV"
const char *sp;
int length = 0;
@ -282,7 +283,7 @@ uint16_t setPanelSupport(struct aqualinkdata *aqdata)
// Rev >= F Dimmer. But need serial protocol so set to I
// Rev >= H (Think this was first RS485)
// Rev >= HH Serial Adapter. (first support)
// Rev >= HH - (some panels support serial adapter, some don't)
// Rev >= I Serial Adapter.
// Rev >= I One Touch protocol
// Rev >= L JandyColors Smart Light Control
@ -310,10 +311,10 @@ uint16_t setPanelSupport(struct aqualinkdata *aqdata)
// Rev >= Y TruSense Water Chemistry Analyzer
// Rev >= Yg Virtual Device called Label Auxiliraries
/*
if (aqdata->panel_rev[0] >= 79) // O in ascii
aqdata->panel_support_options |= RSP_SUP_VSP;
*/
if (aqdata->panel_rev[0] >= 73){ // I in ascii
aqdata->panel_support_options |= RSP_SUP_ONET;
aqdata->panel_support_options |= RSP_SUP_RSSA;
@ -1160,6 +1161,7 @@ int getWaterTemp(struct aqualinkdata *aqdata)
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)) {
@ -1197,17 +1199,30 @@ bool setDeviceState(struct aqualinkdata *aqdata, int deviceIndex, bool isON, req
// 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) && 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.
if (isRSSA_ENABLED) {
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 ( /*isPLIGHT(button->special_mask) &&*/ ((clight_detail *)button->special_mask_ptr)->lightType == LC_PROGRAMABLE ) {
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)) {
@ -1226,6 +1241,7 @@ bool setDeviceState(struct aqualinkdata *aqdata, int deviceIndex, bool isON, req
//if (button->rssd_code != VBUTTON_RSSD) {
//LOG(PANL_LOG, LOG_NOTICE, "********** USE AQ_SET_IAQTOUCH_DEVICE_ON_OFF ********\n");
aq_programmer(AQ_SET_IAQTOUCH_DEVICE_ON_OFF, msg, aqdata);
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);
@ -1266,7 +1282,7 @@ bool setDeviceState(struct aqualinkdata *aqdata, int deviceIndex, bool isON, req
// 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) {
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) {
@ -1325,7 +1341,66 @@ bool programDeviceValue(struct aqualinkdata *aqdata, action_type type, int value
void programDeviceLightBrightness(struct aqualinkdata *aqdata, int value, int deviceIndex, bool expectMultiple, request_source source)
{
// If Value is 101
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) {
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;
}
*/
return;
}
if (!isRSSA_ENABLED) {
LOG(PANL_LOG,LOG_ERR, "Light mode brightness is only supported with `rssa_device_id` set\n");
@ -1340,6 +1415,10 @@ void programDeviceLightBrightness(struct aqualinkdata *aqdata, int value, int de
// 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) {
@ -1416,6 +1495,7 @@ void programDeviceLightMode(struct aqualinkdata *aqdata, int value, int deviceIn
// 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);
@ -1423,7 +1503,7 @@ void programDeviceLightMode(struct aqualinkdata *aqdata, int value, int deviceIn
}
} else {
// Dimmer or any color light can simply be set with value
set_aqualink_rssadapter_aux_extended_state(light->button, value);
set_aqualink_rssadapter_aux_extended_state(light->button, value + 128);
}
/*
} else if (isRSSA_ENABLED && light->lightType == LC_DIMMER2) {
@ -1533,6 +1613,18 @@ bool panel_device_request(struct aqualinkdata *aqdata, action_type type, int dev
// Programmable light has been updated, so update the status in AqualinkD
void updateLightProgram(struct aqualinkdata *aqdata, int value, clight_detail *light)
{
light->currentValue = value;
if (value > 0 && light->lastValue != value) {
light->lastValue = value;
if (_aqconfig_.save_light_programming_value && light->lightType == LC_PROGRAMABLE ) {
LOG(PANL_LOG,LOG_NOTICE, "Writing light programming value to config for %s\n",light->button->label);
writeCfg(aqdata);
}
}
}
void updateButtonLightProgram(struct aqualinkdata *aqdata, int value, int button)
{
/*
@ -1554,6 +1646,9 @@ void updateButtonLightProgram(struct aqualinkdata *aqdata, int value, int button
return;
}
updateLightProgram(aqdata, value, light);
/*
light->currentValue = value;
if (value > 0 && light->lastValue != value) {
light->lastValue = value;
@ -1562,6 +1657,7 @@ void updateButtonLightProgram(struct aqualinkdata *aqdata, int value, int button
writeCfg(aqdata);
}
}
*/
}
clight_detail *getProgramableLight(struct aqualinkdata *aqdata, int button)

View File

@ -68,7 +68,8 @@ const char* getShortPanelString();
bool panel_device_request(struct aqualinkdata *aqdata, action_type type, int deviceIndex, int value, request_source source);
void updateButtonLightProgram(struct aqualinkdata *aqdata, int value, int button);
void updateLightProgram(struct aqualinkdata *aqdata, int value, clight_detail *light);
void updateButtonLightProgram(struct aqualinkdata *aqdata, int value, int button);
int getWaterTemp(struct aqualinkdata *aqdata);

View File

@ -68,7 +68,8 @@ const func_ptr _prog_functions[AQP_RSSADAPTER_MAX] = {
[AQ_GET_DIAGNOSTICS_MODEL] = get_allbutton_diag_model,
[AQ_GET_PROGRAMS] = get_allbutton_programs,
[AQ_SET_LIGHTPROGRAM_MODE] = set_allbutton_light_programmode,
[AQ_SET_LIGHTCOLOR_MODE] = set_allbutton_light_colormode,
[AQ_SET_LIGHTCOLOR_MODE] = set_allbutton_light_colormode,
[AQ_SET_LIGHTDIMMER] = set_allbutton_light_dimmer,
[AQ_SET_SWG_PERCENT] = set_allbutton_SWG,
[AQ_GET_AUX_LABELS] = get_allbutton_aux_labels,
[AQ_SET_BOOST] = set_allbutton_boost,
@ -449,11 +450,22 @@ void kick_aq_program_thread(struct aqualinkdata *aq_data, emulation_type source_
}
}
void _aq_programmer_(program_type r_type, char *args, aqkey *button, int value, int alt_value, struct aqualinkdata *aq_data, bool allowOveride);
void aq_program(program_type r_type, aqkey *button, int value, int alt_value, struct aqualinkdata *aq_data){
_aq_programmer_(r_type, NULL, button, value, alt_value, aq_data, true);
}
void aq_programmer(program_type r_type, char *args, struct aqualinkdata *aq_data){
_aq_programmer(r_type, args, aq_data, true);
}
void _aq_programmer(program_type r_type, char *args, struct aqualinkdata *aq_data, bool allowOveride)
{
_aq_programmer_(r_type, args, NULL, -1, -1, aq_data, allowOveride);
}
void _aq_programmer_(program_type r_type, char *args, aqkey *button, int value, int alt_value, struct aqualinkdata *aq_data, bool allowOveride)
{
struct programmingThreadCtrl *programmingthread = malloc(sizeof(struct programmingThreadCtrl));
@ -648,6 +660,11 @@ void _aq_programmer(program_type r_type, char *args, struct aqualinkdata *aq_dat
if (args != NULL /*&& type != AQ_SEND_CMD*/)
strncpy(programmingthread->thread_args, args, sizeof(programmingthread->thread_args)-1);
programmingthread->pArgs.button = button;
programmingthread->pArgs.value = value;
programmingthread->pArgs.alt_value = alt_value;
switch(type) {
case AQ_GET_RSSADAPTER_SETPOINTS:
get_aqualink_rssadapter_setpoints();
@ -814,6 +831,9 @@ const char *ptypeName(program_type type)
break;
case AQ_SET_LIGHTCOLOR_MODE:
return "Set light color (using Panel)";
break;
case AQ_SET_LIGHTDIMMER:
return "Set light dimmer";
break;
case AQ_SET_SWG_PERCENT:
return "Set SWG percent";
@ -1023,7 +1043,8 @@ const char *programtypeDisplayName(program_type type)
case AQ_SET_LIGHTPROGRAM_MODE:
case AQ_SET_LIGHTCOLOR_MODE:
case AQ_SET_IAQTOUCH_LIGHTCOLOR_MODE:
return "Programming: setting light color";
case AQ_SET_LIGHTDIMMER:
return "Programming: setting light mode";
break;
case AQ_SET_SWG_PERCENT:
case AQ_SET_ONETOUCH_SWG_PERCENT:

View File

@ -56,7 +56,8 @@ typedef enum {
AQ_GET_DIAGNOSTICS_MODEL,
AQ_GET_PROGRAMS,
AQ_SET_LIGHTPROGRAM_MODE,
AQ_SET_LIGHTCOLOR_MODE,
AQ_SET_LIGHTCOLOR_MODE,
AQ_SET_LIGHTDIMMER,
AQ_SET_SWG_PERCENT,
AQ_GET_AUX_LABELS,
AQ_SET_BOOST,
@ -144,13 +145,35 @@ typedef enum {
#define AQP_RSSADAPTER_MAX AQ_ADD_RSSADAPTER_SPA_HEATER_TEMP
struct aqualinkdata;
typedef struct aqualinkkey aqkey;
/*
struct aqualinkkey;
typedef struct aqualinkkey aqkey;
*/
/*
struct aqualinkdata;
struct programmingThreadCtrl;
*/
struct programmerArgs {
aqkey *button;
int value;
int alt_value;
//char cval[PTHREAD_ARG];
};
struct programmingThreadCtrl {
pthread_t thread_id;
//void *thread_args;
struct programmerArgs pArgs;
char thread_args[PTHREAD_ARG];
struct aqualinkdata *aq_data;
};
typedef enum pump_type {
PT_UNKNOWN = -1,
@ -162,7 +185,10 @@ typedef enum pump_type {
//void aq_programmer(program_type type, void *args, struct aqualinkdata *aq_data);
void aq_programmer(program_type type, char *args, struct aqualinkdata *aq_data);
//void kick_aq_program_thread(struct aqualinkdata *aq_data);
// Below is NEW version of above.
void aq_program(program_type r_type, aqkey *button, int value, int value2, struct aqualinkdata *aq_data);
//void kick_aq_program_thread(struct aqualinkdata *aq_data);
void kick_aq_program_thread(struct aqualinkdata *aq_data, emulation_type source_type);
bool in_programming_mode(struct aqualinkdata *aq_data);
bool in_ot_programming_mode(struct aqualinkdata *aq_data);

View File

@ -531,6 +531,7 @@ typedef enum {
DRS_JLIGHT
} rsDeviceType;
/*
typedef enum {
ON,
OFF,
@ -544,7 +545,7 @@ typedef struct aqualinkled
//int number;
aqledstate state;
} aqled;
*/
// Battery Status Identifiers
enum {
OK = 0,

View File

@ -91,10 +91,24 @@ typedef enum temperatureUOM {
} temperatureUOM;
*/
typedef enum {
ON,
OFF,
FLASH,
ENABLE,
LED_S_UNKNOWN
} aqledstate;
typedef struct aqualinkled
{
//int number;
aqledstate state;
} aqled;
typedef struct aqualinkkey
{
//int number;
//aqledstate *state;
//aqledstate ledstate; // In the future there is no need to aqled struct so move code over to this.
aqled *led;
char *label;
char *name;
@ -108,6 +122,9 @@ typedef struct aqualinkkey
void *special_mask_ptr;
} aqkey;
//#include "aq_programmer.h"
// special_mask for above aqualinkkey structure.
#define VS_PUMP (1 << 0)
#define PROGRAM_LIGHT (1 << 1)
@ -126,7 +143,21 @@ struct programmingthread {
program_type ptype;
//void *thread_args;
};
/*
struct programmerArgs {
aqkey *button;
int value;
//char cval[PTHREAD_ARG];
};
struct programmingThreadCtrl {
pthread_t thread_id;
//void *thread_args;
struct programmerArgs pArgs;
char thread_args[PTHREAD_ARG];
struct aqualinkdata *aq_data;
};
*/
/*
typedef enum panel_status {
CONNECTED,

View File

@ -756,6 +756,7 @@ bool auto_configure(unsigned char* packet, int rs_fd) {
static unsigned char lastID = 0x00;
static bool seen_iAqualink2 = false;
static bool ignore_AqualinkTouch = false;
static bool ignore_OneTouch = false;
static int foundIDs = 0;
static int packetsReceived=0;
@ -799,6 +800,17 @@ bool auto_configure(unsigned char* packet, int rs_fd) {
foundIDs--;
}
}
if ( !isMASKSET(_aqualink_data.panel_support_options, RSP_SUP_ONET)) {
LOG(AQUA_LOG,LOG_NOTICE, "Ignoring OneTouch probes due to panel rev\n");
ignore_OneTouch = true;
if ( _aqconfig_.extended_device_id >= 0x40 && _aqconfig_.extended_device_id <= 0x43 ) {
_aqconfig_.extended_device_id = 0x00;
//_aqconfig_.enable_iaqualink = false;
//_aqconfig_.read_RS485_devmask &= ~ READ_RS485_IAQUALNK;
//firstprobe = 0x00;
foundIDs--;
}
}
}
}
caculate_ack_packet(rs_fd, packet, ALLBUTTON);
@ -833,14 +845,14 @@ bool auto_configure(unsigned char* packet, int rs_fd) {
_aqconfig_.rssa_device_id = lastID;
LOG(AQUA_LOG,LOG_NOTICE, "Found valid unused RSSA ID 0x%02hhx\n",lastID);
foundIDs++;
} else if ( (lastID >= 0x40 && lastID <= 0x43) &&
} else if ( (lastID >= 0x40 && lastID <= 0x43) && ignore_OneTouch == false &&
(_aqconfig_.extended_device_id == 0x00 || _aqconfig_.extended_device_id == 0xFF) ) {
_aqconfig_.extended_device_id = lastID;
_aqconfig_.extended_device_id_programming = true;
// Don't increase foundIDs as we prefer not to use this one.
LOG(AQUA_LOG,LOG_NOTICE, "Found valid unused extended ID 0x%02hhx\n",lastID);
} else if ( (lastID >= 0x30 && lastID <= 0x33) && ignore_AqualinkTouch == false &&
(_aqconfig_.extended_device_id < 0x30 || _aqconfig_.extended_device_id > 0x33)) { //Overide is it's been set to Touch or not set.
(_aqconfig_.extended_device_id < 0x30 || _aqconfig_.extended_device_id > 0x33)) { //Overide if it's been set to Touch or not set.
_aqconfig_.extended_device_id = lastID;
_aqconfig_.extended_device_id_programming = true;
if (!seen_iAqualink2) {
@ -1205,19 +1217,30 @@ void main_loop()
blank_read = 0;
if (i++ > 1000) {
if(!got_probe) {
LOG(AQUA_LOG,LOG_ERR, "No probe on '0x%02hhx', giving up! (please check config)\n",_aqconfig_.device_id);
if (_aqconfig_.deamonize) {
LOG(AQUA_LOG,LOG_ERR, "No probe on device_id '0x%02hhx', Can't start! (please check config)\n",_aqconfig_.device_id);
i=0;
} else {
LOG(AQUA_LOG,LOG_ERR, "No probe on device_id '0x%02hhx', giving up! (please check config)\n",_aqconfig_.device_id);
stopPacketLogger();
close_serial_port(rs_fd);
stop_net_services();
stop_sensors_thread();
return;
}
}
if(!got_probe_rssa) {
LOG(AQUA_LOG,LOG_ERR, "No probe on '0x%02hhx', giving up! (please check config)\n",_aqconfig_.rssa_device_id);
LOG(AQUA_LOG,LOG_ERR, "No probe on '0x%02hhx', disabling rssa_device_id (please check config)\n",_aqconfig_.rssa_device_id);
_aqconfig_.rssa_device_id = 0x00;
got_probe_rssa = true;
}
if(!got_probe_extended) {
LOG(AQUA_LOG,LOG_ERR, "No probe on '0x%02hhx', giving up! (please check config)\n",_aqconfig_.extended_device_id);
LOG(AQUA_LOG,LOG_ERR, "No probe on '0x%02hhx', disabling extended_device_id (please check config)\n",_aqconfig_.extended_device_id);
_aqconfig_.extended_device_id = 0x00;
_aqconfig_.extended_device_id_programming = false;
_aqconfig_.enable_iaqualink = false;
got_probe_extended = true;
}
stopPacketLogger();
close_serial_port(rs_fd);
stop_net_services();
stop_sensors_thread();
return;
}
}
}

View File

@ -7,6 +7,7 @@
#define LIGHT_COLOR_NAME 16
#define LIGHT_COLOR_OPTIONS 19
//#define LIGHT_DIMER_OPTIONS 4
//#define LIGHT_COLOR_TYPES LC_DIMMER+1
// The status returned from RS Serial Adapter has this added as a base.

View File

@ -1712,6 +1712,7 @@ void check_print_config (struct aqualinkdata *aqdata)
{
int i, j;
char name[MAX_PRINTLEN];
bool dzset = true;
// Sanity checks
@ -1897,12 +1898,26 @@ void check_print_config (struct aqualinkdata *aqdata)
_cfgParams[i].config_mask |= CFG_GREYED_OUT;
}
// Don't show PDA stuff on RS panel
// Don't show PDA stuff in config editor on RS panel
if ( strcmp(_cfgParams[i].name, CFG_N_pda_sleep_mode) == 0 && !isPDA_PANEL) {
_cfgParams[i].config_mask |= CFG_GREYED_OUT;
_cfgParams[i].config_mask |= CFG_READONLY;
}
// Don't print domoticz settings if off.
if ( strstr(_cfgParams[i].name, "dzidx" ) != NULL ||
strcmp(_cfgParams[i].name, CFG_N_convert_dz_temp) == 0 ) {
if (!dzset || ( _cfgParams[i].value_type == CFG_INT && *(int *)_cfgParams[i].value_ptr <= 0) ) {
continue;
}
} else if ( strcmp(_cfgParams[i].name, CFG_N_mqtt_dz_sub_topic) == 0 ||
strcmp(_cfgParams[i].name, CFG_N_mqtt_dz_pub_topic) == 0) {
if (*(char **)_cfgParams[i].value_ptr == NULL) {
dzset = false;
continue;
}
}
rsm_nchar_replace(name, MAX_PRINTLEN, _cfgParams[i].name, "_", " ");
switch (_cfgParams[i].value_type) {
case CFG_STRING:

View File

@ -70,6 +70,15 @@ bool processPentairPacket(unsigned char *packet, int packet_length, struct aqual
aqdata->pumps[i].status = (packet[PEN_HI_B_STATUS] * 256) + packet[PEN_LO_B_STATUS];
aqdata->pumps[i].pressureCurve = packet[PEN_PPC];
// This is for RS485 mode only (no info from OneTouch or iAqualinkTouch)
if (!isONET_ENABLED && !isIAQT_ENABLED) {
if ( /*aqdata->pumps[i].mode > 0 ||*/ aqdata->pumps[i].rpm > 0 || aqdata->pumps[i].gpm > 0 || aqdata->pumps[i].watts > 0) {
aqdata->pumps[i].pStatus = PS_OK;
} else {
aqdata->pumps[i].pStatus = PS_OFF;
}
}
changedAnything = true;
break;
}

View File

@ -556,11 +556,12 @@ int build_device_JSON(struct aqualinkdata *aqdata, char* buffer, int size, bool
temperatureUOM uom = getTemperatureUOM(aqdata->sensors[i].uom);
if (uom == UNKNOWN) {
length += sprintf(buffer+length, "{\"type\": \"value\", \"id\": \"%s\", \"name\": \"%s\", \"state\": \"on\", \"value\": \"%.*f\" },",
length += sprintf(buffer+length, "{\"type\": \"value\", \"id\": \"%s\", \"name\": \"%s\", \"state\": \"on\", \"value\": \"%.*f\", \"uom\": \"%s\" },",
aqdata->sensors[i].ID,
aqdata->sensors[i].label,
2,
aqdata->sensors[i].value);
aqdata->sensors[i].value,
aqdata->sensors[i].uom);
} else if ( !homekit && (aqdata->temp_units == FAHRENHEIT && uom == CELSIUS) ) {
length += sprintf(buffer+length, "{\"type\": \"temperature\", \"id\": \"%s\", \"name\": \"%s\", \"state\": \"on\", \"value\": \"%.*f\" },",
aqdata->sensors[i].ID,

View File

@ -4,5 +4,5 @@
#define AQUALINKD_SHORT_NAME "AqualinkD"
// Use Magor . Minor . Patch
#define AQUALINKD_VERSION "2.6.9"
#define AQUALINKD_VERSION "2.6.10"

View File

@ -1030,7 +1030,9 @@
if (value == undefined || value.startsWith("-999") || value.startsWith(" ")) {
value = '--';
} else {
if ((type = document.getElementById(id).getAttribute('type')) != null) {
if ((uom = document.getElementById(id).getAttribute('UOM')) != null) {
ext = uom;
} else if ((type = document.getElementById(id).getAttribute('type')) != null) {
if (type == 'temperature' || type == 'setpoint_thermo' || type == 'setpoint_freeze' || type == 'setpoint_chiller')
ext = '&deg;';
else if (type == 'setpoint_swg')
@ -1059,6 +1061,13 @@
tile.innerHTML = value + ext;
}
function setTileUOM(id, uom) {
try {
type = document.getElementById(id).setAttribute('UOM', uom);
console.log("Set UOM to "+uom+" for "+id);
} catch (e) {}
}
function setTileOnText(id, text) {
try {
var tile = document.getElementById(id);
@ -1347,6 +1356,10 @@
}
} else if (object.type == 'value' || object.type == 'temperature') {
add_tile(object.id, object.name, object.state, 'value', object.type);
if (object.uom !== undefined) {
setTileUOM(object.id, object.uom);
}
setTileValue(object.id, object.value);
} else if (object.type == 'setpoint_thermo' || object.type == 'setpoint_swg' || object.type == 'setpoint_freeze' || object.type == 'setpoint_chiller') {
add_tile(object.id, object.name, object.state, 'thermostat', object.type);