mirror of https://github.com/sfeakes/AqualinkD.git
V3 dev updates
parent
7913ee5959
commit
abf1e30f6c
|
|
@ -155,10 +155,10 @@ NEED TO FIX FOR THIS RELEASE.
|
|||
* Autoconfigure will *try* to work for PDA panels.
|
||||
* Added example script to generate HTTPS certificates. (./extras/generate-certs.sh)
|
||||
* Cleaned up exit & errors when running as daemon and docker.
|
||||
* Fixed issues with external sensors and homekit.
|
||||
* Added preliminary support for Jandy Infinite water color lights
|
||||
- Need to finish off :-
|
||||
* HAT serial optimizations broke some USB serial adapters
|
||||
* Finish off assigning light mode & functionality to a vbutton (for Jandy Infinite water color support )
|
||||
* cleanup rs_msg_utils.c
|
||||
* WebUI Config in aqmanager.
|
||||
|
||||
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
|
|
@ -62,6 +62,7 @@
|
|||
#define LIGHT_DIMMER_VALUE_TOPIC "/brightness"
|
||||
|
||||
#define SENSOR_TOPIC "Sensor"
|
||||
#define FULL_SENSOR_TOPIC SENSOR_TOPIC "/"
|
||||
|
||||
/*
|
||||
#define AIR_TEMPERATURE "Air"
|
||||
|
|
|
|||
|
|
@ -11,13 +11,19 @@
|
|||
Jandy Colors
|
||||
Jandy LED Light
|
||||
Sam/SL
|
||||
Color Logic
|
||||
Color Logic
|
||||
Intelibright
|
||||
Haywood Universal Color
|
||||
|
||||
*/
|
||||
bool isShowMode(const char *mode);
|
||||
|
||||
/*
|
||||
Jandy Colors
|
||||
Jandy LED Light
|
||||
SAm/SAL Light
|
||||
IntelliBrite
|
||||
Hayw Univ Color
|
||||
*/
|
||||
|
||||
/****** This list MUST be in order of clight_type enum *******/
|
||||
char *_color_light_options[NUMBER_LIGHT_COLOR_TYPES][LIGHT_COLOR_OPTIONS] =
|
||||
|
|
|
|||
|
|
@ -73,6 +73,8 @@ unsigned char _currentPage;
|
|||
unsigned char _lastMsgType = 0x00;
|
||||
//unsigned char _last_kick_type = -1;
|
||||
|
||||
static char _popupMsg[AQ_MSGLONGLEN + 1];
|
||||
|
||||
int _deviceStatusLines = 0;
|
||||
char _homeStatus[IAQ_STATUS_PAGE_LINES][AQ_MSGLEN+1];
|
||||
char _deviceStatus[IAQ_STATUS_PAGE_LINES][AQ_MSGLEN+1];
|
||||
|
|
@ -89,6 +91,11 @@ unsigned char iaqtLastMsg()
|
|||
return _lastMsgType;
|
||||
}
|
||||
|
||||
const char *iaqtPopupMsg()
|
||||
{
|
||||
return _popupMsg;
|
||||
}
|
||||
|
||||
void set_iaqtouch_lastmsg(unsigned char msgtype)
|
||||
{
|
||||
_lastMsgType = msgtype;
|
||||
|
|
@ -836,7 +843,7 @@ bool process_iaqtouch_packet(unsigned char *packet, int length, struct aqualinkd
|
|||
//static int _pollCnt = 0;
|
||||
//static int probesSinceLastPageCMD=0;
|
||||
static bool gotStatus = true;
|
||||
static char message[AQ_MSGLONGLEN + 1];
|
||||
//static char message[AQ_MSGLONGLEN + 1];
|
||||
bool fake_pageend = false;
|
||||
//char buff[1024];
|
||||
// NSF Take this out
|
||||
|
|
@ -967,17 +974,17 @@ bool process_iaqtouch_packet(unsigned char *packet, int length, struct aqualinkd
|
|||
} else if (packet[PKT_CMD] == CMD_IAQ_MSG_LONG) {
|
||||
char *sp;
|
||||
// Set disply message if PDA panel
|
||||
memset(message, 0, AQ_MSGLONGLEN + 1);
|
||||
rsm_strncpy(message, packet + 6, AQ_MSGLONGLEN, length-9);
|
||||
LOG(IAQT_LOG,LOG_NOTICE, "Popup message '%s'\n",message);
|
||||
memset(_popupMsg, 0, AQ_MSGLONGLEN + 1);
|
||||
rsm_strncpy(_popupMsg, packet + 6, AQ_MSGLONGLEN, length-9);
|
||||
LOG(IAQT_LOG,LOG_NOTICE, "Popup message '%s'\n",_popupMsg);
|
||||
|
||||
// Change this message, since you can't press OK. 'Light will turn off in 5 seconds. To change colors press Ok now.'
|
||||
if ((sp = rsm_strncasestr(message, "To change colors press Ok now", strlen(message))) != NULL)
|
||||
if ((sp = rsm_strncasestr(_popupMsg, "To change colors press Ok now", strlen(_popupMsg))) != NULL)
|
||||
{
|
||||
*sp = '\0';
|
||||
}
|
||||
|
||||
SET_IF_CHANGED_STRCPY(aqdata->last_display_message, message, aqdata->is_dirty); // Also display the message on web UI
|
||||
SET_IF_CHANGED_STRCPY(aqdata->last_display_message, _popupMsg, aqdata->is_dirty); // Also display the message on web UI
|
||||
|
||||
if (in_programming_mode(aqdata)) {
|
||||
SET_IF_CHANGED(aqdata->is_display_message_programming, true, aqdata->is_dirty);
|
||||
|
|
@ -1070,6 +1077,13 @@ if not programming && poll packet {
|
|||
// But may be better to simply increase FULL_STATUS_POLL_COUNT when it's not enabled.
|
||||
uint8_t nextPageRequestKey = KEY_IAQTCH_HOME;
|
||||
|
||||
if (_pollCnt > FULL_STATUS_POLL_COUNT + 5) {
|
||||
LOG(IAQT_LOG,LOG_ERR,"Poll count=%d, too high, looks like page is stuck\n",_pollCnt);
|
||||
_pollCnt=0;
|
||||
} else {
|
||||
LOG(IAQT_LOG,LOG_DEBUG,"Poll count=%d, Curent Page=0x%02hhx\n",_pollCnt, _currentPage);
|
||||
}
|
||||
|
||||
if (_pollCnt++ > FULL_STATUS_POLL_COUNT) {
|
||||
switch(_currentPage) {
|
||||
case IAQ_PAGE_DEVICES:
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ struct iaqt_page_button *iaqtFindButtonByIndex(int index);
|
|||
const char *iaqtGetMessageLine(int index);
|
||||
const char *iaqtGetTableInfoLine(int index);
|
||||
unsigned char iaqtLastMsg();
|
||||
const char *iaqtPopupMsg();
|
||||
const char *iaqt_page_name(const unsigned char page);
|
||||
int num2iaqtRSset (unsigned char* packetbuffer, int num, bool pad4unknownreason);
|
||||
int char2iaqtRSset (unsigned char* packetbuffer, char *msg, int msg_len);
|
||||
|
|
|
|||
|
|
@ -836,21 +836,41 @@ PRINTF("******** WAIT for next page\n");
|
|||
pButton = iaqtFindButtonByLabel(mode_name);
|
||||
|
||||
if (pButton == NULL) {
|
||||
LOG(IAQT_LOG, LOG_ERR, "IAQ Touch did find color '%s' in color light page\n",mode_name);
|
||||
LOG(IAQT_LOG, LOG_ERR, "IAQ Touch didn't find color '%s' in color light page\n",mode_name);
|
||||
goto f_end;
|
||||
}
|
||||
|
||||
LOG(IAQT_LOG, LOG_DEBUG, "IAQ Touch found '%s' sending keycode '0x%02hhx'\n", mode_name, pButton->keycode);
|
||||
LOG(IAQT_LOG, LOG_DEBUG, "IAQ Touch found '%s' sending keycode '0x%02hhx' = '0x%02hhx' for light selection\n", mode_name, pButton->keycode, pButton->keycode+16);
|
||||
PRINTF("******** current page is '0x%02hhx'\n",iaqtCurrentPage());
|
||||
send_aqt_cmd(pButton->keycode);
|
||||
// NSF Key code is +16 for some reason. ie key 0x07=(send 0x17). 0x0a=(send 0x1a)
|
||||
send_aqt_cmd(pButton->keycode + 16);
|
||||
waitfor_iaqt_queue2empty();
|
||||
// Wait for popup message to disapera
|
||||
// This is iAq Popup messag | HEX: 0x10|0x02|0x33|0x2c|0x00|0x01|0x50|0x6c|0x65|0x61|0x73|0x65|0x20|0x77|0x61|0x69|0x74|0x2e|0x2e|0x2e|0x0a|0x20|0x43|0x79|0x63|0x6c|0x69|0x6e|0x67|0x20|0x74|0x6f|0x20|0x63|0x68|0x6f|0x73|0x65|0x6e|0x20|0x63|0x6f|0x6c|0x6f|0x72|0x2e|0x00|0x00|0x00|0x00|0x2e|0x10|0x03|
|
||||
// This is popup message clear | HEX: 0x10|0x02|0x33|0x2c|0x00|0x00|0x20|0x00|0x00|0x00|0x00|0x91|0x10|0x03|
|
||||
// 5th bit 0x00 = clear. (anything else message)
|
||||
|
||||
unsigned char msg;
|
||||
int i=0;
|
||||
while ( (msg = waitfor_iaqt_nextMessage(aqdata, CMD_IAQ_MSG_LONG)) != NUL) {
|
||||
const char *pmsg = iaqtPopupMsg();
|
||||
PRINTF("******** popupMsg = %s ********\n",pmsg);
|
||||
if (pmsg[0] == ' ') {
|
||||
PRINTF("******** popupMsg clear ********\n");
|
||||
break;
|
||||
}
|
||||
if (++i > 5) {
|
||||
LOG(IAQT_LOG, LOG_WARNING, "IAQ Touch didn't see correct messages, color may no change\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*
|
||||
unsigned char page;
|
||||
PRINTF("******** current page is '0x%02hhx'\n",iaqtCurrentPage());
|
||||
while ( (page = waitfor_iaqt_nextPage(aqdata)) != NUL) {
|
||||
PRINTF("******** next page is '0x%02hhx'\n",page); // page = 0x48 IAQ_PAGE_COLOR_LIGHT
|
||||
}
|
||||
|
||||
*/
|
||||
//LOG(IAQT_LOG, LOG_ERR, "IAQ Touch WAIYING FOR 1 MESSAGES\n");
|
||||
//waitfor_iaqt_messages(aqdata, 1);
|
||||
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@
|
|||
#include "serialadapter.h"
|
||||
#include "rs_msg_utils.h"
|
||||
|
||||
#include "color_lights.h"
|
||||
|
||||
#define IAQUA_QLEN 20
|
||||
|
||||
typedef struct iaqulnkcmd
|
||||
|
|
@ -330,6 +332,83 @@ void iAqSetButtonState(struct aqualinkdata *aqdata, int index, const unsigned ch
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
const char* colorLightNameFromHex(unsigned char hexid) {
|
||||
switch (hexid) {
|
||||
case 0x01:
|
||||
return "Jandy Color Light";
|
||||
break;
|
||||
case 0x02:
|
||||
return "Sam/SAL light";
|
||||
break;
|
||||
case 0x03:
|
||||
return "Color Logic (Guess)";
|
||||
break;
|
||||
case 0x04:
|
||||
return "Jandy LED Light";
|
||||
break;
|
||||
case 0x05:
|
||||
return "Intelibrite Light";
|
||||
break;
|
||||
case 0x06:
|
||||
return "Haywood universal color Light";
|
||||
break;
|
||||
default:
|
||||
return "Unknown Color Light";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const char* decodeTypeBits(unsigned char BIT2, unsigned char BIT3, unsigned char BIT4) {
|
||||
switch (BIT3) {
|
||||
case 0x01:
|
||||
return "Dimable light";
|
||||
break;
|
||||
case 0x02:
|
||||
return colorLightNameFromHex(BIT4);
|
||||
break;
|
||||
case 0x00:
|
||||
default:
|
||||
return "";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
This is not right. BIT2 is not the mode. it's always 0x07 for color light
|
||||
|
||||
const char* getColorLightMode(unsigned char BIT2, unsigned char BIT3, unsigned char BIT4) {
|
||||
// BIT2 = Mode
|
||||
// BIT4 = Light Type.
|
||||
switch (BIT4) {
|
||||
case 0x01:
|
||||
return light_mode_name(LC_JANDY, BIT2, IAQUALNK); //"Jandy Color Light";
|
||||
break;
|
||||
case 0x02:
|
||||
return light_mode_name(LC_SAL, BIT2, IAQUALNK); //"Sam/SAL light";
|
||||
break;
|
||||
case 0x03:
|
||||
return light_mode_name(LC_CLOGIG, BIT2, IAQUALNK); //"Color Logic (Guess)";
|
||||
break;
|
||||
case 0x04:
|
||||
return light_mode_name(LC_JANDYLED, BIT2, IAQUALNK); //"Jandy LED Light";
|
||||
break;
|
||||
case 0x05:
|
||||
return light_mode_name(LC_INTELLIB, BIT2, IAQUALNK); //"Intelibrite Light";
|
||||
break;
|
||||
case 0x06:
|
||||
return light_mode_name(LC_HAYWCL, BIT2, IAQUALNK); //"Haywood universal color Light";
|
||||
break;
|
||||
default:
|
||||
return "Unknown Mode";
|
||||
break;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
Status packets are requested on iAqualink ID 0xA? but received on AqualinkTouch ID 0x3?
|
||||
They are also sent when iAqualink is connected and a device changes.
|
||||
|
|
@ -509,6 +588,31 @@ bool process_iAqualinkStatusPacket(unsigned char *packet, int length, struct aqu
|
|||
}
|
||||
else if (packet[PKT_CMD] == CMD_IAQ_AUX_STATUS)
|
||||
{
|
||||
/*
|
||||
Example output. We can get color light information from here.
|
||||
Aux7 bit2=0x07. (This is not the MODE. it's always 0x07 for color light)
|
||||
Bit3 = (0x01=Dimmer, 0x02=ColorLight)
|
||||
Bit4 = (Type of color light)
|
||||
Info: iAqualink2:Cleaner = On | bit1=0x01 bit2=0x01 bit3=0x00 bit4=0x00
|
||||
Info: iAqualink2:Waterfall = On | bit1=0x01 bit2=0x01 bit3=0x00 bit4=0x00
|
||||
Info: iAqualink2:Air Blower = Off | bit1=0x00 bit2=0x01 bit3=0x00 bit4=0x00
|
||||
Info: iAqualink2:Pool Light = Off | bit1=0x00 bit2=0x01 bit3=0x00 bit4=0x00
|
||||
Info: iAqualink2:Aux5 = Off | bit1=0x00 bit2=0x01 bit3=0x00 bit4=0x00
|
||||
Info: iAqualink2:Aux6 = Off | bit1=0x00 bit2=0x01 bit3=0x00 bit4=0x00
|
||||
Info: iAqualink2:Aux7 = On | bit1=0x01 bit2=0x07 bit3=0x02 bit4=0x01
|
||||
Info: iAqualink2:Extra Aux = Off | bit1=0x00 bit2=0x01 bit3=0x00 bit4=0x00
|
||||
|
||||
Jandy Color = JC
|
||||
Info: iAqualink2:Aux7 = On | bit1=0x01 bit2=0x07 bit3=0x02 bit4=0x01
|
||||
Jandy LED = JL
|
||||
Info: iAqualink2:Aux7 = On | bit1=0x01 bit2=0x07 bit3=0x02 bit4=0x04
|
||||
Sam/SAL = SL
|
||||
Info: iAqualink2:Aux7 = On | bit1=0x01 bit2=0x07 bit3=0x02 bit4=0x02
|
||||
Intelibrite = IB
|
||||
Info: iAqualink2:Aux7 = On | bit1=0x01 bit2=0x07 bit3=0x02 bit4=0x05
|
||||
Haywood universal color = HU
|
||||
Info: iAqualink2:Aux7 = On | bit1=0x01 bit2=0x07 bit3=0x02 bit4=0x06
|
||||
*/
|
||||
logPacket(IAQL_LOG, LOG_INFO, packet, length, true);
|
||||
// Look at notes in iaqualink.c for how this packet is made up
|
||||
// Since this is so similar to above CMD_IAQ_1TOUCH_STATUS, we should look at using same logic for both.
|
||||
|
|
@ -521,7 +625,15 @@ bool process_iAqualinkStatusPacket(unsigned char *packet, int length, struct aqu
|
|||
int labellen = packet[status + 4];
|
||||
if (labelstart + labellen < length)
|
||||
{
|
||||
LOG(IAQL_LOG, LOG_INFO, "%-15.*s = %s | bit1=0x%02hhx bit2=0x%02hhx bit3=0x%02hhx bit4=0x%02hhx\n", labellen, &packet[labelstart], (packet[status] == 0x00 ? "Off" : "On "), packet[status], packet[status + 1], packet[status + 2], packet[status + 3]);
|
||||
LOG(IAQL_LOG, LOG_INFO, "%-15.*s = %s | bit1=0x%02hhx bit2=0x%02hhx bit3=0x%02hhx bit4=0x%02hhx %s\n",
|
||||
labellen,
|
||||
&packet[labelstart],
|
||||
(packet[status] == 0x00 ? "Off" : "On "),
|
||||
packet[status], packet[status + 1],
|
||||
packet[status + 2],
|
||||
packet[status + 3],
|
||||
decodeTypeBits(packet[status + 1], packet[status + 2], packet[status + 3])
|
||||
);
|
||||
}
|
||||
if (isPDA_PANEL) {
|
||||
for (int bi=2 ; bi < aqdata->total_buttons ; bi++) {
|
||||
|
|
@ -544,6 +656,8 @@ bool process_iAqualinkStatusPacket(unsigned char *packet, int length, struct aqu
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool process_iaqualink_packet(unsigned char *packet, int length, struct aqualinkdata *aqdata)
|
||||
{
|
||||
|
||||
|
|
|
|||
|
|
@ -556,26 +556,30 @@ int build_device_JSON(struct aqualinkdata *aqdata, char* buffer, int size, bool
|
|||
temperatureUOM t_uom = getTemperatureUOM(aqdata->sensors[i].uom);
|
||||
|
||||
if (aqdata->sensors[i].uom == NULL) {
|
||||
length += sprintf(buffer+length, "{\"type\": \"value\", \"id\": \"%s\", \"name\": \"%s\", \"state\": \"on\", \"value\": \"%.*f\", \"uom\": \"\" },",
|
||||
length += sprintf(buffer+length, "{\"type\": \"value\", \"id\": \"%s%s\", \"name\": \"%s\", \"state\": \"on\", \"value\": \"%.*f\", \"uom\": \"\" },",
|
||||
FULL_SENSOR_TOPIC,
|
||||
aqdata->sensors[i].ID,
|
||||
aqdata->sensors[i].label,
|
||||
2,
|
||||
aqdata->sensors[i].value);
|
||||
} else if (t_uom == UNKNOWN) {
|
||||
length += sprintf(buffer+length, "{\"type\": \"value\", \"id\": \"%s\", \"name\": \"%s\", \"state\": \"on\", \"value\": \"%.*f\", \"uom\": \"%s\" },",
|
||||
length += sprintf(buffer+length, "{\"type\": \"value\", \"id\": \"%s%s\", \"name\": \"%s\", \"state\": \"on\", \"value\": \"%.*f\", \"uom\": \"%s\" },",
|
||||
FULL_SENSOR_TOPIC,
|
||||
aqdata->sensors[i].ID,
|
||||
aqdata->sensors[i].label,
|
||||
2,
|
||||
aqdata->sensors[i].value,
|
||||
aqdata->sensors[i].uom);
|
||||
} else if ( !homekit && (aqdata->temp_units == FAHRENHEIT && t_uom == CELSIUS) ) {
|
||||
length += sprintf(buffer+length, "{\"type\": \"temperature\", \"id\": \"%s\", \"name\": \"%s\", \"state\": \"on\", \"value\": \"%.*f\" },",
|
||||
length += sprintf(buffer+length, "{\"type\": \"temperature\", \"id\": \"%s%s\", \"name\": \"%s\", \"state\": \"on\", \"value\": \"%.*f\" },",
|
||||
FULL_SENSOR_TOPIC,
|
||||
aqdata->sensors[i].ID,
|
||||
aqdata->sensors[i].label,
|
||||
2,
|
||||
degCtoF(aqdata->sensors[i].value));
|
||||
} else {
|
||||
length += sprintf(buffer+length, "{\"type\": \"temperature\", \"id\": \"%s\", \"name\": \"%s\", \"state\": \"%s\", \"value\": \"%.*f\" },",
|
||||
length += sprintf(buffer+length, "{\"type\": \"temperature\", \"id\": \"%s%s\", \"name\": \"%s\", \"state\": \"%s\", \"value\": \"%.*f\" },",
|
||||
FULL_SENSOR_TOPIC,
|
||||
aqdata->sensors[i].ID,
|
||||
aqdata->sensors[i].label,
|
||||
"on",
|
||||
|
|
|
|||
|
|
@ -739,7 +739,7 @@ void publish_mqtt_discovery(struct aqualinkdata *aqdata, struct mg_connection *n
|
|||
for (i=0; i < aqdata->num_sensors; i++) {
|
||||
//sprintf(idbuf, "%s_%s","sensor",aqdata->sensors[i].label);
|
||||
//sprintf(topic, "%s/%s",SENSOR_TOPIC,aqdata->sensors[i].label);
|
||||
sprintf(topic, "%s/%s",SENSOR_TOPIC,aqdata->sensors[i].ID);
|
||||
sprintf(topic, "%s%s",FULL_SENSOR_TOPIC,aqdata->sensors[i].ID);
|
||||
rsm_char_replace(idbuf, topic, "/", "_");
|
||||
//sprintf(msg, HASSIO_SENSOR_DISCOVER,connections,_aqconfig_.mqtt_aq_topic,idbuf,aqdata->sensors[i].label,_aqconfig_.mqtt_aq_topic,topic, "°C", "mdi:thermometer");
|
||||
// Use HASSIO_TEMP_SENSOR_DISCOVER over HASSIO_SENSOR_DISCOVER since it has device class temperature and HA will convert automatically.
|
||||
|
|
|
|||
|
|
@ -940,7 +940,7 @@ void mqtt_broadcast_aqualinkstate(struct mg_connection *nc)
|
|||
for (i=0; i < _aqualink_data->num_sensors; i++) {
|
||||
if ( _aqualink_data->sensors[i].value != TEMP_UNKNOWN && _last_mqtt_aqualinkdata.sensors[i].value != _aqualink_data->sensors[i].value) {
|
||||
char topic[50];
|
||||
sprintf(topic, "%s/%s", SENSOR_TOPIC, _aqualink_data->sensors[i].ID);
|
||||
sprintf(topic, "%s%s", FULL_SENSOR_TOPIC, _aqualink_data->sensors[i].ID);
|
||||
send_mqtt_float_msg(nc, topic, _aqualink_data->sensors[i].value);
|
||||
_last_mqtt_aqualinkdata.sensors[i].value = _aqualink_data->sensors[i].value;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue