pull/69/head
sfeakes 2023-05-30 18:14:04 -05:00
parent 1cb3be4ede
commit 9f91af03ce
21 changed files with 385 additions and 347 deletions

View File

@ -78,15 +78,16 @@ Designed to mimic AqualinkRS6 All Button keypad and (like the keypad) is used to
* Allow selecting of pre-defined VSP programs (Aqualink Touch & OneTouch protocols.) * Allow selecting of pre-defined VSP programs (Aqualink Touch & OneTouch protocols.)
* Add set time to OneTouch protocol. * Add set time to OneTouch protocol.
# Update in Release 2.3.0d (pre release) # Update in Release 2.3.0e (pre release)
* This is pre-release, please treat it as such. * This is pre-release, please treat it as such.
* Proceed with caution on PDA panels <i>I have not been able to test it fully on all variants</i> and you may need to go back to your current (or previous) version of AqualinkD * Proceed with caution on PDA panels <i>I have not been able to test it fully on all variants</i> and you may need to go back to your current (or previous) version of AqualinkD
* Changed a lot of logic around different protocols. * Changed a lot of logic around different protocols.
* Add support for dimmers.
* AqualinkD will find out the fastest way to change something depending on the protocols available. * AqualinkD will find out the fastest way to change something depending on the protocols available.
* Added scheduler (click time in web ui). supports full calendar year (ie seasons), See wiki for details. * Added scheduler (click time in web ui). supports full calendar year (ie seasons), See wiki for details.
* Added timers for devices (ie can turn on Pump for x minutes), Long press on device in WebUI. * Added timers for devices (ie can turn on Pump for x minutes), Long press on device in WebUI.
* Timers supported in MQTT/API. * Timers supported in MQTT/API.
* Add support for dimmers.
* Extended SWG status now in web UI.
* Serial logging / error checking enhancements. * Serial logging / error checking enhancements.
* Added simulator back. (+ Improved UI). * Added simulator back. (+ Improved UI).
* Fix issue with incorrect device state after duplicate MQTT messages being sent in rapid succession ( < 0.5 second). * Fix issue with incorrect device state after duplicate MQTT messages being sent in rapid succession ( < 0.5 second).

View File

