Updates for V3

pull/476/head
sfeakes 2025-09-29 19:04:51 -05:00
parent a9262b8265
commit 3c265d5d16
18 changed files with 238 additions and 88 deletions

View File

@ -56,8 +56,8 @@ DBGFLAGS = -g -O0 -Wall -D AQ_DEBUG -D AQ_TM_DEBUG
#MGFLAGS = -D MG_ENABLE_HTTP_SSI=0 -D MG_ENABLE_DIRECTORY_LISTING=0 -D MG_ENABLE_HTTP_CGI=0
# Mongoose 7.19 flags
#MGFLAGS = -D MG_TLS = 2 #(2=MG_TLS_OPENSSL. 3=MG_TLS_BUILTIN)
MGFLAGS =
#MGFLAGS = -D MG_TLS=2 #(2=MG_TLS_OPENSSL. 3=MG_TLS_BUILTIN) --or-- -DMG_TLS=MG_TLS_BUILTIN
MGFLAGS = -D MG_TLS=3
# Detect OS and set some specifics
ifeq ($(OS),Windows_NT)

View File

@ -139,6 +139,7 @@ NEED TO FIX FOR THIS RELEASE.
# Updates in 3.0.0 (dev)
* Serial optimization for AqualinkD HAT.
* upgraded network library ( HTTP(S), MQTT(S), WS )
* Added support for HTTPS and MQTTS
* Added options to force upgrades in aqmanager. (add ?upgrade or ?devupgrade to url to enable upgrade button)
* MQTT Discovery for all supporting hubs (HomeAssistant Domoticz Hubitat OpenHAB etc)
* Moved Domoticz support over to MQTT autodiscovery.
@ -157,7 +158,6 @@ NEED TO FIX FOR THIS RELEASE.
* With aqmanager is packet_logger still valid? (maybe for raw, but it's not been used in years)
* Get panel size and clean up the ap_panel code around config size/type and reported size/type
* WebUI Config in aqmanager.
* button pre-state was for domotics, delete
# Updates in 2.6.11 (Sept 14 2025)

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -162,8 +162,8 @@ int save_schedules_js(const char* inBuf, int inSize, char* outBuf, int outSize)
LOG(SCHD_LOG,LOG_DEBUG, "Write to cron Min:%s Hour:%s DayM:%s Month:%s DayW:%s URL:%s Value:%s\n",cline.minute,cline.hour,cline.daym,cline.month,cline.dayw,cline.url,cline.value);
//LOG(SCHD_LOG,LOG_INFO, "%s%s %s %s %s %s curl -s -S --show-error -o /dev/null localhost:%s%s -d value=%s -X PUT\n",(cline.enabled?"":"#"),cline.minute, cline.hour, cline.daym, cline.month, cline.dayw, _aqconfig_.socket_port, cline.url, cline.value);
//fprintf(fp, "%s%s %s %s %s %s root curl -s -S --show-error -o /dev/null localhost:%s%s -d value=%s -X PUT\n",(cline.enabled?"":"#"),cline.minute, cline.hour, cline.daym, cline.month, cline.dayw, _aqconfig_.socket_port, cline.url, cline.value);
LOG(SCHD_LOG,LOG_INFO, "%s%s %s %s %s %s curl -s -S --show-error -o /dev/null %s%s -d value=%s -X PUT\n",(cline.enabled?"":"#"),cline.minute, cline.hour, cline.daym, cline.month, cline.dayw, (iface->localurl==NULL?_aqconfig_.listen_address:iface->localurl), cline.url, cline.value);
fprintf(fp, "%s%s %s %s %s %s root curl -s -S --show-error -o /dev/null %s%s -d value=%s -X PUT\n",(cline.enabled?"":"#"),cline.minute, cline.hour, cline.daym, cline.month, cline.dayw, (iface->localurl==NULL?_aqconfig_.listen_address:iface->localurl), cline.url, cline.value);
LOG(SCHD_LOG,LOG_INFO, "%s%s %s %s %s %s curl -s -S --show-error %s -o /dev/null %s%s -d value=%s -X PUT\n",(cline.enabled?"":"#"),cline.minute, cline.hour, cline.daym, cline.month, cline.dayw, (iface->isLocalurlTLS?"--insecure":""),(iface->localurl==NULL?_aqconfig_.listen_address:iface->localurl), cline.url, cline.value);
fprintf(fp, "%s%s %s %s %s %s root curl -s -S --show-error %s -o /dev/null %s%s -d value=%s -X PUT\n",(cline.enabled?"":"#"),cline.minute, cline.hour, cline.daym, cline.month, cline.dayw, (iface->isLocalurlTLS?"--insecure":""),(iface->localurl==NULL?_aqconfig_.listen_address:iface->localurl), cline.url, cline.value);
}
}

View File

@ -22,9 +22,11 @@
#include <sys/mount.h>
#include <sys/statvfs.h>
#include <sys/wait.h>
#include <stdarg.h>
#include "aqualink.h"
#include "aq_scheduler.h"
#include "aq_systemutils.h"
bool remount_root_ro(bool readonly)
{
@ -247,4 +249,68 @@ bool run_aqualinkd_upgrade(uint8_t type)
//printf("Command execution complete.\n");
LOG(AQUA_LOG, LOG_NOTICE, "AqualinkD is upgrading!");
return true;
}
}
#if MG_TLS > 0
char* read_pem_file(const char* fmt, ...) {
char filepath[1024];
// Build file path from format + arguments
va_list args;
va_start(args, fmt);
vsnprintf(filepath, sizeof(filepath), fmt, args);
va_end(args);
FILE* file = fopen(filepath, "rb");
if (!file) {
LOG(AQUA_LOG, LOG_ERR, "Failed to open file %s\n",filepath);
return NULL;
}
// Move to end to check file size
if (fseek(file, 0, SEEK_END) != 0) {
LOG(AQUA_LOG, LOG_ERR, "fseek failed on %s\n",filepath);
fclose(file);
return NULL;
}
long filesize = ftell(file);
if (filesize < 0) {
LOG(AQUA_LOG, LOG_ERR, "ftell failed on %s\n",filepath);
fclose(file);
return NULL;
}
// Enforce size sanity check
if (filesize > MAX_PEM_SIZE) {
LOG(AQUA_LOG, LOG_ERR, "Error: PEM file %s too large (%ld bytes, limit is %d)\n", filepath, filesize, MAX_PEM_SIZE);
fclose(file);
return NULL;
}
// Allocate buffer (+1 for null terminator)
char* buffer = malloc(filesize + 1);
if (!buffer) {
LOG(AQUA_LOG, LOG_ERR, "malloc failed on %s\n",filepath);
fclose(file);
return NULL;
}
rewind(file);
size_t bytesRead = fread(buffer, 1, filesize, file);
if (bytesRead != (size_t)filesize) {
LOG(AQUA_LOG, LOG_ERR, "fread failed on %s\n",filepath);
free(buffer);
fclose(file);
return NULL;
}
buffer[filesize] = '\0'; // Null-terminate
fclose(file);
return buffer;
}
#endif

View File

@ -1,6 +1,10 @@
#ifndef AQ_FILESYSTEM_H_
#define AQ_FILESYSTEM_H_
#if MG_TLS > 0
#define MAX_PEM_SIZE (64 * 1024) // 64KB limit
char* read_pem_file(const char* fmt, ...);
#endif
FILE *aq_open_file( char *filename, bool *ro_root, bool* created_file);
bool aq_close_file(FILE *file, bool ro_root);

View File

@ -71,7 +71,10 @@
//#define DEFAULT_CONFIG_FILE "./aqualinkd.conf"
static volatile bool _keepRunning = true;
#ifdef SELF_RESTART
static volatile bool _restart = false;
#endif
//char** _argv;
//static struct aqconfig _aqconfig_;
static struct aqualinkdata _aqualink_data;
@ -125,8 +128,10 @@ void intHandler(int sig_num)
execve(newargv[0], newargv, newenviron);
exit (EXIT_SUCCESS);
}
#ifdef SELF_RESTART
} else {
_restart = true;
#endif
}
}
//LOG(AQUA_LOG,LOG_NOTICE, "Stopping!\n");
@ -405,7 +410,9 @@ void printHelp()
int main(int argc, char *argv[])
{
#ifdef SELF_RESTART
_restart = false;
#endif
char defaultCfg[] = "./aqualinkd.conf";
char *cfgFile;
@ -538,6 +545,13 @@ int startup(char *self, char *cfgFile)
_aqualink_data.updated = true;
//_aqualink_data.chiller_button == NULL; // HATE having this here, but needs to be null before config.
//sd_journal_print(LOG_NOTICE, "Starting %s v%s !\n", AQUALINKD_NAME, AQUALINKD_VERSION);
// Setup a log level just to get this message out, will be re-set once config is read
setSystemLogLevel(LOG_NOTICE);
LOG(AQUA_LOG,LOG_NOTICE, "Starting %s v%s !\n", AQUALINKD_NAME, AQUALINKD_VERSION);
sprintf(_aqualink_data.self, basename(self));
clearDebugLogMask();
read_config(&_aqualink_data, cfgFile);
@ -561,7 +575,7 @@ int startup(char *self, char *cfgFile)
setLoggingPrms(_aqconfig_.log_level, _aqconfig_.deamonize, _aqconfig_.log_file, NULL);
#endif
LOG(AQUA_LOG,LOG_NOTICE, "Starting %s v%s !\n", AQUALINKD_NAME, AQUALINKD_VERSION);
//LOG(AQUA_LOG,LOG_NOTICE, "Starting %s v%s !\n", AQUALINKD_NAME, AQUALINKD_VERSION);
check_upgrade_log();
@ -1479,7 +1493,11 @@ void main_loop()
//if (_aqconfig_.debug_RSProtocol_packets) stopPacketLogger();
stopPacketLogger();
if (! _restart) { // Stop network if we are not restarting
#ifdef SELF_RESTART
if (! _restart)
#endif
{
// Stop network if we are not restarting
stop_net_services();
stop_sensors_thread();
}
@ -1488,7 +1506,7 @@ void main_loop()
close_serial_port(rs_fd);
// Clear webbrowser
//mg_mgr_free(&mgr);
/*
if (! _restart) {
// NSF need to run through config memory and clean up.
LOG(AQUA_LOG,LOG_NOTICE, "Exit!\n");
@ -1502,6 +1520,24 @@ void main_loop()
_restart = false;
startup(_self, _cfgFile);
}
*/
#ifdef SELF_RESTART
if (! _restart) {
LOG(AQUA_LOG,LOG_WARNING, "Waiting for process to fininish!\n");
delay(5 * 1000);
LOG(AQUA_LOG,LOG_WARNING, "Restarting!\n");
_keepRunning = true;
_restart = false;
startup(_self, _cfgFile);
} else
#else
{
// NSF need to run through config memory and clean up.
LOG(AQUA_LOG,LOG_NOTICE, "Exit!\n");
//exit(EXIT_FAILURE);
exit(exit_code);
}
#endif
}

View File

@ -191,6 +191,20 @@ void init_parameters (struct aqconfig * parms)
_cfgParams[_numCfgParams].config_mask |= CFG_FORCE_RESTART;
_cfgParams[_numCfgParams].default_value = (void *)_dcfg_web_port;
#if MG_TLS > 0
_numCfgParams++;
_cfgParams[_numCfgParams].value_ptr = &_aqconfig_.cert_dir;
_cfgParams[_numCfgParams].value_type = CFG_STRING;
_cfgParams[_numCfgParams].name = CFG_N_cert_dir;
_cfgParams[_numCfgParams].default_value = (void *)&_dcfg_null;
_cfgParams[_numCfgParams].config_mask |= CFG_ALLOW_BLANK;
//_cfgParams[_numCfgParams].config_mask |= CFG_READONLY;
_cfgParams[_numCfgParams].config_mask |= CFG_GRP_ADVANCED;
_cfgParams[_numCfgParams].config_mask |= CFG_FORCE_RESTART;
#endif
_numCfgParams++;
_cfgParams[_numCfgParams].value_ptr = &_aqconfig_.serial_port;
_cfgParams[_numCfgParams].value_type = CFG_STRING;
@ -319,11 +333,24 @@ void init_parameters (struct aqconfig * parms)
_cfgParams[_numCfgParams].default_value = (void *)_dcfg_mqtt_discovery;
_cfgParams[_numCfgParams].config_mask |= CFG_ALLOW_BLANK;
_numCfgParams++;
_numCfgParams++;
_cfgParams[_numCfgParams].value_ptr = &_aqconfig_.mqtt_discovery_use_mac;
_cfgParams[_numCfgParams].value_type = CFG_BOOL;
_cfgParams[_numCfgParams].name = CFG_N_mqtt_discovery_use_mac;
_cfgParams[_numCfgParams].default_value = (void *)&_dcfg_true;
#if MG_TLS > 0
_numCfgParams++;
_cfgParams[_numCfgParams].value_ptr = &_aqconfig_.mqtt_cert_dir;
_cfgParams[_numCfgParams].value_type = CFG_STRING;
_cfgParams[_numCfgParams].name = CFG_N_mqtt_cert_dir;
_cfgParams[_numCfgParams].default_value = (void *)&_dcfg_null;
_cfgParams[_numCfgParams].config_mask |= CFG_ALLOW_BLANK;
//_cfgParams[_numCfgParams].config_mask |= CFG_READONLY;
_cfgParams[_numCfgParams].config_mask |= CFG_GRP_ADVANCED;
_cfgParams[_numCfgParams].config_mask |= CFG_FORCE_RESTART;
#endif
_numCfgParams++;
_cfgParams[_numCfgParams].value_ptr = &_aqconfig_.mqtt_timed_update;

View File

@ -42,6 +42,10 @@
struct aqconfig
{
#if MG_TLS > 0
char *cert_dir; // for future
char *mqtt_cert_dir;
#endif
char *config_file;
char *listen_address;
char *serial_port;
@ -233,6 +237,8 @@ int _numCfgParams;
#define CFG_N_MG_log_level "mg_log_level"
#define CFG_V_log_level "[\"DEBUG_SERIAL\", \"DEBUG\", \"INFO\", \"NOTICE\", \"WARNING\", \"ERROR\"]"
#define CFG_N_listen_address "listen_address"
#define CFG_N_cert_dir "https_cert_dir"
#define CFG_N_web_directory "web_directory"
#define CFG_N_device_id "device_id"
@ -262,6 +268,7 @@ int _numCfgParams;
#define CFG_N_mqtt_discovery_topic "mqtt_discovery_topic"
#define CFG_N_mqtt_discovery_use_mac "mqtt_discovery_use_mac"
#define CFG_N_mqtt_timed_update "mqtt_timed_update"
#define CFG_N_mqtt_cert_dir "mqtt_cert_dir"
#define CFG_N_light_programming_mode "light_programming_mode"
#define CFG_N_light_programming_initial_on "light_programming_initial_on"

View File

@ -145,6 +145,13 @@ const net_iface *get_first_valid_interface()
} else {
LOG(NET_LOG, LOG_ERR,"Could not understand URL '%s' (unable to get protocol & port) \n",_aqconfig_.listen_address);
}
if (_aqconfig_.listen_address[(int)(protocol - _aqconfig_.listen_address)-1] == 's' ||
_aqconfig_.listen_address[(int)(protocol - _aqconfig_.listen_address)-1] == 'S')
info.isLocalurlTLS = true;
else
info.isLocalurlTLS = false;
LOG(NET_LOG, LOG_DEBUG, "Interface %s = %s, %s\n", info.name, info.ip, info.mac);
} else {
LOG(NET_LOG, LOG_ERR,"Could not find a valid network interface");

View File

@ -11,6 +11,7 @@ typedef struct {
char url[INET_ADDRSTRLEN + 14]; // allow for "https://" and ":80801"
char localurl[10 + 14]; // allow for "https://" "localhost" ":80801"
char rawmac[18];
bool isLocalurlTLS;
} net_iface;
/*

View File

@ -47,6 +47,7 @@
#include "version.h"
#include "color_lights.h"
#include "net_interface.h"
#include "aq_systemutils.h"
#ifdef AQ_PDA
#include "pda.h"
@ -57,6 +58,14 @@ struct mg_connection *mg_next(struct mg_mgr *s, struct mg_connection *conn) {
}
#define FAST_SUFFIX_3_CI(str, len, SUFFIX) ( \
(len) >= 3 && \
tolower((unsigned char)(str)[(len)-3]) == tolower((unsigned char)(SUFFIX)[0]) && \
tolower((unsigned char)(str)[(len)-2]) == tolower((unsigned char)(SUFFIX)[1]) && \
tolower((unsigned char)(str)[(len)-1]) == tolower((unsigned char)(SUFFIX)[2]) \
)
/*
#if defined AQ_DEBUG || defined AQ_TM_DEBUG
#include "timespec_subtract.h"
@ -111,7 +120,8 @@ static int is_websocket_aqmanager(const struct mg_connection *nc) {
return nc->aq_flags & AQ_MG_CON_WS_AQM;
}
static int is_mqtt(const struct mg_connection *nc) {
return nc->aq_flags & AQ_MG_CON_MQTT;
//return nc->aq_flags & AQ_MG_CON_MQTT;
return nc->aq_flags & (AQ_MG_CON_MQTT | AQ_MG_CON_MQTT_CONNECTING);
}
/*
static void set_mqtt(struct mg_connection *nc) {
@ -575,21 +585,6 @@ void send_mqtt_swg_state_msg(struct mg_connection *nc, char *dev_name, aqledstat
void send_mqtt_heater_state_msg(struct mg_connection *nc, char *dev_name, aqledstate state)
{
send_mqtt_led_state_msg(nc, dev_name, state, MQTT_ON, MQTT_OFF);
/*
static char mqtt_pub_topic[250];
sprintf(mqtt_pub_topic, "%s/%s",_aqconfig_.mqtt_aq_topic, dev_name);
if (state == ENABLE) {
send_mqtt(nc, mqtt_pub_topic, MQTT_OFF);
sprintf(mqtt_pub_topic, "%s/%s%s",_aqconfig_.mqtt_aq_topic, dev_name, ENABELED_SUBT);
send_mqtt(nc, mqtt_pub_topic, MQTT_ON);
} else {
send_mqtt(nc, mqtt_pub_topic, (state==OFF?MQTT_OFF:MQTT_ON));
sprintf(mqtt_pub_topic, "%s/%s%s",_aqconfig_.mqtt_aq_topic, dev_name, ENABELED_SUBT);
send_mqtt(nc, mqtt_pub_topic, (state==OFF?MQTT_OFF:MQTT_ON));
}
*/
}
@ -604,18 +599,7 @@ void send_mqtt_temp_msg(struct mg_connection *nc, char *dev_name, long value)
sprintf(mqtt_pub_topic, "%s/%s", _aqconfig_.mqtt_aq_topic, dev_name);
send_mqtt(nc, mqtt_pub_topic, degC);
}
/*
void send_mqtt_temp_msg_new(struct mg_connection *nc, char *dev_name, long value)
{
static char mqtt_pub_topic[250];
static char degC[5];
// NSF remove false below once we have finished.
sprintf(degC, "%.2f", (false && _aqualink_data->temp_units==FAHRENHEIT && _aqconfig_.convert_mqtt_temp)?degFtoC(value):value );
//sprintf(degC, "%d", value );
sprintf(mqtt_pub_topic, "%s/%s", _aqconfig_.mqtt_aq_topic, dev_name);
send_mqtt(nc, mqtt_pub_topic, degC);
}
*/
void send_mqtt_setpoint_msg(struct mg_connection *nc, char *dev_name, long value)
{
static char mqtt_pub_topic[250];
@ -646,14 +630,6 @@ void send_mqtt_float_msg(struct mg_connection *nc, char *dev_name, float value)
void send_mqtt_int_msg(struct mg_connection *nc, char *dev_name, int value) {
send_mqtt_numeric_msg(nc, dev_name, value);
/*
static char mqtt_pub_topic[250];
static char msg[10];
sprintf(msg, "%d", value);
sprintf(mqtt_pub_topic, "%s/%s", _aqconfig_.mqtt_aq_topic, dev_name);
send_mqtt(nc, mqtt_pub_topic, msg);
*/
}
void send_mqtt_string_msg(struct mg_connection *nc, const char *dev_name, const char *msg) {
@ -1628,19 +1604,9 @@ void action_web_request(struct mg_connection *nc, struct mg_http_message *http_m
// If we have a get request, pass it
if (strncmp(http_msg->uri.buf, "/api", 4 ) != 0) {
//if (strstr(http_msg->method.p, "GET") && http_msg->query_string.len > 0) {
// 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);
//mg_http_serve_file(nc, http_msg, _http_server_opts.root_dir, &_http_server_opts);
mg_http_serve_dir(nc, http_msg, &_http_server_opts);
// _aqconfig_.web_directory
DEBUG_TIMER_STOP(tid, NET_LOG, "action_web_request() serve file took");
//}
//} else if (strstr(http_msg->method.p, "PUT")) {
} else {
char buf[JSON_BUFFER_SIZE];
float value = 0;
@ -1772,7 +1738,6 @@ void action_web_request(struct mg_connection *nc, struct mg_http_message *http_m
}
}
void action_websocket_request(struct mg_connection *nc, struct mg_ws_message *wm) {
char buffer[100];
struct JSONkvptr jsonkv;
@ -1907,17 +1872,6 @@ void action_websocket_request(struct mg_connection *nc, struct mg_ws_message *wm
}
}
/*
static void mqtt_subscribe(struct mg_connection *c, const char *topic) {
static uint8_t qos=1;// PUT IN FUNCTION HEADDER can't be bothered with ack, so set to 0
struct mg_mqtt_opts opts = {};
memset(&opts, 0, sizeof(opts));
opts.topic = mg_str(topic);
opts.qos = qos;
mg_mqtt_sub(c, &opts);
LOG(NET_LOG,LOG_INFO, "MQTT: Subscribing to '%s'\n", topic);
}
*/
static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
struct mg_mqtt_message *mqtt_msg;
@ -1978,11 +1932,65 @@ static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
break;
case MG_EV_ACCEPT:
if (is_mqtt(nc)) {
return;
}
// Only want HTTPS & WS connections
#if MG_TLS > 0
if (nc->is_tls) {
static char *crt;
static char *key;
struct mg_tls_opts opts;
memset(&opts, 0, sizeof(opts));
if (crt == NULL || key == NULL) {
LOG(NET_LOG,LOG_NOTICE, "HTTPS: loading certs from : %s\n", _aqconfig_.cert_dir);
crt = read_pem_file("%s/crt.pem",_aqconfig_.cert_dir);
key = read_pem_file("%s/key.pem",_aqconfig_.cert_dir);
}
opts.cert = mg_str(crt);
opts.key = mg_str(key);
#ifdef TLS_TWOWAY
static char *ca;
if (ca == NULL)
ca = read_pem_file("%s/ca.pem",_aqconfig_.cert_dir);
opts.ca = mg_str(ca);
#endif
mg_tls_init(nc, &opts);
}
#endif
break;
case MG_EV_CONNECT: {
set_mqttconnected(nc);
//set_mqtt(nc);
_mqtt_exit_flag = false;
LOG(NET_LOG,LOG_DEBUG, "MQTT: Connected to : %s\n", _aqconfig_.mqtt_server);
#if MG_TLS > 0
if (nc->is_tls) {
static char *crt;
static char *key;
static char *ca;
struct mg_tls_opts opts;
memset(&opts, 0, sizeof(opts));
if (crt == NULL || key == NULL) {
LOG(NET_LOG,LOG_NOTICE, "MQTTS: loading certs from : %s\n", _aqconfig_.mqtt_cert_dir);
crt = read_pem_file("%s/crt.pem",_aqconfig_.cert_dir);
key = read_pem_file("%s/key.pem",_aqconfig_.cert_dir);
ca = read_pem_file("%s/ca.pem",_aqconfig_.cert_dir);
}
opts.cert = mg_str(crt);
opts.key = mg_str(key);
opts.ca = mg_str(ca);
mg_tls_init(nc, &opts);
}
#endif
} break;
case MG_EV_MQTT_OPEN:
@ -2016,17 +2024,9 @@ static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
case MG_EV_MQTT_MSG:
mqtt_msg = (struct mg_mqtt_message *)ev_data;
//if ( mqtt_msg->topic.buf[mqtt_msg->topic.len-3] == 's' || mqtt_msg->topic.buf[mqtt_msg->topic.len-3] == 'S')
/*
if (mqtt_msg->id != 0) { // NSF Not good check mongoose.h # 2842
LOG(NET_LOG,LOG_DEBUG, "MQTT: received (msg_id: %d), looks like my own message, ignoring\n", mqtt_msg->id);
break;
}*/
// NSF Need to change strlen to a global so it's not executed every time we check a topic
if ( ( mqtt_msg->topic.buf[mqtt_msg->topic.len-3] == 's' || mqtt_msg->topic.buf[mqtt_msg->topic.len-3] == 'S') &&
( mqtt_msg->topic.buf[mqtt_msg->topic.len-2] == 'e' || mqtt_msg->topic.buf[mqtt_msg->topic.len-2] == 'E') &&
( mqtt_msg->topic.buf[mqtt_msg->topic.len-1] == 't' || mqtt_msg->topic.buf[mqtt_msg->topic.len-1] == 'T') &&
(_aqconfig_.mqtt_aq_topic != NULL && strncmp(mqtt_msg->topic.buf, _aqconfig_.mqtt_aq_topic, strlen(_aqconfig_.mqtt_aq_topic)) == 0) )
// We are only subscribed to aqualink topic, (so not checking that).
// Just check we have "set" as string end
if ( FAST_SUFFIX_3_CI(mqtt_msg->topic.buf, mqtt_msg->topic.len, "set"))
{
DEBUG_TIMER_START(&tid);
action_mqtt_message(nc, mqtt_msg);

View File

@ -4,5 +4,5 @@
#define AQUALINKD_SHORT_NAME "AqualinkD"
// Use Magor . Minor . Patch
#define AQUALINKD_VERSION "3.0.0 (dev 3)"
#define AQUALINKD_VERSION "3.0.0 (dev 4)"

View File

@ -104,14 +104,13 @@
// this will show RPM for all pumps (ie Jandy VF pumps)
//var show_vsp_gpm=false;
// By default all Temperatures & Value tiles are on when they have a value other than 0.
// this will turn them off permanently
//var turn_off_sensortiles = true;
// Keeps sensor tiles in on state showing last reading. (default true= turn off tiles when device is off. ie SWG=off turn off PPM tile)
//var turn_off_sensortiles = false;
// This will turn on/off the Spa Heater when you turn on/off Spa Mode.
//var link_spa_and_spa_heater = true;
/*
/* Example of setting custom range and appropriate messages
var tile_thresholds = {
"SWG/PPM": {
outofrange: {min: 2600, max: 3500, mintext:"Add Salt"},

View File

@ -663,7 +663,7 @@
}
}
const _turn_off_sensortiles = (typeof turn_off_sensortiles !== 'undefined') ? turn_off_sensortiles : false;
const _turn_off_sensortiles = (typeof turn_off_sensortiles !== 'undefined') ? turn_off_sensortiles : true;
const _show_vsp_gpm = (typeof show_vsp_gpm !== 'undefined') ? show_vsp_gpm : true;
const _link_spa_and_heater = (typeof link_spa_and_spa_heater !== 'undefined') ? link_spa_and_spa_heater : false;
@ -1129,14 +1129,17 @@
}
}
if ((type == 'temperature' || type == 'value') && _turn_off_sensortiles == false) {
if ((type == 'temperature' || type == 'value') /*&& _turn_off_sensortiles == false*/) {
// Anything specific (SWG PPM should be off if SWG is off)
// This needs a try catch, or is above try block good enough?
if (id == 'SWG/PPM' && document.getElementById('SWG').getAttribute('status') != 'on' ) {
if (id == 'SWG/PPM' && document.getElementById('SWG').getAttribute('status') != 'on' && _turn_off_sensortiles) {
setTileOn(id, 'off');
setTileOnText(id, "");
} else if ( (id == 'CHEM/ORP' || id == 'CHEM/pH' ) && document.getElementById('Filter_Pump').getAttribute('status') == 'off' && _turn_off_sensortiles) {
setTileOn(id, 'off');
setTileOnText(id, "");
// Generic for all.
} else if (value == 0 || value == '--') {
} else if ((value == 0 || value == '--') && _turn_off_sensortiles) {
setTileOn(id, 'off');
setTileOnText(id, "");
} else {