mirror of https://github.com/sfeakes/AqualinkD.git
2.0.0b
parent
41ebef22e3
commit
50c48ef6b1
7
Makefile
7
Makefile
|
@ -12,7 +12,7 @@ LIBS := -l pthread -l m
|
|||
|
||||
# debug of not
|
||||
#DBG = -g -O0 -fsanitize=address
|
||||
DBG = -g
|
||||
#DBG = -g -O0
|
||||
#DBG = -D ONETOUCH
|
||||
#DBG =
|
||||
|
||||
|
@ -33,13 +33,14 @@ CFLAGS = $(GCCFLAGS) $(DBG) $(LIBS) -D MG_DISABLE_MD5 -D MG_DISABLE_HTTP_DIGEST_
|
|||
# Add inputs and outputs from these tool invocations to the build variables
|
||||
|
||||
# define the C source files
|
||||
SRCS = aqualinkd.c utils.c config.c aq_serial.c init_buttons.c aq_programmer.c net_services.c json_messages.c pda.c pda_menu.c pda_aq_programmer.c aquapure.c onetouch.c onetouch_aq_programmer.c packetLogger.c pentair_messages.c mongoose.c
|
||||
SRCS = aqualinkd.c utils.c config.c aq_serial.c init_buttons.c aq_programmer.c net_services.c json_messages.c pda.c pda_menu.c \
|
||||
pda_aq_programmer.c devices_jandy.c onetouch.c onetouch_aq_programmer.c packetLogger.c devices_pentair.c color_lights.c mongoose.c
|
||||
DBG_SRC = timespec_subtract.c
|
||||
|
||||
# If run with `make DEBUG=true` add debug files and pass parameter for compile
|
||||
ifeq ($(DEBUG), true)
|
||||
SRCS := $(SRCS) $(DBG_SRC)
|
||||
CFLAGS := $(CFLAGS) -D AQ_DEBUG
|
||||
CFLAGS := -g -O0 $(CFLAGS) -D AQ_DEBUG
|
||||
endif
|
||||
|
||||
SL_SRC = serial_logger.c aq_serial.c utils.c packetLogger.c
|
||||
|
|
16
README.md
16
README.md
|
@ -67,13 +67,12 @@ Designed to mimic AqualinkRS6 All Button keypad and (like the keypad) is used to
|
|||
* http://aqualink.ip/simulator.html <- (RS8 All Button Control Panel simulator)
|
||||
* http://aqualink.ip/debug.html <- (Turn on/off debug/serial debug & download logs)
|
||||
#<a name="release"></a>
|
||||
# Update in Release 2.0.0a
|
||||
# Update in Release 2.0.0b
|
||||
* Big update, lots of core changes, <b>please read wiki section https://github.com/sfeakes/AqualinkD/wiki#Version_2</b>
|
||||
* Full Variable Speed Pump support.
|
||||
* Please consider this ALPHA version, no need to upgrade unless you need VSP support. Use a previous version unless you want VSP.
|
||||
* I've noticed there is an issues with colored lights if your light is configured as such in the control panel. For this release suggest you either :-
|
||||
* A) use AqualinkD to control the colors and configure Jandy control panel as normal light
|
||||
* B) Don't use AqualinkD to turn light on/off (or if you do, wait ~10 seconds)
|
||||
* Full Variable Speed Pump support. (Can read,set & change RPM,GPM)
|
||||
* Full support for all Colored Lights (even if Jandy Control Panel doesn't support them)
|
||||
* Chemlink pH & ORP now supported. (along with posting MQTT information)
|
||||
* There are some configuration changes, make sure to read wiki (link above)
|
||||
# Update in Release 1.3.9a
|
||||
* Improved Debugging for serial.
|
||||
* Added panel Timeout mode support to UI and MQTT
|
||||
|
@ -387,7 +386,10 @@ Other Information (Salt Water Generator)
|
|||
aqualinkd/SWG/Percent ( SWG Generating %, i.e. 50)
|
||||
aqualinkd/SWG/PPM ( SWG Parts Per Million i.e. 3100)
|
||||
aqualinkd/SWG/Percent_f (since we use a homekit thermostat for SWG and use degC as %, we need to pass degF for US phone)
|
||||
|
||||
aqualinkd/CHEM/pH (pH reading if Chemlink installed)
|
||||
aqualinkd/CHEM/pH_f (since we use a homekit temperature for pH and use degC as %, we need to pass degF for US phone)
|
||||
aqualinkd/CHEM/ORP (ORP reading if Chemlink installed)
|
||||
aqualinkd/CHEM/ORP_f (since we use a homekit temperature for pH and use degC as %, we need to pass degF for US phone)
|
||||
```
|
||||
|
||||
To turn something on, or set information, simply add `set` to the end of the above topics, and post 1 or 0 in the message for a button, or a number for a setpoint. Topics Aqualinkd will act on.
|
||||
|
|
|
@ -23,6 +23,12 @@
|
|||
#define SWG_EXTENDED_TOPIC SWG_TOPIC "/fullstatus"
|
||||
#define SWG_BOOST_TOPIC SWG_TOPIC "/Boost"
|
||||
|
||||
#define CHEM_TOPIC "CHEM"
|
||||
#define CHEM_PH_TOPIC CHEM_TOPIC "/pH"
|
||||
#define CHRM_PH_F_TOPIC CHEM_TOPIC "/pH_f"
|
||||
#define CHEM_ORP_TOPIC CHEM_TOPIC "/ORP"
|
||||
#define CHRM_ORP_F_TOPIC CHEM_TOPIC "/ORP_f"
|
||||
|
||||
#define FREEZE_PROTECT "Freeze_Protect"
|
||||
#define FREEZE_PROTECT_ENABELED FREEZE_PROTECT ENABELED_SUBT
|
||||
|
||||
|
|
193
aq_programmer.c
193
aq_programmer.c
|
@ -31,6 +31,7 @@
|
|||
#include "init_buttons.h"
|
||||
#include "pda_aq_programmer.h"
|
||||
#include "onetouch_aq_programmer.h"
|
||||
#include "color_lights.h"
|
||||
|
||||
#ifdef AQ_DEBUG
|
||||
#include <time.h>
|
||||
|
@ -53,6 +54,7 @@ void *get_freeze_protect_temp( void *ptr );
|
|||
void *get_aqualink_diag_model( void *ptr );
|
||||
void *get_aqualink_aux_labels( void *ptr );
|
||||
//void *threadded_send_cmd( void *ptr );
|
||||
void *set_aqualink_light_programmode( void *ptr );
|
||||
void *set_aqualink_light_colormode( void *ptr );
|
||||
void *set_aqualink_PDA_init( void *ptr );
|
||||
void *set_aqualink_SWG( void *ptr );
|
||||
|
@ -294,8 +296,8 @@ int setpoint_check(int type, int value, struct aqualinkdata *aqdata)
|
|||
|
||||
if (rtn != value)
|
||||
logMessage(LOG_WARNING, "Setpoint of %d for %s is outside range, using %d\n",value,type_msg,rtn);
|
||||
else
|
||||
logMessage(LOG_NOTICE, "Setting setpoint of %s to %d\n",type_msg,rtn);
|
||||
//else
|
||||
// logMessage(LOG_NOTICE, "Setting setpoint of %s to %d\n",type_msg,rtn);
|
||||
|
||||
return rtn;
|
||||
}
|
||||
|
@ -502,7 +504,13 @@ void aq_programmer(program_type r_type, char *args, struct aqualinkdata *aq_data
|
|||
return;
|
||||
}
|
||||
break;
|
||||
case AQ_SET_COLORMODE:
|
||||
case AQ_SET_LIGHTPROGRAM_MODE:
|
||||
if( pthread_create( &programmingthread->thread_id , NULL , set_aqualink_light_programmode, (void*)programmingthread) < 0) {
|
||||
logMessage (LOG_ERR, "could not create thread\n");
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case AQ_SET_LIGHTCOLOR_MODE:
|
||||
if( pthread_create( &programmingthread->thread_id , NULL , set_aqualink_light_colormode, (void*)programmingthread) < 0) {
|
||||
logMessage (LOG_ERR, "could not create thread\n");
|
||||
return;
|
||||
|
@ -599,7 +607,7 @@ void aq_programmer(program_type r_type, char *args, struct aqualinkdata *aq_data
|
|||
}
|
||||
break;
|
||||
default:
|
||||
logMessage (LOG_ERR, "Don't understand thread type\n");
|
||||
logMessage (LOG_ERR, "Didn't understand programming mode type\n");
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -671,7 +679,7 @@ void cleanAndTerminateThread(struct programmingThreadCtrl *threadCtrl)
|
|||
struct timespec elapsed;
|
||||
clock_gettime(CLOCK_REALTIME, &threadCtrl->aq_data->last_active_time);
|
||||
timespec_subtract(&elapsed, &threadCtrl->aq_data->last_active_time, &threadCtrl->aq_data->start_active_time);
|
||||
logMessage(LOG_DEBUG, "Thread %d,%p (%s) finished in %d.%03ld sec\n",
|
||||
logMessage(LOG_NOTICE, "Thread %d,%p (%s) finished in %d.%03ld sec\n",
|
||||
threadCtrl->aq_data->active_thread.ptype,
|
||||
threadCtrl->aq_data->active_thread.thread_id,
|
||||
ptypeName(threadCtrl->aq_data->active_thread.ptype),
|
||||
|
@ -921,7 +929,7 @@ void *set_aqualink_SWG( void *ptr )
|
|||
return ptr;
|
||||
}
|
||||
|
||||
logMessage(LOG_DEBUG, "programming SWG percent to %d\n", val);
|
||||
logMessage(LOG_NOTICE, "programming SWG percent to %d\n", val);
|
||||
|
||||
if ( select_menu_item(aq_data, "SET AQUAPURE") != true ) {
|
||||
logMessage(LOG_WARNING, "Could not select SET AQUAPURE menu\n");
|
||||
|
@ -1021,7 +1029,97 @@ void *set_aqualink_light_colormode( void *ptr )
|
|||
threadCtrl = (struct programmingThreadCtrl *) ptr;
|
||||
struct aqualinkdata *aq_data = threadCtrl->aq_data;
|
||||
|
||||
waitForSingleThreadOrTerminate(threadCtrl, AQ_SET_COLORMODE);
|
||||
waitForSingleThreadOrTerminate(threadCtrl, AQ_SET_LIGHTCOLOR_MODE);
|
||||
|
||||
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]);
|
||||
|
||||
if (btn < 0 || btn >= TOTAL_BUTTONS ) {
|
||||
logMessage(LOG_ERR, "Can't program light mode on button %d\n", btn);
|
||||
cleanAndTerminateThread(threadCtrl);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
aqkey *button = &aq_data->aqbuttons[btn];
|
||||
unsigned char code = button->code;
|
||||
|
||||
//logMessage(LOG_NOTICE, "Light Programming #: %d, on button: %s, color light type: %d\n", val, button->label, typ);
|
||||
|
||||
mode_name = light_mode_name(typ, val-1);
|
||||
|
||||
if (mode_name == NULL) {
|
||||
logMessage(LOG_ERR, "Light Programming #: %d, on button: %s, color light type: %d, couldn't find mode name '%s'\n", val, button->label, typ, mode_name);
|
||||
cleanAndTerminateThread(threadCtrl);
|
||||
return ptr;
|
||||
} else {
|
||||
logMessage(LOG_NOTICE, "Light Programming #: %d, on button: %s, color light type: %d, name '%s'\n", val, button->label, typ, mode_name);
|
||||
}
|
||||
|
||||
// Simply turn the light off if value is 0
|
||||
if (val <= 0) {
|
||||
if ( button->led->state == ON ) {
|
||||
send_cmd(code);
|
||||
}
|
||||
cleanAndTerminateThread(threadCtrl);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// Needs to start programming sequence with light off
|
||||
if ( button->led->state == ON ) {
|
||||
logMessage(LOG_INFO, "Light Programming Initial state on, turning off\n");
|
||||
send_cmd(code);
|
||||
waitfor_queue2empty();
|
||||
if ( !waitForMessage(threadCtrl->aq_data, "OFF", 5)) // Message like 'Aux3 Off'
|
||||
logMessage(LOG_ERR, "Light Programming didn't receive OFF message\n");
|
||||
}
|
||||
|
||||
// Now turn on and wait for the message "color mode name<>*"
|
||||
send_cmd(code);
|
||||
waitfor_queue2empty();
|
||||
i=0;
|
||||
|
||||
do{
|
||||
if ( !waitForMessage(threadCtrl->aq_data, "~*", 3))
|
||||
logMessage(LOG_ERR, "Light Programming didn't receive color light mode message\n");
|
||||
|
||||
if (strncasecmp(aq_data->last_message, mode_name, strlen(mode_name)) == 0) {
|
||||
logMessage(LOG_INFO, "Light Programming found color 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 <= LIGHT_COLOR_OPTIONS);
|
||||
|
||||
if (i == LIGHT_COLOR_OPTIONS) {
|
||||
logMessage(LOG_ERR, "Light Programming didn't receive color light mode message for '%s'\n",mode_name);
|
||||
}
|
||||
|
||||
cleanAndTerminateThread(threadCtrl);
|
||||
|
||||
// just stop compiler error, ptr is not valid as it's just been freed
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
||||
void *set_aqualink_light_programmode( void *ptr )
|
||||
{
|
||||
int i;
|
||||
struct programmingThreadCtrl *threadCtrl;
|
||||
threadCtrl = (struct programmingThreadCtrl *) ptr;
|
||||
struct aqualinkdata *aq_data = threadCtrl->aq_data;
|
||||
|
||||
waitForSingleThreadOrTerminate(threadCtrl, AQ_SET_LIGHTPROGRAM_MODE);
|
||||
|
||||
char *buf = (char*)threadCtrl->thread_args;
|
||||
int val = atoi(&buf[0]);
|
||||
|
@ -1535,7 +1633,8 @@ void _waitfor_queue2empty(bool longwait)
|
|||
{
|
||||
int i=0;
|
||||
|
||||
while ( (_pgm_command != NUL) && ( i++ < (30*(longwait?2:1) ) ) ) {
|
||||
//while ( (_pgm_command != NUL) && ( i++ < (30*(longwait?2:1) ) ) ) {
|
||||
while ( (_pgm_command != NUL) && ( i++ < (50*(longwait?2:1) ) ) ) {
|
||||
//sleep(1); // NSF Change to smaller time.
|
||||
//logMessage(LOG_DEBUG, "******** QUEUE IS FULL ******** delay\n");
|
||||
delay(50);
|
||||
|
@ -1544,7 +1643,7 @@ void _waitfor_queue2empty(bool longwait)
|
|||
if (_pgm_command != NUL) {
|
||||
if (pda_mode()) {
|
||||
// Wait for longer in PDA mode since it's slower.
|
||||
while ( (_pgm_command != NUL) && ( i++ < (130*(longwait?2:1)) ) ) {
|
||||
while ( (_pgm_command != NUL) && ( i++ < (150*(longwait?2:1)) ) ) {
|
||||
delay(100);
|
||||
}
|
||||
}
|
||||
|
@ -1866,8 +1965,11 @@ const char *ptypeName(program_type type)
|
|||
case AQ_GET_PROGRAMS:
|
||||
return "Get programs";
|
||||
break;
|
||||
case AQ_SET_COLORMODE:
|
||||
return "Set light color";
|
||||
case AQ_SET_LIGHTPROGRAM_MODE:
|
||||
return "Set light color (using AqualinkD)";
|
||||
break;
|
||||
case AQ_SET_LIGHTCOLOR_MODE:
|
||||
return "Set light color (using Panel)";
|
||||
break;
|
||||
case AQ_PDA_INIT:
|
||||
return "Init PDA";
|
||||
|
@ -1891,7 +1993,7 @@ const char *ptypeName(program_type type)
|
|||
return "SWG Boost";
|
||||
break;
|
||||
case AQ_SET_ONETOUCH_PUMP_RPM:
|
||||
return "Set Pump RPM";
|
||||
return "Set OneTouch Pump RPM";
|
||||
break;
|
||||
case AQ_SET_ONETOUCH_MACRO:
|
||||
return "Set OneTouch Macro";
|
||||
|
@ -1923,3 +2025,70 @@ const char *ptypeName(program_type type)
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Cleaner version of above for UI display purposes.
|
||||
const char *programtypeDisplayName(program_type type)
|
||||
{
|
||||
switch (type) {
|
||||
case AQ_GET_POOL_SPA_HEATER_TEMPS:
|
||||
case AQ_GET_ONETOUCH_SETPOINTS:
|
||||
case AQ_GET_FREEZE_PROTECT_TEMP:
|
||||
case AQ_PDA_INIT:
|
||||
return "Programming: retrieving setpoints";
|
||||
break;
|
||||
case AQ_SET_ONETOUCH_TIME:
|
||||
case AQ_SET_TIME:
|
||||
return "Programming: setting time";
|
||||
break;
|
||||
case AQ_SET_POOL_HEATER_TEMP:
|
||||
case AQ_SET_ONETOUCH_POOL_HEATER_TEMP:
|
||||
case AQ_SET_SPA_HEATER_TEMP:
|
||||
case AQ_SET_ONETOUCH_SPA_HEATER_TEMP:
|
||||
return "Programming: setting heater";
|
||||
break;
|
||||
case AQ_SET_FRZ_PROTECTION_TEMP:
|
||||
case AQ_SET_ONETOUCH_FREEZEPROTECT:
|
||||
return "Programming: setting Freeze protect";
|
||||
break;
|
||||
case AQ_GET_DIAGNOSTICS_MODEL:
|
||||
return "Programming: retrieving diagnostics";
|
||||
break;
|
||||
case AQ_GET_PROGRAMS:
|
||||
return "Programming: retrieving programs";
|
||||
break;
|
||||
case AQ_SET_LIGHTPROGRAM_MODE:
|
||||
case AQ_SET_LIGHTCOLOR_MODE:
|
||||
return "Programming: setting light color";
|
||||
break;
|
||||
case AQ_SET_SWG_PERCENT:
|
||||
case AQ_SET_ONETOUCH_SWG_PERCENT:
|
||||
return "Programming: setting SWG percent";
|
||||
break;
|
||||
case AQ_PDA_DEVICE_STATUS:
|
||||
return "Programming: retrieving PDA Device status";
|
||||
break;
|
||||
case AQ_PDA_DEVICE_ON_OFF:
|
||||
return "Programming: setting device on/off";
|
||||
break;
|
||||
case AQ_GET_AUX_LABELS:
|
||||
return "Programming: retrieving AUX labels";
|
||||
break;
|
||||
case AQ_PDA_WAKE_INIT:
|
||||
return "Programming: PDA wakeup";
|
||||
break;
|
||||
case AQ_SET_BOOST:
|
||||
case AQ_SET_ONETOUCH_BOOST:
|
||||
return "Programming: setting SWG Boost";
|
||||
break;
|
||||
case AQ_SET_ONETOUCH_PUMP_RPM:
|
||||
return "Programming: setting Pump RPM";
|
||||
break;
|
||||
case AQ_SET_ONETOUCH_MACRO:
|
||||
return "Programming: setting OneTouch Macro";
|
||||
break;
|
||||
|
||||
default:
|
||||
return "Programming: please wait!";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,7 +40,8 @@ typedef enum {
|
|||
AQ_GET_DIAGNOSTICS_MODEL,
|
||||
//AQ_SEND_CMD,
|
||||
AQ_GET_PROGRAMS,
|
||||
AQ_SET_COLORMODE,
|
||||
AQ_SET_LIGHTPROGRAM_MODE,
|
||||
AQ_SET_LIGHTCOLOR_MODE,
|
||||
AQ_PDA_INIT,
|
||||
AQ_SET_SWG_PERCENT,
|
||||
AQ_PDA_DEVICE_STATUS,
|
||||
|
@ -83,6 +84,8 @@ void aq_send_cmd(unsigned char cmd);
|
|||
void queueGetProgramData(emulation_type source_type, struct aqualinkdata *aq_data);
|
||||
void queueGetExtendedProgramData(emulation_type source_type, struct aqualinkdata *aq_data, bool labels);
|
||||
unsigned char pop_aq_cmd(struct aqualinkdata *aq_data);
|
||||
|
||||
|
||||
//bool push_aq_cmd(unsigned char cmd);
|
||||
|
||||
//void send_cmd(unsigned char cmd, struct aqualinkdata *aq_data);
|
||||
|
@ -96,6 +99,7 @@ int setpoint_check(int type, int value, struct aqualinkdata *aqdata);
|
|||
int RPM_check(pump_type type, int value, struct aqualinkdata *aqdata);
|
||||
//int RPM_check(int type, int value, struct aqualinkdata *aqdata);
|
||||
const char *ptypeName(program_type type);
|
||||
const char *programtypeDisplayName(program_type type);
|
||||
|
||||
// These shouldn't be here, but just for the PDA AQ PROGRAMMER
|
||||
void send_cmd(unsigned char cmd);
|
||||
|
|
|
@ -84,6 +84,11 @@ bool onetouch_enabled()
|
|||
{
|
||||
return _onetouch_enabled;
|
||||
}
|
||||
bool VSP_enabled()
|
||||
{
|
||||
// At present this is dependant on onetouch.
|
||||
return onetouch_enabled();
|
||||
}
|
||||
|
||||
void set_extended_device_id_programming(bool mode)
|
||||
{
|
||||
|
|
20
aq_serial.h
20
aq_serial.h
|
@ -25,6 +25,18 @@
|
|||
#define SWG_DEV_ID 0x50
|
||||
#define IAQ_DEV_ID 0x33
|
||||
|
||||
/* Few Device ID's in decimal for quick checking
|
||||
# Pentair pump ID's
|
||||
# 0x60 to 0x6F (0x60, 0x61 0x62, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F)
|
||||
# Jandy pump ID's
|
||||
# 0x78, 0x79, 0x7A, 0x7B
|
||||
*/
|
||||
#define PENTAIR_DEC_PUMP_MIN 96
|
||||
#define PENTAIR_DEC_PUMP_MAX 111
|
||||
#define JANDY_DEC_PUMP_MIN 120
|
||||
#define JANDY_DEC_PUMP_MAX 123
|
||||
|
||||
|
||||
// PACKET DEFINES Jandy
|
||||
#define NUL 0x00
|
||||
#define DLE 0x10
|
||||
|
@ -270,6 +282,13 @@ SPILLOVER IS DISABLED WHILE SPA IS ON
|
|||
#define IAQ_KEY_AUX6 0x1e
|
||||
#define IAQ_KEY_AUX7 0x1f
|
||||
|
||||
// At the moment just used for next ack
|
||||
typedef enum {
|
||||
DRS_NONE,
|
||||
DRS_SWG,
|
||||
DRS_EPUMP
|
||||
} rsDeviceType;
|
||||
|
||||
typedef enum {
|
||||
ON,
|
||||
OFF,
|
||||
|
@ -320,6 +339,7 @@ const char* get_packet_type(unsigned char* packet , int length);
|
|||
|
||||
void set_onetouch_enabled(bool mode);
|
||||
bool onetouch_enabled();
|
||||
bool VSP_enabled();
|
||||
|
||||
void set_extended_device_id_programming(bool mode);
|
||||
bool extended_device_id_programming();
|
||||
|
|
23
aqualink.h
23
aqualink.h
|
@ -23,6 +23,7 @@
|
|||
#define DATE_STRING_LEN 30
|
||||
|
||||
#define MAX_PUMPS 4
|
||||
#define MAX_LIGHTS 4
|
||||
|
||||
enum {
|
||||
FAHRENHEIT,
|
||||
|
@ -90,11 +91,27 @@ typedef struct pumpd
|
|||
int pumpIndex;
|
||||
pump_type pumpType;
|
||||
//int buttonID;
|
||||
protocolType ptype;
|
||||
protocolType prclType;
|
||||
aqkey *button;
|
||||
//bool updated;
|
||||
} pump_detail;
|
||||
|
||||
// color light modes (Aqualink program, Jandy, Jandy LED, SAm/SAL, Color Logic, Intellibrite)
|
||||
typedef enum clight_type {
|
||||
LC_PROGRAMABLE=0,
|
||||
LC_JANDY,
|
||||
LC_JANDYLED,
|
||||
LC_SAL,
|
||||
LC_CLOGIG,
|
||||
LC_INTELLIB
|
||||
} clight_type;
|
||||
|
||||
typedef struct clightd
|
||||
{
|
||||
clight_type lightType;
|
||||
aqkey *button;
|
||||
} clight_detail;
|
||||
|
||||
struct aqualinkdata
|
||||
{
|
||||
//char crap[AQ_MSGLEN];
|
||||
|
@ -132,9 +149,13 @@ struct aqualinkdata
|
|||
unsigned char last_packet_type;
|
||||
int num_pumps;
|
||||
pump_detail pumps[MAX_PUMPS];
|
||||
int num_lights;
|
||||
clight_detail lights[MAX_LIGHTS];
|
||||
int open_websockets;
|
||||
bool boost;
|
||||
char boost_msg[10];
|
||||
float ph;
|
||||
int orp;
|
||||
//bool last_msg_was_status;
|
||||
//bool ar_swg_connected;
|
||||
#ifdef AQ_DEBUG
|
||||
|
|
102
aqualinkd.c
102
aqualinkd.c
|
@ -39,10 +39,10 @@
|
|||
#include "net_services.h"
|
||||
#include "pda_menu.h"
|
||||
#include "pda.h"
|
||||
#include "pentair_messages.h"
|
||||
#include "devices_pentair.h"
|
||||
#include "pda_aq_programmer.h"
|
||||
#include "packetLogger.h"
|
||||
#include "aquapure.h"
|
||||
#include "devices_jandy.h"
|
||||
#include "onetouch.h"
|
||||
#include "onetouch_aq_programmer.h"
|
||||
#include "version.h"
|
||||
|
@ -496,7 +496,8 @@ void processMessage(char *message)
|
|||
if (_aqualink_data.active_thread.thread_id == 0 &&
|
||||
stristr(msg, "JANDY AquaLinkRS") == NULL &&
|
||||
stristr(msg, "PUMP O") == NULL &&// Catch 'PUMP ON' and 'PUMP OFF' but not 'PUMP WILL TURN ON'
|
||||
stristr(msg, "MAINTAIN") == NULL /* && // Catch 'MAINTAIN TEMP IS OFF'
|
||||
stristr(msg, "MAINTAIN") == NULL && // Catch 'MAINTAIN TEMP IS OFF'
|
||||
stristr(msg, "0 PSI") == NULL /* // Catch some erronious message on test harness
|
||||
stristr(msg, "CLEANER O") == NULL &&
|
||||
stristr(msg, "SPA O") == NULL &&
|
||||
stristr(msg, "AUX") == NULL*/
|
||||
|
@ -575,7 +576,7 @@ bool process_packet(unsigned char *packet, int length)
|
|||
}
|
||||
|
||||
// COLOR MODE programming relies on state changes, so let any threads know
|
||||
if (_aqualink_data.active_thread.ptype == AQ_SET_COLORMODE) {
|
||||
if (_aqualink_data.active_thread.ptype == AQ_SET_LIGHTPROGRAM_MODE) {
|
||||
//printf ("Light thread kicking\n");
|
||||
kick_aq_program_thread(&_aqualink_data, ALLBUTTON);
|
||||
}
|
||||
|
@ -742,6 +743,7 @@ int main(int argc, char *argv[])
|
|||
bool cmdln_debugRS485 = false;
|
||||
bool cmdln_lograwRS485 = false;
|
||||
_aqualink_data.num_pumps = 0;
|
||||
_aqualink_data.num_lights = 0;
|
||||
|
||||
/*
|
||||
static unsigned char msg_loop; // = '\0';
|
||||
|
@ -898,26 +900,30 @@ int main(int argc, char *argv[])
|
|||
|
||||
for (i = 0; i < TOTAL_BUTONS; i++)
|
||||
{
|
||||
char vsp[] = "None";
|
||||
int alid = 0;
|
||||
//char ext[] = " VSP ID None | AL ID 0 ";
|
||||
char ext[40];
|
||||
ext[0] = '\0';
|
||||
for (j = 0; j < _aqualink_data.num_pumps; j++) {
|
||||
//if (_aqualink_data.pumps[j].buttonID == i) {
|
||||
if (_aqualink_data.pumps[j].button == &_aqualink_data.aqbuttons[i]) {
|
||||
sprintf(vsp,"0x%02hhx",_aqualink_data.pumps[j].pumpID);
|
||||
alid = _aqualink_data.pumps[j].pumpIndex;
|
||||
//printf("Pump %d %d %d\n",_aqualink_data.pumps[j].pumpID, _aqualink_data.pumps[j].buttonID, _aqualink_data.pumps[j].ptype);
|
||||
sprintf(ext, "VSP ID 0x%02hhx | PMP ID %-1d |",_aqualink_data.pumps[j].pumpID, _aqualink_data.pumps[j].pumpIndex);
|
||||
}
|
||||
}
|
||||
if (!_aqconfig_.pda_mode) {
|
||||
logMessage(LOG_NOTICE, "Config BTN %-13s = label %-15s | VSP ID %-4s | AL ID %-1d | dzidx %-3d | %s\n",
|
||||
_aqualink_data.aqbuttons[i].name, _aqualink_data.aqbuttons[i].label, vsp, alid, _aqualink_data.aqbuttons[i].dz_idx,
|
||||
(i>0 && (i==_aqconfig_.light_programming_button_pool || i==_aqconfig_.light_programming_button_spa)?"Programable":"") );
|
||||
} else {
|
||||
logMessage(LOG_NOTICE, "Config BTN %-13s = label %-15s | VSP ID %-4s | AL ID %-1d | PDAlabel %-15s | dzidx %d\n",
|
||||
_aqualink_data.aqbuttons[i].name, _aqualink_data.aqbuttons[i].label, vsp, alid,
|
||||
_aqualink_data.aqbuttons[i].pda_label, _aqualink_data.aqbuttons[i].dz_idx );
|
||||
for (j = 0; j < _aqualink_data.num_lights; j++) {
|
||||
if (_aqualink_data.lights[j].button == &_aqualink_data.aqbuttons[i]) {
|
||||
sprintf(ext,"Light Progm | CTYPE %-1d |",_aqualink_data.lights[j].lightType);
|
||||
}
|
||||
}
|
||||
if (_aqualink_data.aqbuttons[i].dz_idx > 0)
|
||||
sprintf(ext+strlen(ext), "dzidx %-3d", _aqualink_data.aqbuttons[i].dz_idx);
|
||||
|
||||
if (!_aqconfig_.pda_mode) {
|
||||
logMessage(LOG_NOTICE, "Config BTN %-13s = label %-15s | %s\n",
|
||||
_aqualink_data.aqbuttons[i].name, _aqualink_data.aqbuttons[i].label, ext);
|
||||
} else {
|
||||
logMessage(LOG_NOTICE, "Config BTN %-13s = label %-15s | PDAlabel %-15s | %s\n",
|
||||
_aqualink_data.aqbuttons[i].name, _aqualink_data.aqbuttons[i].label,
|
||||
_aqualink_data.aqbuttons[i].pda_label, ext);
|
||||
}
|
||||
//logMessage(LOG_NOTICE, "Button %d\n", i+1, _aqualink_data.aqbuttons[i].label , _aqualink_data.aqbuttons[i].dz_idx);
|
||||
}
|
||||
|
||||
if (_aqconfig_.deamonize == true)
|
||||
|
@ -1023,7 +1029,8 @@ void main_loop()
|
|||
int rs_fd;
|
||||
int packet_length;
|
||||
unsigned char packet_buffer[AQ_MAXPKTLEN+1];
|
||||
bool interestedInNextAck = false;
|
||||
//bool interestedInNextAck = false;
|
||||
rsDeviceType interestedInNextAck = DRS_NONE;
|
||||
bool changed = false;
|
||||
//int swg_zero_cnt = 0;
|
||||
int swg_noreply_cnt = 0;
|
||||
|
@ -1051,6 +1058,8 @@ void main_loop()
|
|||
_aqualink_data.frz_protect_state = OFF;
|
||||
_aqualink_data.battery = OK;
|
||||
_aqualink_data.open_websockets = 0;
|
||||
_aqualink_data.ph = TEMP_UNKNOWN;
|
||||
_aqualink_data.orp = TEMP_UNKNOWN;
|
||||
|
||||
pthread_mutex_init(&_aqualink_data.active_thread.thread_mutex, NULL);
|
||||
pthread_cond_init(&_aqualink_data.active_thread.thread_cond, NULL);
|
||||
|
@ -1148,20 +1157,20 @@ void main_loop()
|
|||
}
|
||||
else if (packet_length > 0)
|
||||
{
|
||||
/* // Use this to check wait time in mg_mgr_poll(&mgr, xx); at bottom of for, and adjust as needed.
|
||||
if (blank_read > 0) {
|
||||
logMessage(LOG_NOTICE, "RS empry reads %d\n", blank_read);
|
||||
}
|
||||
*/
|
||||
blank_read = 0;
|
||||
changed = false;
|
||||
/*
|
||||
// This is handeled by aq_serial now
|
||||
if (_aqconfig_.debug_RSProtocol_packets || getLogLevel() >= LOG_DEBUG_SERIAL)
|
||||
logPacket(packet_buffer, packet_length);
|
||||
*/
|
||||
|
||||
if (packet_length > 0 && packet_buffer[PKT_DEST] == _aqconfig_.device_id)
|
||||
{
|
||||
if (getLogLevel() >= LOG_DEBUG)
|
||||
logMessage(LOG_DEBUG, "RS received packet of type %s length %d\n", get_packet_type(packet_buffer, packet_length), packet_length);
|
||||
|
||||
changed = process_packet(packet_buffer, packet_length);
|
||||
|
||||
// If we are not in PDA or Simulator mode, just sent ACK & any CMD, else caculate the ACK.
|
||||
if (!_aqualink_data.simulate_panel && !_aqconfig_.pda_mode) {
|
||||
//send_ack(rs_fd, pop_aq_cmd(&_aqualink_data));
|
||||
|
@ -1179,29 +1188,39 @@ void main_loop()
|
|||
else if (packet_length > 0 && _aqconfig_.read_all_devices == true)
|
||||
{
|
||||
//logPacket(packet_buffer, packet_length);
|
||||
if (packet_buffer[PKT_DEST] == DEV_MASTER && interestedInNextAck == true)
|
||||
if (packet_buffer[PKT_DEST] == DEV_MASTER && interestedInNextAck != DRS_NONE)
|
||||
{
|
||||
swg_noreply_cnt = 0;
|
||||
changed = processPacketFromSWG(packet_buffer, packet_length, &_aqualink_data);
|
||||
interestedInNextAck = false;
|
||||
}
|
||||
//else if (interestedInNextAck == true && packet_buffer[PKT_DEST] != DEV_MASTER && _aqualink_data.ar_swg_status != 0x00)
|
||||
else if (interestedInNextAck == true && packet_buffer[PKT_DEST] != DEV_MASTER && _aqualink_data.ar_swg_status != SWG_STATUS_OFF)
|
||||
{
|
||||
if ( ++swg_noreply_cnt < 3 ) {
|
||||
_aqualink_data.ar_swg_status = SWG_STATUS_OFF;
|
||||
changed = true;
|
||||
if (interestedInNextAck == DRS_SWG) {
|
||||
swg_noreply_cnt = 0;
|
||||
changed = processPacketFromSWG(packet_buffer, packet_length, &_aqualink_data);
|
||||
} else if (interestedInNextAck == DRS_EPUMP) {
|
||||
changed = processPacketFromJandyPump(packet_buffer, packet_length, &_aqualink_data);
|
||||
}
|
||||
interestedInNextAck = false;
|
||||
interestedInNextAck = DRS_NONE;
|
||||
}
|
||||
else if ( packet_buffer[PKT_DEST] != DEV_MASTER && interestedInNextAck != DRS_NONE )
|
||||
{ // We were expecting an ack from device as next message but didn;t get it, device must be off
|
||||
if (interestedInNextAck == DRS_SWG && _aqualink_data.ar_swg_status != SWG_STATUS_OFF) {
|
||||
if ( ++swg_noreply_cnt < 3 ) {
|
||||
_aqualink_data.ar_swg_status = SWG_STATUS_OFF;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
interestedInNextAck = DRS_NONE;
|
||||
}
|
||||
else if (packet_buffer[PKT_DEST] == SWG_DEV_ID)
|
||||
{
|
||||
interestedInNextAck = true;
|
||||
interestedInNextAck = DRS_SWG;
|
||||
changed = processPacketToSWG(packet_buffer, packet_length, &_aqualink_data, _aqconfig_.swg_zero_ignore);
|
||||
}
|
||||
else if (packet_buffer[PKT_DEST] >= JANDY_DEC_PUMP_MIN && packet_buffer[PKT_DEST] <= JANDY_DEC_PUMP_MAX)
|
||||
{
|
||||
interestedInNextAck = DRS_EPUMP;
|
||||
changed = processPacketToJandyPump(packet_buffer, packet_length, &_aqualink_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
interestedInNextAck = false;
|
||||
interestedInNextAck = DRS_NONE;
|
||||
}
|
||||
|
||||
if (_aqconfig_.read_pentair_packets && getProtocolType(packet_buffer) == PENTAIR) {
|
||||
|
@ -1216,7 +1235,8 @@ void main_loop()
|
|||
broadcast_aqualinkstate(mgr.active_connections);
|
||||
}
|
||||
|
||||
mg_mgr_poll(&mgr, 10);
|
||||
//mg_mgr_poll(&mgr, 10);
|
||||
mg_mgr_poll(&mgr, 5);
|
||||
tcdrain(rs_fd); // Make sure buffer has been sent.
|
||||
|
||||
// Any unactioned commands
|
||||
|
|
|
@ -0,0 +1,139 @@
|
|||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
//#define COLOR_LIGHTS_C_
|
||||
#include "color_lights.h"
|
||||
|
||||
/****** This list MUST be in order of clight_type enum *******/
|
||||
const char *_color_light_options[LIGHT_COLOR_TYPES+1][LIGHT_COLOR_OPTIONS] =
|
||||
{
|
||||
// AqualnkD Colors ignored as no names in control panel.
|
||||
{ "bogus" },
|
||||
{ // Jandy Color
|
||||
"Alpine White",
|
||||
"Sky Blue",
|
||||
"Cobalt Blue",
|
||||
"Caribbean Blue",
|
||||
"Spring Green",
|
||||
"Emerald Green",
|
||||
"Emerald Rose",
|
||||
"Magenta",
|
||||
"Violet",
|
||||
"Color Splash"
|
||||
},
|
||||
{ // Jandy LED
|
||||
"Alpine White",
|
||||
"Sky Blue",
|
||||
"Cobalt Blue",
|
||||
"Caribbean Blue",
|
||||
"Spring Green",
|
||||
"Emerald Green",
|
||||
"Emerald Rose",
|
||||
"Magenta",
|
||||
"Violet",
|
||||
"Slow Splash",
|
||||
"Fast Splash",
|
||||
"USA",
|
||||
"Fat Tuesday",
|
||||
"Disco Tech"
|
||||
},
|
||||
{ // SAm/SAL
|
||||
"White",
|
||||
"Light Green",
|
||||
"Green",
|
||||
"Cyan",
|
||||
"Blue",
|
||||
"Lavender",
|
||||
"Magenta"
|
||||
},
|
||||
{ // Color Logic
|
||||
"Voodoo Lounge",
|
||||
"Blue Sea",
|
||||
"Royal Blue",
|
||||
"Afternoon Skies",
|
||||
//"Aqua Green",
|
||||
"Emerald",
|
||||
"Sangria",
|
||||
"Cloud White",
|
||||
//"Warm Red",
|
||||
//"Flamingo",
|
||||
//"Vivid Violet",
|
||||
//"Sangria",
|
||||
"Twilight",
|
||||
"Tranquility",
|
||||
"Gemstone",
|
||||
"USA",
|
||||
"Mardi Gras",
|
||||
"Cool Cabaret"
|
||||
},
|
||||
{ // IntelliBrite
|
||||
"SAm",
|
||||
"Party",
|
||||
"Romance",
|
||||
"Caribbean",
|
||||
"American",
|
||||
"Cal Sunset",
|
||||
"Royal",
|
||||
"Blue",
|
||||
"Green",
|
||||
"Red",
|
||||
"White",
|
||||
"Magenta"
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const char *light_mode_name(clight_type type, int index)
|
||||
{
|
||||
return _color_light_options[type][index];
|
||||
}
|
||||
|
||||
bool isShowMode(const char *mode)
|
||||
{
|
||||
if (strcmp(mode, "Color Splash") == 0 ||
|
||||
strcmp(mode, "Slow Splash") == 0 ||
|
||||
strcmp(mode, "Fast Splash") == 0 ||
|
||||
strcmp(mode, "Fat Tuesday") == 0 ||
|
||||
strcmp(mode, "Disco Tech") == 0 ||
|
||||
strcmp(mode, "Voodoo Lounge") == 0 ||
|
||||
strcmp(mode, "Twilight") == 0 ||
|
||||
strcmp(mode, "Tranquility") == 0 ||
|
||||
strcmp(mode, "Gemstone") == 0 ||
|
||||
strcmp(mode, "USA") == 0 ||
|
||||
strcmp(mode, "Mardi Gras") == 0 ||
|
||||
strcmp(mode, "Cool Cabaret") == 0 ||
|
||||
strcmp(mode, "SAm") == 0 ||
|
||||
strcmp(mode, "Party") == 0 ||
|
||||
strcmp(mode, "Romance") == 0 ||
|
||||
strcmp(mode, "Caribbean") == 0 ||
|
||||
strcmp(mode, "American") == 0 ||
|
||||
strcmp(mode, "Cal Sunset") == 0)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
int build_color_lights_js(struct aqualinkdata *aqdata, char* buffer, int size)
|
||||
{
|
||||
memset(&buffer[0], 0, size);
|
||||
int length = 0;
|
||||
int i, j;
|
||||
|
||||
length += sprintf(buffer+length, "var _light_program = [];\n");
|
||||
length += sprintf(buffer+length, "_light_program[0] = light_program;\n");
|
||||
|
||||
for (i=1; i < LIGHT_COLOR_TYPES; i++) {
|
||||
length += sprintf(buffer+length, "_light_program[%d] = [", i);
|
||||
for (j=0; j < LIGHT_COLOR_OPTIONS; j++) {
|
||||
if (_color_light_options[i][j] != NULL)
|
||||
length += sprintf(buffer+length, "\"%s%s\",", _color_light_options[i][j], (isShowMode(_color_light_options[i][j])?" - Show":"") );
|
||||
}
|
||||
buffer[--length] = '\0';
|
||||
length += sprintf(buffer+length, "];\n");
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
|
||||
#ifndef COLOR_LIGHTS_H_
|
||||
#define COLOR_LIGHTS_H_
|
||||
|
||||
#include "aqualink.h"
|
||||
|
||||
#define LIGHT_COLOR_NAME 16
|
||||
#define LIGHT_COLOR_OPTIONS 17
|
||||
#define LIGHT_COLOR_TYPES LC_INTELLIB
|
||||
|
||||
/*
|
||||
// color light modes (Aqualink program, Jandy, Jandy LED, SAm/SAL, Color Logic, Intellibrite)
|
||||
typedef enum clight_type {
|
||||
LC_PROGRAMABLE=0,
|
||||
LC_JANDY,
|
||||
LC_JANDYLED,
|
||||
LC_SAL,
|
||||
LC_CLOGIG,
|
||||
LC_INTELLIB
|
||||
} clight_type;
|
||||
*/
|
||||
const char *light_mode_name(clight_type type, int index);
|
||||
int build_color_lights_js(struct aqualinkdata *aqdata, char* buffer, int size);
|
||||
|
||||
|
||||
|
||||
//char *_color_light_options_[LIGHT_COLOR_TYPES][LIGHT_COLOR_OPTIONS][LIGHT_COLOR_NAME];
|
||||
|
||||
#endif //COLOR_LIGHTS_H_
|
||||
|
||||
/*
|
||||
Color Name Jandy Colors Jandy LED SAm/SAL Color Logic IntelliBrite
|
||||
----------------------------------------------------------------------------------------------
|
||||
Color Splash 11 8
|
||||
Alpine White 1 1
|
||||
Sky Blue 2 2
|
||||
Cobalt Blue 3 3
|
||||
Caribbean Blu 4 4
|
||||
Spring Green 5 5
|
||||
Emerald Green 6 6
|
||||
Emerald Rose 7 7
|
||||
Magenta 8 8
|
||||
Garnet Red 9 9
|
||||
Violet 10 10
|
||||
Slow Splash 11
|
||||
Fast Splash 12
|
||||
USA!!! 13
|
||||
Fat Tuesday 14
|
||||
Disco Tech 15
|
||||
White 1
|
||||
Light Green 2
|
||||
Green 3
|
||||
Cyan 4
|
||||
Blue 5
|
||||
Lavender 6
|
||||
Magenta 7
|
||||
Light Magenta
|
||||
Voodoo Lounge 1
|
||||
Deep Blue Sea 2
|
||||
Afternoon Skies 3
|
||||
Afternoon Sky
|
||||
Emerald 4
|
||||
Sangria 5
|
||||
Cloud White 6
|
||||
Twilight 7
|
||||
Tranquility 8
|
||||
Gemstone 9
|
||||
USA! 10
|
||||
Mardi Gras 11
|
||||
Cool Cabaret 12
|
||||
SAm 1
|
||||
Party 2
|
||||
Romance 3
|
||||
Caribbean 4
|
||||
American 5
|
||||
Cal Sunset 6
|
||||
Royal 7
|
||||
Blue 8
|
||||
Green 9
|
||||
Red 10
|
||||
White 11
|
||||
Magenta 12
|
||||
*/
|
44
config.c
44
config.c
|
@ -77,8 +77,8 @@ void init_parameters (struct aqconfig * parms)
|
|||
parms->light_programming_mode = 0;
|
||||
parms->light_programming_initial_on = 15;
|
||||
parms->light_programming_initial_off = 12;
|
||||
parms->light_programming_button_pool = TEMP_UNKNOWN;
|
||||
parms->light_programming_button_spa = TEMP_UNKNOWN;
|
||||
//parms->light_programming_button_pool = TEMP_UNKNOWN;
|
||||
//parms->light_programming_button_spa = TEMP_UNKNOWN;
|
||||
parms->deamonize = true;
|
||||
parms->log_file = '\0';
|
||||
parms->pda_mode = false;
|
||||
|
@ -383,11 +383,13 @@ bool setConfigValue(struct aqualinkdata *aqdata, char *param, char *value) {
|
|||
_aqconfig_.light_programming_initial_off = strtoul(value, NULL, 10);
|
||||
rtn=true;
|
||||
} else if (strncasecmp(param, "light_programming_button_spa", 28) == 0) {
|
||||
_aqconfig_.light_programming_button_spa = strtoul(value, NULL, 10) - 1;
|
||||
logMessage(LOG_ERR, "Config error, 'light_programming_button_spa' no longer supported\n");
|
||||
//_aqconfig_.light_programming_button_spa = strtoul(value, NULL, 10) - 1;
|
||||
rtn=true;
|
||||
} else if (strncasecmp(param, "light_programming_button", 24) == 0 ||
|
||||
strncasecmp(param, "light_programming_button_pool", 29) == 0) {
|
||||
_aqconfig_.light_programming_button_pool = strtoul(value, NULL, 10) - 1;
|
||||
logMessage(LOG_ERR, "Config error, 'light_programming_button' & 'light_programming_button_pool' are no longer supported\n");
|
||||
//_aqconfig_.light_programming_button_pool = strtoul(value, NULL, 10) - 1;
|
||||
rtn=true;
|
||||
} else if (strncasecmp(param, "SWG_percent_dzidx", 17) == 0) {
|
||||
_aqconfig_.dzidx_swg_percent = strtoul(value, NULL, 10);
|
||||
|
@ -479,18 +481,32 @@ bool setConfigValue(struct aqualinkdata *aqdata, char *param, char *value) {
|
|||
} else if (strncasecmp(param + 9, "_PDA_label", 10) == 0) {
|
||||
aqdata->aqbuttons[num].pda_label = cleanalloc(value);
|
||||
rtn=true;
|
||||
} else if (strncasecmp(param + 9, "_lightMode", 10) == 0) {
|
||||
if (aqdata->num_lights < MAX_LIGHTS) {
|
||||
int type = strtoul(value, NULL, 10);
|
||||
if (type < LC_PROGRAMABLE || type > LC_INTELLIB) {
|
||||
logMessage(LOG_ERR, "Config error, unknown light mode '%s'\n",type);
|
||||
} else {
|
||||
aqdata->lights[aqdata->num_lights].button = &aqdata->aqbuttons[num];
|
||||
aqdata->lights[aqdata->num_lights].lightType = type;
|
||||
aqdata->num_lights++;
|
||||
}
|
||||
} else {
|
||||
logMessage(LOG_ERR, "Config error, (colored|programmable) Lights limited to %d, ignoring %s'\n",MAX_LIGHTS,param);
|
||||
}
|
||||
rtn=true;
|
||||
} else if (strncasecmp(param + 9, "_pumpID", 7) == 0) {
|
||||
pump_detail *pump = getpump(aqdata, num);
|
||||
if (pump != NULL) {
|
||||
pump->pumpID = strtoul(cleanalloc(value), NULL, 16);
|
||||
if (pump->pumpID < 119) {
|
||||
pump->ptype = PENTAIR;
|
||||
if (pump->pumpID <= PENTAIR_DEC_PUMP_MAX) {
|
||||
pump->prclType = PENTAIR;
|
||||
} else {
|
||||
pump->ptype = JANDY;
|
||||
pump->prclType = JANDY;
|
||||
//pump->pumpType = EPUMP; // For testing let the interface set this
|
||||
}
|
||||
} else {
|
||||
logMessage(LOG_ERR, "Config error, VSP Pumps limited to %d, ignoring %s'\n",MAX_PUMPS-1,param);
|
||||
logMessage(LOG_ERR, "Config error, VSP Pumps limited to %d, ignoring %s'\n",MAX_PUMPS,param);
|
||||
}
|
||||
rtn=true;
|
||||
} else if (strncasecmp(param + 9, "_pumpIndex", 10) == 0) { //button_01_pumpIndex=1
|
||||
|
@ -498,7 +514,7 @@ bool setConfigValue(struct aqualinkdata *aqdata, char *param, char *value) {
|
|||
if (pump != NULL) {
|
||||
pump->pumpIndex = strtoul(value, NULL, 10);
|
||||
} else {
|
||||
logMessage(LOG_ERR, "Config error, VSP Pumps limited to %d, ignoring %s'\n",MAX_PUMPS-1,param);
|
||||
logMessage(LOG_ERR, "Config error, VSP Pumps limited to %d, ignoring %s'\n",MAX_PUMPS,param);
|
||||
}
|
||||
rtn=true;
|
||||
}
|
||||
|
@ -528,6 +544,8 @@ bool setConfigValue(struct aqualinkdata *aqdata, char *param, char *value) {
|
|||
return rtn;
|
||||
}
|
||||
|
||||
|
||||
|
||||
pump_detail *getpump(struct aqualinkdata *aqdata, int button)
|
||||
{
|
||||
//static int _pumpindex = 0;
|
||||
|
@ -674,8 +692,11 @@ void writeIntValue (FILE *fp, char *msg, int value)
|
|||
fprintf(fp, "%s = %d\n", msg, value);
|
||||
}
|
||||
|
||||
|
||||
bool writeCfg (struct aqualinkdata *aqdata)
|
||||
{
|
||||
{
|
||||
logMessage(LOG_ERR, "writeCfg() not implimented\n");
|
||||
/*
|
||||
FILE *fp;
|
||||
int i;
|
||||
bool fs = remount_root_ro(false);
|
||||
|
@ -747,6 +768,7 @@ bool writeCfg (struct aqualinkdata *aqdata)
|
|||
}
|
||||
fclose(fp);
|
||||
remount_root_ro(fs);
|
||||
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
4
config.h
4
config.h
|
@ -51,8 +51,8 @@ struct aqconfig
|
|||
float light_programming_mode;
|
||||
int light_programming_initial_on;
|
||||
int light_programming_initial_off;
|
||||
int light_programming_button_pool;
|
||||
int light_programming_button_spa;
|
||||
//int light_programming_button_pool;
|
||||
//int light_programming_button_spa;
|
||||
bool override_freeze_protect;
|
||||
bool pda_mode;
|
||||
bool onetouch_mode;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "aquapure.h"
|
||||
#include "devices_jandy.h"
|
||||
#include "aq_serial.h"
|
||||
#include "aqualink.h"
|
||||
#include "utils.h"
|
||||
|
@ -176,4 +176,15 @@ void get_swg_status_mqtt(struct aqualinkdata *aqdata, char *message, int *status
|
|||
*dzalert = 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool processPacketToJandyPump(unsigned char *packet_buffer, int packet_length, struct aqualinkdata *aqdata)
|
||||
{
|
||||
logMessage(LOG_DEBUG, "Need to log ePump message here for future\n");
|
||||
return false;
|
||||
}
|
||||
bool processPacketFromJandyPump(unsigned char *packet_buffer, int packet_length, struct aqualinkdata *aqdata)
|
||||
{
|
||||
logMessage(LOG_DEBUG, "Need to log ePump message here for future\n");
|
||||
return false;
|
||||
}
|
|
@ -7,6 +7,8 @@
|
|||
|
||||
bool processPacketToSWG(unsigned char *packet, int packet_length, struct aqualinkdata *aqdata, int swg_zero_ignore);
|
||||
bool processPacketFromSWG(unsigned char *packet, int packet_length, struct aqualinkdata *aqdata);
|
||||
bool processPacketToJandyPump(unsigned char *packet_buffer, int packet_length, struct aqualinkdata *aqdata);
|
||||
bool processPacketFromJandyPump(unsigned char *packet_buffer, int packet_length, struct aqualinkdata *aqdata);
|
||||
|
||||
void get_swg_status_mqtt(struct aqualinkdata *aqdata, char *message, int *status, int *dzalert);
|
||||
aqledstate get_swg_led_state(struct aqualinkdata *aqdata);
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
#include "aqualink.h"
|
||||
#include "aq_serial.h"
|
||||
#include "pentair_messages.h"
|
||||
#include "devices_pentair.h"
|
||||
#include "utils.h"
|
||||
|
||||
bool processPentairPacket(unsigned char *packet, int packet_length, struct aqualinkdata *aqdata)
|
||||
|
@ -35,12 +35,12 @@ bool processPentairPacket(unsigned char *packet, int packet_length, struct aqual
|
|||
|
||||
//static int pumpIndex = 1;
|
||||
|
||||
if ( packet[PEN_PKT_CMD] == PEN_CMD_STATUS && packet[PEN_PKT_FROM] >= 96 && packet[PEN_PKT_FROM] <= 111 ){
|
||||
if ( packet[PEN_PKT_CMD] == PEN_CMD_STATUS && packet[PEN_PKT_FROM] >= PENTAIR_DEC_PUMP_MIN && packet[PEN_PKT_FROM] <= PENTAIR_DEC_PUMP_MAX ){
|
||||
// We have Pentair Pump packet, let's see if it's configured.
|
||||
//printf("PUMP\n");
|
||||
|
||||
for (i = 0; i < MAX_PUMPS; i++) {
|
||||
if ( aqdata->pumps[i].ptype == PENTAIR && aqdata->pumps[i].pumpID == packet[PEN_PKT_FROM] ) {
|
||||
if ( aqdata->pumps[i].prclType == PENTAIR && aqdata->pumps[i].pumpID == packet[PEN_PKT_FROM] ) {
|
||||
// We found the pump.
|
||||
logMessage(LOG_INFO, "Pentair Pump Status message = RPM %d | WATTS %d\n",
|
||||
(packet[PEN_HI_B_RPM] * 256) + packet[PEN_LO_B_RPM],
|
|
@ -0,0 +1,52 @@
|
|||
|
||||
Color Name Jandy Colors Jandy LED SAm/SAL Color Logic IntelliBrite
|
||||
----------------------------------------------------------------------------------------------
|
||||
Color Splash 11 8
|
||||
Alpine White 1 1
|
||||
Sky Blue 2 2
|
||||
Cobalt Blue 3 3
|
||||
Caribbean Blu 4 4
|
||||
Spring Green 5 5
|
||||
Emerald Green 6 6
|
||||
Emerald Rose 7 7
|
||||
Magenta 8 8
|
||||
Garnet Red 9 9
|
||||
Violet 10 10
|
||||
Slow Splash 11
|
||||
Fast Splash 12
|
||||
USA!!! 13
|
||||
Fat Tuesday 14
|
||||
Disco Tech 15
|
||||
White 1
|
||||
Light Green 2
|
||||
Green 3
|
||||
Cyan 4
|
||||
Blue 5
|
||||
Lavender 6
|
||||
Magenta 7
|
||||
Light Magenta
|
||||
Voodoo Lounge 1
|
||||
Deep Blue Sea 2
|
||||
Afternoon Skies 3
|
||||
Afternoon Sky 4
|
||||
Emerald 5
|
||||
Sangria 6
|
||||
Cloud White 7
|
||||
Twilight 8
|
||||
Tranquility 9
|
||||
Gemstone 10
|
||||
USA! 11
|
||||
Mardi Gras 12
|
||||
Cool Cabaret 13
|
||||
SAm 1
|
||||
Party 2
|
||||
Romance 3
|
||||
Caribbean 4
|
||||
American 5
|
||||
Cal Sunset 6
|
||||
Royal 7
|
||||
Blue 8
|
||||
Green 9
|
||||
Red 10
|
||||
White 11
|
||||
Magenta 12
|
|
@ -28,7 +28,7 @@
|
|||
#include "json_messages.h"
|
||||
#include "domoticz.h"
|
||||
#include "aq_mqtt.h"
|
||||
#include "aquapure.h"
|
||||
#include "devices_jandy.h"
|
||||
#include "version.h"
|
||||
|
||||
|
||||
|
@ -40,11 +40,12 @@
|
|||
//{"type": "aux_labels","Pool Pump": "Pool Pump","Spa Mode": "Spa Mode","Cleaner": "Aux 1","Waterfall": "Aux 2","Spa Blower": "Aux 2","Pool Light": "Aux 4","Spa Light ": "Aux 5","Aux 6": "Aux 6","Aux 7": "Aux 7","Heater": "Heater","Heater": "Heater","Solar Heater": "Solar Heater","(null)": "(null)"}
|
||||
|
||||
//SPA WILL TURN OFF AFTER COOL DOWN CYCLE
|
||||
|
||||
#include "aq_programmer.h"
|
||||
const char* getStatus(struct aqualinkdata *aqdata)
|
||||
{
|
||||
if (aqdata->active_thread.thread_id != 0 && !aqdata->simulate_panel) {
|
||||
return JSON_PROGRAMMING;
|
||||
//return JSON_PROGRAMMING;
|
||||
return programtypeDisplayName(aqdata->active_thread.ptype);
|
||||
}
|
||||
|
||||
//if (aqdata->last_message != NULL && stristr(aqdata->last_message, "SERVICE") != NULL ) {
|
||||
|
@ -163,7 +164,7 @@ int LED2int(aqledstate state)
|
|||
}
|
||||
}
|
||||
|
||||
#define AUX_BUFFER_SIZE 100
|
||||
#define AUX_BUFFER_SIZE 200
|
||||
|
||||
char *get_aux_information(aqkey *button, struct aqualinkdata *aqdata, char *buffer)
|
||||
{
|
||||
|
@ -172,21 +173,28 @@ char *get_aux_information(aqkey *button, struct aqualinkdata *aqdata, char *buff
|
|||
buffer[0] = '\0';
|
||||
|
||||
for (i=0; i < aqdata->num_pumps; i++) {
|
||||
if (button == aqdata->pumps[i].button) {
|
||||
|
||||
//if (aqdata->pumps[i].rpm != TEMP_UNKNOWN || aqdata->pumps[i].gpm != TEMP_UNKNOWN || aqdata->pumps[i].watts != TEMP_UNKNOWN) {
|
||||
length += sprintf(buffer, ",\"Pump_RPM\":\"%d\",\"Pump_GPM\":\"%d\",\"Pump_Watts\":\"%d\",\"Pump_Type\":\"%s\"",
|
||||
if (button == aqdata->pumps[i].button) {
|
||||
length += sprintf(buffer, ",\"type_ext\":\"switch_vsp\",\"Pump_RPM\":\"%d\",\"Pump_GPM\":\"%d\",\"Pump_Watts\":\"%d\",\"Pump_Type\":\"%s\"",
|
||||
aqdata->pumps[i].rpm,aqdata->pumps[i].gpm,aqdata->pumps[i].watts,
|
||||
(aqdata->pumps[i].pumpType==VFPUMP?"vfPump":(aqdata->pumps[i].pumpType==VSPUMP?"vsPump":"ePump")));
|
||||
break;
|
||||
//}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
}
|
||||
|
||||
for (i=0; i < aqdata->num_lights; i++) {
|
||||
if (button == aqdata->lights[i].button) {
|
||||
length += sprintf(buffer, ",\"type_ext\": \"switch_program\", \"Light_Type\":\"%d\"", aqdata->lights[i].lightType);
|
||||
return buffer;
|
||||
}
|
||||
}
|
||||
|
||||
length += sprintf(buffer, ",\"type_ext\": \"switch\"");
|
||||
return buffer;
|
||||
}
|
||||
|
||||
int build_device_JSON(struct aqualinkdata *aqdata, int programable_switch1, int programable_switch2, char* buffer, int size, bool homekit)
|
||||
//int build_device_JSON(struct aqualinkdata *aqdata, int programable_switch1, int programable_switch2, char* buffer, int size, bool homekit)
|
||||
int build_device_JSON(struct aqualinkdata *aqdata, char* buffer, int size, bool homekit)
|
||||
{
|
||||
char aux_info[AUX_BUFFER_SIZE];
|
||||
memset(&buffer[0], 0, size);
|
||||
|
@ -232,16 +240,19 @@ int build_device_JSON(struct aqualinkdata *aqdata, int programable_switch1, int
|
|||
((homekit)?2:0),
|
||||
((homekit_f)?degFtoC(aqdata->spa_temp):aqdata->spa_temp),
|
||||
LED2int(aqdata->aqbuttons[i].led->state));
|
||||
} else if ( (programable_switch1 > 0 && programable_switch1 == i) ||
|
||||
(programable_switch2 > 0 && programable_switch2 == i)) {
|
||||
/*
|
||||
length += sprintf(buffer+length, "{\"type\": \"switch_program\", \"id\": \"%s\", \"name\": \"%s\", \"state\": \"%s\", \"status\": \"%s\", \"int_status\": \"%d\" %s},",
|
||||
} else {
|
||||
get_aux_information(&aqdata->aqbuttons[i], aqdata, aux_info);
|
||||
length += sprintf(buffer+length, "{\"type\": \"switch\", \"type_ext\": \"switch_vsp\", \"id\": \"%s\", \"name\": \"%s\", \"state\": \"%s\", \"status\": \"%s\", \"int_status\": \"%d\" %s},",
|
||||
aqdata->aqbuttons[i].name,
|
||||
aqdata->aqbuttons[i].label,
|
||||
aqdata->aqbuttons[i].led->state==ON?JSON_ON:JSON_OFF,
|
||||
LED2text(aqdata->aqbuttons[i].led->state),
|
||||
LED2int(aqdata->aqbuttons[i].led->state),
|
||||
get_aux_information(&aqdata->aqbuttons[i], aqdata, aux_info));*/
|
||||
aux_info);
|
||||
}
|
||||
/*
|
||||
} else if ( (programable_switch1 > 0 && programable_switch1 == i) ||
|
||||
(programable_switch2 > 0 && programable_switch2 == i)) {
|
||||
length += sprintf(buffer+length, "{\"type\": \"switch\", \"type_ext\": \"switch_program\", \"id\": \"%s\", \"name\": \"%s\", \"state\": \"%s\", \"status\": \"%s\", \"int_status\": \"%d\"},",
|
||||
aqdata->aqbuttons[i].name,
|
||||
aqdata->aqbuttons[i].label,
|
||||
|
@ -266,7 +277,7 @@ int build_device_JSON(struct aqualinkdata *aqdata, int programable_switch1, int
|
|||
aux_info);
|
||||
//get_aux_information(&aqdata->aqbuttons[i], aqdata, aux_info));
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
if ( aqdata->frz_protect_set_point != TEMP_UNKNOWN && aqdata->air_temp != TEMP_UNKNOWN) {
|
||||
|
@ -333,6 +344,23 @@ int build_device_JSON(struct aqualinkdata *aqdata, int programable_switch1, int
|
|||
|
||||
}
|
||||
|
||||
if ( aqdata->ph != TEMP_UNKNOWN ) {
|
||||
length += sprintf(buffer+length, "{\"type\": \"value\", \"id\": \"%s\", \"name\": \"%s\", \"state\": \"%s\", \"value\": \"%.*f\" },",
|
||||
((homekit_f)?CHRM_PH_F_TOPIC:CHEM_PH_TOPIC),
|
||||
"Water Chemistry pH",
|
||||
"on",
|
||||
((homekit)?2:1),
|
||||
((homekit_f)?(degFtoC(aqdata->ph)):aqdata->ph));
|
||||
}
|
||||
if ( aqdata->orp != TEMP_UNKNOWN ) {
|
||||
length += sprintf(buffer+length, "{\"type\": \"value\", \"id\": \"%s\", \"name\": \"%s\", \"state\": \"%s\", \"value\": \"%.*f\" },",
|
||||
((homekit_f)?CHRM_ORP_F_TOPIC:CHEM_ORP_TOPIC),
|
||||
"Water Chemistry ORP",
|
||||
"on",
|
||||
((homekit)?2:0),
|
||||
((homekit_f)?(degFtoC(aqdata->orp)):aqdata->orp));
|
||||
}
|
||||
|
||||
length += sprintf(buffer+length, "{\"type\": \"temperature\", \"id\": \"%s\", \"name\": \"%s\", \"state\": \"%s\", \"value\": \"%.*f\" },",
|
||||
AIR_TEMP_TOPIC,
|
||||
/*AIR_TEMPERATURE,*/
|
||||
|
@ -433,6 +461,12 @@ int build_aqualink_status_JSON(struct aqualinkdata *aqdata, char* buffer, int si
|
|||
if ( aqdata->swg_percent == 101 )
|
||||
length += sprintf(buffer+length, ",\"swg_boost_msg\":\"%s\"",aqdata->boost_msg );
|
||||
|
||||
if ( aqdata->ph != TEMP_UNKNOWN )
|
||||
length += sprintf(buffer+length, ",\"chem_ph\":\"%.1f\"",aqdata->ph );
|
||||
|
||||
if ( aqdata->orp != TEMP_UNKNOWN )
|
||||
length += sprintf(buffer+length, ",\"chem_orp\":\"%d\"",aqdata->orp );
|
||||
|
||||
length += sprintf(buffer+length, ",\"leds\":{" );
|
||||
for (i=0; i < TOTAL_BUTTONS; i++)
|
||||
{
|
||||
|
@ -676,3 +710,5 @@ bool parseJSONmqttrequest(const char *str, size_t len, int *idx, int *nvalue, ch
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
//FUNCTION PROTOTYPES
|
||||
|
||||
#define JSON_LABEL_SIZE 300
|
||||
#define JSON_BUFFER_SIZE 4000
|
||||
#define JSON_STATUS_SIZE 1024
|
||||
#define JSON_MQTT_MSG_SIZE 100
|
||||
|
||||
|
@ -42,8 +43,8 @@ bool parseJSONmqttrequest(const char *str, size_t len, int *idx, int *nvalue, ch
|
|||
int build_aqualink_error_status_JSON(char* buffer, int size, char *msg);
|
||||
int build_mqtt_status_message_JSON(char* buffer, int size, int idx, int nvalue, char *svalue);
|
||||
//int build_device_JSON(struct aqualinkdata *aqdata, int programable_switch, char* buffer, int size, bool homekit);
|
||||
int build_device_JSON(struct aqualinkdata *aqdata, int programable_switch1, int programable_switch2, char* buffer, int size, bool homekit);
|
||||
|
||||
//int build_device_JSON(struct aqualinkdata *aqdata, int programable_switch1, int programable_switch2, char* buffer, int size, bool homekit);
|
||||
int build_device_JSON(struct aqualinkdata *aqdata, char* buffer, int size, bool homekit);
|
||||
|
||||
#endif /* JSON_MESSAGES_H_ */
|
||||
|
||||
|
|
|
@ -34,7 +34,8 @@
|
|||
#include "domoticz.h"
|
||||
#include "aq_mqtt.h"
|
||||
#include "pda.h"
|
||||
#include "aquapure.h"
|
||||
#include "devices_jandy.h"
|
||||
#include "color_lights.h"
|
||||
|
||||
|
||||
//static struct aqconfig *_aqconfig_;
|
||||
|
@ -405,6 +406,17 @@ void mqtt_broadcast_aqualinkstate(struct mg_connection *nc)
|
|||
_last_mqtt_aqualinkdata.battery = _aqualink_data->battery;
|
||||
send_mqtt_string_msg(nc, BATTERY_STATE, _aqualink_data->battery==OK?MQTT_ON:MQTT_OFF);
|
||||
}
|
||||
|
||||
if (_aqualink_data->ph != TEMP_UNKNOWN && _aqualink_data->ph != _last_mqtt_aqualinkdata.ph) {
|
||||
_last_mqtt_aqualinkdata.ph = _aqualink_data->ph;
|
||||
send_mqtt_float_msg(nc, CHEM_PH_TOPIC, _aqualink_data->ph);
|
||||
send_mqtt_float_msg(nc, CHRM_PH_F_TOPIC, roundf(degFtoC(_aqualink_data->ph)));
|
||||
}
|
||||
if (_aqualink_data->orp != TEMP_UNKNOWN && _aqualink_data->orp != _last_mqtt_aqualinkdata.orp) {
|
||||
_last_mqtt_aqualinkdata.orp = _aqualink_data->orp;
|
||||
send_mqtt_numeric_msg(nc, CHEM_ORP_TOPIC, _aqualink_data->orp);
|
||||
send_mqtt_float_msg(nc, CHRM_ORP_F_TOPIC, roundf(degFtoC(_aqualink_data->orp)));
|
||||
}
|
||||
|
||||
if (_aqualink_data->ar_swg_status != _last_mqtt_aqualinkdata.ar_swg_status ||
|
||||
_aqualink_data->swg_percent != _last_mqtt_aqualinkdata.swg_percent) { // Percent can also effect status
|
||||
|
@ -559,25 +571,41 @@ int getTempforMeteohub(char *buffer)
|
|||
|
||||
void set_light_mode(char *value, int button)
|
||||
{
|
||||
int i;
|
||||
clight_detail *light = NULL;
|
||||
|
||||
if (_aqconfig_.pda_mode == true) {
|
||||
logMessage(LOG_ERR, "Light mode control not supported in PDA mode\n");
|
||||
return;
|
||||
}
|
||||
if (_aqconfig_.light_programming_button_pool != button &&
|
||||
_aqconfig_.light_programming_button_spa != button) {
|
||||
for (i=0; i < _aqualink_data->num_lights; i++) {
|
||||
if (&_aqualink_data->aqbuttons[button] == _aqualink_data->lights[i].button) {
|
||||
// Found the programmable light
|
||||
light = &_aqualink_data->lights[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (light == NULL) {
|
||||
logMessage(LOG_ERR, "Light mode control not configured for button %d\n",button);
|
||||
return;
|
||||
}
|
||||
|
||||
char buf[LIGHT_MODE_BUFER];
|
||||
|
||||
if (light->lightType == LC_PROGRAMABLE ) {
|
||||
// 5 below is light index, need to look this up so it's not hard coded.
|
||||
sprintf(buf, "%-5s%-5d%-5d%-5d%.2f",value,
|
||||
sprintf(buf, "%-5s%-5d%-5d%-5d%.2f",value,
|
||||
button,
|
||||
_aqconfig_.light_programming_initial_on,
|
||||
_aqconfig_.light_programming_initial_off,
|
||||
_aqconfig_.light_programming_mode );
|
||||
//logMessage(LOG_NOTICE, "WEB: requset light mode %s\n", buf);
|
||||
aq_programmer(AQ_SET_COLORMODE, buf, _aqualink_data);
|
||||
aq_programmer(AQ_SET_LIGHTPROGRAM_MODE, buf, _aqualink_data);
|
||||
} else {
|
||||
sprintf(buf, "%-5s%-5d%-5d",value, button, light->lightType);
|
||||
aq_programmer(AQ_SET_LIGHTCOLOR_MODE, buf, _aqualink_data);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -600,6 +628,12 @@ void action_web_request(struct mg_connection *nc, struct http_message *http_msg)
|
|||
mg_get_http_var(&http_msg->query_string, "command", command, sizeof(command));
|
||||
logMessage(LOG_INFO, "WEB: Message command='%s'\n", command);
|
||||
|
||||
if (strcmp(command, "dynamic_config") == 0) {
|
||||
char data[JSON_BUFFER_SIZE];
|
||||
int size = build_color_lights_js(_aqualink_data, data, JSON_BUFFER_SIZE);
|
||||
mg_send_head(nc, 200, size, "Content-Type: text/javascript");
|
||||
mg_send(nc, data, size);
|
||||
} else
|
||||
// if (strstr(http_msg->query_string.p, "command=status")) {
|
||||
if (strcmp(command, "status") == 0) {
|
||||
char data[JSON_STATUS_SIZE];
|
||||
|
@ -614,19 +648,25 @@ void action_web_request(struct mg_connection *nc, struct http_message *http_msg)
|
|||
mg_send_head(nc, 200, size, "Content-Type: text/plain");
|
||||
mg_send(nc, data, size);
|
||||
} else if (strcmp(command, "poollightmode") == 0) {
|
||||
logMessage(LOG_ERR, "WEB: poollightmode taken out for update (forgot to put it back)\n");
|
||||
/*
|
||||
char value[20];
|
||||
mg_get_http_var(&http_msg->query_string, "value", value, sizeof(value));
|
||||
//aq_programmer(AQ_SET_COLORMODE, value, _aqualink_data);
|
||||
set_light_mode(value, _aqconfig_.light_programming_button_pool);
|
||||
mg_send_head(nc, 200, strlen(GET_RTN_OK), "Content-Type: text/plain");
|
||||
mg_send(nc, GET_RTN_OK, strlen(GET_RTN_OK));
|
||||
*/
|
||||
} else if (strcmp(command, "spalightmode") == 0) {
|
||||
logMessage(LOG_ERR, "WEB: spalightmode taken out for update (forgot to put it back)\n");
|
||||
/*
|
||||
char value[20];
|
||||
mg_get_http_var(&http_msg->query_string, "value", value, sizeof(value));
|
||||
//aq_programmer(AQ_SET_COLORMODE, value, _aqualink_data);
|
||||
set_light_mode(value, _aqconfig_.light_programming_button_spa);
|
||||
mg_send_head(nc, 200, strlen(GET_RTN_OK), "Content-Type: text/plain");
|
||||
mg_send(nc, GET_RTN_OK, strlen(GET_RTN_OK));
|
||||
*/
|
||||
} else if (strcmp(command, "diag") == 0) {
|
||||
aq_programmer(AQ_GET_DIAGNOSTICS_MODEL, NULL, _aqualink_data);
|
||||
mg_send_head(nc, 200, strlen(GET_RTN_OK), "Content-Type: text/plain");
|
||||
|
@ -659,14 +699,25 @@ void action_web_request(struct mg_connection *nc, struct http_message *http_msg)
|
|||
logMessage(LOG_INFO, "Web: request to set Freeze protect to %s\n", value);
|
||||
mg_send_head(nc, 200, strlen(GET_RTN_OK), "Content-Type: text/plain");
|
||||
mg_send(nc, GET_RTN_OK, strlen(GET_RTN_OK));
|
||||
} else if (strcmp(command, "extended_device_prg") == 0) {
|
||||
char value[20];
|
||||
char message[JSON_LABEL_SIZE];
|
||||
mg_get_http_var(&http_msg->query_string, "value", value, sizeof(value));
|
||||
bool prg = request2bool(value);
|
||||
if (prg && !onetouch_enabled())
|
||||
prg = false; // Ignore request if onetouch is not enabeled
|
||||
set_extended_device_id_programming(prg);
|
||||
sprintf(message,"{\"extended_device_prg\":\"%s\"}", bool2text(prg));
|
||||
mg_send_head(nc, 200, strlen(message), "Content-Type: application/json");
|
||||
mg_send(nc, message, strlen(message));
|
||||
} else if (strcmp(command, "devices") == 0) {
|
||||
char message[JSON_LABEL_SIZE*10];
|
||||
int size = build_device_JSON(_aqualink_data, _aqconfig_.light_programming_button_pool, _aqconfig_.light_programming_button_spa, message, JSON_LABEL_SIZE*10, false);
|
||||
char message[JSON_BUFFER_SIZE];
|
||||
int size = build_device_JSON(_aqualink_data, message, JSON_BUFFER_SIZE, false);
|
||||
mg_send_head(nc, 200, size, "Content-Type: application/json");
|
||||
mg_send(nc, message, size);
|
||||
} else if (strcmp(command, "homebridge") == 0) {
|
||||
char message[JSON_LABEL_SIZE*10];
|
||||
int size = build_device_JSON(_aqualink_data, _aqconfig_.light_programming_button_pool, _aqconfig_.light_programming_button_spa, message, JSON_LABEL_SIZE*10, true);
|
||||
char message[JSON_BUFFER_SIZE];
|
||||
int size = build_device_JSON(_aqualink_data, message, JSON_BUFFER_SIZE, true);
|
||||
mg_send_head(nc, 200, size, "Content-Type: application/json");
|
||||
mg_send(nc, message, size);
|
||||
} else if (strcmp(command, "setconfigprm") == 0) {
|
||||
|
@ -866,8 +917,8 @@ void action_websocket_request(struct mg_connection *nc, struct websocket_message
|
|||
build_aux_labels_JSON(_aqualink_data, labels, JSON_LABEL_SIZE);
|
||||
ws_send(nc, labels);
|
||||
} else if (strcmp(request.first.value, "GET_DEVICES") == 0) {
|
||||
char message[JSON_LABEL_SIZE*10];
|
||||
build_device_JSON(_aqualink_data, _aqconfig_.light_programming_button_pool, _aqconfig_.light_programming_button_spa, message, JSON_LABEL_SIZE*10, false);
|
||||
char message[JSON_BUFFER_SIZE];
|
||||
build_device_JSON(_aqualink_data, message, JSON_BUFFER_SIZE, false);
|
||||
ws_send(nc, message);
|
||||
} else if ( strcmp(request.first.value, "simulator") == 0) {
|
||||
_aqualink_data->simulate_panel = true;
|
||||
|
@ -920,11 +971,13 @@ void action_websocket_request(struct mg_connection *nc, struct websocket_message
|
|||
aq_programmer(AQ_SET_SWG_PERCENT, request.second.value, _aqualink_data);
|
||||
_aqualink_data->swg_percent = value; // Set the value as if it's already been set, just incase it's 0 as we won't get that message, or will update next time
|
||||
}
|
||||
} else if (strcmp(request.first.value, "POOL_LIGHT_MODE") == 0) {
|
||||
set_light_mode(request.second.value, _aqconfig_.light_programming_button_pool);
|
||||
//} else if (strcmp(request.first.value, "POOL_LIGHT_MODE") == 0) {
|
||||
// set_light_mode(request.second.value, _aqconfig_.light_programming_button_pool);
|
||||
} else if (strcmp(request.first.value, "LIGHT_MODE") == 0) {
|
||||
// second is mode & third is button_id
|
||||
int i;
|
||||
for (i = 0; i < TOTAL_BUTTONS; i++) {
|
||||
// NSF I could pull the text here for the real light color name. 4th value in json
|
||||
if (strcmp(request.third.value, _aqualink_data->aqbuttons[i].name) == 0) {
|
||||
set_light_mode(request.second.value, i);
|
||||
break;
|
||||
|
@ -1119,7 +1172,7 @@ void action_domoticz_mqtt_message(struct mg_connection *nc, struct mg_mqtt_messa
|
|||
logMessage(LOG_INFO, "MQTT: DZ: received '%s' for '%s', already '%s', Ignoring\n", (nvalue==DZ_OFF?"OFF":"ON"), _aqualink_data->aqbuttons[i].name, (nvalue==DZ_OFF?"OFF":"ON"));
|
||||
} else {
|
||||
// NSF Below if needs to check that the button pressed is actually a light. Add this later
|
||||
if (_aqualink_data->active_thread.ptype == AQ_SET_COLORMODE ) {
|
||||
if (_aqualink_data->active_thread.ptype == AQ_SET_LIGHTPROGRAM_MODE ) {
|
||||
logMessage(LOG_NOTICE, "MQTT: DZ: received '%s' for '%s', IGNORING as we are programming light mode\n", (nvalue==DZ_OFF?"OFF":"ON"), _aqualink_data->aqbuttons[i].name);
|
||||
} else {
|
||||
logMessage(LOG_INFO, "MQTT: DZ: received '%s' for '%s', turning '%s'\n", (nvalue==DZ_OFF?"OFF":"ON"), _aqualink_data->aqbuttons[i].name,(nvalue==DZ_OFF?"OFF":"ON"));
|
||||
|
@ -1229,7 +1282,7 @@ static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
|
|||
|
||||
int qos=0;// can't be bothered with ack, so set to 0
|
||||
|
||||
logMessage(LOG_INFO, "MQTT: Connection acknowledged\n");
|
||||
logMessage(LOG_DEBUG, "MQTT: Connection acknowledged\n");
|
||||
mqtt_msg = (struct mg_mqtt_message *)ev_data;
|
||||
if (mqtt_msg->connack_ret_code != MG_EV_MQTT_CONNACK_ACCEPTED) {
|
||||
logMessage(LOG_WARNING, "Got mqtt connection error: %d\n", mqtt_msg->connack_ret_code);
|
||||
|
@ -1262,7 +1315,7 @@ static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
|
|||
break;
|
||||
case MG_EV_MQTT_PUBACK:
|
||||
mqtt_msg = (struct mg_mqtt_message *)ev_data;
|
||||
logMessage(LOG_INFO, "MQTT: Message publishing acknowledged (msg_id: %d)\n", mqtt_msg->message_id);
|
||||
logMessage(LOG_DEBUG, "MQTT: Message publishing acknowledged (msg_id: %d)\n", mqtt_msg->message_id);
|
||||
break;
|
||||
case MG_EV_MQTT_SUBACK:
|
||||
logMessage(LOG_INFO, "MQTT: Subscription(s) acknowledged\n");
|
||||
|
|
48
onetouch.c
48
onetouch.c
|
@ -281,18 +281,46 @@ bool log_qeuiptment_status(struct aqualinkdata *aq_data)
|
|||
//printf ("Set Pump Type to %d\n",aq_data->pumps[i].pumpType);
|
||||
}
|
||||
}
|
||||
|
||||
//aqdata->pumps[pumpIndex-1].rpm = atoi((char *) &packet_buffer[13]);
|
||||
} else if (ot_strcmp(_menu[2],"AQUAPURE") == 0) {
|
||||
/* Info: OneTouch Menu Line 0 = Equipment Status
|
||||
Info: OneTouch Menu Line 1 =
|
||||
Info: OneTouch Menu Line 2 = AQUAPURE 60%
|
||||
Info: OneTouch Menu Line 3 = Salt 7600 PPM */
|
||||
int swgp = atoi(&_menu[2][11]);
|
||||
if ( aq_data->swg_percent != swgp ) {
|
||||
aq_data->swg_percent = swgp;
|
||||
rtn = true;
|
||||
}
|
||||
logMessage(LOG_DEBUG, "OneTouch SWG = %d\n",swgp);
|
||||
|
||||
} else if (true == false) {
|
||||
/*
|
||||
Debug: OneTouch Menu Line 0 = Equipment Status
|
||||
Debug: OneTouch Menu Line 1 =
|
||||
Debug: OneTouch Menu Line 2 = AQUAPURE 30%
|
||||
Debug: OneTouch Menu Line 3 = Salt 3800 PPM
|
||||
Debug: OneTouch Menu Line 4 = Add 2 lbs Salt
|
||||
*/
|
||||
if (ot_strcmp(_menu[3],"Salt") == 0) {
|
||||
int ppm = atoi(&_menu[3][6]);
|
||||
if ( aq_data->swg_ppm != ppm ) {
|
||||
aq_data->swg_ppm = ppm;
|
||||
rtn = true;
|
||||
}
|
||||
logMessage(LOG_DEBUG, "OneTouch PPM = %d\n",ppm);
|
||||
}
|
||||
} else if (ot_strcmp(_menu[2],"Chemlink") == 0) {
|
||||
/* Info: OneTouch Menu Line 0 = Equipment Status
|
||||
Info: OneTouch Menu Line 1 =
|
||||
Info: OneTouch Menu Line 2 = Chemlink 1
|
||||
Info: OneTouch Menu Line 3 = ORP 750/PH 7.0 */
|
||||
if (ot_strcmp(_menu[3],"ORP") == 0) {
|
||||
int orp = atoi(&_menu[3][4]);
|
||||
char *indx = strchr(_menu[3], '/');
|
||||
float ph = atof(indx+3);
|
||||
if (aq_data->ph != ph || aq_data->orp != orp) {
|
||||
aq_data->ph = ph;
|
||||
aq_data->orp = orp;
|
||||
return true;
|
||||
}
|
||||
logMessage(LOG_INFO, "OneTouch Cemlink ORP = %d PH = %f\n",orp,ph);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
return rtn;
|
||||
}
|
||||
|
||||
|
|
|
@ -129,7 +129,7 @@ bool highlight_onetouch_menu_item(struct aqualinkdata *aq_data, char *item)
|
|||
// Also need page up and down " ^^ More vv"
|
||||
if ( (index = onetouch_menu_find_index(item)) != -1) {
|
||||
cnt = index - onetouch_menu_hlightindex();
|
||||
logMessage(LOG_DEBUG, "*** OneTouch menu caculator selected=%d, wanted=%d, move=%d times ***\n",onetouch_menu_hlightindex(),index,cnt);
|
||||
logMessage(LOG_DEBUG, "OneTouch menu caculator selected=%d, wanted=%d, move=%d timesn",onetouch_menu_hlightindex(),index,cnt);
|
||||
for (i=0; i < cnt; i ++) {
|
||||
send_ot_cmd(KEY_ONET_DOWN);
|
||||
waitfor_ot_queue2empty();
|
||||
|
@ -209,6 +209,7 @@ bool goto_onetouch_system_menu(struct aqualinkdata *aq_data)
|
|||
// Get back to a known point, the system menu
|
||||
while (get_onetouch_memu_type() != OTM_SYSTEM && get_onetouch_memu_type() != OTM_ONETOUCH && i < 5 ) {
|
||||
send_ot_cmd(KEY_ONET_BACK);
|
||||
waitfor_ot_queue2empty();
|
||||
waitForNextOT_Menu(aq_data);
|
||||
i++;
|
||||
}
|
||||
|
@ -244,6 +245,7 @@ bool goto_onetouch_system_menu(struct aqualinkdata *aq_data)
|
|||
|
||||
bool goto_onetouch_menu(struct aqualinkdata *aq_data, ot_menu_type menu)
|
||||
{
|
||||
bool equErr = false;
|
||||
char *second_menu = false;
|
||||
char *third_menu = false;
|
||||
|
||||
|
@ -292,14 +294,10 @@ bool goto_onetouch_menu(struct aqualinkdata *aq_data, ot_menu_type menu)
|
|||
return true;
|
||||
break;
|
||||
case OTM_EQUIPTMENT_ONOFF:
|
||||
//if ( select_onetouch_menu_item(aq_data, "Equipment ON/OFF") == false ) { // NSF Should use this
|
||||
if ( ot_strcmp(onetouch_menu_hlight(), "Equipment ON/OFF") == 0) {
|
||||
send_ot_cmd(KEY_ONET_SELECT);
|
||||
waitfor_ot_queue2empty();
|
||||
waitForNextOT_Menu(aq_data);
|
||||
return true;
|
||||
if ( select_onetouch_menu_item(aq_data, "Equipment ON/OFF") == false ) {
|
||||
logMessage(LOG_ERR, "OneTouch device programmer couldn't select 'Equipment ON/OFF' menu %d\n",menu);
|
||||
equErr = true;
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
case OTM_MENUHELP:
|
||||
case OTM_SET_TEMP:
|
||||
|
@ -308,51 +306,31 @@ bool goto_onetouch_menu(struct aqualinkdata *aq_data, ot_menu_type menu)
|
|||
case OTM_FREEZE_PROTECT:
|
||||
case OTM_BOOST:
|
||||
case OTM_SYSTEM_SETUP:
|
||||
if ( select_onetouch_menu_item(aq_data, " Menu / Help") == false ) {
|
||||
if ( select_onetouch_menu_item(aq_data, "Menu / Help") == false ) {
|
||||
logMessage(LOG_ERR, "OneTouch device programmer couldn't select menu %d\n",menu);
|
||||
break;
|
||||
}
|
||||
if (second_menu)
|
||||
select_onetouch_menu_item(aq_data, second_menu);
|
||||
if (third_menu)
|
||||
select_onetouch_menu_item(aq_data, third_menu);
|
||||
/*
|
||||
if (menu == OTM_SET_HEATER) {
|
||||
select_onetouch_menu_item(aq_data, "Set Temp");
|
||||
} else if (menu == OTM_SET_TIME) {
|
||||
select_onetouch_menu_item(aq_data, "Set Time");
|
||||
} else if (menu == OTM_SET_AQUAPURE) {
|
||||
select_onetouch_menu_item(aq_data, "Set AQUAPURE");
|
||||
}
|
||||
*/
|
||||
break;
|
||||
default:
|
||||
logMessage(LOG_ERR, "OneTouch device programmer doesn't know how to access menu %d\n",menu);
|
||||
break;
|
||||
}
|
||||
|
||||
// We can't detect Equiptment menu yet, so use the find test above not get_onetouch_memu_type() below
|
||||
if (menu == OTM_EQUIPTMENT_ONOFF ) {
|
||||
return !equErr;
|
||||
}
|
||||
|
||||
if (get_onetouch_memu_type() != menu)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
bool in_ot_programming_mode(struct aqualinkdata *aq_data)
|
||||
{
|
||||
//( type != AQ_SET_PUMP_RPM || type != AQ_SET_OT_MACRO )) {
|
||||
|
||||
if ( ( aq_data->active_thread.thread_id != 0 ) &&
|
||||
( aq_data->active_thread.ptype == AQ_SET_PUMP_RPM ||
|
||||
aq_data->active_thread.ptype == AQ_SET_OT_MACRO ||
|
||||
aq_data->active_thread.ptype == AQ_GET_OT_POOL_SPA_HEATER_TEMPS)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
// Return the digit at factor
|
||||
// num=12 factor=10 would return 2
|
||||
|
@ -422,7 +400,8 @@ void *set_aqualink_pump_rpm( void *ptr )
|
|||
|
||||
waitForSingleThreadOrTerminate(threadCtrl, AQ_SET_ONETOUCH_PUMP_RPM);
|
||||
|
||||
logMessage(LOG_NOTICE, "OneTouch Set Pump %d to RPM %d, from '%s'\n",pumpIndex,pumpRPM,buf);
|
||||
logMessage(LOG_NOTICE, "OneTouch Set Pump %d to RPM %d\n",pumpIndex,pumpRPM);
|
||||
|
||||
|
||||
if (! goto_onetouch_menu(aq_data, OTM_EQUIPTMENT_ONOFF) ){
|
||||
logMessage(LOG_ERR, "OneTouch device programmer didn't get Equiptment on/off menu\n");
|
||||
|
@ -461,21 +440,26 @@ void *set_aqualink_pump_rpm( void *ptr )
|
|||
//printf("FOUND MENU")
|
||||
if (strstr(onetouch_menu_hlight(), "RPM") != NULL ) {
|
||||
// RPM 3450 & 600 max & min
|
||||
// Panel will change 2nd,3rd & 4th digits depending on previos digit
|
||||
// so reget the RPM after every change.
|
||||
int RPM = ot_atoi(&onetouch_menu_hlight()[7]);
|
||||
intPress(digitDiff(RPM, pumpRPM, 10000));
|
||||
send_ot_cmd(KEY_ONET_SELECT);
|
||||
waitfor_ot_queue2empty();
|
||||
RPM = ot_atoi(&onetouch_menu_hlight()[7]);
|
||||
intPress(digitDiff(RPM, pumpRPM, 1000));
|
||||
send_ot_cmd(KEY_ONET_SELECT);
|
||||
waitfor_ot_queue2empty();
|
||||
RPM = ot_atoi(&onetouch_menu_hlight()[7]);
|
||||
intPress(digitDiff(RPM, pumpRPM, 100));
|
||||
send_ot_cmd(KEY_ONET_SELECT);
|
||||
waitfor_ot_queue2empty();
|
||||
RPM = ot_atoi(&onetouch_menu_hlight()[7]);
|
||||
intPress(digitDiff(RPM, pumpRPM, 10));
|
||||
// Get the new RPM.
|
||||
aq_data->pumps[structIndex].rpm = ot_atoi(&onetouch_menu_hlight()[7]);
|
||||
send_ot_cmd(KEY_ONET_SELECT);
|
||||
waitfor_ot_queue2empty();
|
||||
// Reset the pump RPM
|
||||
aq_data->pumps[structIndex].rpm = RPM;
|
||||
waitfor_ot_queue2empty();
|
||||
} else if (strstr(onetouch_menu_hlight(), "GPM") != NULL ) {
|
||||
// GPM 130 max, GPM 15 min
|
||||
for (i=0; i < 24 ; i++) { // Max of 23 key presses to get from max to min
|
||||
|
@ -486,8 +470,8 @@ void *set_aqualink_pump_rpm( void *ptr )
|
|||
} else if (GPM < pumpRPM) {
|
||||
send_ot_cmd(KEY_ONET_UP);
|
||||
} else {
|
||||
aq_data->pumps[structIndex].gpm = ot_atoi(&onetouch_menu_hlight()[8]);;
|
||||
send_ot_cmd(KEY_ONET_SELECT);
|
||||
aq_data->pumps[structIndex].gpm = GPM;
|
||||
waitfor_ot_queue2empty();
|
||||
break;
|
||||
}
|
||||
|
@ -531,7 +515,7 @@ void *set_aqualink_onetouch_macro( void *ptr )
|
|||
{
|
||||
struct programmingThreadCtrl *threadCtrl;
|
||||
threadCtrl = (struct programmingThreadCtrl *) ptr;
|
||||
struct aqualinkdata *aq_data = threadCtrl->aq_data;
|
||||
//struct aqualinkdata *aq_data = threadCtrl->aq_data;
|
||||
|
||||
//sprintf(msg, "%-5d%-5d",index, (strcmp(value, "on") == 0)?ON:OFF);
|
||||
// Use above to set
|
||||
|
@ -783,6 +767,8 @@ void *set_aqualink_onetouch_time( void *ptr )
|
|||
|
||||
waitForSingleThreadOrTerminate(threadCtrl, AQ_SET_ONETOUCH_TIME);
|
||||
|
||||
logMessage(LOG_ERR, "OneTouch set time not implimented\n");
|
||||
|
||||
logMessage(LOG_DEBUG, "OneTouch set time\n");
|
||||
|
||||
if ( !goto_onetouch_menu(aq_data, OTM_SET_TIME) ){
|
||||
|
|
Binary file not shown.
|
@ -99,10 +99,8 @@ read_pentair_packets = no
|
|||
# AqualinkD can only detect a SWG if it's on, so after a restart you will not see/access a SWG until the the next time the pump is on.
|
||||
force_SWG = no
|
||||
|
||||
# Button inxed light probramming button is assigned to. (look at your button labels below)
|
||||
light_programming_button_pool = 0
|
||||
light_programming_button_spa = 0
|
||||
|
||||
# Lights can be programmed by control panel or AqualinkD (if controlpanel doesn;t support specific light or light mode you want)
|
||||
# IF YOU WANT AQUALINKD TO PROGRAM THE LIGHT, IT MUST NOT BE CONFIGURED AS A COLOR LIGHT IN THE JANDY CONTROL PANEL.
|
||||
# Light probramming mode. 0=safe mode, but slow.
|
||||
# any number greater is seconds to wait between button presses.
|
||||
# 0.4 seems to be the minimum. (workd for light modes below 10 presses)
|
||||
|
@ -148,6 +146,7 @@ use_panel_aux_labels=no
|
|||
#
|
||||
# button_01_pumpIndex=1
|
||||
# If you have assigned this pump an index number in your Aqualink control panel, (Between 1 & 4), put it here for VSP, RPM, Primp information to be captured.
|
||||
#
|
||||
|
||||
# Labels for standard butons (shown in web UI), and domoticz idx's
|
||||
button_01_label=Filter Pump
|
||||
|
|
21
utils.c
21
utils.c
|
@ -351,10 +351,20 @@ void logMessage(int msg_level, char *format, ...)
|
|||
strncpy(buffer, " ", 8);
|
||||
vsprintf (&buffer[8], format, args);
|
||||
va_end(args);
|
||||
int i;
|
||||
|
||||
//test(msg_level, buffer);
|
||||
//fprintf (stderr, buffer);
|
||||
|
||||
// Make all printable chars
|
||||
for(i = 8; i < strlen(buffer); i++) {
|
||||
if ( (buffer[i] < 0 || buffer[i] > 125) && buffer[1] != 10 )
|
||||
buffer[i] = ' ';
|
||||
}
|
||||
//if ( buffer[i] != '\n' )
|
||||
// buffer[i+1] = '\n';
|
||||
|
||||
|
||||
// Logging has not been setup yet, so STD error & syslog
|
||||
if (_log_level == -1) {
|
||||
fprintf (stderr, buffer);
|
||||
|
@ -372,16 +382,18 @@ void logMessage(int msg_level, char *format, ...)
|
|||
//return;
|
||||
}
|
||||
|
||||
int len;
|
||||
//int len;
|
||||
char *strLevel = elevel2text(msg_level);
|
||||
strncpy(buffer, strLevel, strlen(strLevel));
|
||||
len = strlen(buffer);
|
||||
//len = strlen(buffer);
|
||||
/*
|
||||
if ( buffer[len-1] != '\n') {
|
||||
strcat(buffer, "\n");
|
||||
}
|
||||
*/
|
||||
|
||||
// Sent the log to the UI if configured.
|
||||
if (msg_level <= LOG_WARNING && _loq_display_message != NULL) {
|
||||
if (msg_level <= LOG_ERR && _loq_display_message != NULL) {
|
||||
snprintf(_loq_display_message, 127, buffer);
|
||||
}
|
||||
|
||||
|
@ -571,7 +583,8 @@ char* stristr(const char* haystack, const char* needle) {
|
|||
int ascii(char *destination, char *source) {
|
||||
unsigned int i;
|
||||
for(i = 0; i < strlen(source); i++) {
|
||||
if ( source[i] >= 0 && source[i] < 128 )
|
||||
//if ( source[i] >= 0 && source[i] < 128 )
|
||||
if ( source[i] >= 0 && source[i] < 127 )
|
||||
destination[i] = source[i];
|
||||
else
|
||||
destination[i] = ' ';
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
|
||||
|
||||
#define AQUALINKD_NAME "Aqualink Daemon"
|
||||
#define AQUALINKD_VERSION "2.0.0a"
|
||||
#define AQUALINKD_VERSION "2.0.0b"
|
||||
|
|
|
@ -26,11 +26,12 @@
|
|||
"Pool_Water",
|
||||
"Spa_Water",
|
||||
"Freeze_Protect",
|
||||
"CHEM/pH",
|
||||
"CHEM/ORP"
|
||||
//"Solar_Heater",
|
||||
];
|
||||
|
||||
// Add the light program names below, the name index MUST correlate to
|
||||
// the number of pulses. ie (Blue Sea is #2 or 2 pulses)
|
||||
// This get's picked up by dynamic_config.js and used as mode 0
|
||||
var light_program = [
|
||||
"Voodoo Lounge - Show",
|
||||
"Blue Sea",
|
||||
|
@ -50,6 +51,7 @@
|
|||
"Mardi Gras - Show",
|
||||
"Cool Cabaret - Show"
|
||||
];
|
||||
|
||||
/*
|
||||
* BELOW IS NOT RELIVENT FOR simple.html or simple inteface
|
||||
*
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
<link href='aqualinkd.png' rel='apple-touch-icon'>
|
||||
<link href='aqualinkd.png' rel='icon'>
|
||||
<script src='config.js'></script>
|
||||
<script src='?command=dynamic_config'></script>
|
||||
<style>
|
||||
:root {
|
||||
--fonts: 'HelveticaNeue-Light', 'Helvetica Neue Light', 'Helvetica Neue', Helvetica, Arial, 'Lucida Grande', sans-serif;
|
||||
|
@ -478,7 +479,8 @@
|
|||
//init();
|
||||
function init() {
|
||||
setSizeSpecifics();
|
||||
populateLightProgram();
|
||||
populateLightProgram(-1);
|
||||
//populateLightProgram(0);
|
||||
document.getElementById('thermostat_options').classList.remove("hide");
|
||||
document.getElementById('swg_options').classList.remove("hide");
|
||||
document.getElementById('pswitch_options').classList.remove("hide");
|
||||
|
@ -490,7 +492,9 @@
|
|||
resetBackgroundSize();
|
||||
}
|
||||
|
||||
function populateLightProgram() {
|
||||
function populateLightProgram(type=0) {
|
||||
var light_program = _light_program[type];
|
||||
|
||||
if (_lightProgramDropdown) {
|
||||
option = document.getElementById('pswitch_option_list');
|
||||
try {
|
||||
|
@ -504,20 +508,27 @@
|
|||
} catch (e) {}
|
||||
} else {
|
||||
var tbody = document.getElementById('pswitch_table').getElementsByTagName('tbody')[0];
|
||||
if (type == -1) {
|
||||
// -1 is Just init, so create another row, just to delete later.
|
||||
row = tbody.insertRow(2);
|
||||
row.innerHTML = "<td align='center'>Solid Color</td><td align='center'>Light Show</td>";
|
||||
light_program = _light_program[0]; // Use aqualinkd light modes to set size below
|
||||
}
|
||||
var html1 = '';
|
||||
var html2 = '';
|
||||
var fLen = light_program.length;
|
||||
var i;
|
||||
for (i = 0; i < fLen; i++) {
|
||||
if (light_program[i].endsWith(" - Show"))
|
||||
html2 = html2 + "<div class='option_radiocontainer'><label><span class='radio'><input type='radio' name='light_program' value='" + (i+1) + "' onchange='updatePwsitchOptions(this);'><span class='option_radio-value' aria-hidden='true'></span></span>" + light_program[i].substr(0, (light_program[i].length - 7)) + "</label></div>";
|
||||
html2 = html2 + "<div class='option_radiocontainer'><label><span class='radio'><input type='radio' name='light_program' value='" + (i+1) + "' onchange='updatePwsitchOptions(this, "+type+");'><span class='option_radio-value' aria-hidden='true'></span></span>" + light_program[i].substr(0, (light_program[i].length - 7)) + "</label></div>";
|
||||
else
|
||||
html1 = html1 + "<div class='option_radiocontainer'><label><span class='radio'><input type='radio' name='light_program' value='" + (i+1) + "' onchange='updatePwsitchOptions(this);'><span class='option_radio-value' aria-hidden='true'></span></span>" + light_program[i] + "</label></div>";
|
||||
html1 = html1 + "<div class='option_radiocontainer'><label><span class='radio'><input type='radio' name='light_program' value='" + (i+1) + "' onchange='updatePwsitchOptions(this, "+type+");'><span class='option_radio-value' aria-hidden='true'></span></span>" + light_program[i] + "</label></div>";
|
||||
}
|
||||
var row;
|
||||
row = tbody.deleteRow(2);
|
||||
row = tbody.insertRow(2);
|
||||
row.innerHTML = "<td align='center'>Solid Color</td><td align='center'>Light Show</td>";
|
||||
tbody.deleteRow(3);
|
||||
row = tbody.insertRow(3);
|
||||
row.innerHTML = "<td align='left' valign='top'>" + html1 + "</td><td align='left' valign='top'>" + html2 + "</td>";
|
||||
}
|
||||
|
@ -789,7 +800,7 @@
|
|||
if (document.getElementById(id).getAttribute('status') == 'on') {
|
||||
document.getElementById(id + '_status').innerHTML = text;
|
||||
} else {
|
||||
console.log("Tile "+id+" status is '"+document.getElementById(id).getAttribute('status')+"' not setting text to '"+text+"'");
|
||||
//console.log("Tile "+id+" status is '"+document.getElementById(id).getAttribute('status')+"' not setting text to '"+text+"'");
|
||||
}
|
||||
} catch(exception) {}
|
||||
}
|
||||
|
@ -942,7 +953,12 @@
|
|||
|
||||
add_tile(object.id, object.name, object.state, 'switch', ext_type, 'hk/' + img + '-off.png', 'hk/' + img + '-on.png');
|
||||
setTileOn(object.id, object.status, null);
|
||||
if (typeof object.type_ext !== 'undefined' && object.type_ext == 'switch_vsp') {
|
||||
if (typeof object.type_ext !== 'undefined' && object.type_ext == 'switch_program') {
|
||||
if (typeof object.Light_Type !== 'undefined') {
|
||||
document.getElementById(object.id).setAttribute('lighttype', object.Light_Type);
|
||||
}
|
||||
// Other switch_program types (other than light_type) GO HERE
|
||||
} else if (typeof object.type_ext !== 'undefined' && object.type_ext == 'switch_vsp') {
|
||||
if (typeof object.Pump_RPM !== 'undefined' && object.Pump_RPM) {
|
||||
if (object.Pump_RPM == -2) {
|
||||
setTileOnText(object.id, 'Pump Offline'); // Small txt
|
||||
|
@ -982,7 +998,6 @@
|
|||
}
|
||||
|
||||
function showTileOptions(show, id, contex) {
|
||||
console.log("showTileOptions " + show + " "+id+" "+contex);
|
||||
var active_option;
|
||||
if (show == true) {
|
||||
var wrapH = document.getElementById('wrapper').clientHeight + 'px';
|
||||
|
@ -1001,6 +1016,11 @@
|
|||
document.getElementById('thermostat_options').style.display = 'none';
|
||||
document.getElementById('pswitch_options').style.display = 'none';
|
||||
document.getElementById('vspswitch_options').style.display = 'none';
|
||||
} else if (id != null && document.getElementById(id).getAttribute('type') == 'setpoint_freeze') {
|
||||
active_option = document.getElementById('swg_options');
|
||||
document.getElementById('thermostat_options').style.display = 'none';
|
||||
document.getElementById('pswitch_options').style.display = 'none';
|
||||
document.getElementById('vspswitch_options').style.display = 'none';
|
||||
} else if (id != null && document.getElementById(id).getAttribute('type') == 'switch_vsp') {
|
||||
active_option = document.getElementById('vspswitch_options');
|
||||
document.getElementById('thermostat_options').style.display = 'none';
|
||||
|
@ -1058,17 +1078,14 @@
|
|||
close_button = document.getElementById("swg_options_close");
|
||||
ext = '°' + _temperature_units;
|
||||
} else if (type == 'switch_program') {
|
||||
//slider = document.getElementById("pswitch_option_slider_range");
|
||||
//slider_output = document.getElementById("pswitch_option_slider_text_value");
|
||||
populateLightProgram(tile.getAttribute('lighttype') );
|
||||
title = document.getElementById("pswitch_option_title");
|
||||
close_button = document.getElementById("pswitch_options_close");
|
||||
//ext = '°' + _temperature_units;
|
||||
} else if (type == 'switch_vsp') {
|
||||
slider = document.getElementById("vspoption_slider_range");
|
||||
slider_output = document.getElementById("vspoption_slider_text_value");
|
||||
title = document.getElementById("vspswitch_option_title");
|
||||
close_button = document.getElementById("vspswitch_option_close");
|
||||
//ext = '°' + _temperature_units;
|
||||
} else {
|
||||
slider = document.getElementById("option_slider_range");
|
||||
slider_output = document.getElementById("option_slider_text_value");
|
||||
|
@ -1113,7 +1130,9 @@
|
|||
ext = ' RPM';
|
||||
}
|
||||
}
|
||||
|
||||
title.innerHTML = document.getElementById(id + '_name').innerHTML;
|
||||
|
||||
if (type == 'switch_program') {
|
||||
var pswitch = document.getElementById("pswitch_option_list");
|
||||
oswitch = document.getElementById("pswitch_option_switch");
|
||||
|
@ -1126,19 +1145,24 @@
|
|||
} else if (type == 'setpoint_swg') {
|
||||
slider.value = sp_value;
|
||||
oswitch = document.getElementById("swg_option_switch");
|
||||
//oswitch.checked = tile_state;
|
||||
//console.log("Boost attribute " + getTileAttribute(id, "boost") + " for "+id);
|
||||
oswitch.checked = getTileAttribute(id, "Boost")=='on'?true:false ;
|
||||
var oswitch_output = document.getElementById("swg_option_switch_text_value");
|
||||
document.getElementById("swg_option_switch_row").style.display = "table-row";
|
||||
oswitch.checked = getTileAttribute(id, "Boost")=='on'?true:false ;
|
||||
slider_output.innerHTML = slider.value + ext;
|
||||
oswitch_output.innerHTML = ((oswitch.checked) ? "Boost On" : "Boost Off");
|
||||
slider.oninput = function() {
|
||||
slider_output.innerHTML = this.value + ext;
|
||||
//sp_value = this.value
|
||||
}
|
||||
oswitch.onclick = function() {
|
||||
oswitch_output.innerHTML = ((oswitch.checked) ? "Boost On" : "Boost Off");
|
||||
//setTileOn(id, ((oswitch.checked)?"on":"off"), null);
|
||||
}
|
||||
} else if (type == 'setpoint_freeze') {
|
||||
slider.value = sp_value;
|
||||
oswitch = document.getElementById("swg_option_switch");
|
||||
document.getElementById("swg_option_switch_row").style.display = "none";
|
||||
slider_output.innerHTML = slider.value + ext;
|
||||
slider.oninput = function() {
|
||||
slider_output.innerHTML = this.value + ext;
|
||||
}
|
||||
} else if (type == 'switch_vsp') {
|
||||
slider.value = sp_value;
|
||||
|
@ -1190,7 +1214,7 @@
|
|||
var mode=false;
|
||||
if (_lightProgramDropdown) {
|
||||
if (pswitch.selectedIndex > 0) {
|
||||
send_light_mode(pswitch.selectedIndex, id);
|
||||
send_light_mode(pswitch.selectedIndex, id, pswitch.options[pswitch.selectedIndex].text);
|
||||
mode=true;
|
||||
}
|
||||
} else {
|
||||
|
@ -1198,7 +1222,7 @@
|
|||
var x;
|
||||
for (x = 0; x < radio.length; x++) {
|
||||
if (radio[x].checked == true) {
|
||||
send_light_mode(radio[x].value, id);
|
||||
send_light_mode(radio[x].value, id, document.getElementById('pswitch_option_switch_text_value').innerHTML);
|
||||
mode=true;
|
||||
break;
|
||||
}
|
||||
|
@ -1268,6 +1292,11 @@
|
|||
setTileValue("Temperature/Air", data.air_temp);
|
||||
setTileValue("Temperature/Pool", data.pool_temp);
|
||||
setTileValue("Temperature/Spa", data.spa_temp);
|
||||
|
||||
if (typeof(data.chem_ph) !== 'undefined')
|
||||
setTileValue("CHEM/pH", data.chem_ph);
|
||||
if (typeof(data.chem_orp) !== 'undefined')
|
||||
setTileValue("CHEM/ORP", data.chem_orp);
|
||||
/*
|
||||
setTileValue("Air", data.air_temp);
|
||||
setTileValue("Pool_Water", data.pool_temp);
|
||||
|
@ -1454,13 +1483,14 @@
|
|||
socket_di.send(JSON.stringify(temperature));
|
||||
}
|
||||
|
||||
function send_light_mode(value, id) {
|
||||
console.log("Set light mode to "+value+" id="+id);
|
||||
function send_light_mode(value, id, textvalue) {
|
||||
console.log("Set light mode to "+value+" id="+id+" text="+textvalue);
|
||||
var mode = {};
|
||||
//mode.parameter = 'POOL_LIGHT_MODE';
|
||||
mode.parameter = 'LIGHT_MODE';
|
||||
mode.value = value;
|
||||
mode.button = id;
|
||||
mode.text_value = textvalue;
|
||||
socket_di.send(JSON.stringify(mode));
|
||||
}
|
||||
|
||||
|
@ -1487,9 +1517,12 @@
|
|||
}, 5000);
|
||||
}
|
||||
|
||||
function updatePwsitchOptions(source) {
|
||||
function updatePwsitchOptions(source, light_type) {
|
||||
if (source.type == 'radio') {
|
||||
document.getElementById('pswitch_option_switch_text_value').innerHTML = light_program[source.value-1];
|
||||
var modename = _light_program[light_type][source.value-1];
|
||||
if (modename.endsWith(" - Show"))
|
||||
modename = modename.substr(0, (modename.length - 7));
|
||||
document.getElementById('pswitch_option_switch_text_value').innerHTML = modename;
|
||||
document.getElementById('pswitch_option_switch').checked = true;
|
||||
} else if (source.type == 'checkbox') {
|
||||
//console.log(source);
|
||||
|
@ -1567,7 +1600,7 @@
|
|||
<th colspan='2'><span id="swg_option_title"></span>
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<tr id="swg_option_switch_row">
|
||||
<td align='right' width='50%'><span class="option_text" id='swg_option_switch_text_value'></span>
|
||||
</td>
|
||||
<td align='left' width='50%'>
|
||||
|
|
Loading…
Reference in New Issue