@ -109,7 +109,7 @@ setPanel("RS-8 Combo");
*/ */
char _panelString[36]; char _panelString[60];
void setPanelString() void setPanelString()
{ {
sprintf(_panelString, "%s%s-%d %s%s%s", sprintf(_panelString, "%s%s-%d %s%s%s",

View File

@ -81,8 +81,8 @@ bool waitForButtonState(struct aqualinkdata *aq_data, aqkey* button, aqledstate
bool waitForEitherMessage(struct aqualinkdata *aq_data, char* message1, char* message2, int numMessageReceived); bool waitForEitherMessage(struct aqualinkdata *aq_data, char* message1, char* message2, int numMessageReceived);
bool push_aq_cmd(unsigned char cmd); bool push_aq_cmd(unsigned char cmd);
void waitfor_queue2empty(); //void waitfor_queue2empty();
void longwaitfor_queue2empty(); //void longwaitfor_queue2empty();
void _aq_programmer(program_type r_type, char *args, struct aqualinkdata *aq_data, bool allowOveride); void _aq_programmer(program_type r_type, char *args, struct aqualinkdata *aq_data, bool allowOveride);

View File

@ -119,6 +119,9 @@ void queueGetProgramData(emulation_type source_type, struct aqualinkdata *aq_dat
//void queueGetExtendedProgramData(emulation_type source_type, struct aqualinkdata *aq_data, bool labels); //void queueGetExtendedProgramData(emulation_type source_type, struct aqualinkdata *aq_data, bool labels);
unsigned char pop_aq_cmd(struct aqualinkdata *aq_data); unsigned char pop_aq_cmd(struct aqualinkdata *aq_data);
void waitForSingleThreadOrTerminate(struct programmingThreadCtrl *threadCtrl, program_type type);
void cleanAndTerminateThread(struct programmingThreadCtrl *threadCtrl);
//void force_queue_delete() // Yes I want compiler warning if this is used. //void force_queue_delete() // Yes I want compiler warning if this is used.
@ -137,11 +140,6 @@ int RPM_check(pump_type type, int value, struct aqualinkdata *aqdata);
const char *ptypeName(program_type type); const char *ptypeName(program_type type);
const char *programtypeDisplayName(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);
bool push_aq_cmd(unsigned char cmd);
void waitForSingleThreadOrTerminate(struct programmingThreadCtrl *threadCtrl, program_type type);
void cleanAndTerminateThread(struct programmingThreadCtrl *threadCtrl);
bool waitForMessage(struct aqualinkdata *aq_data, char* message, int numMessageReceived);
#endif #endif

View File

@ -51,7 +51,10 @@ const char* get_packet_type(unsigned char* packet , int length)
switch (packet[PKT_CMD]) { switch (packet[PKT_CMD]) {
case CMD_ACK: case CMD_ACK:
if (packet[5] == NUL)
return "Ack"; return "Ack";
else
return "Ack w/ Command";
break; break;
case CMD_STATUS: case CMD_STATUS:
return "Status"; return "Status";
@ -919,7 +922,7 @@ int get_packet(int fd, unsigned char* packet)
} }
LOG(RSSD_LOG,LOG_DEBUG_SERIAL, "Serial read %d bytes\n",index); LOG(RSSD_LOG,LOG_DEBUG_SERIAL, "Serial read %d bytes\n",index);
if (_aqconfig_.log_protocol_packets) if (_aqconfig_.log_protocol_packets || getLogLevel(RSSD_LOG) >= LOG_DEBUG_SERIAL)
logPacketRead(packet, index); logPacketRead(packet, index);
// Return the packet length. // Return the packet length.
return index; return index;

View File

@ -1235,6 +1235,14 @@ int main(int argc, char *argv[])
LOG(AQUA_LOG,LOG_NOTICE, "Config light_pgm_mode = %.2f\n", _aqconfig_.light_programming_mode); LOG(AQUA_LOG,LOG_NOTICE, "Config light_pgm_mode = %.2f\n", _aqconfig_.light_programming_mode);
LOG(AQUA_LOG,LOG_NOTICE, "Debug RS485 protocol = %s\n", bool2text(_aqconfig_.log_protocol_packets)); LOG(AQUA_LOG,LOG_NOTICE, "Debug RS485 protocol = %s\n", bool2text(_aqconfig_.log_protocol_packets));
LOG(AQUA_LOG,LOG_NOTICE, "Debug RS485 protocol raw = %s\n", bool2text(_aqconfig_.log_raw_bytes)); LOG(AQUA_LOG,LOG_NOTICE, "Debug RS485 protocol raw = %s\n", bool2text(_aqconfig_.log_raw_bytes));
if ( _aqconfig_.RSSD_LOG_filter != NUL)
LOG(AQUA_LOG,LOG_NOTICE, "Log RS485 packets from = 0x%02hhx\n", _aqconfig_.RSSD_LOG_filter
);
//LOG(AQUA_LOG,LOG_NOTICE, "Use PDA 4 auxiliary info = %s\n", bool2text(_aqconfig_.use_PDA_auxiliary)); //LOG(AQUA_LOG,LOG_NOTICE, "Use PDA 4 auxiliary info = %s\n", bool2text(_aqconfig_.use_PDA_auxiliary));
//LOG(AQUA_LOG,LOG_NOTICE, "Read Pentair Packets = %s\n", bool2text(_aqconfig_.read_pentair_packets)); //LOG(AQUA_LOG,LOG_NOTICE, "Read Pentair Packets = %s\n", bool2text(_aqconfig_.read_pentair_packets));
// logMessage (LOG_NOTICE, "Config serial_port = %s\n", config_parameters->serial_port); // logMessage (LOG_NOTICE, "Config serial_port = %s\n", config_parameters->serial_port);
@ -1861,52 +1869,6 @@ void main_loop()
if (getProtocolType(packet_buffer) == JANDY) if (getProtocolType(packet_buffer) == JANDY)
{ {
_aqualink_data.updated = processJandyPacket(packet_buffer, packet_length, &_aqualink_data); _aqualink_data.updated = processJandyPacket(packet_buffer, packet_length, &_aqualink_data);
/*
// We received the ack from a Jandy device we are interested in
if (packet_buffer[PKT_DEST] == DEV_MASTER && interestedInNextAck != DRS_NONE)
{
if (interestedInNextAck == DRS_SWG)
{
_aqualink_data.updated = processPacketFromSWG(packet_buffer, packet_length, &_aqualink_data);
}
else if (interestedInNextAck == DRS_EPUMP)
{
_aqualink_data.updated = processPacketFromJandyPump(packet_buffer, packet_length, &_aqualink_data);
}
interestedInNextAck = DRS_NONE;
previous_packet_to = NUL;
}
// We were expecting an ack from Jandy device but didn't receive it.
else if (packet_buffer[PKT_DEST] != DEV_MASTER && interestedInNextAck != DRS_NONE )
{
if (interestedInNextAck == DRS_SWG && _aqualink_data.ar_swg_device_status != SWG_STATUS_OFF)
{ // SWG Offline
processMissingAckPacketFromSWG(previous_packet_to, &_aqualink_data);
}
else if (interestedInNextAck == DRS_EPUMP)
{ // ePump offline
processMissingAckPacketFromJandyPump(previous_packet_to, &_aqualink_data);
}
interestedInNextAck = DRS_NONE;
previous_packet_to = NUL;
}
else if (READ_RSDEV_SWG && packet_buffer[PKT_DEST] == SWG_DEV_ID)
{
interestedInNextAck = DRS_SWG;
_aqualink_data.updated = processPacketToSWG(packet_buffer, packet_length, &_aqualink_data, _aqconfig_.swg_zero_ignore);
previous_packet_to = packet_buffer[PKT_DEST];
}
else if (READ_RSDEV_ePUMP && packet_buffer[PKT_DEST] >= JANDY_DEC_PUMP_MIN && packet_buffer[PKT_DEST] <= JANDY_DEC_PUMP_MAX)
{
interestedInNextAck = DRS_EPUMP;
_aqualink_data.updated = processPacketToJandyPump(packet_buffer, packet_length, &_aqualink_data);
previous_packet_to = packet_buffer[PKT_DEST];
}
else
{
interestedInNextAck = DRS_NONE;
previous_packet_to = NUL;
}*/
} }
// Process Pentair Device Packed (pentair have to & from in message, so no need to) // Process Pentair Device Packed (pentair have to & from in message, so no need to)
else if (getProtocolType(packet_buffer) == PENTAIR && READ_RSDEV_vsfPUMP) { else if (getProtocolType(packet_buffer) == PENTAIR && READ_RSDEV_vsfPUMP) {

View File

@ -79,6 +79,7 @@ void init_parameters (struct aqconfig * parms)
//parms->device_id = strtoul(DEFAULT_DEVICE_ID, &p, 16); //parms->device_id = strtoul(DEFAULT_DEVICE_ID, &p, 16);
parms->device_id = strtoul(DEFAULT_DEVICE_ID, NULL, 16); parms->device_id = strtoul(DEFAULT_DEVICE_ID, NULL, 16);
parms->rssa_device_id = NUL; parms->rssa_device_id = NUL;
parms->RSSD_LOG_filter = NUL;
parms->paneltype_mask = 0; parms->paneltype_mask = 0;
#if defined AQ_ONETOUCH || defined AQ_IAQTOUCH #if defined AQ_ONETOUCH || defined AQ_IAQTOUCH
parms->extended_device_id = NUL; parms->extended_device_id = NUL;
@ -381,6 +382,9 @@ bool setConfigValue(struct aqualinkdata *aqdata, char *param, char *value) {
} else if (strncasecmp(param, "rssa_device_id", 14) == 0) { } else if (strncasecmp(param, "rssa_device_id", 14) == 0) {
_aqconfig_.rssa_device_id = strtoul(cleanalloc(value), NULL, 16); _aqconfig_.rssa_device_id = strtoul(cleanalloc(value), NULL, 16);
rtn=true; rtn=true;
} else if (strncasecmp(param, "RSSD_LOG_filter", 15) == 0) {
_aqconfig_.RSSD_LOG_filter = strtoul(cleanalloc(value), NULL, 16);
rtn=true;
#if defined AQ_ONETOUCH || defined AQ_IAQTOUCH #if defined AQ_ONETOUCH || defined AQ_IAQTOUCH
} else if (strncasecmp (param, "extended_device_id_programming", 30) == 0) { } else if (strncasecmp (param, "extended_device_id_programming", 30) == 0) {
// Has to be before the below. // Has to be before the below.

View File

@ -77,6 +77,7 @@ struct aqconfig
bool display_warnings_web; bool display_warnings_web;
bool log_protocol_packets; // Read & Write as packets bool log_protocol_packets; // Read & Write as packets
bool log_raw_bytes; // Read as bytes bool log_raw_bytes; // Read as bytes
unsigned char RSSD_LOG_filter;
//bool log_raw_RS_bytes; //bool log_raw_RS_bytes;
bool readahead_b4_write; bool readahead_b4_write;
bool mqtt_timed_update; bool mqtt_timed_update;

View File

@ -501,6 +501,9 @@ int build_aqualink_status_JSON(struct aqualinkdata *aqdata, char* buffer, int si
if ( aqdata->orp != TEMP_UNKNOWN ) if ( aqdata->orp != TEMP_UNKNOWN )
length += sprintf(buffer+length, ",\"chem_orp\":\"%d\"",aqdata->orp ); length += sprintf(buffer+length, ",\"chem_orp\":\"%d\"",aqdata->orp );
if ( READ_RSDEV_SWG )
length += sprintf(buffer+length, ",\"swg_fullstatus\": \"%d\"", aqdata->ar_swg_device_status);
length += sprintf(buffer+length, ",\"leds\":{" ); length += sprintf(buffer+length, ",\"leds\":{" );
for (i=0; i < aqdata->total_buttons; i++) for (i=0; i < aqdata->total_buttons; i++)
{ {

View File

@ -13,6 +13,7 @@ static FILE *_byteLogFile = NULL;
static bool _logfile_raw = false; static bool _logfile_raw = false;
static bool _logfile_packets = false; static bool _logfile_packets = false;
//static bool _includePentair = false; //static bool _includePentair = false;
static unsigned char _lastReadFrom = NUL;
void _logPacket(int16_t from, unsigned char *packet_buffer, int packet_length, bool error, bool force, bool is_read); void _logPacket(int16_t from, unsigned char *packet_buffer, int packet_length, bool error, bool force, bool is_read);
int _beautifyPacket(char *buff, unsigned char *packet_buffer, int packet_length, bool error, bool is_read); int _beautifyPacket(char *buff, unsigned char *packet_buffer, int packet_length, bool error, bool is_read);
@ -95,9 +96,29 @@ void debuglogPacket(int16_t from, unsigned char *packet_buffer, int packet_lengt
void _logPacket(int16_t from, unsigned char *packet_buffer, int packet_length, bool error, bool force, bool is_read) void _logPacket(int16_t from, unsigned char *packet_buffer, int packet_length, bool error, bool force, bool is_read)
{ {
// No point in continuing if loglevel is < debug_serial and not writing to file // No point in continuing if loglevel is < debug_serial and not writing to file
if ( force == false && error == false && getLogLevel(from) < LOG_DEBUG_SERIAL /*&& _logfile_raw == false*/ && _logfile_packets == false) { if ( force == false &&
error == false &&
getLogLevel(from) < LOG_DEBUG_SERIAL &&
/*_logfile_raw == false &&*/
_logfile_packets == false ) {
return; return;
} }
if ( _aqconfig_.RSSD_LOG_filter != NUL ) {
if (is_read) {
_lastReadFrom = packet_buffer[PKT_DEST];
if ( is_read && _aqconfig_.RSSD_LOG_filter != packet_buffer[PKT_DEST]) {
return;
}
} else if (!is_read && _lastReadFrom != _aqconfig_.RSSD_LOG_filter) // Must be write
return;
/*
if ( is_read && _aqconfig_.RSSD_LOG_filter != packet_buffer[PKT_DEST]) {
return;
}
*/
}
char buff[1000]; char buff[1000];
_beautifyPacket(buff, packet_buffer, packet_length, error, is_read); _beautifyPacket(buff, packet_buffer, packet_length, error, is_read);
@ -110,6 +131,8 @@ void _logPacket(int16_t from, unsigned char *packet_buffer, int packet_length, b
else { else {
if (force) if (force)
LOG(from,LOG_DEBUG, "%s", buff); LOG(from,LOG_DEBUG, "%s", buff);
//else if (is_read && _aqconfig_.serial_debug_filter != NUL && _aqconfig_.serial_debug_filter == packet_buffer[PKT_DEST])
// LOG(from,LOG_NOTICE, "%s", buff);
else else
LOG(from,LOG_DEBUG_SERIAL, "%s", buff); LOG(from,LOG_DEBUG_SERIAL, "%s", buff);
} }

266
pda.c
View File

@ -32,10 +32,6 @@
#include "devices_jandy.h" #include "devices_jandy.h"
#include "rs_msg_utils.h" #include "rs_msg_utils.h"
// This needs to be tested on a real panel.
//#define NEW_UPDATE_METHOD
// static struct aqualinkdata _aqualink_data; // static struct aqualinkdata _aqualink_data;
static struct aqualinkdata *_aqualink_data; static struct aqualinkdata *_aqualink_data;
static unsigned char _last_packet_type; static unsigned char _last_packet_type;
@ -137,31 +133,30 @@ void set_pda_led(struct aqualinkled *led, char state)
} }
} }
#ifdef NEW_UPDATE_METHOD
void equiptment_update_cycle(int eqID) { void equiptment_update_cycle(int eqID) {
// If you have a -1, it's a reset to clear / update information. // If you have a -1, it's a reset to clear / update information.
int i; int i;
static uint32_t update_equiptment_bitmask = 0; static uint32_t update_equiptment_bitmask = 0;
if (eqID == -1) { if (eqID == -1) {
LOG(PDA_LOG,LOG_DEBUG, "(not implimented) Start new equiptment cycle\n"); LOG(PDA_LOG,LOG_DEBUG, "Start new equiptment cycle\n");
for (i=0; i < _aqualink_data->total_buttons; i++) { for (i=0; i < _aqualink_data->total_buttons - 2 ; i++) { // total_buttons - 2 because we don't get heaters in this cycle
if ((update_equiptment_bitmask & (1 << (i+1))) != (1 << (i+1))) { if ((update_equiptment_bitmask & (1 << (i+1))) != (1 << (i+1))) {
if (_aqualink_data->aqbuttons[i].led->state != OFF) { if (_aqualink_data->aqbuttons[i].led->state != OFF) {
_aqualink_data->aqbuttons[i].led->state = OFF; _aqualink_data->aqbuttons[i].led->state = OFF;
_aqualink_data->updated = true; _aqualink_data->updated = true;
LOG(PDA_LOG,LOG_DEBUG, "(not implimented) Turn off equiptment id %d %s not seen in last cycle\n", i, _aqualink_data->aqbuttons[i].name); LOG(PDA_LOG,LOG_DEBUG, "Turn off equiptment id %d %s not seen in last cycle\n", i, _aqualink_data->aqbuttons[i].name);
} }
} }
} }
update_equiptment_bitmask = 0; update_equiptment_bitmask = 0;
} else { } else {
update_equiptment_bitmask |= (1 << (eqID+1)); update_equiptment_bitmask |= (1 << (eqID+1));
LOG(PDA_LOG,LOG_DEBUG, "(not implimented) Added equiptment id %d %s to updated cycle\n", eqID, _aqualink_data->aqbuttons[eqID].name); LOG(PDA_LOG,LOG_DEBUG, "Added equiptment id %d %s to updated cycle\n", eqID, _aqualink_data->aqbuttons[eqID].name);
} }
} }
#endif
void pass_pda_equiptment_status_item_OLD(char *msg) void pass_pda_equiptment_status_item_OLD(char *msg)
{ {
@ -250,10 +245,8 @@ void pass_pda_equiptment_status_item_OLD(char *msg)
{ {
if (strcasecmp(msg, _aqualink_data->aqbuttons[i].label) == 0) if (strcasecmp(msg, _aqualink_data->aqbuttons[i].label) == 0)
{ {
#ifdef NEW_UPDATE_METHOD
equiptment_update_cycle(i); equiptment_update_cycle(i);
#endif LOG(PDA_LOG,LOG_DEBUG, "Status for %s = '%.*s'\n", _aqualink_data->aqbuttons[i].label, AQ_MSGLEN, msg);
LOG(PDA_LOG,LOG_DEBUG, "*** Found Status for %s = '%.*s'\n", _aqualink_data->aqbuttons[i].label, AQ_MSGLEN, msg);
// It's on (or delayed) if it's listed here. // It's on (or delayed) if it's listed here.
if (_aqualink_data->aqbuttons[i].led->state != FLASH) if (_aqualink_data->aqbuttons[i].led->state != FLASH)
{ {
@ -419,10 +412,14 @@ void process_pda_packet_msg_long_set_time(const char *msg)
LOG(PDA_LOG,LOG_DEBUG, "process_pda_packet_msg_long_set_temp\n"); LOG(PDA_LOG,LOG_DEBUG, "process_pda_packet_msg_long_set_temp\n");
if (msg[4] == '/' && msg[7] == '/'){ if (msg[4] == '/' && msg[7] == '/'){
//DATE //DATE
rsm_strncpycut(_aqualink_data->date, msg, AQ_MSGLEN-1, AQ_MSGLEN-1); //rsm_strncpycut(_aqualink_data->date, msg, AQ_MSGLEN-1, AQ_MSGLEN-1);
strncpy(_aqualink_data->date, msg + 11, 3);
} else if (msg[6] == ':' && msg[11] == 'M') { } else if (msg[6] == ':' && msg[11] == 'M') {
// TIME // TIME
rsm_strncpycut(_aqualink_data->time, msg, AQ_MSGLEN-1, AQ_MSGLEN-1); //rsm_strncpycut(_aqualink_data->time, msg, AQ_MSGLEN-1, AQ_MSGLEN-1);
if (msg[4] == ' ')
strncpy(_aqualink_data->time, msg + 5, 6);
else
} }
*/ */
} }
@ -538,6 +535,25 @@ void process_pda_packet_msg_long_unknown(const char *msg)
} }
} }
void pda_pump_update(struct aqualinkdata *aq_data, int updated) {
const int bitmask[MAX_PUMPS] = {1,2,4,8};
static unsigned char updates = '\0';
int i;
if (updated == -1) {
for(i=0; i < MAX_PUMPS; i++) {
if ((updates & bitmask[i]) != bitmask[i]) {
aq_data->pumps[i].rpm = PUMP_OFF_RPM;
aq_data->pumps[i].gpm = PUMP_OFF_GPM;
aq_data->pumps[i].watts = PUMP_OFF_WAT;
}
}
updates = '\0';
} else if (updated >=0 && updated < MAX_PUMPS) {
updates |= bitmask[updated];
}
}
void log_pump_information() { void log_pump_information() {
int i; int i;
//bool rtn = false; //bool rtn = false;
@ -578,9 +594,10 @@ void log_pump_information() {
for (i=0; i < _aqualink_data->num_pumps; i++) { for (i=0; i < _aqualink_data->num_pumps; i++) {
if (_aqualink_data->pumps[i].pumpIndex == pump_index) { if (_aqualink_data->pumps[i].pumpIndex == pump_index) {
LOG(PDA_LOG,LOG_INFO, "PDA Pump label: %s Index: %d, ID: %d, RPM: %d, Watts: %d, GPM: %d\n",_aqualink_data->pumps[i].button->name, i ,pump_index,pump_index,rpm,watts,gpm);
//printf("**** FOUND PUMP %d at index %d *****\n",pump_index,i); //printf("**** FOUND PUMP %d at index %d *****\n",pump_index,i);
//aq_data->pumps[i].updated = true; //aq_data->pumps[i].updated = true;
//pump_update(_aqualink_data, i); pda_pump_update(_aqualink_data, i);
_aqualink_data->pumps[i].rpm = rpm; _aqualink_data->pumps[i].rpm = rpm;
_aqualink_data->pumps[i].watts = watts; _aqualink_data->pumps[i].watts = watts;
_aqualink_data->pumps[i].gpm = gpm; _aqualink_data->pumps[i].gpm = gpm;
@ -594,27 +611,19 @@ void log_pump_information() {
_aqualink_data->pumps[i].pumpType = EPUMP; _aqualink_data->pumps[i].pumpType = EPUMP;
} }
//printf ("Set Pump Type to %d\n",aq_data->pumps[i].pumpType); //printf ("Set Pump Type to %d\n",aq_data->pumps[i].pumpType);
return;
} }
} }
LOG(PDA_LOG,LOG_ERR, "PDA Could not find config for Pump %s, Index %d, RPM %d, Watts %d, GPM %d\n",m3_line,pump_index,rpm,watts,gpm);
} }
} }
void process_pda_packet_msg_long_equiptment_status(const char *msg_line, int lineindex, bool reset) void process_pda_packet_msg_long_equiptment_status(const char *msg_line, int lineindex, bool reset)
{ {
//pass_pda_equiptment_status_item(msg); LOG(PDA_LOG,LOG_DEBUG, "*** Pass Equiptment msg '%.16s'\n", msg_line);
#ifdef NEW_UPDATE_METHOD
if (reset) {
equiptment_update_cycle(-1);
LOG(PDA_LOG,LOG_DEBUG, "*************** Equiptment reset\n");
return;
}
#endif
LOG(PDA_LOG,LOG_DEBUG, "*************** Pass Equiptment msg '%.16s'\n", msg_line);
if (msg_line == NULL) { if (msg_line == NULL) {
LOG(PDA_LOG,LOG_DEBUG, "*************** Pass Equiptment msg is NULL do nothing\n"); LOG(PDA_LOG,LOG_DEBUG, "*** Pass Equiptment msg is NULL do nothing\n");
return; return;
} }
@ -643,16 +652,8 @@ void process_pda_packet_msg_long_equiptment_status(const char *msg_line, int lin
// FILTER PUMP // FILTER PUMP
// CLEANER // CLEANER
// //
// Equipment Status
// // VSP Pumps are not read here, since they are over multiple lines.
// Intelliflo VS 1
// RPM: 1700
// Watts: 367
//
//
//
//
//
// Check message for status of device // Check message for status of device
// Loop through all buttons and match the PDA text. // Loop through all buttons and match the PDA text.
@ -679,52 +680,28 @@ void process_pda_packet_msg_long_equiptment_status(const char *msg_line, int lin
//if (_aqualink_data->ar_swg_status == SWG_STATUS_OFF) {_aqualink_data->ar_swg_status = SWG_STATUS_ON;} //if (_aqualink_data->ar_swg_status == SWG_STATUS_OFF) {_aqualink_data->ar_swg_status = SWG_STATUS_ON;}
LOG(PDA_LOG,LOG_DEBUG, "SALT = %d\n", _aqualink_data->swg_ppm); LOG(PDA_LOG,LOG_DEBUG, "SALT = %d\n", _aqualink_data->swg_ppm);
} }
else if ((index = rsm_strnstr(msg, MSG_PMP_RPM, AQ_MSGLEN)) != NULL)
{ // Default to pump 0, should check for correct pump
_aqualink_data->pumps[0].rpm = atoi(index + strlen(MSG_PMP_RPM));
LOG(PDA_LOG,LOG_DEBUG, "RPM = %d\n", _aqualink_data->pumps[0].rpm);
log_pump_information();
}
else if ((index = rsm_strnstr(msg, MSG_PMP_WAT, AQ_MSGLEN)) != NULL)
{ // Default to pump 0, should check for correct pump
_aqualink_data->pumps[0].watts = atoi(index + strlen(MSG_PMP_WAT));
LOG(PDA_LOG,LOG_DEBUG, "Watts = %d\n", _aqualink_data->pumps[0].watts);
log_pump_information();
}
else if ((index = rsm_strnstr(msg, MSG_PMP_GPM, AQ_MSGLEN)) != NULL)
{ // Default to pump 0, should check for correct pump
_aqualink_data->pumps[0].gpm = atoi(index + strlen(MSG_PMP_GPM));
LOG(PDA_LOG,LOG_DEBUG, "GPM = %d\n", _aqualink_data->pumps[0].gpm);
log_pump_information();
}
else if ((index = rsm_strnstr(msg, "(Offline)", AQ_MSGLEN)) != NULL)
{ // Default to pump 0, should check for correct pump
//_aqualink_data->pumps[0].gpm = atoi(index + strlen(MSG_PMP_GPM));
LOG(PDA_LOG,LOG_DEBUG, "Pump offline\n");
log_pump_information();
}
else if (rsm_strncmp(msg_line, "POOL HEAT ENA",AQ_MSGLEN) == 0) else if (rsm_strncmp(msg_line, "POOL HEAT ENA",AQ_MSGLEN) == 0)
{ {
_aqualink_data->aqbuttons[_aqualink_data->pool_heater_index].led->state = ENABLE; _aqualink_data->aqbuttons[_aqualink_data->pool_heater_index].led->state = ENABLE;
LOG(PDA_LOG,LOG_DEBUG, "Pool Hearter is enabled\n"); LOG(PDA_LOG,LOG_DEBUG, "Pool Hearter is enabled\n");
//equiptment_update_cycle(_aqualink_data->pool_heater_index);
} }
else if (rsm_strncmp(msg_line, "SPA HEAT ENA",AQ_MSGLEN) == 0) else if (rsm_strncmp(msg_line, "SPA HEAT ENA",AQ_MSGLEN) == 0)
{ {
_aqualink_data->aqbuttons[_aqualink_data->spa_heater_index].led->state = ENABLE; _aqualink_data->aqbuttons[_aqualink_data->spa_heater_index].led->state = ENABLE;
LOG(PDA_LOG,LOG_DEBUG, "Pool Hearter is enabled\n"); LOG(PDA_LOG,LOG_DEBUG, "Spa Hearter is enabled\n");
//equiptment_update_cycle(_aqualink_data->spa_heater_index);
} }
else else
{ {
for (i = 0; i < _aqualink_data->total_buttons; i++) for (i = 0; i < _aqualink_data->total_buttons; i++)
{ {
//LOG(PDA_LOG,LOG_DEBUG, "*** check msg '%s' against '%s'\n",labelBuff,_aqualink_data->aqbuttons[i].label); //LOG(PDA_LOG,LOG_DEBUG, "*** check msg '%s' against '%s'\n",labelBuff,_aqualink_data->aqbuttons[i].label);
LOG(PDA_LOG,LOG_DEBUG, "*** check msg '%.*s' against '%s'\n",AQ_MSGLEN,msg_line,_aqualink_data->aqbuttons[i].label); //LOG(PDA_LOG,LOG_DEBUG, "*** check msg '%.*s' against '%s'\n",AQ_MSGLEN,msg_line,_aqualink_data->aqbuttons[i].label);
if (rsm_strncmp(msg_line, _aqualink_data->aqbuttons[i].label, AQ_MSGLEN-1) == 0) if (rsm_strncmp(msg_line, _aqualink_data->aqbuttons[i].label, AQ_MSGLEN-1) == 0)
//if (rsm_strcmp(_aqualink_data->aqbuttons[i].label, labelBuff) == 0) //if (rsm_strcmp(_aqualink_data->aqbuttons[i].label, labelBuff) == 0)
{ {
#ifdef NEW_UPDATE_METHOD
equiptment_update_cycle(i); equiptment_update_cycle(i);
#endif
LOG(PDA_LOG,LOG_DEBUG, "Found Status for %s = '%.*s'\n", _aqualink_data->aqbuttons[i].label, AQ_MSGLEN, msg_line); LOG(PDA_LOG,LOG_DEBUG, "Found Status for %s = '%.*s'\n", _aqualink_data->aqbuttons[i].label, AQ_MSGLEN, msg_line);
// It's on (or delayed) if it's listed here. // It's on (or delayed) if it's listed here.
if (_aqualink_data->aqbuttons[i].led->state != FLASH) if (_aqualink_data->aqbuttons[i].led->state != FLASH)
@ -808,138 +785,73 @@ bool process_pda_packet(unsigned char *packet, int length)
//int i; //int i;
char *msg; char *msg;
int index = -1; int index = -1;
static bool equiptment_updated = false; static bool equiptment_update_loop = false;
//static bool init = false; static bool read_equiptment_menu = false;
if (getLogLevel(PDA_LOG) == LOG_DEBUG) {
char buff[1024];
beautifyPacket(buff, packet, length, true);
LOG(PDA_LOG,LOG_DEBUG, "%s", buff);
}
/* process_pda_menu_packet(packet, length, in_programming_mode(_aqualink_data));
// Some panels don't give the startup messages we used to key the init sequence, so check here
// need to put this in a better spot some time in the future
if (_initWithRS == false && pda_m_type() == PM_FW_VERSION && packet[PKT_CMD] == CMD_PDA_CLEAR ) {
_initWithRS == true;
queueGetProgramData(AQUAPDA, _aqualink_data);
}
*/
process_pda_menu_packet(packet, length);
// NSF.
//_aqualink_data->last_msg_was_status = false;
// debugPacketPrint(0x00, packet, length);
switch (packet[PKT_CMD]) switch (packet[PKT_CMD])
{ {
case CMD_ACK: case CMD_ACK:
LOG(PDA_LOG,LOG_DEBUG, "RS Received ACK length %d.\n", length); LOG(PDA_LOG,LOG_DEBUG, "RS Received ACK length %d.\n", length);
//if (init == false) break;
/*
if (_initWithRS == false) case CMD_PDA_CLEAR:
{ read_equiptment_menu = false; // Reset the have read menu flag, since this is new menu.
LOG(PDA_LOG,LOG_DEBUG, "Running PDA_INIT\n");
aq_programmer(AQ_PDA_INIT, NULL, _aqualink_data);
//init = true;
}*/
break; break;
case CMD_STATUS: case CMD_STATUS:
_aqualink_data->last_display_message[0] = '\0'; _aqualink_data->last_display_message[0] = '\0';
if (equiptment_updated == true && pda_m_type() != PM_EQUIPTMENT_STATUS) if (equiptment_update_loop == false && pda_m_type() == PM_EQUIPTMENT_STATUS)
{
LOG(PDA_LOG,LOG_DEBUG, "**** PDA Start new Equiptment loop ****\n");
equiptment_update_loop = true;
// Need to process the equiptment full MENU here
}
else if (read_equiptment_menu == false && equiptment_update_loop == true && pda_m_type() == PM_EQUIPTMENT_STATUS)
{
LOG(PDA_LOG,LOG_DEBUG, "**** PDA read Equiptment page ****\n");
log_pump_information();
read_equiptment_menu = true;
}
else if (equiptment_update_loop == true && pda_m_type() != PM_EQUIPTMENT_STATUS)
{
LOG(PDA_LOG,LOG_DEBUG, "**** PDA End Equiptment loop ****\n");
// Moved onto different MENU. Probably need to update any pump changes
equiptment_update_loop = false;
// End of equiptment status chain of menus, reset any pump or equiptment that wasn't listed in menus as long as we are not in programming mode
if (!in_programming_mode(_aqualink_data) ) {
pda_pump_update(_aqualink_data, -1);
equiptment_update_cycle(-1);
}
}
else if (_initWithRS == false && pda_m_type() == PM_FW_VERSION)
{ {
process_pda_packet_msg_long_equiptment_status(NULL, 0, true);
equiptment_updated = false;
} else if (_initWithRS == false && pda_m_type() == PM_FW_VERSION) {
_initWithRS = true; _initWithRS = true;
LOG(PDA_LOG,LOG_DEBUG, "**** PDA INIT ****\n"); LOG(PDA_LOG,LOG_DEBUG, "**** PDA INIT ****\n");
//aq_programmer(AQ_PDA_INIT, NULL, _aqualink_data); //printf("**** PDA INIT PUT BACK IN ****\n");
queueGetProgramData(AQUAPDA, _aqualink_data); queueGetProgramData(AQUAPDA, _aqualink_data);
} }
/*
// If we get a status packet, and we are on the status menu, this is a list of what's on
// or pending so unless flash turn everything off, and just turn on items that are listed.
// This is the only way to update a device that's been turned off by a real PDA / keypad.
// Note: if the last line of the status menu is present it may be cut off
if (pda_m_type() == PM_EQUIPTMENT_STATUS)
{
if (_aqualink_data->frz_protect_state == ON)
_aqualink_data->frz_protect_state = ENABLE;
//if (_aqualink_data->ar_swg_status == SWG_STATUS_ON)
// _aqualink_data->ar_swg_status = SWG_STATUS_OFF;
if (_aqualink_data->swg_led_state == ON)
setSWGenabled(_aqualink_data);
// Need to remove this when new way works.
#ifndef NEW_UPDATE_METHOD
if (pda_m_line(PDA_LINES - 1)[0] == '\0')
{
for (i = 0; i < _aqualink_data->total_buttons; i++)
{
if (_aqualink_data->aqbuttons[i].led->state != FLASH)
{
_aqualink_data->aqbuttons[i].led->state = OFF;
}
}
}
else
{
LOG(PDA_LOG,LOG_DEBUG, "PDA Equipment status may be truncated.\n");
}
for (i = 1; i < PDA_LINES; i++)
pass_pda_equiptment_status_item(pda_m_line(i));
#else
if (!equiptment_updated) {
equiptment_updated = true;
for (i = 1; i < PDA_LINES; i++) {
pass_pda_equiptment_status_item(pda_m_line(i));
}
}
#endif
}
if (pda_m_type() == PM_FREEZE_PROTECT_DEVICES)
{
process_pda_freeze_protect_devices();
}*/
break; break;
case CMD_MSG_LONG:
{
//printf ("*******************************************************************************************\n");
//printf ("menu type %d\n",pda_m_type());
case CMD_MSG_LONG:
msg = (char *)packet + PKT_DATA + 1; msg = (char *)packet + PKT_DATA + 1;
index = packet[PKT_DATA] & 0xF; index = packet[PKT_DATA] & 0xF;
//strcpy(_aqualink_data->last_message, msg);
if (packet[PKT_DATA] == 0x82) if (packet[PKT_DATA] == 0x82)
{ // Air & Water temp is always this ID { // Air & Water temp is always this ID
process_pda_packet_msg_long_temp(msg); process_pda_packet_msg_long_temp(msg);
#ifdef NEW_UPDATE_METHOD
// if (!equiptment_updated) {
// equiptment_update_cycle(-1); // Reset equiptment cycle
// equiptment_updated = false;
// }
#endif
} }
else if (packet[PKT_DATA] == 0x40) else if (packet[PKT_DATA] == 0x40)
{ // Time is always on this ID { // Time is always on this ID
process_pda_packet_msg_long_time(msg); process_pda_packet_msg_long_time(msg);
// If it wasn't a specific msg, (above) then run through and see what kind
// of message it is depending on the PDA menu. Note don't process EQUIPTMENT
// STATUS menu here, wait until a CMD_STATUS is received.
} }
else { else
switch (pda_m_type()) { {
switch (pda_m_type())
{
case PM_EQUIPTMENT_CONTROL: case PM_EQUIPTMENT_CONTROL:
process_pda_packet_msg_long_equipment_control(msg); process_pda_packet_msg_long_equipment_control(msg);
break; break;
@ -949,7 +861,6 @@ bool process_pda_packet(unsigned char *packet, int length)
break; break;
case PM_EQUIPTMENT_STATUS: case PM_EQUIPTMENT_STATUS:
process_pda_packet_msg_long_equiptment_status(msg, index, false); process_pda_packet_msg_long_equiptment_status(msg, index, false);
equiptment_updated = true;
break; break;
case PM_SET_TEMP: case PM_SET_TEMP:
process_pda_packet_msg_long_set_temp(msg); process_pda_packet_msg_long_set_temp(msg);
@ -969,11 +880,9 @@ bool process_pda_packet(unsigned char *packet, int length)
case PM_AUX_LABEL_DEVICE: case PM_AUX_LABEL_DEVICE:
process_pda_packet_msg_long_level_aux_device(msg); process_pda_packet_msg_long_level_aux_device(msg);
break; break;
case PM_SET_TIME: case PM_SET_TIME:
process_pda_packet_msg_long_set_time(msg); process_pda_packet_msg_long_set_time(msg);
break; break;
//case PM_FW_VERSION: //case PM_FW_VERSION:
// process_pda_packet_msg_long_FW_version(msg); // process_pda_packet_msg_long_FW_version(msg);
//break; //break;
@ -983,13 +892,9 @@ bool process_pda_packet(unsigned char *packet, int length)
break; break;
} }
} }
// printf("** Line index='%d' Highligh='%s' Message='%.*s'\n",pda_m_hlightindex(), pda_m_hlight(), AQ_MSGLEN, msg);
LOG(PDA_LOG,LOG_INFO, "PDA Menu '%d' Selectedline '%s', Last line received '%.*s'\n", pda_m_type(), pda_m_hlight(), AQ_MSGLEN, msg);
break; break;
}
case CMD_PDA_0x1B: case CMD_PDA_0x1B:
{
LOG(PDA_LOG,LOG_DEBUG, "**** CMD_PDA_0x1B ****\n"); LOG(PDA_LOG,LOG_DEBUG, "**** CMD_PDA_0x1B ****\n");
// We get two of these on startup, one with 0x00 another with 0x01 at index 4. Just act on one. // We get two of these on startup, one with 0x00 another with 0x01 at index 4. Just act on one.
// Think this is PDA finishd showing startup screen // Think this is PDA finishd showing startup screen
@ -1011,7 +916,6 @@ bool process_pda_packet(unsigned char *packet, int length)
aq_programmer(AQ_PDA_WAKE_INIT, NULL, _aqualink_data); aq_programmer(AQ_PDA_WAKE_INIT, NULL, _aqualink_data);
} }
} }
}
break; break;
} }
@ -1023,7 +927,13 @@ bool process_pda_packet(unsigned char *packet, int length)
kick_aq_program_thread(_aqualink_data, AQUAPDA); kick_aq_program_thread(_aqualink_data, AQUAPDA);
} }
// HERE AS A TEST. NEED TO FULLY TEST THIS IS GOES TO PROD.
else if (packet[PKT_CMD] == CMD_STATUS)
{
kick_aq_program_thread(_aqualink_data, AQUAPDA);
}
return rtn; return rtn;
} }

View File

@ -33,6 +33,7 @@
#include "pda_aq_programmer.h" #include "pda_aq_programmer.h"
#include "config.h" #include "config.h"
#include "aq_panel.h" #include "aq_panel.h"
#include "rs_msg_utils.h"
#ifdef AQ_DEBUG #ifdef AQ_DEBUG
@ -123,7 +124,8 @@ bool wait_pda_selected_item(struct aqualinkdata *aq_data)
} }
bool waitForPDAnextMenu(struct aqualinkdata *aq_data) { bool waitForPDAnextMenu(struct aqualinkdata *aq_data) {
waitForPDAMessageType(aq_data,CMD_PDA_CLEAR,10); if (!waitForPDAMessageType(aq_data,CMD_PDA_CLEAR,10))
return false;
return waitForPDAMessageTypes(aq_data,CMD_PDA_HIGHLIGHT,CMD_PDA_HIGHLIGHTCHARS,15); return waitForPDAMessageTypes(aq_data,CMD_PDA_HIGHLIGHT,CMD_PDA_HIGHLIGHTCHARS,15);
} }
@ -250,10 +252,12 @@ bool find_pda_menu_item(struct aqualinkdata *aq_data, char *menuText, int charli
if ((min_index != -1) && ((index - i) > (i - min_index + max_index - index + 1))) { if ((min_index != -1) && ((index - i) > (i - min_index + max_index - index + 1))) {
cnt = i - min_index + max_index - index + 1; cnt = i - min_index + max_index - index + 1;
for (i=0; i < cnt; i++) { for (i=0; i < cnt; i++) {
waitfor_queue2empty();
send_cmd(KEY_PDA_UP); send_cmd(KEY_PDA_UP);
} }
} else { } else {
for (i=pda_m_hlightindex(); i < index; i++) { for (i=pda_m_hlightindex(); i < index; i++) {
waitfor_queue2empty();
send_cmd(KEY_PDA_DOWN); send_cmd(KEY_PDA_DOWN);
} }
} }
@ -261,10 +265,12 @@ bool find_pda_menu_item(struct aqualinkdata *aq_data, char *menuText, int charli
if ((min_index != -1) && ((i - index) > (index - min_index + max_index - i + 1))) { if ((min_index != -1) && ((i - index) > (index - min_index + max_index - i + 1))) {
cnt = i - min_index + max_index - index + 1; cnt = i - min_index + max_index - index + 1;
for (i=0; i < cnt; i++) { for (i=0; i < cnt; i++) {
waitfor_queue2empty();
send_cmd(KEY_PDA_UP); send_cmd(KEY_PDA_UP);
} }
} else { } else {
for (i=pda_m_hlightindex(); i > index; i--) { for (i=pda_m_hlightindex(); i > index; i--) {
waitfor_queue2empty();
send_cmd(KEY_PDA_UP); send_cmd(KEY_PDA_UP);
} }
} }
@ -291,7 +297,7 @@ bool _select_pda_menu_item(struct aqualinkdata *aq_data, char *menuText, bool wa
LOG(PDA_LOG,LOG_DEBUG, "PDA Device programmer selected menu item '%s'\n",menuText); LOG(PDA_LOG,LOG_DEBUG, "PDA Device programmer selected menu item '%s'\n",menuText);
if (waitForNextMenu) if (waitForNextMenu)
waitForPDAnextMenu(aq_data); return waitForPDAnextMenu(aq_data);
return true; return true;
} }
@ -306,6 +312,7 @@ bool _select_pda_menu_item(struct aqualinkdata *aq_data, char *menuText, bool wa
// https://www.jandy.com/-/media/zodiac/global/downloads/h/h0574200.pdf // https://www.jandy.com/-/media/zodiac/global/downloads/h/h0574200.pdf
// and 6594 - AquaLink RS Control Panel Installation Manual // and 6594 - AquaLink RS Control Panel Installation Manual
// https://www.jandy.com/-/media/zodiac/global/downloads/0748-91071/6594.pdf // https://www.jandy.com/-/media/zodiac/global/downloads/0748-91071/6594.pdf
bool goto_pda_menu(struct aqualinkdata *aq_data, pda_menu_type menu) { bool goto_pda_menu(struct aqualinkdata *aq_data, pda_menu_type menu) {
bool ret = true; bool ret = true;
int cnt = 0; int cnt = 0;
@ -600,8 +607,10 @@ void *set_aqualink_PDA_init( void *ptr )
//printf("****** Version '%s' ********\n",aq_data->version); //printf("****** Version '%s' ********\n",aq_data->version);
LOG(PDA_LOG,LOG_DEBUG, "PDA type=%d, version=%s\n", _PDA_Type, aq_data->version); LOG(PDA_LOG,LOG_DEBUG, "PDA type=%d, version=%s\n", _PDA_Type, aq_data->version);
// don't wait for version menu to time out press back to get to home menu faster // don't wait for version menu to time out press back to get to home menu faster
send_cmd(KEY_PDA_BACK); //send_cmd(KEY_PDA_BACK);
if (! waitForPDAnextMenu(aq_data)) { //if (! waitForPDAnextMenu(aq_data)) { // waitForPDAnextMenu waits for highlight chars, which we don't get on normal menu
if (! waitForPDAMessageType(aq_data,CMD_PDA_CLEAR,10)) {
LOG(PDA_LOG,LOG_ERR, "PDA Init :- wait for next menu failed\n"); LOG(PDA_LOG,LOG_ERR, "PDA Init :- wait for next menu failed\n");
} }
} }
@ -626,6 +635,8 @@ void *set_aqualink_PDA_init( void *ptr )
pda_reset_sleep(); pda_reset_sleep();
goto_pda_menu(aq_data, PM_HOME);
cleanAndTerminateThread(threadCtrl); cleanAndTerminateThread(threadCtrl);
// just stop compiler error, ptr is not valid as it's just been freed // just stop compiler error, ptr is not valid as it's just been freed
@ -677,9 +688,13 @@ bool get_PDA_freeze_protect_temp(struct aqualinkdata *aq_data) {
bool get_PDA_aqualink_pool_spa_heater_temps(struct aqualinkdata *aq_data) { bool get_PDA_aqualink_pool_spa_heater_temps(struct aqualinkdata *aq_data) {
// Get heater setpoints // Get heater setpoints
if (! goto_pda_menu(aq_data, PM_SET_TEMP)) {
LOG(PDA_LOG,LOG_ERR, "Could not get heater setpoints, trying again!\n");
// Going to try this twice.
if (! goto_pda_menu(aq_data, PM_SET_TEMP)) { if (! goto_pda_menu(aq_data, PM_SET_TEMP)) {
return false; return false;
} }
}
return true; return true;
} }
@ -715,13 +730,17 @@ bool waitForPDAMessageHighlight(struct aqualinkdata *aq_data, int highlighIndex,
} }
bool waitForPDAMessageType(struct aqualinkdata *aq_data, unsigned char mtype, int numMessageReceived) bool _waitForPDAMessageType(struct aqualinkdata *aq_data, unsigned char mtype, int numMessageReceived, bool forceNext)
{ {
LOG(PDA_LOG,LOG_DEBUG, "waitForPDAMessageType 0x%02hhx\n",mtype); LOG(PDA_LOG,LOG_DEBUG, "waitForPDAMessageType 0x%02hhx\n",mtype);
int i=0; int i=0;
pthread_mutex_lock(&aq_data->active_thread.thread_mutex); pthread_mutex_lock(&aq_data->active_thread.thread_mutex);
if (forceNext) { // Ignore current message type, and wait for next
pthread_cond_wait(&aq_data->active_thread.thread_cond, &aq_data->active_thread.thread_mutex);
}
while( ++i <= numMessageReceived) while( ++i <= numMessageReceived)
{ {
LOG(PDA_LOG,LOG_DEBUG, "waitForPDAMessageType 0x%02hhx, last message type was 0x%02hhx (%d of %d)\n",mtype,aq_data->last_packet_type,i,numMessageReceived); LOG(PDA_LOG,LOG_DEBUG, "waitForPDAMessageType 0x%02hhx, last message type was 0x%02hhx (%d of %d)\n",mtype,aq_data->last_packet_type,i,numMessageReceived);
@ -743,6 +762,16 @@ bool waitForPDAMessageType(struct aqualinkdata *aq_data, unsigned char mtype, in
return true; return true;
} }
bool waitForPDAMessageType(struct aqualinkdata *aq_data, unsigned char mtype, int numMessageReceived){
return _waitForPDAMessageType(aq_data, mtype, numMessageReceived, false);
}
bool waitForPDANextMessageType(struct aqualinkdata *aq_data, unsigned char mtype, int numMessageReceived){
return _waitForPDAMessageType(aq_data, mtype, numMessageReceived, true);
}
// Wait for Message, hit return on particular menu. // Wait for Message, hit return on particular menu.
bool waitForPDAMessageTypesOrMenu(struct aqualinkdata *aq_data, unsigned char mtype1, unsigned char mtype2, int numMessageReceived, char *text, int line) bool waitForPDAMessageTypesOrMenu(struct aqualinkdata *aq_data, unsigned char mtype1, unsigned char mtype2, int numMessageReceived, char *text, int line)
{ {
@ -785,6 +814,10 @@ bool waitForPDAMessageTypes(struct aqualinkdata *aq_data, unsigned char mtype1,
return waitForPDAMessageTypesOrMenu(aq_data, mtype1, mtype2, numMessageReceived, NULL, 0); return waitForPDAMessageTypesOrMenu(aq_data, mtype1, mtype2, numMessageReceived, NULL, 0);
} }
/*
Use -1 for cur_val if you want this to find the delected value and change it.
Use number for cur_val to increase / decrease from known start point
*/
bool set_PDA_numeric_field_value(struct aqualinkdata *aq_data, int val, int cur_val, char *select_label, int step) { bool set_PDA_numeric_field_value(struct aqualinkdata *aq_data, int val, int cur_val, char *select_label, int step) {
int i=0; int i=0;
@ -792,19 +825,43 @@ bool set_PDA_numeric_field_value(struct aqualinkdata *aq_data, int val, int cur_
// :TODO: Should probably change below to call find_pda_menu_item(), rather than doing it here // :TODO: Should probably change below to call find_pda_menu_item(), rather than doing it here
// If we lease this, need to limit on the number of loops // If we lease this, need to limit on the number of loops
//while ( strncasecmp(pda_m_hlight(), select_label, 8) != 0 ) { //while ( strncasecmp(pda_m_hlight(), select_label, 8) != 0 ) {
while ( strncasecmp(pda_m_hlight(), select_label, strlen(select_label)) != 0 ) { //while ( strncasecmp(pda_m_hlight(), select_label, strlen(select_label)) != 0 ) {
while ( rsm_strncmp(pda_m_hlight(), select_label, strlen(select_label)) != 0 ) {
LOG(PDA_LOG,LOG_DEBUG, "Numeric selector selecting '%s' current selection '%s'\n", select_label, pda_m_hlight());
send_cmd(KEY_PDA_DOWN); send_cmd(KEY_PDA_DOWN);
delay(500); // Last message probably was CMD_PDA_HIGHLIGHT, so wait before checking. //delay(500); // Last message probably was CMD_PDA_HIGHLIGHT, so wait before checking.
waitForPDAMessageType(aq_data,CMD_PDA_HIGHLIGHT,2); waitfor_queue2empty();
waitForPDAMessageType(aq_data,CMD_PDA_HIGHLIGHT,5);
if (i > 10) { if (i > 10) {
LOG(PDA_LOG,LOG_ERR, "Numeric selector could not find string '%s'\n", select_label); LOG(PDA_LOG,LOG_ERR, "Numeric selector could not find string '%s'\n", select_label);
return false; return false;
} }
i++; i++;
} }
LOG(PDA_LOG,LOG_DEBUG, "Numeric selector, selecting '%s'\n", pda_m_hlight());
send_cmd(KEY_PDA_SELECT); send_cmd(KEY_PDA_SELECT);
} }
if (cur_val == -1) {
char *hghlight_chars;
int hlight_length=0;
int i=0;
//hghlight_chars = pda_m_hlightchars(&hlight_length);
while (hlight_length >= 15 || hlight_length <= 0) {
delay(500);
waitForPDANextMessageType(aq_data,CMD_PDA_HIGHLIGHTCHARS,5);
hghlight_chars = pda_m_hlightchars(&hlight_length);
LOG(PDA_LOG,LOG_DEBUG, "Numeric selector, highlight chars '%.*s'\n",hlight_length , hghlight_chars);
if (++i >= 20) {
LOG(PDA_LOG,LOG_ERR, "Numeric selector, didn't find highlight chars, current selection is '%.*s'\n",hlight_length , hghlight_chars);
return false;
}
}
cur_val = atoi(hghlight_chars);
LOG(PDA_LOG,LOG_DEBUG, "Numeric selector, highlight chars '%.*s', numeric value using %d\n",hlight_length , hghlight_chars, cur_val);
}
if (val < cur_val) { if (val < cur_val) {
LOG(PDA_LOG,LOG_DEBUG, "Numeric selector %s value : lower from %d to %d\n", select_label, cur_val, val); LOG(PDA_LOG,LOG_DEBUG, "Numeric selector %s value : lower from %d to %d\n", select_label, cur_val, val);
for (i = cur_val; i > val; i=i-step) { for (i = cur_val; i > val; i=i-step) {
@ -816,7 +873,7 @@ bool set_PDA_numeric_field_value(struct aqualinkdata *aq_data, int val, int cur_
send_cmd(KEY_PDA_UP); send_cmd(KEY_PDA_UP);
} }
} else { } else {
LOG(PDA_LOG,LOG_INFO, "Numeric selector %s value : already at %d\n", select_label, val); LOG(PDA_LOG,LOG_DEBUG, "Numeric selector %s value : already at %d\n", select_label, val);
} }
send_cmd(KEY_PDA_SELECT); send_cmd(KEY_PDA_SELECT);
@ -829,12 +886,15 @@ bool set_PDA_aqualink_SWG_setpoint(struct aqualinkdata *aq_data, int val) {
if (! goto_pda_menu(aq_data, PM_AQUAPURE)) { if (! goto_pda_menu(aq_data, PM_AQUAPURE)) {
LOG(PDA_LOG,LOG_ERR, "Error finding SWG setpoints menu\n"); LOG(PDA_LOG,LOG_ERR, "Error finding SWG setpoints menu\n");
return false;
} }
if (aq_data->aqbuttons[SPA_INDEX].led->state != OFF) if (aq_data->aqbuttons[SPA_INDEX].led->state != OFF) {
return set_PDA_numeric_field_value(aq_data, val, aq_data->swg_percent, "SET SPA", 5); //int cur_val = atoi
else return set_PDA_numeric_field_value(aq_data, val, -1, "SET SPA", 5);
return set_PDA_numeric_field_value(aq_data, val, aq_data->swg_percent, "SET POOL", 5); } else {
return set_PDA_numeric_field_value(aq_data, val, -1, "SET POOL", 5);
}
//return true; //return true;
} }

View File

@ -24,6 +24,14 @@ bool get_PDA_aqualink_aux_labels(struct aqualinkdata *aq_data);
bool set_PDA_aqualink_boost(struct aqualinkdata *aq_data, bool val); bool set_PDA_aqualink_boost(struct aqualinkdata *aq_data, bool val);
bool set_PDA_aqualink_time(struct aqualinkdata *aq_data); bool set_PDA_aqualink_time(struct aqualinkdata *aq_data);
// These are from aq_programmer.c , exposed here for PDA AQ PROGRAMMER
void send_cmd(unsigned char cmd);
bool push_aq_cmd(unsigned char cmd);
bool waitForMessage(struct aqualinkdata *aq_data, char* message, int numMessageReceived);
void waitfor_queue2empty();
void longwaitfor_queue2empty();
//void pda_programming_thread_check(struct aqualinkdata *aq_data); //void pda_programming_thread_check(struct aqualinkdata *aq_data);
#endif // AQ_PDA_PROGRAMMER_H_ #endif // AQ_PDA_PROGRAMMER_H_

View File

@ -44,7 +44,7 @@ void print_menu()
} }
if (_hlightcharindexstart > -1) { if (_hlightcharindexstart > -1) {
LOG(PDA_LOG,LOG_DEBUG, "PDA Menu highlighted characters numer=%d start=%d end=%d actual='%.*s'\n",(_hlightcharindexstop-_hlightcharindexstart),_hlightcharindexstart,_hlightcharindexstop,(_hlightcharindexstop-_hlightcharindexstart),&_menu[_hlightindex][_hlightcharindexstart+1]); LOG(PDA_LOG,LOG_DEBUG, "PDA Menu highlighted characters line#=%d numer=%d start=%d end=%d actual='%.*s'\n",_hlightindex,(_hlightcharindexstop-_hlightcharindexstart),_hlightcharindexstart,_hlightcharindexstop,(_hlightcharindexstop-_hlightcharindexstart),&_menu[_hlightindex][_hlightcharindexstart+1]);
} }
} }
@ -69,7 +69,11 @@ char *pda_m_line(int index)
char *pda_m_hlightchars(int *len) char *pda_m_hlightchars(int *len)
{ {
*len = _hlightcharindexstop - _hlightcharindexstart + 1; if (_hlightindex <= -1) {
*len = 0;
return NULL;
}
*len = _hlightcharindexstop - _hlightcharindexstart;
return &_menu[_hlightindex][_hlightcharindexstart]; return &_menu[_hlightindex][_hlightcharindexstart];
} }
@ -196,7 +200,7 @@ Line 0 = EQUIPMENT
(Line 0 is first. Highlight when complete) (Line 0 is first. Highlight when complete)
*/ */
bool process_pda_menu_packet(unsigned char* packet, int length) bool process_pda_menu_packet(unsigned char* packet, int length, bool force_print_menu)
{ {
bool rtn = true; bool rtn = true;
signed char first_line; signed char first_line;
@ -204,6 +208,7 @@ bool process_pda_menu_packet(unsigned char* packet, int length)
signed char line_shift; signed char line_shift;
signed char i; signed char i;
int index = 0; int index = 0;
static bool printed_page = false;
switch (packet[PKT_CMD]) { switch (packet[PKT_CMD]) {
@ -212,6 +217,13 @@ bool process_pda_menu_packet(unsigned char* packet, int length)
_hlightcharindexstart = -1; _hlightcharindexstart = -1;
_hlightcharindexstop = -1; _hlightcharindexstop = -1;
memset(_menu, 0, PDA_LINES * (AQ_MSGLEN+1)); memset(_menu, 0, PDA_LINES * (AQ_MSGLEN+1));
printed_page = false;
break;
case CMD_STATUS:
if ( printed_page == false && (getLogLevel(PDA_LOG) >= LOG_DEBUG)){
print_menu();
printed_page = true;
}
break; break;
case CMD_MSG_LONG: case CMD_MSG_LONG:
/* /*
@ -226,7 +238,7 @@ bool process_pda_menu_packet(unsigned char* packet, int length)
strncpy(_menu[index], (char*)packet+PKT_DATA+1, AQ_MSGLEN); strncpy(_menu[index], (char*)packet+PKT_DATA+1, AQ_MSGLEN);
_menu[index][AQ_MSGLEN] = '\0'; _menu[index][AQ_MSGLEN] = '\0';
} }
if (getLogLevel(PDA_LOG) >= LOG_DEBUG){print_menu();} if (getLogLevel(PDA_LOG) >= LOG_DEBUG && force_print_menu ){print_menu();}
break; break;
case CMD_PDA_HIGHLIGHT: case CMD_PDA_HIGHLIGHT:
// when switching from hlight to hlightchars index 255 is sent to turn off hlight // when switching from hlight to hlightchars index 255 is sent to turn off hlight
@ -239,7 +251,8 @@ bool process_pda_menu_packet(unsigned char* packet, int length)
_hlightcharindexstart = -1; _hlightcharindexstart = -1;
_hlightcharindexstop = -1; _hlightcharindexstop = -1;
} }
if (getLogLevel(PDA_LOG) >= LOG_DEBUG){print_menu();} //if (getLogLevel(PDA_LOG) >= LOG_DEBUG){print_menu();}
if (getLogLevel(PDA_LOG) >= LOG_DEBUG && force_print_menu ){print_menu();}
break; break;
case CMD_PDA_HIGHLIGHTCHARS: case CMD_PDA_HIGHLIGHTCHARS:
// pkt[4] = line, pkt[5] = startchar, pkt[6] = endchar, pkt[7] = clr/inv // pkt[4] = line, pkt[5] = startchar, pkt[6] = endchar, pkt[7] = clr/inv
@ -253,13 +266,16 @@ bool process_pda_menu_packet(unsigned char* packet, int length)
// https://github.com/ballle98/AqualinkD/issues/46 // https://github.com/ballle98/AqualinkD/issues/46
// Character highlight should not update highlight index // Character highlight should not update highlight index
if (packet[4] <= PDA_LINES) { if (packet[4] <= PDA_LINES) {
_hlightindex = packet[4];
_hlightcharindexstart = packet[5]; _hlightcharindexstart = packet[5];
_hlightcharindexstop = packet[6]; _hlightcharindexstop = packet[6];
} else { } else {
_hlightindex = -1;
_hlightcharindexstart = -1; _hlightcharindexstart = -1;
_hlightcharindexstop = -1; _hlightcharindexstop = -1;
} }
if (getLogLevel(PDA_LOG) >= LOG_DEBUG){print_menu();} //if (getLogLevel(PDA_LOG) >= LOG_DEBUG){print_menu();}
if (getLogLevel(PDA_LOG) >= LOG_DEBUG && force_print_menu ){print_menu();}
break; break;
case CMD_PDA_SHIFTLINES: case CMD_PDA_SHIFTLINES:
// press up from top - shift menu down by 1 // press up from top - shift menu down by 1

View File

@ -68,7 +68,7 @@ typedef enum pda_menu_type {
*/ */
//bool pda_mode(); //bool pda_mode();
//void set_pda_mode(bool val); //void set_pda_mode(bool val);
bool process_pda_menu_packet(unsigned char* packet, int length); bool process_pda_menu_packet(unsigned char* packet, int length, bool force_print_menu);
int pda_m_hlightindex(); int pda_m_hlightindex();
char *pda_m_hlight(); char *pda_m_hlight();
char *pda_m_line(int index); char *pda_m_line(int index);

Binary file not shown.

View File

@ -123,11 +123,14 @@ report_zero_pool_temp = no
# MQTT will only post updated information, this option AqualinkD will re-post all MQTT information every ~5 minutes. # MQTT will only post updated information, this option AqualinkD will re-post all MQTT information every ~5 minutes.
#mqtt_timed_update = no #mqtt_timed_update = no
# Please see forum for this, only set to yes when logging information to support # Please see forum for this, only set to yes when logging information to support new devices. (or debugging protocol)
# new devices. Inflrmation will be written to /tmp/RS485.log & /tmp/RS485_raw.log respectively # Information will be written to /tmp/RS485.log & /tmp/RS485_raw.log respectively
#debug_RSProtocol_packets = no #debug_RSProtocol_packets = no
#debug_RSProtocol_bytes = no #debug_RSProtocol_bytes = no
# Log any packets from this device.
#serial_debug_filter = 0x00
# Not documented. These will change how RS485 / Serial works, Only use if asked to for problem solving purposes. # Not documented. These will change how RS485 / Serial works, Only use if asked to for problem solving purposes.
#serial_readahead_b4_write = yes #serial_readahead_b4_write = yes
#thread_netservices = yes #thread_netservices = yes

View File

@ -103,7 +103,7 @@ int rsm_strncmp(const char *haystack, const char *needle, int length)
while(isspace(*ep1)) ep1--; while(isspace(*ep1)) ep1--;
//LOG(AQUA_LOG,LOG_DEBUG, "CHECK haystack SP1='%c' EP1='%c' SP2='%c' '%.*s' for '%s' length=%d\n",*sp1,*ep1,*sp2,(ep1-sp1)+1,sp1,sp2,(ep1-sp1)+1); LOG(AQUA_LOG,LOG_DEBUG, "CHECK haystack SP1='%c' EP1='%c' SP2='%c' '%.*s' for '%s' length=%d\n",*sp1,*ep1,*sp2,(ep1-sp1)+1,sp1,sp2,(ep1-sp1)+1);
// Need to write this myself for speed // Need to write this myself for speed
// Need to check if full length string (no space on end), that the +1 is accurate. MIN should do it // Need to check if full length string (no space on end), that the +1 is accurate. MIN should do it
return strncasecmp(sp1, sp2, MIN((ep1-sp1)+1,length)); return strncasecmp(sp1, sp2, MIN((ep1-sp1)+1,length));

View File

@ -82,7 +82,9 @@ int getLogLevel(int16_t from)
// RSSD_LOG should default to INFO unless the mask is explicitly set. // RSSD_LOG should default to INFO unless the mask is explicitly set.
// IE Even if DEBUG is set, (Note ignored for the moment) // IE Even if DEBUG is set, (Note ignored for the moment)
if ( ((_logforcemask & from) == from ) && _log_level < LOG_DEBUG_SERIAL) if ( from == RSSD_LOG && ((_logforcemask & from) == from ) && _log_level < LOG_DEBUG_SERIAL)
return LOG_DEBUG_SERIAL;
else if ( ((_logforcemask & from) == from ) && _log_level < LOG_DEBUG_SERIAL)
return LOG_DEBUG; return LOG_DEBUG;
return _log_level; return _log_level;

View File

@ -60,6 +60,22 @@
"Cool Cabaret - Show" "Cool Cabaret - Show"
]; ];
// all SWG return a status number, some have different meanings. Change the text below to suit, NOT THE NUMBER.
var swgStatus = {
0: "On",
1: "No flow",
2: "Low salt",
4: "High salt",
8: "Clean cell",
9: "Turning off",
16: "High current",
32: "Low volts",
64: "Low temp",
128: "Check PCB",
255: "Off"
}
/* /*
* BELOW IS NOT RELIVENT FOR simple.html or simple inteface * BELOW IS NOT RELIVENT FOR simple.html or simple inteface
* *

View File

@ -580,6 +580,25 @@
else else
var _link_spa_and_heater=false; var _link_spa_and_heater=false;
// If swgStatus was defined in config.js, use it, else create our own
if (typeof swgStatus !== 'undefined') {
var _swgStatus = swgStatus;
} else {
var _swgStatus = {
0: "On",
1: "No flow",
2: "Low salt",
4: "High salt",
8: "Clean cell",
9: "Turning off",
16: "High current",
32: "Low volts",
64: "Low temp",
128: "Check PCB",
255: "Off"
}
}
function init() { function init() {
setSizeSpecifics(); setSizeSpecifics();
populateLightProgram(-1); populateLightProgram(-1);
@ -1014,6 +1033,7 @@
return status; return status;
} }
function setTileOn(id, status) { function setTileOn(id, status) {
//console.log("setTileOn "+id+ " "+status); //console.log("setTileOn "+id+ " "+status);
var tile; var tile;
@ -1052,7 +1072,12 @@
var type; var type;
if ((type = tile.getAttribute('type')) != null) { if ((type = tile.getAttribute('type')) != null) {
if (type == 'setpoint_swg') { if (type == 'setpoint_swg') {
if (tile.getAttribute('Boost') == 'on') var exstatus = parseInt(tile.getAttribute('fullstatus'))
// Could also ignore "Enabled" in below, that way we don't jump different stats on startup
if (exstatus > 0 && exstatus < 255) {// Not off or on
//text = swgFullstatus2String(exstatus);
text = _swgStatus[exstatus];
} else if (tile.getAttribute('Boost') == 'on')
text = "Boost"; text = "Boost";
else if (status == 'enabled') else if (status == 'enabled')
text = 'Enabled'; text = 'Enabled';
@ -2035,11 +2060,14 @@
if (typeof(data.swg_ppm) !== 'undefined') if (typeof(data.swg_ppm) !== 'undefined')
setTileValue("SWG/PPM", data.swg_ppm); setTileValue("SWG/PPM", data.swg_ppm);
if (typeof(data.swg_fullstatus) !== 'undefined')
setTileAttribute('SWG', "fullstatus", data.swg_fullstatus);
if (typeof(data.chem_ph) !== 'undefined') if (typeof(data.chem_ph) !== 'undefined')
setTileValue("CHEM/pH", data.chem_ph); setTileValue("CHEM/pH", data.chem_ph);
if (typeof(data.chem_orp) !== 'undefined') if (typeof(data.chem_orp) !== 'undefined')
setTileValue("CHEM/ORP", data.chem_orp); setTileValue("CHEM/ORP", data.chem_orp);
/* /*
setTileValue("Air", data.air_temp); setTileValue("Air", data.air_temp);
setTileValue("Pool_Water", data.pool_temp); setTileValue("Pool_Water", data.pool_temp);
@ -2050,7 +2078,7 @@
if (obj.toString() == 'SWG/Boost') { if (obj.toString() == 'SWG/Boost') {
//console.log("BOOST IS "+data.leds[obj]); //console.log("BOOST IS "+data.leds[obj]);
setTileAttribute('SWG', "Boost", data.leds[obj]); setTileAttribute('SWG', "Boost", data.leds[obj]);
setTileValue //setTileValue
} }
} }
for (var obj in data.timers) { for (var obj in data.timers) {