mirror of https://github.com/sfeakes/AqualinkD.git
Fixed HomeKit issue added SWG information.
parent
da3880b66c
commit
87ba041453
|
@ -6,6 +6,8 @@
|
|||
#define AIR_TEMP_TOPIC "Temperature/Air"
|
||||
#define POOL_TEMP_TOPIC "Temperature/Pool"
|
||||
#define SPA_TEMP_TOPIC "Temperature/Spa"
|
||||
#define SWG_PERCENT_TOPIC "SWG/Percent"
|
||||
#define SWG_PPM_TOPIC "SWG/PPM"
|
||||
|
||||
#define FREEZE_PROTECT "Freeze_Protect"
|
||||
|
||||
|
|
114
aqualinkd.c
114
aqualinkd.c
|
@ -166,8 +166,8 @@ void queueGetProgramData()
|
|||
aq_programmer(AQ_GET_FREEZE_PROTECT_TEMP, NULL, &_aqualink_data);
|
||||
//aq_programmer(AQ_GET_PROGRAMS, NULL, &_aqualink_data); // only displays to log at present, also seems to confuse getting set_points
|
||||
}
|
||||
|
||||
void processMessage(char *message)
|
||||
/*
|
||||
void processMessage_OLD(char *message)
|
||||
{
|
||||
char *msg;
|
||||
static bool _initWithRS = false;
|
||||
|
@ -260,6 +260,101 @@ void processMessage(char *message)
|
|||
// We processed the next message, kick any threads waiting on the message.
|
||||
kick_aq_program_thread(&_aqualink_data);
|
||||
}
|
||||
*/
|
||||
|
||||
void processMessage(char *message)
|
||||
{
|
||||
char *msg;
|
||||
static bool _initWithRS = false;
|
||||
static bool _gotREV = false;
|
||||
// NSF replace message with msg
|
||||
msg = cleanwhitespace(message);
|
||||
_aqualink_data.last_message = msg;
|
||||
|
||||
//aqualink_strcpy(_aqualink_data.message, msg);
|
||||
|
||||
logMessage(LOG_DEBUG, "RS Message :- '%s'\n",msg);
|
||||
|
||||
// Check long messages in this if/elseif block first, as some messages are similar.
|
||||
// ie "POOL TEMP" and "POOL TEMP IS SET TO" so want correct match first.
|
||||
//
|
||||
if(stristr(msg, LNG_MSG_BATTERY_LOW) != NULL) {
|
||||
_aqualink_data.battery = LOW;
|
||||
}
|
||||
else if(stristr(msg, LNG_MSG_POOL_TEMP_SET) != NULL) {
|
||||
//logMessage(LOG_DEBUG, "pool htr long message: %s", &message[20]);
|
||||
_aqualink_data.pool_htr_set_point = atoi(message+20);
|
||||
}
|
||||
else if(stristr(msg, LNG_MSG_SPA_TEMP_SET) != NULL) {
|
||||
//logMessage(LOG_DEBUG, "spa htr long message: %s", &message[19]);
|
||||
_aqualink_data.spa_htr_set_point = atoi(message+19);
|
||||
}
|
||||
else if(stristr(msg, LNG_MSG_FREEZE_PROTECTION_SET) != NULL) {
|
||||
//logMessage(LOG_DEBUG, "frz protect long message: %s", &message[28]);
|
||||
_aqualink_data.frz_protect_set_point = atoi(message+28);
|
||||
}
|
||||
else if(strncasecmp(msg, MSG_AIR_TEMP, MSG_AIR_TEMP_LEN) == 0) {
|
||||
_aqualink_data.air_temp = atoi(msg+8);
|
||||
if (msg[strlen(msg)-1] == 'F')
|
||||
_aqualink_data.temp_units = FAHRENHEIT;
|
||||
else if (msg[strlen(msg)-1] == 'C')
|
||||
_aqualink_data.temp_units = CELSIUS;
|
||||
else
|
||||
_aqualink_data.temp_units = UNKNOWN;
|
||||
}
|
||||
else if(strncasecmp(msg, MSG_POOL_TEMP, MSG_POOL_TEMP_LEN) == 0) {
|
||||
_aqualink_data.pool_temp = atoi(msg+9);
|
||||
}
|
||||
else if(strncasecmp(msg, MSG_SPA_TEMP, MSG_SPA_TEMP_LEN) == 0) {
|
||||
_aqualink_data.spa_temp = atoi(msg+8);
|
||||
}
|
||||
else if(msg[2] == '/' && msg[5] == '/' && msg[8] == ' ') {// date in format '08/29/16 MON'
|
||||
strcpy(_aqualink_data.date, msg);
|
||||
}
|
||||
else if(strncasecmp(msg, MSG_SWG_PCT, MSG_SWG_PCT_LEN) == 0) {
|
||||
_aqualink_data.swg_percent = atoi(msg+MSG_SWG_PCT_LEN);
|
||||
logMessage(LOG_DEBUG, "Stored SWG Percent as %d\n", _aqualink_data.swg_percent);
|
||||
}
|
||||
else if(strncasecmp(msg, MSG_SWG_PPM, MSG_SWG_PPM_LEN) == 0) {
|
||||
_aqualink_data.swg_ppm = atoi(msg+MSG_SWG_PPM_LEN);
|
||||
logMessage(LOG_DEBUG, "Stored SWG PPM as %d\n", _aqualink_data.swg_ppm);
|
||||
}
|
||||
else if( (msg[1] == ':' || msg[2] == ':') && msg[strlen(msg)-1] == 'M') { // time in format '9:45 AM'
|
||||
strcpy(_aqualink_data.time, msg);
|
||||
// Setting time takes a long time, so don't try until we have all other programmed data.
|
||||
if ( (_initWithRS == true) && strlen(_aqualink_data.date) > 1 && checkAqualinkTime() != true ) {
|
||||
logMessage(LOG_NOTICE, "RS time is NOT accurate '%s %s', re-setting on controller!\n", _aqualink_data.time, _aqualink_data.date);
|
||||
aq_programmer(AQ_SET_TIME, NULL, &_aqualink_data);
|
||||
} else {
|
||||
logMessage(LOG_DEBUG, "RS time is accurate '%s %s'\n", _aqualink_data.time, _aqualink_data.date);
|
||||
}
|
||||
// If we get a time message before REV, the controller didn't see us as we started too quickly.
|
||||
if ( _gotREV == false ) {
|
||||
logMessage(LOG_NOTICE, "Getting control panel information\n",msg);
|
||||
aq_programmer(AQ_GET_DIAGNOSTICS_MODEL, NULL, &_aqualink_data);
|
||||
_gotREV = true; // Force it to true just incase we don't understand the model#
|
||||
}
|
||||
}
|
||||
else if(strstr(msg, " REV ") != NULL) { // '8157 REV MMM'
|
||||
// A master firmware revision message.
|
||||
strcpy(_aqualink_data.version, msg);
|
||||
_gotREV = true;
|
||||
logMessage(LOG_NOTICE, "Control Panel %s\n",msg);
|
||||
if ( _initWithRS == false) {
|
||||
queueGetProgramData();
|
||||
_initWithRS = true;
|
||||
}
|
||||
}
|
||||
else if(stristr(msg, " TURNS ON") != NULL) {
|
||||
logMessage(LOG_NOTICE, "Program data '%s'\n",msg);
|
||||
}
|
||||
else {
|
||||
logMessage(LOG_DEBUG, "Ignoring '%s'\n",msg);
|
||||
}
|
||||
|
||||
// We processed the next message, kick any threads waiting on the message.
|
||||
kick_aq_program_thread(&_aqualink_data);
|
||||
}
|
||||
|
||||
bool process_packet(unsigned char* packet, int length)
|
||||
{
|
||||
|
@ -280,7 +375,7 @@ bool process_packet(unsigned char* packet, int length)
|
|||
if (processing_long_msg > 0 && packet[PKT_CMD] != CMD_MSG_LONG) {
|
||||
processing_long_msg = 0;
|
||||
//logMessage(LOG_ERR, "RS failed to receive complete long message, received '%s'\n",message);
|
||||
//logMessage(LOG_DEBUG, "RS Finished receiving of MSG_LONG '%s'\n",message);
|
||||
//logMessage(LOG_DEBUG, "RS didn't finished receiving of MSG_LONG '%s'\n",message);
|
||||
processMessage(message);
|
||||
}
|
||||
|
||||
|
@ -301,13 +396,19 @@ bool process_packet(unsigned char* packet, int length)
|
|||
_aqualink_data.pool_temp = TEMP_UNKNOWN;
|
||||
}
|
||||
//logMessage(LOG_DEBUG, "RS Pool temp set to %d | Spa temp %d\n",_aqualink_data.pool_temp,_aqualink_data.spa_temp);
|
||||
/*
|
||||
strcpy(message, "AquaPure 1%");
|
||||
processMessage(message);
|
||||
strcpy(message, "Salt 3200 PPM");
|
||||
processMessage(message);
|
||||
*/
|
||||
break;
|
||||
case CMD_MSG:
|
||||
memset(message, 0, AQ_MSGLONGLEN+1);
|
||||
strncpy(message, (char*)packet+PKT_DATA+1, AQ_MSGLEN);
|
||||
|
||||
//logMessage(LOG_DEBUG_SERIAL, "RS Received message '%s'\n",message);
|
||||
if (packet[PKT_DATA] == 1) // Start of long message, get them all before processing
|
||||
break;
|
||||
break;
|
||||
|
||||
processMessage(message);
|
||||
break;
|
||||
|
@ -315,6 +416,7 @@ bool process_packet(unsigned char* packet, int length)
|
|||
// First in sequence is normal message.
|
||||
processing_long_msg++;
|
||||
strncpy(&message[processing_long_msg*AQ_MSGLEN], (char*)packet+PKT_DATA+1, AQ_MSGLEN);
|
||||
//logMessage(LOG_DEBUG_SERIAL, "RS Received long message '%s'\n",message);
|
||||
if (processing_long_msg == 3) {
|
||||
//logMessage(LOG_DEBUG, "RS Finished receiving of MSG_LONG '%s'\n",message);
|
||||
processMessage(message);
|
||||
|
@ -327,7 +429,7 @@ bool process_packet(unsigned char* packet, int length)
|
|||
rtn = false;
|
||||
break;
|
||||
default:
|
||||
logMessage(LOG_INFO, "RS Received unknown packet.\n",length);
|
||||
logMessage(LOG_INFO, "RS Received unknown packet, 0x%02hhx\n",packet[PKT_CMD]);
|
||||
rtn = false;
|
||||
break;
|
||||
}
|
||||
|
|
2
config.h
2
config.h
|
@ -40,6 +40,8 @@ struct aqconfig
|
|||
int dzidx_air_temp;
|
||||
int dzidx_pool_water_temp;
|
||||
int dzidx_spa_water_temp;
|
||||
int dzidx_swg_percent;
|
||||
int dzidx_swg_ppm;
|
||||
float light_programming_mode;
|
||||
//int dzidx_pool_thermostat; // Domoticz virtual thermostats are crap removed until better
|
||||
//int dzidx_spa_thermostat; // Domoticz virtual thermostats are crap removed until better
|
||||
|
|
|
@ -112,7 +112,13 @@ int build_aqualink_status_JSON(struct aqualinkdata *aqdata, char* buffer, int si
|
|||
length += sprintf(buffer+length, ",\"spa_temp\":\" \"");
|
||||
else
|
||||
length += sprintf(buffer+length, ",\"spa_temp\":\"%d\"",aqdata->spa_temp );
|
||||
|
||||
if ( aqdata->swg_percent != TEMP_UNKNOWN )
|
||||
length += sprintf(buffer+length, ",\"swg_percent\":\"%d\"",aqdata->swg_percent );
|
||||
|
||||
if ( aqdata->swg_ppm != TEMP_UNKNOWN )
|
||||
length += sprintf(buffer+length, ",\"swg_ppm\":\"%d\"",aqdata->swg_ppm );
|
||||
|
||||
if ( aqdata->temp_units == FAHRENHEIT )
|
||||
length += sprintf(buffer+length, ",\"temp_units\":\"%s\"",JSON_FAHRENHEIT );
|
||||
else if ( aqdata->temp_units == CELSIUS )
|
||||
|
|
|
@ -163,6 +163,15 @@ void send_domoticz_mqtt_temp_msg(struct mg_connection *nc, int idx, int value)
|
|||
build_mqtt_status_JSON(mqtt_msg ,JSON_MQTT_MSG_SIZE, idx, 0, (_aqualink_data->temp_units==FAHRENHEIT)?roundf(degFtoC(value)):value);
|
||||
send_mqtt(nc, _aqualink_config->mqtt_dz_pub_topic, mqtt_msg);
|
||||
}
|
||||
void send_domoticz_mqtt_numeric_msg(struct mg_connection *nc, int idx, int value)
|
||||
{
|
||||
if (idx <= 0)
|
||||
return;
|
||||
|
||||
char mqtt_msg[JSON_MQTT_MSG_SIZE];
|
||||
build_mqtt_status_JSON(mqtt_msg ,JSON_MQTT_MSG_SIZE, idx, 0, value);
|
||||
send_mqtt(nc, _aqualink_config->mqtt_dz_pub_topic, mqtt_msg);
|
||||
}
|
||||
|
||||
void send_mqtt_state_msg(struct mg_connection *nc, char *dev_name, aqledstate state)
|
||||
{
|
||||
|
@ -189,6 +198,15 @@ void send_mqtt_setpoint_msg(struct mg_connection *nc, char *dev_name, long value
|
|||
sprintf(mqtt_pub_topic, "%s/%s/setpoint", _aqualink_config->mqtt_aq_topic, dev_name);
|
||||
send_mqtt(nc, mqtt_pub_topic, degC);
|
||||
}
|
||||
void send_mqtt_numeric_msg(struct mg_connection *nc, char *dev_name, int value)
|
||||
{
|
||||
static char mqtt_pub_topic[250];
|
||||
static char msg[10];
|
||||
|
||||
sprintf(msg, "%d", value);
|
||||
sprintf(mqtt_pub_topic, "%s/%s", _aqualink_config->mqtt_aq_topic, dev_name);
|
||||
send_mqtt(nc, mqtt_pub_topic, msg);
|
||||
}
|
||||
|
||||
|
||||
void mqtt_broadcast_aqualinkstate(struct mg_connection *nc)
|
||||
|
@ -229,6 +247,16 @@ void mqtt_broadcast_aqualinkstate(struct mg_connection *nc)
|
|||
send_mqtt_setpoint_msg(nc, FREEZE_PROTECT, _aqualink_data->frz_protect_set_point);
|
||||
//send_domoticz_mqtt_temp_msg(nc, _aqualink_config->dzidx_rfz_protect, _aqualink_data->frz_protect_set_point);
|
||||
}
|
||||
if (_aqualink_data->swg_percent != TEMP_UNKNOWN && _aqualink_data->swg_percent != _last_mqtt_aqualinkdata.swg_percent) {
|
||||
_last_mqtt_aqualinkdata.swg_percent = _aqualink_data->swg_percent;
|
||||
send_mqtt_numeric_msg(nc, SWG_PERCENT_TOPIC, _aqualink_data->swg_percent);
|
||||
send_domoticz_mqtt_numeric_msg(nc, _aqualink_config->dzidx_swg_percent, _aqualink_data->swg_percent);
|
||||
}
|
||||
if (_aqualink_data->swg_ppm != TEMP_UNKNOWN && _aqualink_data->swg_ppm != _last_mqtt_aqualinkdata.swg_ppm) {
|
||||
_last_mqtt_aqualinkdata.swg_ppm = _aqualink_data->swg_ppm;
|
||||
send_mqtt_numeric_msg(nc, SWG_PPM_TOPIC, _aqualink_data->swg_ppm);
|
||||
send_domoticz_mqtt_numeric_msg(nc, _aqualink_config->dzidx_swg_ppm, _aqualink_data->swg_ppm);
|
||||
}
|
||||
|
||||
//logMessage(LOG_INFO, "mqtt_broadcast_aqualinkstate: START LEDs\n");
|
||||
|
||||
|
@ -424,7 +452,17 @@ void action_websocket_request(struct mg_connection *nc, struct websocket_message
|
|||
|
||||
void action_mqtt_message(struct mg_connection *nc, struct mg_mqtt_message *msg) {
|
||||
int i;
|
||||
logMessage(LOG_DEBUG, "MQTT: topic %.*s %.2f\n",msg->topic.len, msg->topic.p, atof(msg->payload.p));
|
||||
//logMessage(LOG_DEBUG, "MQTT: topic %.*s %.2f\n",msg->topic.len, msg->topic.p, atof(msg->payload.p));
|
||||
logMessage(LOG_DEBUG, "MQTT: topic %.*s %.*s\n",msg->topic.len, msg->topic.p, msg->payload.len, msg->payload.p);
|
||||
|
||||
//Need to do this in a better manor, but for present it's ok.
|
||||
static char tmp[20];
|
||||
strncpy(tmp, msg->payload.p, msg->payload.len);
|
||||
tmp[msg->payload.len] = '\0';
|
||||
|
||||
float value = atof(tmp);
|
||||
//logMessage(LOG_DEBUG, "MQTT: topic converted %.*s %s %.2f\n",msg->topic.len, msg->topic.p, tmp, value);
|
||||
|
||||
//printf("Topic %.*s\n",msg->topic.len, msg->topic.p);
|
||||
// get the parts from the topic
|
||||
char *pt1 = (char *)&msg->topic.p[strlen(_aqualink_config->mqtt_aq_topic)+1];
|
||||
|
@ -450,36 +488,36 @@ void action_mqtt_message(struct mg_connection *nc, struct mg_mqtt_message *msg)
|
|||
//aqualinkd/Pool_Heater/set
|
||||
|
||||
if (pt3 != NULL && (strncmp(pt2, "setpoint", 8) == 0) && (strncmp(pt3, "set", 3) == 0)) {
|
||||
int val = _aqualink_data->unactioned.value = (_aqualink_data->temp_units == FAHRENHEIT) ? round(degCtoF(atof(msg->payload.p))) : round(atof(msg->payload.p));
|
||||
int val = _aqualink_data->unactioned.value = (_aqualink_data->temp_units == FAHRENHEIT) ? round(degCtoF(value)) : round(value);
|
||||
if (strncmp(pt1, BTN_POOL_HTR, strlen(BTN_POOL_HTR)) == 0) {
|
||||
if (val <= HEATER_MAX && val >= MEATER_MIN) {
|
||||
logMessage(LOG_INFO, "MQTT: request to set pool heater setpoint to %.2fc\n", atof(msg->payload.p));
|
||||
logMessage(LOG_INFO, "MQTT: request to set pool heater setpoint to %.2fc\n", value);
|
||||
_aqualink_data->unactioned.type = POOL_HTR_SETOINT;
|
||||
} else {
|
||||
logMessage(LOG_ERR, "MQTT: request to set pool heater setpoint to %.2fc is outside of range\n", atof(msg->payload.p));
|
||||
logMessage(LOG_ERR, "MQTT: request to set pool heater setpoint to %.2fc is outside of range\n", value);
|
||||
send_mqtt_setpoint_msg(nc, BTN_POOL_HTR, _aqualink_data->pool_htr_set_point);
|
||||
}
|
||||
} else if (strncmp(pt1, BTN_SPA_HTR, strlen(BTN_SPA_HTR)) == 0) {
|
||||
if (val <= HEATER_MAX && val >= MEATER_MIN) {
|
||||
logMessage(LOG_INFO, "MQTT: request to set spa heater setpoint to %.2fc\n", atof(msg->payload.p));
|
||||
logMessage(LOG_INFO, "MQTT: request to set spa heater setpoint to %.2fc\n", value);
|
||||
_aqualink_data->unactioned.type = SPA_HTR_SETOINT;
|
||||
} else {
|
||||
logMessage(LOG_ERR, "MQTT: request to set spa heater setpoint to %.2fc is outside of range\n", atof(msg->payload.p));
|
||||
logMessage(LOG_ERR, "MQTT: request to set spa heater setpoint to %.2fc is outside of range\n", value);
|
||||
send_mqtt_setpoint_msg(nc, BTN_SPA_HTR, _aqualink_data->spa_htr_set_point);
|
||||
}
|
||||
} else if (strncmp(pt1, FREEZE_PROTECT, strlen(FREEZE_PROTECT)) == 0) {
|
||||
if (val <= FREEZE_PT_MAX && val >= FREEZE_PT_MIN) {
|
||||
logMessage(LOG_INFO, "MQTT: request to set freeze protect to %.2fc\n", atof(msg->payload.p));
|
||||
logMessage(LOG_INFO, "MQTT: request to set freeze protect to %.2fc\n", value);
|
||||
_aqualink_data->unactioned.type = FREEZE_SETPOINT;
|
||||
} else {
|
||||
logMessage(LOG_ERR, "MQTT: request to set freeze protect to %.2fc is outside of range\n", atof(msg->payload.p));
|
||||
logMessage(LOG_ERR, "MQTT: request to set freeze protect to %.2fc is outside of range\n", value);
|
||||
}
|
||||
} else {
|
||||
// Not sure what the setpoint is, ignore.
|
||||
logMessage(LOG_DEBUG, "MQTT: ignoring %.*s don't recognise button setpoint\n", msg->topic.len, msg->topic.p);
|
||||
return;
|
||||
}
|
||||
// logMessage(LOG_INFO, "MQTT: topic %.*s %.2f, setting %s\n",msg->topic.len, msg->topic.p, atof(msg->payload.p));
|
||||
// logMessage(LOG_INFO, "MQTT: topic %.*s %.2f, setting %s\n",msg->topic.len, msg->topic.p, value);
|
||||
time(&_aqualink_data->unactioned.requested);
|
||||
|
||||
} else if (pt2 != NULL && (strncmp(pt2, "set", 3) == 0) && (strncmp(pt2, "setpoint", 8) != 0)) {
|
||||
|
@ -490,7 +528,7 @@ void action_mqtt_message(struct mg_connection *nc, struct mg_mqtt_message *msg)
|
|||
// Message is either a 1 or 0 for on or off
|
||||
int status = atoi(msg->payload.p);
|
||||
if ( status > 1 || status < 0) {
|
||||
logMessage(LOG_ERR, "MQTT: topic %.*s %.2f\n",msg->topic.len, msg->topic.p, atof(msg->payload.p));
|
||||
logMessage(LOG_ERR, "MQTT: topic %.*s %.2f\n",msg->topic.len, msg->topic.p, value);
|
||||
logMessage(LOG_ERR, "MQTT: received unknown status of '%.*s' for '%s', Ignoring!\n", msg->payload.len, msg->payload.p, _aqualink_data->aqbuttons[i].name);
|
||||
}
|
||||
else if ( (_aqualink_data->aqbuttons[i].led->state == OFF && status==0) ||
|
||||
|
|
Binary file not shown.
Loading…
Reference in New Issue