pull/319/head
sfeakes 2024-06-18 18:53:05 -05:00
parent a3b8546557
commit b684f920a3
19 changed files with 306 additions and 128 deletions

View File

@ -110,6 +110,12 @@ Designed to mimic AqualinkRS devices, used to fully configure the master control
# Call for Help.
* The only Jandy devices I have not decoded yet are LX heater & Chemical Feeder. If you have either of these devices and are willing to post some logs, please let me know, or post in the [Discussions area](https://github.com/sfeakes/AqualinkD/discussions)
# Updates in 2.3.8 (Dev)
* Code & Repo refactor
* Decoded more Pentair VSP pump status.
* Changed VSP pump status handling (display more in web UI)
* VSP Pump status & other attributes in HASSIO
# Updates in Release 2.3.7
* Fix for Pentair VSP losing connection & bouncing SWG to 0 and back.
* Added more VSP data (Mode, Status, Pressure Curve, both RPM & GPM) for all Pentair Pumps (VS/VF/VSF).

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -157,6 +157,7 @@ void _processMessage(char *message, struct aqualinkdata *aq_data, bool reset)
//static int swg_msg_count = 0;
//static int boost_msg_count = 0;
static int16_t msg_loop = 0;
static aqledstate default_frz_protect_state = OFF;
// NSF replace message with msg
#ifdef AQ_RS16
int16_t rs16;
@ -186,7 +187,7 @@ void _processMessage(char *message, struct aqualinkdata *aq_data, bool reset)
// Anything that wasn't on during the last set of messages, turn off
if ((msg_loop & MSG_FREEZE) != MSG_FREEZE)
aq_data->frz_protect_state = OFF;
aq_data->frz_protect_state = default_frz_protect_state;
if ((msg_loop & MSG_SERVICE) != MSG_SERVICE &&
(msg_loop & MSG_TIMEOUT) != MSG_TIMEOUT ) {
@ -287,6 +288,7 @@ void _processMessage(char *message, struct aqualinkdata *aq_data, bool reset)
//LOG(ALLB_LOG,LOG_DEBUG, "frz protect long message: %s", &message[28]);
aq_data->frz_protect_set_point = atoi(message + 28);
aq_data->frz_protect_state = ENABLE;
default_frz_protect_state = ENABLE;
if (aq_data->temp_units == UNKNOWN)
setUnits(msg, aq_data);
@ -371,7 +373,7 @@ void _processMessage(char *message, struct aqualinkdata *aq_data, bool reset)
else if (stristr(msg, LNG_MSG_FREEZE_PROTECTION_ACTIVATED) != NULL)
{
msg_loop |= MSG_FREEZE;
aq_data->frz_protect_state = ON;
aq_data->frz_protect_state = default_frz_protect_state;
//freeze_msg_count = 0;
strcpy(aq_data->last_display_message, msg); // Also display the message on web UI
}

View File

@ -148,13 +148,26 @@ typedef enum simulator_type {
} simulator_type;
*/
#define PUMP_PRIMING -1
#define PUMP_OFFLINE -2
#define PUMP_ERROR -3
//#define PUMP_PRIMING -1
//#define PUMP_OFFLINE -2
//#define PUMP_ERROR -3
#define PUMP_OFF_RPM 0
#define PUMP_OFF_GPM PUMP_OFF_RPM
#define PUMP_OFF_WAT PUMP_OFF_RPM
// FUTURE VSP STATUS, keep panel status and RS485 status seperate
typedef enum panel_vsp_status
{
PS_OK = 0, // Start at 0 to match actual status from RS, but go down from their.
PS_OFF = -1,
PS_PRIMING = -2,
PS_OFFLINE = -3,
PS_ERROR = -4
} panel_vsp_status;
typedef struct pumpd
{
int rpm;
@ -171,6 +184,7 @@ typedef struct pumpd
int mode; // 0 local control, 1 remote control
//int driveState; // Haven't figured out what this is yet
int status;
panel_vsp_status pStatus; // FUTURE VSP STATUS,
int pressureCurve;
} pump_detail;

View File

@ -573,13 +573,15 @@ int startup(char *self, char *cfgFile)
LOG(AQUA_LOG,LOG_NOTICE, "Config use_aux_labels = %s\n", bool2text(_aqconfig_.use_panel_aux_labels));
LOG(AQUA_LOG,LOG_NOTICE, "Config override frz prot = %s\n", bool2text(_aqconfig_.override_freeze_protect));
#ifndef MG_DISABLE_MQTT
LOG(AQUA_LOG,LOG_NOTICE, "Config mqtt_server = %s\n", _aqconfig_.mqtt_server);
LOG(AQUA_LOG,LOG_NOTICE, "Config mqtt_dz_sub_topic = %s\n", _aqconfig_.mqtt_dz_sub_topic);
LOG(AQUA_LOG,LOG_NOTICE, "Config mqtt_dz_pub_topic = %s\n", _aqconfig_.mqtt_dz_pub_topic);
LOG(AQUA_LOG,LOG_NOTICE, "Config mqtt_aq_topic = %s\n", _aqconfig_.mqtt_aq_topic);
LOG(AQUA_LOG,LOG_NOTICE, "Config mqtt_user = %s\n", _aqconfig_.mqtt_user);
LOG(AQUA_LOG,LOG_NOTICE, "Config mqtt_passwd = %s\n", _aqconfig_.mqtt_passwd);
LOG(AQUA_LOG,LOG_NOTICE, "Config mqtt_ID = %s\n", _aqconfig_.mqtt_ID);
LOG(AQUA_LOG,LOG_NOTICE, "Config mqtt server = %s\n", _aqconfig_.mqtt_server);
LOG(AQUA_LOG,LOG_NOTICE, "Config mqtt DZ sub topic = %s\n", _aqconfig_.mqtt_dz_sub_topic);
LOG(AQUA_LOG,LOG_NOTICE, "Config mqtt DZ pub topic = %s\n", _aqconfig_.mqtt_dz_pub_topic);
LOG(AQUA_LOG,LOG_NOTICE, "Config mqtt AQ topic = %s\n", _aqconfig_.mqtt_aq_topic);
LOG(AQUA_LOG,LOG_NOTICE, "Config mqtt user = %s\n", _aqconfig_.mqtt_user);
LOG(AQUA_LOG,LOG_NOTICE, "Config mqtt passwd = %s\n", _aqconfig_.mqtt_passwd);
LOG(AQUA_LOG,LOG_NOTICE, "Config mqtt timed update = %s\n", bool2text(_aqconfig_.mqtt_timed_update));
LOG(AQUA_LOG,LOG_NOTICE, "Config mqtt HA dis topic = %s\n", _aqconfig_.mqtt_hass_discover_topic);
LOG(AQUA_LOG,LOG_NOTICE, "Config mqtt ID = %s\n", _aqconfig_.mqtt_ID);
if (_aqconfig_.dzidx_air_temp !=TEMP_UNKNOWN) {
LOG(AQUA_LOG,LOG_NOTICE, "Config idx water temp = %d\n", _aqconfig_.dzidx_air_temp);
}
@ -868,6 +870,7 @@ void main_loop()
_aqualink_data.pumps[i].mode = TEMP_UNKNOWN;
//_aqualink_data.pumps[i].driveState = TEMP_UNKNOWN;
_aqualink_data.pumps[i].status = TEMP_UNKNOWN;
_aqualink_data.pumps[i].pStatus = PS_OFF;
_aqualink_data.pumps[i].pressureCurve = TEMP_UNKNOWN;
}

View File

@ -766,6 +766,7 @@ pump_detail *getpump(struct aqualinkdata *aqdata, int button)
aqdata->pumps[aqdata->num_pumps].rpm = TEMP_UNKNOWN;
aqdata->pumps[aqdata->num_pumps].watts = TEMP_UNKNOWN;
aqdata->pumps[aqdata->num_pumps].gpm = TEMP_UNKNOWN;
aqdata->pumps[aqdata->num_pumps].pStatus = PS_OFF;
aqdata->num_pumps++;
return &aqdata->pumps[aqdata->num_pumps-1];
}

View File

@ -635,6 +635,21 @@ void processMissingAckPacketFromJandyPump(unsigned char destination, struct aqua
return;
}
int getPumpStatus(int pumpIndex, struct aqualinkdata *aqdata)
{
int rtn = aqdata->pumps[pumpIndex].pStatus;
// look at notes in device_jandy for pump status.
// 1 & 0 are on off, anything else error. So if below 1 use the panel status (pStatus).
// Not set would be -999 TEMP_UNKNOWN
// At moment Jandy pumps wil only have panel status, RS485 not decoded.
if ( aqdata->pumps[pumpIndex].status > 1 ) {
rtn = aqdata->pumps[pumpIndex].status;
}
return rtn;
}

View File

@ -35,4 +35,6 @@ void setSWGdeviceStatus(struct aqualinkdata *aqdata, emulation_type requester, u
void getJandyHeaterError(struct aqualinkdata *aqdata, char *message);
void getJandyHeaterErrorMQTT(struct aqualinkdata *aqdata, char *message);
int getPumpStatus(int pumpIndex, struct aqualinkdata *aqdata);
#endif // AQUAPURE_H_

View File

@ -114,13 +114,36 @@ bool processPentairPacket(unsigned char *packet, int packet_length, struct aqual
/*
VSP Pump Status.
Are you sure it is a VS pump because the flow rate byte(7)(PEN_FLOW) is only valid for VSF and VF pumps?
Mode 0=local control, 1=remote control
DriveState = no idea
Pressure Curve = see manual
Status = below
(packet[PEN_HI_B_STATUS] * 256) + packet[PEN_LO_B_STATUS];
Guess at the status would be.
0 ok ( ok for VSF, looks like off for VF / VS? )
1 ok ( ok for VF / VS?, not sure on VSF )
2 filter warning
4 Overcurrent condition
8 Priming
16 System blocked
32 General alarm
64 Overtemp condition
128 Power outage
256 Overcurrent condition 2
512 Overvoltage condition
1024 Unspecified Error
2048 Unspecified Error
4096 Unspecified Error
8192 Unspecified Error
16384 Unspecified Error
32768 Communication failure
// Below was pulled from another project. 0 doesn;t seem to be accurate.
// 0 is OK on VSF pump
[0, { name: 'off', desc: 'Off' }], // When the pump is disconnected or has no power then we simply report off as the status. This is not the recommended wiring
// for a VS/VF pump as is should be powered at all times. When it is, the status will always report a value > 0.
[1, { name: 'ok', desc: 'Ok' }], // Status is always reported when the pump is not wired to a relay regardless of whether it is on or not

View File

@ -108,7 +108,11 @@ const char *HASSIO_SWG_DISCOVER = "{"
// Need to change the max / min. These do NOT lomit the slider in hassio, only the MQTT limits.
// So the 0-100% should be 600-3450 RPM and 15-130 GPM (ie 1% would = 600 & 0%=off)
// (value-600) / (3450-600) * 100
// (value) / 100 * (3450-600) + 600
// (value) / 100 * (3450-600) + 600
\
const char *HASSIO_VSP_DISCOVER = "{"
"\"device\": {" HASS_DEVICE "},"
"\"availability\": {" HASS_AVAILABILITY "},"
@ -123,10 +127,11 @@ const char *HASSIO_VSP_DISCOVER = "{"
"\"payload_off\": \"0\","
"\"percentage_command_topic\": \"%s/%s/%s/set\"," // aqualinkd,filter_pump , RPM|GPM
"\"percentage_state_topic\": \"%s/%s/%s\"," // aqualinkd,filter_pump , RPM|GPM
"\"percentage_value_template\": \"{{ (((value | float(0) - %d) / %d) * 100) | int }}\"," // 600, (3450-600)
// "\"percentage_value_template\": \"{{ (((value | float(0) - %d) / %d) * 100) | int }}\"," // 600, (3450-600)
"\"percentage_value_template\": \"{%% if value | float(0) > %d %%} {{ (((value | float(0) - %d) / %d) * 100) | int }}{%% else %%} 1{%% endif %%}\"," // min,min,(max-min)
"\"percentage_command_template\": \"{{ ((value | float(0) / 100) * %d) + %d | int }}\"," // (3450-130), 600
"\"speed_range_max\": \"100\","
"\"speed_range_min\": \"0\"," // 18|12 600rpm|15gpm
"\"speed_range_max\": 100,"
"\"speed_range_min\": 1," // 18|12 600rpm|15gpm
"\"qos\": 1,"
"\"retain\": false"
"}";
@ -202,6 +207,53 @@ const char *HASSIO_PUMP_SENSOR_DISCOVER = "{"
"\"icon\": \"mdi:pump\""
"}";
// Same as above but no UOM
const char *HASSIO_PUMP_SENSOR_DISCOVER2 = "{"
"\"device\": {" HASS_DEVICE "},"
"\"availability\": {" HASS_AVAILABILITY "},"
"\"type\": \"sensor\","
"\"unique_id\": \"aqualinkd_%s%d_%s\","
"\"name\": \"%s %s %s\","
"\"state_topic\": \"%s/%s%s\","
"\"value_template\": \"{{ value_json }}\","
"\"icon\": \"mdi:pump\""
"}";
const char *HASS_PUMP_MODE_TEMPLATE = "\"{% set values = { '0':'local control', '1':'remote controled'} %}{{ values[value] if value in values.keys() else 'unknown' }}\"";
const char *HASS_PUMP_STATUS_TEMPLATE = "\"{% set values = { "
"'-4':'Error',"
"'-3':'Offline',"
"'-2':'Priming',"
"'-1':'Off',"
"'0':'On',"
"'1':'Ok', "
"'2':'filter warning', "
"'4':'Overcurrent condition', "
"'8':'Priming', "
"'16':'System blocked', "
"'32':'General alarm', "
"'64':'Overtemp condition', "
"'128':'Power outage',"
"'256':'Overcurrent condition 2',"
"'512':'Overvoltage condition'} %}"
"{{ values[value] if value in values.keys() else 'Unspecified Error' }}\"";
const char *HASSIO_PUMP_TEXT_SENSOR_DISCOVER = "{"
"\"device\": {" HASS_DEVICE "},"
"\"availability\": {" HASS_AVAILABILITY "},"
"\"type\": \"sensor\","
"\"unique_id\": \"aqualinkd_%s%d_%s\","
"\"name\": \"%s %s %s\","
"\"state_topic\": \"%s/%s%s\","
"\"value_template\": %s,"
"\"icon\": \"mdi:pump\""
"}";
/*
Below doesn;t work (int and string values). Maybe try text sensor and add RPM/GPM to number
Or add seperate text sensor. (this would be better options, that way you can see priming AND rpm)
"value_template": "{% set values = { '-1':'priming', '-2':'offline', '-3':'error'} %}{{ values[value] if value in values.keys() else value }}",
*/
const char *HASSIO_TEXT_SENSOR_DISCOVER = "{"
"\"device\": {" HASS_DEVICE "},"
"\"availability\": {" HASS_AVAILABILITY "},"
@ -440,7 +492,7 @@ void publish_mqtt_hassio_discover(struct aqualinkdata *aqdata, struct mg_connect
_aqconfig_.mqtt_aq_topic,aqdata->pumps[i].button->name,
_aqconfig_.mqtt_aq_topic,aqdata->pumps[i].button->name,units,
_aqconfig_.mqtt_aq_topic,aqdata->pumps[i].button->name,units,
minspeed, (maxspeed - minspeed),
minspeed, minspeed, (maxspeed - minspeed),
(maxspeed - minspeed), minspeed);
sprintf(topic, "%s/fan/aqualinkd/aqualinkd_%s_%s/config", _aqconfig_.mqtt_hass_discover_topic, aqdata->pumps[i].button->name, units);
@ -448,6 +500,7 @@ void publish_mqtt_hassio_discover(struct aqualinkdata *aqdata, struct mg_connect
// Create sensors for each pump, against it's pump number
int pn=i+1;
if (aqdata->pumps[i].pumpType==VFPUMP || aqdata->pumps[i].pumpType==VSPUMP) {
// We have GPM info
sprintf(msg, HASSIO_PUMP_SENSOR_DISCOVER,
@ -458,7 +511,46 @@ void publish_mqtt_hassio_discover(struct aqualinkdata *aqdata, struct mg_connect
"GPM");
sprintf(topic, "%s/sensor/aqualinkd/aqualinkd_%s%d_%s/config", _aqconfig_.mqtt_hass_discover_topic, "Pump",pn,"GPM");
send_mqtt(nc, topic, msg);
if (READ_RSDEV_vsfPUMP ) {
// All Pentair hame some other info we gather.
sprintf(msg, HASSIO_PUMP_SENSOR_DISCOVER2,
_aqconfig_.mqtt_aq_topic,
"Pump",pn,"PPC",
aqdata->pumps[i].button->label,(rsm_strncasestr(aqdata->pumps[i].button->label,"pump",strlen(aqdata->pumps[i].button->label))!=NULL)?"":"Pump","Presure Curve",
_aqconfig_.mqtt_aq_topic,aqdata->pumps[i].button->name ,PUMP_PPC_TOPIC);
sprintf(topic, "%s/sensor/aqualinkd/aqualinkd_%s%d_%s/config", _aqconfig_.mqtt_hass_discover_topic, "Pump",pn,"PPC");
send_mqtt(nc, topic, msg);
/*
sprintf(msg, HASSIO_PUMP_SENSOR_DISCOVER2,
_aqconfig_.mqtt_aq_topic,
"Pump",pn,"Mode",
aqdata->pumps[i].button->label,(rsm_strncasestr(aqdata->pumps[i].button->label,"pump",strlen(aqdata->pumps[i].button->label))!=NULL)?"":"Pump","Mode",
_aqconfig_.mqtt_aq_topic,aqdata->pumps[i].button->name ,PUMP_MODE_TOPIC);
sprintf(topic, "%s/sensor/aqualinkd/aqualinkd_%s%d_%s/config", _aqconfig_.mqtt_hass_discover_topic, "Pump",pn,"Mode");
send_mqtt(nc, topic, msg);
*/
sprintf(msg, HASSIO_PUMP_TEXT_SENSOR_DISCOVER,
_aqconfig_.mqtt_aq_topic,
"Pump",pn,"Mode",
aqdata->pumps[i].button->label,(rsm_strncasestr(aqdata->pumps[i].button->label,"pump",strlen(aqdata->pumps[i].button->label))!=NULL)?"":"Pump","Mode",
_aqconfig_.mqtt_aq_topic,aqdata->pumps[i].button->name ,PUMP_MODE_TOPIC,
HASS_PUMP_MODE_TEMPLATE);
sprintf(topic, "%s/sensor/aqualinkd/aqualinkd_%s%d_%s/config", _aqconfig_.mqtt_hass_discover_topic, "Pump",pn,"Mode");
send_mqtt(nc, topic, msg);
}
}
sprintf(msg, HASSIO_PUMP_TEXT_SENSOR_DISCOVER,
_aqconfig_.mqtt_aq_topic,
"Pump",pn,"Status",
aqdata->pumps[i].button->label,(rsm_strncasestr(aqdata->pumps[i].button->label,"pump",strlen(aqdata->pumps[i].button->label))!=NULL)?"":"Pump","Status",
_aqconfig_.mqtt_aq_topic,aqdata->pumps[i].button->name ,PUMP_STATUS_TOPIC,
HASS_PUMP_STATUS_TEMPLATE);
sprintf(topic, "%s/sensor/aqualinkd/aqualinkd_%s%d_%s/config", _aqconfig_.mqtt_hass_discover_topic, "Pump",pn,"Status");
send_mqtt(nc, topic, msg);
// All pumps have the below.
sprintf(msg, HASSIO_PUMP_SENSOR_DISCOVER,
_aqconfig_.mqtt_aq_topic,
"Pump",pn,"RPM",

View File

@ -405,6 +405,7 @@ void iaqt_pump_update(struct aqualinkdata *aq_data, int updated) {
aq_data->pumps[i].rpm = PUMP_OFF_RPM;
aq_data->pumps[i].gpm = PUMP_OFF_GPM;
aq_data->pumps[i].watts = PUMP_OFF_WAT;
aq_data->pumps[i].pStatus = PS_OFF;
LOG(IAQT_LOG,LOG_DEBUG, "Clearing pump %d\n",i);
aq_data->updated =true;
}
@ -460,6 +461,7 @@ void passDeviceStatusPage(struct aqualinkdata *aq_data)
} else if (rsm_strcmp(_deviceStatus[i],"RPM:") == 0) {
if (pump != NULL) {
pump->rpm = rsm_atoi(&_deviceStatus[i][9]);
pump->pStatus = PS_OK;
aq_data->updated = true;
} else
LOG(IAQT_LOG,LOG_WARNING, "Got pump message '%s' but can't find pump\n",_deviceStatus[i]);
@ -467,6 +469,7 @@ void passDeviceStatusPage(struct aqualinkdata *aq_data)
} else if (rsm_strcmp(_deviceStatus[i],"GPM:") == 0) {
if (pump != NULL) {
pump->gpm = rsm_atoi(&_deviceStatus[i][9]);
pump->pStatus = PS_OK;
aq_data->updated = true;
} else
LOG(IAQT_LOG,LOG_WARNING, "Got pump message '%s' but can't find pump\n",_deviceStatus[i]);
@ -474,27 +477,31 @@ void passDeviceStatusPage(struct aqualinkdata *aq_data)
} else if (rsm_strcmp(_deviceStatus[i],"Watts:") == 0) {
if (pump != NULL) {
pump->watts = rsm_atoi(&_deviceStatus[i][9]);
//pump->ppStatus = DON"T SET, WE GET WATTS IN PRIMING
aq_data->updated = true;
} else
LOG(IAQT_LOG,LOG_WARNING, "Got pump message '%s' but can't find pump\n",_deviceStatus[i]);
continue;
} else if (rsm_strcmp(_deviceStatus[i],"*** Priming ***") == 0) {
if (pump != NULL) {
pump->rpm = PUMP_PRIMING;
//pump->rpm = PUMP_PRIMING; // NSF need to remove future
pump->pStatus = PS_PRIMING;
aq_data->updated = true;
} else
LOG(IAQT_LOG,LOG_WARNING, "Got pump message '%s' but can't find pump\n",_deviceStatus[i]);
continue;
} else if (rsm_strcmp(_deviceStatus[i],"(Offline)") == 0) {
if (pump != NULL) {
pump->rpm = PUMP_OFFLINE;
//pump->rpm = PUMP_OFFLINE; // NSF need to remove future
pump->pStatus = PS_OFFLINE;
aq_data->updated = true;
} else
LOG(IAQT_LOG,LOG_WARNING, "Got pump message '%s' but can't find pump\n",_deviceStatus[i]);
continue;
} else if (rsm_strcmp(_deviceStatus[i],"(Priming Error)") == 0) {
if (pump != NULL) {
pump->rpm = PUMP_ERROR;
//pump->rpm = PUMP_ERROR; // NSF need to remove future
pump->pStatus = PS_ERROR;
aq_data->updated = true;
} else
LOG(IAQT_LOG,LOG_WARNING, "Got pump message '%s' but can't find pump\n",_deviceStatus[i]);

View File

@ -242,9 +242,12 @@ char *get_aux_information(aqkey *button, struct aqualinkdata *aqdata, char *buff
//printf("Button %s is VSP\n", button->name);
for (i=0; i < aqdata->num_pumps; i++) {
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")));
length += sprintf(buffer, ",\"type_ext\":\"switch_vsp\",\"Pump_RPM\":\"%d\",\"Pump_GPM\":\"%d\",\"Pump_Watts\":\"%d\",\"Pump_Type\":\"%s\",\"Pump_Status\":\"%d\"",
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")),
getPumpStatus(i, aqdata));
return buffer;
}
@ -656,10 +659,12 @@ printf("Pump GPM %d\n",aqdata->pumps[i].gpm);
printf("Pump GPM %d\n",aqdata->pumps[i].watts);
printf("Pump Type %d\n",aqdata->pumps[i].pumpType);
*/
if (aqdata->pumps[i].pumpType != PT_UNKNOWN && (aqdata->pumps[i].rpm != TEMP_UNKNOWN || aqdata->pumps[i].gpm != TEMP_UNKNOWN || aqdata->pumps[i].watts != TEMP_UNKNOWN)) {
length += sprintf(buffer+length, "\"Pump_%d\":{\"name\":\"%s\",\"id\":\"%s\",\"RPM\":\"%d\",\"GPM\":\"%d\",\"Watts\":\"%d\",\"Pump_Type\":\"%s\"},",
//if (aqdata->pumps[i].pumpType != PT_UNKNOWN && (aqdata->pumps[i].rpm != TEMP_UNKNOWN || aqdata->pumps[i].gpm != TEMP_UNKNOWN || aqdata->pumps[i].watts != TEMP_UNKNOWN)) {
if (aqdata->pumps[i].pumpType != PT_UNKNOWN ) {
length += sprintf(buffer+length, "\"Pump_%d\":{\"name\":\"%s\",\"id\":\"%s\",\"RPM\":\"%d\",\"GPM\":\"%d\",\"Watts\":\"%d\",\"Pump_Type\":\"%s\",\"Status\":\"%d\"},",
i+1,aqdata->pumps[i].button->label,aqdata->pumps[i].button->name,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")));
(aqdata->pumps[i].pumpType==VFPUMP?"vfPump":(aqdata->pumps[i].pumpType==VSPUMP?"vsPump":"ePump")),
getPumpStatus(i, aqdata));
}
}
if (buffer[length-1] == ',')

View File

@ -678,20 +678,24 @@ void send_mqtt_string_msg(struct mg_connection *nc, const char *dev_name, const
send_mqtt(nc, mqtt_pub_topic, msg);
}
#define MQTT_TIMED_UDATE 300 //(in seconds)
void mqtt_broadcast_aqualinkstate(struct mg_connection *nc)
{
static int cnt=0;
int i;
const char *status;
int pumpStatus;
// We get called about every second, so check time every MQTT_TIMED_UDATE / 2
if (_aqconfig_.mqtt_timed_update) {
#ifdef AQ_NO_THREAD_NETSERVICE
if (cnt > 300) { // 100 = about every 2 minutes.
#else
if (cnt > 30) { // 30 = about every 2 minutes.
#endif
reset_last_mqtt_status();
static int cnt=0;
if (cnt >= (MQTT_TIMED_UDATE/2)) {
static time_t last_full_update = 0;
time_t now = time(0); // get time now
if ( (int)difftime(now, last_full_update) > MQTT_TIMED_UDATE ) {
reset_last_mqtt_status();
memcpy(&last_full_update, &now, sizeof(time_t));
}
cnt = 0;
} else {
cnt++;
@ -924,14 +928,16 @@ void mqtt_broadcast_aqualinkstate(struct mg_connection *nc)
_last_mqtt_aqualinkdata.pumps[i].mode = _aqualink_data->pumps[i].mode;
send_mqtt_aux_msg(nc, _aqualink_data->pumps[i].button->name, PUMP_MODE_TOPIC, _aqualink_data->pumps[i].mode);
}
if (_aqualink_data->pumps[i].status != TEMP_UNKNOWN && _aqualink_data->pumps[i].status != _last_mqtt_aqualinkdata.pumps[i].status) {
_last_mqtt_aqualinkdata.pumps[i].status = _aqualink_data->pumps[i].status;
send_mqtt_aux_msg(nc, _aqualink_data->pumps[i].button->name, PUMP_STATUS_TOPIC, _aqualink_data->pumps[i].status);
}
if (_aqualink_data->pumps[i].pressureCurve != TEMP_UNKNOWN && _aqualink_data->pumps[i].pressureCurve != _last_mqtt_aqualinkdata.pumps[i].pressureCurve) {
_last_mqtt_aqualinkdata.pumps[i].pressureCurve = _aqualink_data->pumps[i].pressureCurve;
send_mqtt_aux_msg(nc, _aqualink_data->pumps[i].button->name, PUMP_PPC_TOPIC, _aqualink_data->pumps[i].pressureCurve);
}
pumpStatus = getPumpStatus(i, _aqualink_data);
if (pumpStatus != TEMP_UNKNOWN &&
pumpStatus != _last_mqtt_aqualinkdata.pumps[i].status) {
_last_mqtt_aqualinkdata.pumps[i].status = pumpStatus;
send_mqtt_aux_msg(nc, _aqualink_data->pumps[i].button->name, PUMP_STATUS_TOPIC, pumpStatus);
}
}
}
@ -1430,7 +1436,16 @@ float pass_mg_body(struct mg_str *body) {
return TEMP_UNKNOWN;
}
void log_http_request(int level, char *message, struct http_message *http_msg) {
char *uri = (char *)malloc(http_msg->uri.len + http_msg->query_string.len + 2);
strncpy(uri, http_msg->uri.p, http_msg->uri.len + http_msg->query_string.len + 1);
uri[http_msg->uri.len + http_msg->query_string.len + 1] = '\0';
LOG(NET_LOG,level, "%s: '%s'\n", message, uri);
free(uri);
}
void action_web_request(struct mg_connection *nc, struct http_message *http_msg) {
char *msg = NULL;
@ -1442,13 +1457,14 @@ void action_web_request(struct mg_connection *nc, struct http_message *http_msg)
//DEBUG_TIMER_START(&tid);
if (getLogLevel(NET_LOG) >= LOG_INFO) { // Simply for log message, check we are at
// this log level before running all this
// junk
// this log level before running all this junk
/*
char *uri = (char *)malloc(http_msg->uri.len + http_msg->query_string.len + 2);
strncpy(uri, http_msg->uri.p, http_msg->uri.len + http_msg->query_string.len + 1);
uri[http_msg->uri.len + http_msg->query_string.len + 1] = '\0';
LOG(NET_LOG,LOG_INFO, "URI request: '%s'\n", uri);
free(uri);
free(uri);*/
log_http_request(LOG_INFO, "URI request: ", http_msg);
}
//DEBUG_TIMER_STOP(tid, NET_LOG, "action_web_request debug print crap took");
@ -1457,7 +1473,8 @@ void action_web_request(struct mg_connection *nc, struct http_message *http_msg)
// If we have a get request, pass it
if (strncmp(http_msg->uri.p, "/api", 4 ) != 0) {
if (strstr(http_msg->method.p, "GET") && http_msg->query_string.len > 0) {
LOG(NET_LOG,LOG_ERR, "WEB: Old API stanza requested, ignoring client request\n");
//LOG(NET_LOG,LOG_ERR, "WEB: Old API stanza requested, ignoring client request\n");
log_http_request(LOG_ERR, "Old API stanza requested, ignoring request :", http_msg);
} else {
DEBUG_TIMER_START(&tid);
mg_serve_http(nc, http_msg, _http_server_opts);

View File

@ -337,12 +337,13 @@ bool log_freeze_setpoints(struct aqualinkdata *aq_data)
return rtn;
}
/*
bool get_pumpinfo_from_menu_OLD(struct aqualinkdata *aq_data, int menuLineIdx)
{
int rpm = 0;
int watts = 0;
int gpm = 0;
panel_vsp_status panelStatus = PS_OK;
int pump_index = rsm_atoi(&_menu[menuLineIdx][14]);
if (pump_index <= 0)
pump_index = rsm_atoi(&_menu[menuLineIdx][12]); // Pump inxed is in different position on line ` ePump AC 4`
@ -359,13 +360,16 @@ bool get_pumpinfo_from_menu_OLD(struct aqualinkdata *aq_data, int menuLineIdx)
}
}
else if (rsm_strcmp(_menu[menuLineIdx+1], "*** Priming ***") == 0){
rpm = PUMP_PRIMING;
//rpm = PUMP_PRIMING; // NSF need to remove future
panelStatus = PS_PRIMING;
}
else if (rsm_strcmp(_menu[menuLineIdx+1], "(Offline)") == 0){
rpm = PUMP_OFFLINE;
//rpm = PUMP_OFFLINE; // NSF need to remove future
panelStatus = PS_OFFLINE;
}
else if (rsm_strcmp(_menu[menuLineIdx+1], "(Priming Error)") == 0){
rpm = PUMP_ERROR;
//rpm = PUMP_ERROR; // NSF need to remove future
panelStatus = PS_ERROR;
}
LOG(ONET_LOG, LOG_DEBUG, "Found Pump '%s', Index %d, RPM %d, Watts %d, GPM %d\n", _menu[menuLineIdx], pump_index, rpm, watts, gpm);
@ -380,6 +384,7 @@ bool get_pumpinfo_from_menu_OLD(struct aqualinkdata *aq_data, int menuLineIdx)
aq_data->pumps[i].rpm = rpm;
aq_data->pumps[i].watts = watts;
aq_data->pumps[i].gpm = gpm;
aq_data->pumps[i].pStatus = panelStatus;
// LOG(ONET_LOG,LOG_INFO, "Matched OneTouch Pump to Index %d, RPM %d, Watts %d, GPM %d\n",i,rpm,watts,gpm);
LOG(ONET_LOG, LOG_INFO, "Matched Pump to '%s', Index %d, RPM %d, Watts %d, GPM %d\n", aq_data->pumps[i].button->name, i, rpm, watts, gpm);
if (aq_data->pumps[i].pumpType == PT_UNKNOWN)
@ -400,13 +405,14 @@ bool get_pumpinfo_from_menu_OLD(struct aqualinkdata *aq_data, int menuLineIdx)
LOG(ONET_LOG, LOG_WARNING, "Did not find AqualinkD config for Pump '%s'\n",_menu[menuLineIdx]);
return false;
}
*/
bool get_pumpinfo_from_menu(struct aqualinkdata *aq_data, int menuLineIdx, int pump_number)
{
int rpm = 0;
int watts = 0;
int gpm = 0;
panel_vsp_status pStatus = PS_OK;
char *cidx = NULL;
// valid controlpanel pump numbers are 1,2,3,4
@ -426,13 +432,13 @@ bool get_pumpinfo_from_menu(struct aqualinkdata *aq_data, int menuLineIdx, int p
}
}
else if (rsm_strcmp(_menu[menuLineIdx + 1], "*** Priming ***") == 0){
rpm = PUMP_PRIMING;
pStatus = PS_PRIMING;
}
else if (rsm_strcmp(_menu[menuLineIdx + 1], "(Offline)") == 0){
rpm = PUMP_OFFLINE;
pStatus = PS_OFFLINE;
}
else if (rsm_strcmp(_menu[menuLineIdx + 1], "(Priming Error)") == 0){
rpm = PUMP_ERROR;
pStatus = PS_ERROR;
}
if (rpm==0 && watts==0 && rpm==0) {
@ -449,6 +455,7 @@ bool get_pumpinfo_from_menu(struct aqualinkdata *aq_data, int menuLineIdx, int p
aq_data->pumps[i].rpm = rpm;
aq_data->pumps[i].watts = watts;
aq_data->pumps[i].gpm = gpm;
aq_data->pumps[i].pStatus = pStatus;
if (aq_data->pumps[i].pumpType == PT_UNKNOWN){
if (rsm_strcmp(_menu[menuLineIdx],"Intelliflo VS") == 0)
aq_data->pumps[i].pumpType = VSPUMP;
@ -679,6 +686,7 @@ void pump_update(struct aqualinkdata *aq_data, int updated) {
aq_data->pumps[i].rpm = PUMP_OFF_RPM;
aq_data->pumps[i].gpm = PUMP_OFF_GPM;
aq_data->pumps[i].watts = PUMP_OFF_WAT;
aq_data->pumps[i].pStatus = PS_OFF;
}
}
updates = '\0';

View File

@ -495,6 +495,7 @@ void pda_pump_update(struct aqualinkdata *aq_data, int updated) {
aq_data->pumps[i].rpm = PUMP_OFF_RPM;
aq_data->pumps[i].gpm = PUMP_OFF_GPM;
aq_data->pumps[i].watts = PUMP_OFF_WAT;
aq_data->pumps[i].pStatus = PS_OFF;
}
}
updates = '\0';
@ -541,6 +542,7 @@ void get_pda_pumpinfo_from_menu(int menuLineIdx, int pump_number)
int rpm = 0;
int watts = 0;
int gpm = 0;
panel_vsp_status pStatus = PS_OK;
char *cidx = NULL;
// valid controlpanel pump numbers are 1,2,3,4
@ -559,13 +561,13 @@ void get_pda_pumpinfo_from_menu(int menuLineIdx, int pump_number)
}
}
else if (rsm_strcmp(pda_m_line(menuLineIdx+1), "*** Priming ***") == 0){
rpm = PUMP_PRIMING;
pStatus = PS_PRIMING;
}
else if (rsm_strcmp(pda_m_line(menuLineIdx+1), "(Offline)") == 0){
rpm = PUMP_OFFLINE;
pStatus = PS_OFFLINE;
}
else if (rsm_strcmp(pda_m_line(menuLineIdx+1), "(Priming Error)") == 0){
rpm = PUMP_ERROR;
pStatus = PS_ERROR;
}
if (rpm==0 && watts==0 && rpm==0) {
@ -581,6 +583,7 @@ void get_pda_pumpinfo_from_menu(int menuLineIdx, int pump_number)
_aqualink_data->pumps[i].rpm = rpm;
_aqualink_data->pumps[i].watts = watts;
_aqualink_data->pumps[i].gpm = gpm;
_aqualink_data->pumps[i].pStatus = pStatus;
if (_aqualink_data->pumps[i].pumpType == PT_UNKNOWN){
if (rsm_strcmp(pda_m_line(menuLineIdx),"Intelliflo VS") == 0)
_aqualink_data->pumps[i].pumpType = VSPUMP;

View File

@ -1039,10 +1039,12 @@
try {
if (document.getElementById(id).getAttribute('status') == 'on') {
document.getElementById(id + '_status_line2').innerHTML = text;
return true;
} else {
//console.log("Tile "+id+" status is '"+document.getElementById(id).getAttribute('status')+"' not setting text to '"+text+"'");
}
} catch(exception) {}
return false;
}
function setThermostatTile(id, value, sp_value) {
@ -1242,36 +1244,9 @@
}
}
} 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 == -3) {
setTileOnText(object.id, 'Pump ERROR'); // Small txt
document.getElementById(object.id).setAttribute('setpoint', 0);
} else if (object.Pump_RPM == -2) {
setTileOnText(object.id, 'Pump Offline'); // Small txt
document.getElementById(object.id).setAttribute('setpoint', 0);
} else if (object.Pump_RPM == -1) {
setTileOnText(object.id, 'Pump Priming'); // Small text
document.getElementById(object.id).setAttribute('setpoint', 0);
} else {
if (object.Pump_Type == "vfPump") {
if (_show_vsp_gpm == true) {
setTileOnText(object.id, 'GPM:'+object.Pump_GPM);
setTileOnTextLine2(object.id, 'RPM:'+object.Pump_RPM);
} else {
setTileOnText(object.id, 'RPM:'+object.Pump_RPM);
setTileOnTextLine2(object.id, 'GPM:'+object.Pump_GPM);
}
document.getElementById(object.id).setAttribute('setpoint', object.Pump_GPM);
} else {
setTileOnText(object.id, 'RPM:'+object.Pump_RPM);
document.getElementById(object.id).setAttribute('setpoint', object.Pump_RPM);
if (object.Pump_GPM > 0) {
setTileOnTextLine2(object.id, 'GPM:'+object.Pump_GPM);
} else {
setTileOnTextLine2(object.id, "");
}
}
}
if (typeof object.Pump_RPM !== 'undefined' && object.Pump_RPM &&
typeof object.Pump_Status !== 'undefined' && object.Pump_Status ) {
updatePumpTile(object.id, object.Pump_Status, object.Pump_Type, object.Pump_RPM, object.Pump_GPM, object.Pump_Watts);
}
if (typeof object.Pump_Type !== 'undefined') {
document.getElementById(object.id).setAttribute('pumptype', object.Pump_Type);
@ -2201,60 +2176,65 @@
document.getElementById('SWG' + '_status').innerHTML = 'Boost '+data.swg_boost_msg;
}
}
//obj.leds.'SWG/Boost'
// NSF Really quick hack to show RPM on filter pump. Need to come back and do this correctly.
/*
if ((typeof data.extra["Pump_1"] !== 'undefined') && (typeof data.extra["Pump_1"].RPM !== 'undefined')) {
console.log(data.extra["Pump_1"].RPM);
if (document.getElementById('Filter_Pump').getAttribute('status') == 'on') {
document.getElementById('Filter_Pump_status').innerHTML = 'RPM:'+data.extra["Pump_1"].RPM;
}
}*/
//console.log(data["Pump_1"].RPM);
var i = 1;
while (i < 5) {
//console.log(data["Pump_"+i].RPM);
if ((typeof data["Pump_"+i] !== 'undefined') && (typeof data["Pump_"+i].RPM !== 'undefined')) {
if (data["Pump_"+i].RPM == -3) {
setTileOnText(data["Pump_"+i].id, 'Pump ERROR');
} else if (data["Pump_"+i].RPM == -2) {
setTileOnText(data["Pump_"+i].id, 'Pump Offline');
} else if (data["Pump_"+i].RPM == -1) {
setTileOnText(data["Pump_"+i].id, 'Pump Priming');
} else {
//setTileOnText(object.id, 'RPM:'+object.Pump_RPM);
if (data["Pump_"+i].Pump_Type == "vfPump") {
if (_show_vsp_gpm == true) {
setTileOnText(data["Pump_"+i].id, 'GPM:'+data["Pump_"+i].GPM);
setTileOnTextLine2(data["Pump_"+i].id, 'RPM:'+data["Pump_"+i].RPM);
} else {
setTileOnText(data["Pump_"+i].id, 'RPM:'+data["Pump_"+i].RPM);
setTileOnTextLine2(data["Pump_"+i].id, 'GPM:'+data["Pump_"+i].GPM);
}
document.getElementById(data["Pump_"+i].id).setAttribute('setpoint', data["Pump_"+i].GPM);
} else {
document.getElementById(data["Pump_"+i].id).setAttribute('setpoint', data["Pump_"+i].RPM);
setTileOnText(data["Pump_"+i].id, 'RPM:'+data["Pump_"+i].RPM);
if (data["Pump_"+i].GPM > 0) {
setTileOnTextLine2(data["Pump_"+i].id, 'GPM:'+data["Pump_"+i].GPM);
} else {
setTileOnTextLine2(data["Pump_"+i].id, "");
}
}
}
/*
if (document.getElementById(data["Pump_"+i].id).getAttribute('status') == 'on')
document.getElementById(data["Pump_"+i].id + '_status').innerHTML = 'RPM:'+data["Pump_"+i].RPM;
else
console.log(data["Pump_"+i].id + ' is off, not displaying RPM ' + data["Pump_"+i].RPM);*/
if (typeof data["Pump_"+i] !== 'undefined') {
updatePumpTile(data["Pump_"+i].id, data["Pump_"+i].Status, data["Pump_"+i].Pump_Type, data["Pump_"+i].RPM, data["Pump_"+i].GPM, data["Pump_"+i].Watts);
}
i++;
}
}
function updatePumpTile(tileid, status, type, rpm, gpm, watts) {
var tLine = '';
var bLine = '';
// If we have 1 line, simple (error & priming takes presidence over anything else)
// If we have 2 lines, then BOTTOM (line #1) is ERROR (not priming) or what the pump needs to control (RPM for all except VF which is GPM)
// TOP (line #2) is (priming/RPM/GPM).
// 1,0,-1 are all good states, anything else error
if (status >= 1 || status <= -3) {
if (status == -3) {
setTileOnText(tileid, 'Pump Offline');
} else {
setTileOnText(tileid, 'Pump ERROR');
}
document.getElementById(tileid).setAttribute('setpoint', 0);
setTileOnTextLine2(tileid, "");
return;
}
if (type == "vfPump") {
bLine = ((gpm > 0) ? 'GPM:'+gpm : 'GPM:0');
tLine = ((rpm > 0) ? 'RPM:'+rpm : '');
document.getElementById(tileid).setAttribute('setpoint', ((gpm > 0) ? gpm : 0));
} else if ( rpm > 0) {
bLine = ((rpm > 0) ? 'RPM:'+rpm : 'RPM:0');
if (gpm > 0) {
tLine = 'GPM:'+gpm;
} else if (watts > 0) {
tLine = 'Watts:'+watts;
}
document.getElementById(tileid).setAttribute('setpoint', ((rpm > 0) ? rpm : 0));
} else if ( watts > 0 ) {
bLine = ((watts > 0) ? 'Watts:'+watts : '');
document.getElementById(tileid).setAttribute('setpoint', ((rpm > 0) ? rpm : 0));
}
// If we are in priming. Move lines and display priming
if (status == -2) {
tLine = bLine;
bLine = 'Pump Priming';
} else if (status == -1) {
// Pump is off
var tLine = '';
var bLine = 'On';
}
setTileOnText(tileid, bLine);
setTileOnTextLine2(tileid, tLine);
}
function deviceSort(a, b) {
var pa;
var pb;