mirror of https://github.com/sfeakes/AqualinkD.git
V1.3.3
parent
93d97b2008
commit
07c0a27762
|
@ -63,6 +63,12 @@ Designed to mimic AqualinkRS6 All Button keypad, and just like the keypad you ca
|
|||
* http://aqualink.ip/simple.html <- (Simple opion if you don't like the above)
|
||||
* http://aqualink.ip/simulator.html <- (RS8 All Button Control Panel simulator)
|
||||
#<a name="release"></a>
|
||||
## Update in Release 1.3.3
|
||||
* AqualinkD will now automaticaly find a usable ID if not specifically configured.
|
||||
* Support for reading multiple Variable Speed Pump info & assigning per device. (Please see wiki for new config options).
|
||||
* <span style="color:red">*At present only Pentair VSP supported, if you have Jandy VSP (ePump) and are willing to do some testing, please post on forum as I'd like to get this supported as well.*</span>
|
||||
* Need to check config for `read_all_devices = yes` & `read_pentair_packets = yes` and assign RS485 Pump ID to Device ID in configuration. serial_logger should find ID's for you.
|
||||
* WebUI will display Pump RPM, RPM,Watts,GPH information is also available from MQTT & API.
|
||||
## Update in Release 1.3.2c
|
||||
* Miscellaneous bug fixes and buffer overrun (could cause core dump).
|
||||
* VSP update & Pantair device support.
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
#define POOL_THERMO_TEMP_TOPIC BTN_POOL_HTR "/Temperature"
|
||||
#define SPA_THERMO_TEMP_TOPIC BTN_SPA_HTR "/Temperature"
|
||||
|
||||
#define PUMP_TOPIC "Pump_"
|
||||
//#define PUMP_TOPIC "Pump_"
|
||||
#define PUMP_RPM_TOPIC "/RPM"
|
||||
#define PUMP_GPH_TOPIC "/GPH"
|
||||
#define PUMP_WATTS_TOPIC "/Watts"
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
//#define UNKNOWN TEMP_UNKNOWN
|
||||
#define DATE_STRING_LEN 30
|
||||
|
||||
#define MAX_PUMPS 2
|
||||
#define MAX_PUMPS 4
|
||||
|
||||
enum {
|
||||
FAHRENHEIT,
|
||||
|
@ -71,7 +71,9 @@ typedef struct pumpd
|
|||
int gph;
|
||||
int watts;
|
||||
unsigned char pumpID;
|
||||
int buttonID;
|
||||
//int buttonID;
|
||||
protocolType ptype;
|
||||
aqkey *button;
|
||||
} pump_detail;
|
||||
|
||||
struct aqualinkdata
|
||||
|
|
44
aqualinkd.c
44
aqualinkd.c
|
@ -673,7 +673,7 @@ int main(int argc, char *argv[])
|
|||
{
|
||||
// main_loop ();
|
||||
|
||||
int i;
|
||||
int i, j;
|
||||
//char *cfgFile = DEFAULT_CONFIG_FILE;
|
||||
char defaultCfg[] = "./aqualinkd.conf";
|
||||
char *cfgFile;
|
||||
|
@ -770,7 +770,15 @@ int main(int argc, char *argv[])
|
|||
|
||||
for (i = 0; i < TOTAL_BUTONS; i++)
|
||||
{
|
||||
logMessage(LOG_NOTICE, "Config BTN %-13s = label %-15s | PDAlabel %-15s | dzidx %d\n", _aqualink_data.aqbuttons[i].name, _aqualink_data.aqbuttons[i].label, _aqualink_data.aqbuttons[i].pda_label, _aqualink_data.aqbuttons[i].dz_idx);
|
||||
char vsp[] = "None";
|
||||
for (j = 0; j < MAX_PUMPS; j++) {
|
||||
//if (_aqualink_data.pumps[j].buttonID == i) {
|
||||
if (_aqualink_data.pumps[j].button == &_aqualink_data.aqbuttons[i]) {
|
||||
sprintf(vsp,"0x%02hhx",_aqualink_data.pumps[j].pumpID);
|
||||
//printf("Pump %d %d %d\n",_aqualink_data.pumps[j].pumpID, _aqualink_data.pumps[j].buttonID, _aqualink_data.pumps[j].ptype);
|
||||
}
|
||||
}
|
||||
logMessage(LOG_NOTICE, "Config BTN %-13s = label %-15s | VSP ID %-4s | PDAlabel %-15s | dzidx %d\n", _aqualink_data.aqbuttons[i].name, _aqualink_data.aqbuttons[i].label, vsp, _aqualink_data.aqbuttons[i].pda_label, _aqualink_data.aqbuttons[i].dz_idx);
|
||||
//logMessage(LOG_NOTICE, "Button %d\n", i+1, _aqualink_data.aqbuttons[i].label , _aqualink_data.aqbuttons[i].dz_idx);
|
||||
}
|
||||
|
||||
|
@ -941,6 +949,29 @@ void caculate_ack_packet(int rs_fd, unsigned char *packet_buffer) {
|
|||
}
|
||||
}
|
||||
|
||||
unsigned char find_unused_address(unsigned char* packet) {
|
||||
static int ID[4] = {0,0,0,0}; // 0=0x08, 1=0x09, 2=0x0A, 3=0x0B
|
||||
static unsigned char lastID = 0x00;
|
||||
|
||||
if (packet[PKT_DEST] >= 0x08 && packet[PKT_DEST] <= 0x0B && packet[PKT_CMD] == CMD_PROBE) {
|
||||
//printf("Probe packet to keypad ID 0x%02hhx\n",packet[PKT_DEST]);
|
||||
lastID = packet[PKT_DEST];
|
||||
} else if (packet[PKT_DEST] == DEV_MASTER && lastID != 0x00) {
|
||||
lastID = 0x00;
|
||||
} else if (lastID != 0x00) {
|
||||
ID[lastID-8]++;
|
||||
if (ID[lastID-8] >= 3) {
|
||||
logMessage(LOG_NOTICE, "Found valid unused ID 0x%02hhx\n",lastID);
|
||||
return lastID;
|
||||
}
|
||||
lastID = 0x00;
|
||||
} else {
|
||||
lastID = 0x00;
|
||||
}
|
||||
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
void main_loop()
|
||||
{
|
||||
struct mg_mgr mgr;
|
||||
|
@ -1001,6 +1032,10 @@ void main_loop()
|
|||
init_pda(&_aqualink_data);
|
||||
}
|
||||
|
||||
if (_config_parameters.device_id == 0x00) {
|
||||
logMessage(LOG_NOTICE, "Searching for valid ID, please configure one for faster startup\n");
|
||||
}
|
||||
|
||||
while (_keepRunning == true)
|
||||
{
|
||||
while ((rs_fd < 0 || blank_read >= MAX_ZERO_READ_BEFORE_RECONNECT) && _keepRunning == true)
|
||||
|
@ -1039,6 +1074,11 @@ void main_loop()
|
|||
//logMessage(LOG_DEBUG_SERIAL, "Nothing read on serial\n");
|
||||
blank_read++;
|
||||
}
|
||||
else if (_config_parameters.device_id == 0x00) {
|
||||
blank_read = 0;
|
||||
_config_parameters.device_id = find_unused_address(packet_buffer);
|
||||
continue;
|
||||
}
|
||||
else if (packet_length > 0)
|
||||
{
|
||||
blank_read = 0;
|
||||
|
|
16
config.c
16
config.c
|
@ -308,6 +308,7 @@ void readCfg_OLD (struct aqconfig *config_parameters, struct aqualinkdata *aqdat
|
|||
|
||||
bool setConfigValue(struct aqconfig *config_parameters, struct aqualinkdata *aqdata, char *param, char *value) {
|
||||
bool rtn = false;
|
||||
static int pi=0;
|
||||
|
||||
if (strncasecmp(param, "socket_port", 11) == 0) {
|
||||
config_parameters->socket_port = cleanalloc(value);
|
||||
|
@ -418,6 +419,7 @@ bool setConfigValue(struct aqconfig *config_parameters, struct aqualinkdata *aqd
|
|||
} else if (strncasecmp (param, "read_pentair_packets", 17) == 0) {
|
||||
config_parameters->read_pentair_packets = text2bool(value);
|
||||
config_parameters->read_all_devices = true;
|
||||
rtn=true;
|
||||
} /*
|
||||
else if (strncasecmp (param, "use_PDA_auxiliary", 17) == 0) {
|
||||
config_parameters->use_PDA_auxiliary = text2bool(value);
|
||||
|
@ -448,7 +450,19 @@ bool setConfigValue(struct aqconfig *config_parameters, struct aqualinkdata *aqd
|
|||
rtn=true;
|
||||
} else if (strncasecmp(param + 9, "_pumpID", 7) == 0) {
|
||||
//aqdata->aqbuttons[num].pda_label = cleanalloc(value);
|
||||
//69 to 111 = Pentair, 120 to 123 = Jandy
|
||||
//96 to 111 = Pentair, 120 to 123 = Jandy
|
||||
if (pi < MAX_PUMPS) {
|
||||
aqdata->pumps[pi].button = &aqdata->aqbuttons[num];
|
||||
aqdata->pumps[pi].pumpID = strtoul(cleanalloc(value), NULL, 16);
|
||||
//aqdata->pumps[pi].buttonID = num;
|
||||
if (aqdata->pumps[pi].pumpID < 119)
|
||||
aqdata->pumps[pi].ptype = PENTAIR;
|
||||
else
|
||||
aqdata->pumps[pi].ptype = JANDY;
|
||||
pi++;
|
||||
} else {
|
||||
logMessage(LOG_ERR, "Config error, VSP Pumps limited to %d, ignoring %s'\n",MAX_PUMPS,param);
|
||||
}
|
||||
rtn=true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,10 @@
|
|||
*/
|
||||
void initButtons(struct aqualinkdata *aqdata)
|
||||
{
|
||||
//int i;
|
||||
//for (i = 0; i < MAX_PUMPS; i++)
|
||||
// aqdata->pumps[i].buttonID = -1;
|
||||
|
||||
aqdata->aqbuttons[0].led = &aqdata->aqualinkleds[7-1];
|
||||
aqdata->aqbuttons[0].led->state = LED_S_UNKNOWN;
|
||||
aqdata->aqbuttons[0].label = BTN_PUMP;
|
||||
|
|
|
@ -139,8 +139,29 @@ int LED2int(aqledstate state)
|
|||
}
|
||||
}
|
||||
|
||||
#define AUX_BUFFER_SIZE 100
|
||||
|
||||
char *get_aux_information(aqkey *button, struct aqualinkdata *aqdata, char *buffer)
|
||||
{
|
||||
int i;
|
||||
int length = 0;
|
||||
buffer[0] = '\0';
|
||||
|
||||
for (i=0; i < MAX_PUMPS; i++) {
|
||||
if (button == aqdata->pumps[i].button) {
|
||||
if (aqdata->pumps[i].rpm != TEMP_UNKNOWN || aqdata->pumps[i].gph != TEMP_UNKNOWN || aqdata->pumps[i].watts != TEMP_UNKNOWN) {
|
||||
length += sprintf(buffer, ",\"Pump_RPM\":\"%d\",\"Pump_GPH\":\"%d\",\"Pump_Watts\":\"%d\"", aqdata->pumps[i].rpm,aqdata->pumps[i].gph,aqdata->pumps[i].watts);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
int build_device_JSON(struct aqualinkdata *aqdata, int programable_switch, char* buffer, int size, bool homekit)
|
||||
{
|
||||
char aux_info[AUX_BUFFER_SIZE];
|
||||
memset(&buffer[0], 0, size);
|
||||
int length = 0;
|
||||
int i;
|
||||
|
@ -182,19 +203,21 @@ int build_device_JSON(struct aqualinkdata *aqdata, int programable_switch, char*
|
|||
((homekit && aqdata->temp_units==FAHRENHEIT)?degFtoC(aqdata->spa_temp):aqdata->spa_temp),
|
||||
LED2int(aqdata->aqbuttons[i].led->state));
|
||||
} else if (programable_switch > 0 && programable_switch == i) {
|
||||
length += sprintf(buffer+length, "{\"type\": \"switch_program\", \"id\": \"%s\", \"name\": \"%s\", \"state\": \"%s\", \"status\": \"%s\", \"int_status\": \"%d\" },",
|
||||
length += sprintf(buffer+length, "{\"type\": \"switch_program\", \"id\": \"%s\", \"name\": \"%s\", \"state\": \"%s\", \"status\": \"%s\", \"int_status\": \"%d\" %s},",
|
||||
aqdata->aqbuttons[i].name,
|
||||
aqdata->aqbuttons[i].label,
|
||||
aqdata->aqbuttons[i].led->state==ON?JSON_ON:JSON_OFF,
|
||||
LED2text(aqdata->aqbuttons[i].led->state),
|
||||
LED2int(aqdata->aqbuttons[i].led->state));
|
||||
LED2int(aqdata->aqbuttons[i].led->state),
|
||||
get_aux_information(&aqdata->aqbuttons[i], aqdata, aux_info));
|
||||
} else {
|
||||
length += sprintf(buffer+length, "{\"type\": \"switch\", \"id\": \"%s\", \"name\": \"%s\", \"state\": \"%s\", \"status\": \"%s\", \"int_status\": \"%d\" },",
|
||||
length += sprintf(buffer+length, "{\"type\": \"switch\", \"id\": \"%s\", \"name\": \"%s\", \"state\": \"%s\", \"status\": \"%s\", \"int_status\": \"%d\" %s},",
|
||||
aqdata->aqbuttons[i].name,
|
||||
aqdata->aqbuttons[i].label,
|
||||
aqdata->aqbuttons[i].led->state==ON?JSON_ON:JSON_OFF,
|
||||
LED2text(aqdata->aqbuttons[i].led->state),
|
||||
LED2int(aqdata->aqbuttons[i].led->state));
|
||||
LED2int(aqdata->aqbuttons[i].led->state),
|
||||
get_aux_information(&aqdata->aqbuttons[i], aqdata, aux_info));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -373,18 +396,20 @@ int build_aqualink_status_JSON(struct aqualinkdata *aqdata, char* buffer, int si
|
|||
length += sprintf(buffer+length, ", \"%s\": \"%s\"", FREEZE_PROTECT, aqdata->frz_protect_state==ON?JSON_ON:JSON_ENABLED);
|
||||
}
|
||||
|
||||
//length += sprintf(buffer+length, "}, \"extra\":{" );
|
||||
length += sprintf(buffer+length, "},");
|
||||
|
||||
length += sprintf(buffer+length, "}, \"extra\":{" );
|
||||
for (i=0; i < MAX_PUMPS; i++) {
|
||||
if (aqdata->pumps[i].rpm != TEMP_UNKNOWN || aqdata->pumps[i].gph != TEMP_UNKNOWN || aqdata->pumps[i].watts != TEMP_UNKNOWN) {
|
||||
length += sprintf(buffer+length, "\"Pump_%d\":{\"RPM\":\"%d\",\"GPH\":\"%d\",\"WATTS\":\"%d\"},",i+1,aqdata->pumps[i].rpm,aqdata->pumps[i].gph,aqdata->pumps[i].watts);
|
||||
length += sprintf(buffer+length, "\"Pump_%d\":{\"name\":\"%s\",\"id\":\"%s\",\"RPM\":\"%d\",\"GPH\":\"%d\",\"Watts\":\"%d\"},",
|
||||
i+1,aqdata->pumps[i].button->label,aqdata->pumps[i].button->name,aqdata->pumps[i].rpm,aqdata->pumps[i].gph,aqdata->pumps[i].watts);
|
||||
}
|
||||
}
|
||||
|
||||
if (buffer[length-1] == ',')
|
||||
length--;
|
||||
|
||||
length += sprintf(buffer+length, "}}" );
|
||||
length += sprintf(buffer+length, "}" );
|
||||
|
||||
buffer[length] = '\0';
|
||||
|
||||
|
|
|
@ -194,14 +194,16 @@ void send_mqtt_state_msg(struct mg_connection *nc, char *dev_name, aqledstate st
|
|||
send_mqtt(nc, mqtt_pub_topic, (state==OFF?MQTT_OFF:MQTT_ON));
|
||||
}
|
||||
|
||||
void send_mqtt_aux_msg(struct mg_connection *nc, char *root_topic, int dev_index, char *dev_topic, int value)
|
||||
//void send_mqtt_aux_msg(struct mg_connection *nc, char *root_topic, int dev_index, char *dev_topic, int value)
|
||||
void send_mqtt_aux_msg(struct mg_connection *nc, char *dev_name, char *dev_topic, int value)
|
||||
{
|
||||
static char mqtt_pub_topic[250];
|
||||
static char msg[10];
|
||||
|
||||
sprintf(msg, "%d", value);
|
||||
|
||||
sprintf(mqtt_pub_topic, "%s/%s%d%s",_aqualink_config->mqtt_aq_topic, root_topic, dev_index, dev_topic);
|
||||
//sprintf(mqtt_pub_topic, "%s/%s%d%s",_aqualink_config->mqtt_aq_topic, root_topic, dev_index, dev_topic);
|
||||
sprintf(mqtt_pub_topic, "%s/%s%s",_aqualink_config->mqtt_aq_topic, dev_name, dev_topic);
|
||||
send_mqtt(nc, mqtt_pub_topic, msg);
|
||||
}
|
||||
|
||||
|
@ -533,15 +535,18 @@ void mqtt_broadcast_aqualinkstate(struct mg_connection *nc)
|
|||
|
||||
if (_aqualink_data->pumps[i].rpm != TEMP_UNKNOWN && _aqualink_data->pumps[i].rpm != _last_mqtt_aqualinkdata.pumps[i].rpm) {
|
||||
_last_mqtt_aqualinkdata.pumps[i].rpm = _aqualink_data->pumps[i].rpm;
|
||||
send_mqtt_aux_msg(nc, PUMP_TOPIC, i+1, PUMP_RPM_TOPIC, _aqualink_data->pumps[i].rpm);
|
||||
//send_mqtt_aux_msg(nc, PUMP_TOPIC, i+1, PUMP_RPM_TOPIC, _aqualink_data->pumps[i].rpm);
|
||||
send_mqtt_aux_msg(nc, _aqualink_data->pumps[i].button->name, PUMP_RPM_TOPIC, _aqualink_data->pumps[i].rpm);
|
||||
}
|
||||
if (_aqualink_data->pumps[i].gph != TEMP_UNKNOWN && _aqualink_data->pumps[i].gph != _last_mqtt_aqualinkdata.pumps[i].gph) {
|
||||
_last_mqtt_aqualinkdata.pumps[i].gph = _aqualink_data->pumps[i].gph;
|
||||
send_mqtt_aux_msg(nc, PUMP_TOPIC, i+1, PUMP_GPH_TOPIC, _aqualink_data->pumps[i].gph);
|
||||
//send_mqtt_aux_msg(nc, PUMP_TOPIC, i+1, PUMP_GPH_TOPIC, _aqualink_data->pumps[i].gph);
|
||||
send_mqtt_aux_msg(nc, _aqualink_data->pumps[i].button->name, PUMP_GPH_TOPIC, _aqualink_data->pumps[i].gph);
|
||||
}
|
||||
if (_aqualink_data->pumps[i].watts != TEMP_UNKNOWN && _aqualink_data->pumps[i].watts != _last_mqtt_aqualinkdata.pumps[i].watts) {
|
||||
_last_mqtt_aqualinkdata.pumps[i].watts = _aqualink_data->pumps[i].watts;
|
||||
send_mqtt_aux_msg(nc, PUMP_TOPIC, i+1, PUMP_WATTS_TOPIC, _aqualink_data->pumps[i].watts);
|
||||
//send_mqtt_aux_msg(nc, PUMP_TOPIC, i+1, PUMP_WATTS_TOPIC, _aqualink_data->pumps[i].watts);
|
||||
send_mqtt_aux_msg(nc, _aqualink_data->pumps[i].button->name, PUMP_WATTS_TOPIC, _aqualink_data->pumps[i].watts);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,21 +12,37 @@
|
|||
bool processPentairPacket(unsigned char *packet, int packet_length, struct aqualinkdata *aqdata)
|
||||
{
|
||||
bool changedAnything = false;
|
||||
|
||||
int i;
|
||||
//ID's 96 to 111 = Pentair (or 0x60 to 0x6F)
|
||||
|
||||
// Need to find a better way to support pump index
|
||||
|
||||
static int pumpIndex = 1;
|
||||
//static int pumpIndex = 1;
|
||||
|
||||
if ( packet[PEN_PKT_FROM] == 0x60 && packet[PEN_PKT_CMD] == PEN_CMD_STATUS ){
|
||||
if ( packet[PEN_PKT_CMD] == PEN_CMD_STATUS && packet[PEN_PKT_FROM] >= 96 && packet[PEN_PKT_FROM] <= 111 ){
|
||||
// We have Pentair Pump packet, let's see if it's configured.
|
||||
//printf("PUMP\n");
|
||||
logMessage(LOG_INFO, "Pentair Pump Status message = RPM %d | WATTS %d\n",
|
||||
|
||||
for (i = 0; i < MAX_PUMPS; i++) {
|
||||
if ( aqdata->pumps[i].ptype == PENTAIR && aqdata->pumps[i].pumpID == packet[PEN_PKT_FROM] ) {
|
||||
// We found the pump.
|
||||
logMessage(LOG_INFO, "Pentair Pump Status message = RPM %d | WATTS %d\n",
|
||||
(packet[PEN_HI_B_RPM] * 256) + packet[PEN_LO_B_RPM],
|
||||
(packet[PEN_HI_B_WAT] * 256) + packet[PEN_LO_B_WAT]);
|
||||
|
||||
aqdata->pumps[pumpIndex-1].rpm = (packet[PEN_HI_B_RPM] * 256) + packet[PEN_LO_B_RPM];
|
||||
aqdata->pumps[pumpIndex-1].watts = (packet[PEN_HI_B_WAT] * 256) + packet[PEN_LO_B_WAT];
|
||||
aqdata->pumps[i].rpm = (packet[PEN_HI_B_RPM] * 256) + packet[PEN_LO_B_RPM];
|
||||
aqdata->pumps[i].watts = (packet[PEN_HI_B_WAT] * 256) + packet[PEN_LO_B_WAT];
|
||||
|
||||
changedAnything = true;
|
||||
changedAnything = true;
|
||||
break;
|
||||
}
|
||||
if (changedAnything != true)
|
||||
logMessage(LOG_NOTICE, "Pentair Pump found at ID 0x%02hhx with RPM %d | WATTS %d, but not configured, information ignored!\n",
|
||||
packet[PEN_PKT_FROM],
|
||||
(packet[PEN_HI_B_RPM] * 256) + packet[PEN_LO_B_RPM],
|
||||
(packet[PEN_HI_B_WAT] * 256) + packet[PEN_LO_B_WAT]);
|
||||
}
|
||||
//
|
||||
}
|
||||
|
||||
return changedAnything;
|
||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -58,6 +58,7 @@ report_zero_pool_temp = no
|
|||
# The id of the Aqualink terminal device. Devices probed by RS8 master are:
|
||||
# 08-0b, 10-13, 18-1b, 20-23, 28-2b, 30-33, 38-3b, 40-43
|
||||
# Working RS ID's are 0x0a 0x0b 0x09 0x08 <- 0x08 is usually taken
|
||||
# You can use 0x00 and AqualinkD will find an ID for you, but this makes a slow startup
|
||||
device_id=0x0a
|
||||
|
||||
# Please see forum for this, only set to yes when logging information to support
|
||||
|
@ -75,9 +76,12 @@ device_id=0x0a
|
|||
#pda_sleep_mode = yes
|
||||
|
||||
# Read status information from other devices on the RS485 bus.
|
||||
# At the moment just Salt Water Generators are supported.
|
||||
# At the moment Salt Water Generators and some VSP are supported.
|
||||
read_all_devices = yes
|
||||
|
||||
# IF you have Pantair variable speed pump, set to yes othersise set to no.
|
||||
read_pentair_packets = no
|
||||
|
||||
# If you have a SWG connected to the control panel, set this to yes.
|
||||
# AqualinkD can only detect a SWG if it's on, so after a restart you will not see/access a SWG until the the next time the pump is on.
|
||||
force_SWG = no
|
||||
|
@ -112,10 +116,18 @@ SWG_PPM_dzidx=0
|
|||
# Try to use labels from Control Panel.
|
||||
use_panel_aux_labels=no
|
||||
|
||||
# For the buttons below, if you have a Variable Speed Pump, you can associate it with the device so RPM/GPH/WATTS are displayed
|
||||
# Format is button_01_pumpID=0x60. Leave blank if you don't have a VSP.
|
||||
# Pentair pump ID's
|
||||
# 0x60 to 0x6F (0x60, 0x61 0x61, 0x62, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F)
|
||||
# Jandy pump ID's
|
||||
# 0x78, 0x79, 0x7A, 0x7B
|
||||
|
||||
# Labels for standard butons (shown in web UI), and domoticz idx's
|
||||
button_01_label=Filter Pump
|
||||
#button_01_dzidx=37
|
||||
#button_01_PDA_label=FILTER PUMP
|
||||
#button_01_pumpID=0x60
|
||||
|
||||
button_02_label=Spa Mode
|
||||
#button_02_dzidx=38
|
||||
|
|
Binary file not shown.
133
serial_logger.c
133
serial_logger.c
|
@ -45,6 +45,76 @@ void intHandler(int dummy) {
|
|||
exit(0);
|
||||
}
|
||||
|
||||
#define MASTER " <-- Master control panel"
|
||||
#define SWG " <-- Salt Water Generator (Aquarite mode)"
|
||||
#define KEYPAD " <-- RS Keypad"
|
||||
#define SPA_R " <-- Spa remote"
|
||||
#define AQUA " <-- Aqualink (iAqualink?)"
|
||||
#define HEATER " <-- LX Heater"
|
||||
#define ONE_T " <-- Onetouch device"
|
||||
#define PC_DOCK " <-- PC Interface (RS485 to RS232)"
|
||||
#define PDA " <-- PDA Remote"
|
||||
#define EPUMP " <-- Jandy VSP ePump"
|
||||
#define CHEM " <-- Chemlink"
|
||||
|
||||
#define UNKNOWN " <-- Unknown Device"
|
||||
|
||||
#define P_VSP " <-- Pentair VSP"
|
||||
#define P_MASTER " <-- Pentair Master (Probably Jandy RS Control Panel)"
|
||||
#define P_SWG " <-- Salt Water Generator (Jandy mode)"
|
||||
#define P_BCAST " <-- Broadcast address"
|
||||
#define P_RCTL " <-- Remote wired controller"
|
||||
#define P_RWCTL " <-- Remote wireless controller (Screen Logic)"
|
||||
#define P_CTL " <-- Pool controller (EasyTouch)"
|
||||
|
||||
const char *getDevice(unsigned char ID) {
|
||||
if (ID >= 0x00 && ID <= 0x03)
|
||||
return MASTER;
|
||||
if (ID >= 0x08 && ID <= 0x0B)
|
||||
return KEYPAD;
|
||||
if (ID >= 0x50 && ID <= 0x53)
|
||||
return SWG;
|
||||
if (ID >= 0x20 && ID <= 0x23)
|
||||
return SPA_R;
|
||||
if (ID >= 0x30 && ID <= 0x33)
|
||||
return AQUA;
|
||||
if (ID >= 0x38 && ID <= 0x3b)
|
||||
return HEATER;
|
||||
if (ID >= 0x40 && ID <= 0x43)
|
||||
return ONE_T;
|
||||
if (ID >= 0x58 && ID <= 0x5B)
|
||||
return PC_DOCK;
|
||||
if (ID >= 0x60 && ID <= 0x63)
|
||||
return PDA;
|
||||
if (ID >= 0x70 && ID <= 0x73)
|
||||
return EPUMP;
|
||||
if (ID >= 0x80 && ID <= 0x83)
|
||||
return CHEM;
|
||||
//if (ID == 0x08)
|
||||
// return KEYPAD;
|
||||
|
||||
return UNKNOWN;
|
||||
}
|
||||
|
||||
const char *getPentairDevice(unsigned char ID) {
|
||||
if (ID >= 0x60 && ID <= 0x6F)
|
||||
return P_VSP;
|
||||
if (ID == 0x02)
|
||||
return P_SWG;
|
||||
if (ID == 0x10)
|
||||
return P_MASTER;
|
||||
if (ID == 0x0F)
|
||||
return P_BCAST;
|
||||
if (ID == 0x10)
|
||||
return P_CTL;
|
||||
if (ID == 0x20)
|
||||
return P_RCTL;
|
||||
if (ID == 0x22)
|
||||
return P_RWCTL;
|
||||
|
||||
return UNKNOWN;
|
||||
}
|
||||
|
||||
void advance_cursor() {
|
||||
static int pos=0;
|
||||
char cursor[4]={'/','-','\\','|'};
|
||||
|
@ -59,6 +129,10 @@ bool canUse(unsigned char ID) {
|
|||
if (ID == _goodID[i])
|
||||
return true;
|
||||
}
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (ID == _goodPDAID[i])
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
char* canUseExtended(unsigned char ID) {
|
||||
|
@ -150,7 +224,9 @@ int main(int argc, char *argv[]) {
|
|||
int i = 0;
|
||||
bool found;
|
||||
serial_id_log slog[SLOG_MAX];
|
||||
serial_id_log pent_slog[SLOG_MAX];
|
||||
int sindex = 0;
|
||||
int pent_sindex = 0;
|
||||
int received_packets = 0;
|
||||
int logPackets = PACKET_MAX;
|
||||
int logLevel = LOG_NOTICE;
|
||||
|
@ -233,22 +309,36 @@ int main(int argc, char *argv[]) {
|
|||
if (logLevel > LOG_NOTICE)
|
||||
printPacket(lastID, packet_buffer, packet_length);
|
||||
|
||||
if (packet_buffer[PKT_DEST] != DEV_MASTER) {
|
||||
if (getProtocolType(packet_buffer) == PENTAIR) {
|
||||
found = false;
|
||||
for (i = 0; i <= pent_sindex; i++) {
|
||||
if (pent_slog[i].ID == packet_buffer[PEN_PKT_FROM]) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found == false) {
|
||||
pent_slog[pent_sindex].ID = packet_buffer[PEN_PKT_FROM];
|
||||
pent_slog[pent_sindex].inuse = true;
|
||||
pent_sindex++;
|
||||
}
|
||||
} else {
|
||||
if (packet_buffer[PKT_DEST] != DEV_MASTER) {
|
||||
found = false;
|
||||
for (i = 0; i <= sindex; i++) {
|
||||
if (slog[i].ID == packet_buffer[PKT_DEST]) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found != true && sindex < SLOG_MAX) {
|
||||
}
|
||||
if (found != true && sindex < SLOG_MAX) {
|
||||
slog[sindex].ID = packet_buffer[PKT_DEST];
|
||||
slog[sindex].inuse = false;
|
||||
sindex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (packet_buffer[PKT_DEST] == DEV_MASTER /*&& packet_buffer[PKT_CMD] == CMD_ACK*/) {
|
||||
if (packet_buffer[PKT_DEST] == DEV_MASTER /*&& packet_buffer[PKT_CMD] == CMD_ACK*/) {
|
||||
//logMessage(LOG_NOTICE, "ID is in use 0x%02hhx %x\n", lastID, lastID);
|
||||
for (i = 0; i <= sindex; i++) {
|
||||
if (slog[i].ID == lastID) {
|
||||
|
@ -256,10 +346,10 @@ int main(int argc, char *argv[]) {
|
|||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
lastID = packet_buffer[PKT_DEST];
|
||||
}
|
||||
|
||||
lastID = packet_buffer[PKT_DEST];
|
||||
}
|
||||
received_packets++;
|
||||
|
||||
// NSF TESTING
|
||||
|
@ -285,17 +375,32 @@ int main(int argc, char *argv[]) {
|
|||
//sleep(1);
|
||||
}
|
||||
|
||||
logMessage(LOG_DEBUG, "\n");
|
||||
logMessage(LOG_DEBUG, "\n\n");
|
||||
if (logLevel < LOG_DEBUG)
|
||||
printf("\n\n");
|
||||
|
||||
if (sindex >= SLOG_MAX)
|
||||
logMessage(LOG_ERR, "Ran out of storage, some ID's were not captured, please increase SLOG_MAX and recompile\n");
|
||||
logMessage(LOG_NOTICE, "ID's found\n");
|
||||
logMessage(LOG_NOTICE, "Jandy ID's found\n");
|
||||
for (i = 0; i < sindex; i++) {
|
||||
//logMessage(LOG_NOTICE, "ID 0x%02hhx is %s %s\n", slog[i].ID, (slog[i].inuse == true) ? "in use" : "not used",
|
||||
// (slog[i].inuse == false && canUse(slog[i].ID) == true)? " <-- can use for Aqualinkd" : "");
|
||||
|
||||
logMessage(LOG_NOTICE, "ID 0x%02hhx is %s %s\n", slog[i].ID, (slog[i].inuse == true) ? "in use" : "not used",
|
||||
(slog[i].inuse == false)?canUseExtended(slog[i].ID):"");
|
||||
if (logLevel >= LOG_DEBUG || slog[i].inuse == true || canUse(slog[i].ID) == true) {
|
||||
logMessage(LOG_NOTICE, "ID 0x%02hhx is %s %s\n", slog[i].ID, (slog[i].inuse == true) ? "in use" : "not used",
|
||||
(slog[i].inuse == false)?canUseExtended(slog[i].ID):getDevice(slog[i].ID));
|
||||
}
|
||||
}
|
||||
|
||||
if (pent_sindex > 0) {
|
||||
logMessage(LOG_NOTICE, "\n\n");
|
||||
logMessage(LOG_NOTICE, "Pentair ID's found\n");
|
||||
}
|
||||
for (i=0; i < pent_sindex; i++) {
|
||||
logMessage(LOG_NOTICE, "ID 0x%02hhx is %s %s\n", pent_slog[i].ID, (pent_slog[i].inuse == true) ? "in use" : "not used",
|
||||
(pent_slog[i].inuse == false)?canUseExtended(pent_slog[i].ID):getPentairDevice(pent_slog[i].ID));
|
||||
}
|
||||
|
||||
logMessage(LOG_NOTICE, "\n\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue