Version 3.0.0

pull/492/head
sfeakes 2025-12-13 18:28:03 -06:00
parent a5db4e0100
commit 59480ae97f
29 changed files with 2663 additions and 2708 deletions

View File

@ -1,7 +1,7 @@
#
# Options
#
# make // standard build aqualinkd and serial_logger
# make // standard build aqualinkd and rs485mon
# make debug // Compule standard aqualinkd binary just with debugging
# make aqdebug // Compile with extra aqualink debug information like timings
# make slog // Serial logger
@ -71,7 +71,7 @@ endif
SRCS = aqualinkd.c utils.c config.c aq_serial.c aq_panel.c aq_programmer.c allbutton.c allbutton_aq_programmer.c net_services.c net_interface.c json_messages.c rs_msg_utils.c\
onetouch.c onetouch_aq_programmer.c iaqtouch.c iaqtouch_aq_programmer.c iaqualink.c\
devices_jandy.c packetLogger.c devices_pentair.c color_lights.c serialadapter.c aq_timer.c aq_scheduler.c web_config.c\
serial_logger.c mongoose.c mqtt_discovery.c simulator.c sensors.c aq_systemutils.c timespec_subtract.c auto_configure.c
rs485mon.c mongoose.c mqtt_discovery.c simulator.c sensors.c aq_systemutils.c timespec_subtract.c auto_configure.c
AQ_FLAGS =
@ -90,8 +90,8 @@ ifeq ($(AQ_MANAGER), true)
$(warning AQ_MANAGER requires threads, ignoring AQ_NO_THREAD_NETSERVICE)
endif
else
# No need for serial_logger without aq_manager
SRCS := $(filter-out serial_logger.c, $(SRCS))
# No need for rs485mon without aq_manager
SRCS := $(filter-out rs485mon.c, $(SRCS))
# no threadded net service only valid without aq manager.
ifeq ($(AQ_NO_THREAD_NETSERVICE), true)
AQ_FLAGS := $(AQ_FLAGS) -D AQ_NO_THREAD_NETSERVICE
@ -106,7 +106,7 @@ DBG_CFLAGS = $(DBGFLAGS) $(AQ_FLAGS) $(MGFLAGS)
# Other sources.
DBG_SRC = $(SRCS) debug_timer.c
SL_SRC = serial_logger.c aq_serial.c utils.c packetLogger.c rs_msg_utils.c timespec_subtract.c
SL_SRC = rs485mon.c aq_serial.c utils.c packetLogger.c rs_msg_utils.c timespec_subtract.c
DD_SRC = dummy_device.c aq_serial.c utils.c packetLogger.c rs_msg_utils.c timespec_subtract.c
DR_SRC = dummy_reader.c aq_serial.c utils.c packetLogger.c rs_msg_utils.c timespec_subtract.c
@ -168,7 +168,7 @@ SL_OBJ_FILES_AMD64 := $(patsubst $(SRC_DIR)/%.c,$(SL_OBJ_DIR_AMD64)/%.o,$(SL_SRC
# define the executable file
MAIN = ./release/aqualinkd
SLOG = ./release/serial_logger
RSMON = ./release/rs485mon
DEBG = ./release/aqualinkd-debug
DDEVICE = ./release/dummydevice
DREADER = ./release/dummyreader
@ -177,9 +177,9 @@ MAIN_ARM64 = ./release/aqualinkd-arm64
MAIN_ARMHF = ./release/aqualinkd-armhf
MAIN_AMD64 = ./release/aqualinkd-amd64
SLOG_ARM64 = ./release/serial_logger-arm64
SLOG_ARMHF = ./release/serial_logger-armhf
SLOG_AMD64 = ./release/serial_logger-amd64
RSMON_ARM64 = ./release/rs485mon-arm64
RSMON_ARMHF = ./release/rs485mon-armhf
RSMON_AMD64 = ./release/rs485mon-amd64
#LOGR = ./release/log_reader
#PLAY = ./release/aqualinkd-player
@ -216,11 +216,11 @@ runindocker:
# This is run inside container Dockerfile.releaseBinariies (aqualinkd-releasebin)
buildrelease: clean armhf arm64
$(shell cd release && ln -s ./aqualinkd-armhf ./aqualinkd && ln -s ./serial_logger-armhf ./serial_logger)
$(shell cd release && ln -s ./aqualinkd-armhf ./aqualinkd && ln -s ./rs485mon-armhf ./rs485mon)
# This is run inside container Dockerfile.releaseBinariies (aqualinkd-releasebin)
quickbuild: armhf arm64
$(shell cd release && [ ! -f "./aqualinkd-armhf" ] && ln -s ./aqualinkd-armhf ./aqualinkd && ln -s ./serial_logger-armhf ./serial_logger)
$(shell cd release && [ ! -f "./aqualinkd-armhf" ] && ln -s ./aqualinkd-armhf ./aqualinkd && ln -s ./rs485mon-armhf ./rs485mon)
# This is run inside container Dockerfile.releaseBinariies (aqualinkd-releasebin)
dockerbuildnrun: ./release/aqualinkd
@ -229,16 +229,16 @@ dockerbuildnrun: ./release/aqualinkd
debugbuild: CFLAGS = $(DFLAGS)
debugbuild: armhf arm64
$(shell cd release && [ ! -f "./aqualinkd-armhf" ] && ln -s ./aqualinkd-armhf ./aqualinkd && ln -s ./serial_logger-armhf ./serial_logger)
$(shell cd release && [ ! -f "./aqualinkd-armhf" ] && ln -s ./aqualinkd-armhf ./aqualinkd && ln -s ./rs485mon-armhf ./rs485mon)
# Rules to pass to make.
all: $(MAIN) $(SLOG)
all: $(MAIN) $(RSMON)
$(info $(MAIN) has been compiled)
$(info $(SLOG) has been compiled)
$(info $(RSMON) has been compiled)
slog: $(SLOG)
$(info $(SLOG) has been compiled)
slog: $(RSMON)
$(info $(RSMON) has been compiled)
aqdebug: $(DEBG)
$(info $(DEBG) has been compiled)
@ -251,9 +251,9 @@ dummyreader: $(DREADER)
# Container, add container flag and compile
container: CFLAGS := $(CFLAGS) -D AQ_CONTAINER
container: $(MAIN) $(SLOG)
container: $(MAIN) $(RSMON)
$(info $(MAIN) has been compiled (** For Container use **))
$(info $(SLOG) has been compiled (** For Container use **))
$(info $(RSMON) has been compiled (** For Container use **))
container-arm64: CC := $(CC_ARM64)
container-arm64: container
@ -263,27 +263,27 @@ container-amd64: container
# armhf
armhf: CC := $(CC_ARMHF)
armhf: $(MAIN_ARMHF) $(SLOG_ARMHF)
armhf: $(MAIN_ARMHF) $(RSMON_ARMHF)
$(info $(MAIN_ARMHF) has been compiled)
$(info $(SLOG_ARMHF) has been compiled)
$(info $(RSMON_ARMHF) has been compiled)
# arm64
arm64: CC := $(CC_ARM64)
arm64: $(MAIN_ARM64) $(SLOG_ARM64)
arm64: $(MAIN_ARM64) $(RSMON_ARM64)
$(info $(MAIN_ARM64) has been compiled)
$(info $(SLOG_ARM64) has been compiled)
$(info $(RSMON_ARM64) has been compiled)
# amd64
amd64: CC := $(CC_AMD64)
amd64: $(MAIN_AMD64) $(SLOG_AMD64)
amd64: $(MAIN_AMD64) $(RSMON_AMD64)
$(info $(MAIN_AMD64) has been compiled)
$(info $(SLOG_AMD64) has been compiled)
$(info $(RSMON_AMD64) has been compiled)
#debug, Just change compile flags and call MAIN
debug: CFLAGS = $(DFLAGS)
debug: $(MAIN) $(SLOG)
debug: $(MAIN) $(RSMON)
$(info $(MAIN) has been compiled (** DEBUG **))
$(info $(SLOG) has been compiled (** DEBUG **))
$(info $(RSMON) has been compiled (** DEBUG **))
#install: $(MAIN)
install:
@ -340,27 +340,27 @@ $(MAIN_AMD64): $(OBJ_FILES_AMD64)
$(DEBG): $(DBG_OBJ_FILES)
$(CC) $(DBG_CFLAGS) $(INCLUDES) -o $@ $^ $(LIBS)
$(SLOG): CFLAGS := $(CFLAGS) -D SERIAL_LOGGER
$(SLOG): $(SL_OBJ_FILES)
$(RSMON): CFLAGS := $(CFLAGS) -D RS485MON
$(RSMON): $(SL_OBJ_FILES)
$(CC) $(CFLAGS) $(INCLUDES) -o $@ $^ $(LIBS)
$(SLOG_ARMHF): CFLAGS := $(CFLAGS) -D SERIAL_LOGGER
$(SLOG_ARMHF): $(SL_OBJ_FILES_ARMHF)
$(RSMON_ARMHF): CFLAGS := $(CFLAGS) -D RS485MON
$(RSMON_ARMHF): $(SL_OBJ_FILES_ARMHF)
$(CC) $(CFLAGS) $(INCLUDES) -o $@ $^ $(LIBS)
$(SLOG_ARM64): CFLAGS := $(CFLAGS) -D SERIAL_LOGGER
$(SLOG_ARM64): $(SL_OBJ_FILES_ARM64)
$(RSMON_ARM64): CFLAGS := $(CFLAGS) -D RS485MON
$(RSMON_ARM64): $(SL_OBJ_FILES_ARM64)
$(CC) $(CFLAGS) $(INCLUDES) -o $@ $^ $(LIBS)
$(SLOG_AMD64): CFLAGS := $(CFLAGS) -D SERIAL_LOGGER
$(SLOG_AMD64): $(SL_OBJ_FILES_AMD64)
$(RSMON_AMD64): CFLAGS := $(CFLAGS) -D RS485MON
$(RSMON_AMD64): $(SL_OBJ_FILES_AMD64)
$(CC) $(CFLAGS) $(INCLUDES) -o $@ $^ $(LIBS)
$(DDEVICE): CFLAGS := $(CFLAGS) -D SERIAL_LOGGER -D DUMMY_DEVICE
$(DDEVICE): CFLAGS := $(CFLAGS) -D RS485MON -D DUMMY_DEVICE
$(DDEVICE): $(DD_OBJ_FILES)
$(CC) $(CFLAGS) $(INCLUDES) -o $@ $^ $(LIBS)
$(DREADER): CFLAGS := $(CFLAGS) -D SERIAL_LOGGER -D DUMMY_DEVICE -D DUMMY_READER
$(DREADER): CFLAGS := $(CFLAGS) -D RS485MON -D DUMMY_DEVICE -D DUMMY_READER
$(DREADER): $(DR_OBJ_FILES)
$(CC) $(CFLAGS) $(INCLUDES) -o $@ $^ $(LIBS)
@ -402,7 +402,7 @@ $(SL_OBJ_DIR_AMD64):
clean: clean-buildfiles
$(RM) *.o *~ $(MAIN) $(MAIN_U) $(PLAY) $(PL_EXOBJ) $(DEBG) $(DDEVICE) $(DREADER)
$(RM) $(wildcard *.o) $(wildcard *~) $(MAIN) $(MAIN_ARM64) $(MAIN_ARMHF) $(MAIN_AMD64) $(SLOG) $(DDEVICE) $(SLOG_ARM64) $(SLOG_ARMHF) $(SLOG_AMD64) $(MAIN_U) $(PLAY) $(PL_EXOBJ) $(LOGR) $(PLAY) $(DEBG)
$(RM) $(wildcard *.o) $(wildcard *~) $(MAIN) $(MAIN_ARM64) $(MAIN_ARMHF) $(MAIN_AMD64) $(RSMON) $(DDEVICE) $(RSMON_ARM64) $(RSMON_ARMHF) $(RSMON_AMD64) $(MAIN_U) $(PLAY) $(PL_EXOBJ) $(LOGR) $(PLAY) $(DEBG)
clean-buildfiles:
$(RM) $(wildcard *.o) $(wildcard *~) $(OBJ_FILES) $(DBG_OBJ_FILES) $(SL_OBJ_FILES) $(DD_OBJ_FILES) $(DR_OBJ_FILES) $(OBJ_FILES_ARMHF) $(OBJ_FILES_ARM64) $(OBJ_FILES_AMD64) $(SL_OBJ_FILES_ARMHF) $(SL_OBJ_FILES_ARM64) $(SL_OBJ_FILES_AMD64)

View File

@ -179,8 +179,7 @@ AqualinkD will be moving over to github hosted runners for compiling, currently
* 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
* Renamed serial_logger to rs485mon (more compliant with unix naming standards)
# Updates in 2.6.11 (Sept 14 2025)

View File

@ -55,7 +55,7 @@ LABEL org.opencontainers.image.version=$AQUALINKD_VERSION
COPY --from=aqualinkd-build /home/AqualinkD/release/aqualinkd /usr/local/bin/aqualinkd
COPY --from=aqualinkd-build /home/AqualinkD/release/serial_logger /usr/local/bin/serial_logger
COPY --from=aqualinkd-build /home/AqualinkD/release/rs485mon /usr/local/bin/rs485mon
COPY --from=aqualinkd-build /home/AqualinkD/web/ /var/www/aqualinkd/
COPY --from=aqualinkd-build /home/AqualinkD/release/aqualinkd.conf /etc/aqualinkd.conf

View File

@ -95,7 +95,7 @@ LABEL org.opencontainers.image.version=$AQUALINKD_VERSION
EXPOSE 80/tcp
COPY --from=aqualinkd-build /home/AqualinkD/release/aqualinkd /usr/local/bin/aqualinkd
COPY --from=aqualinkd-build /home/AqualinkD/release/serial_logger /usr/local/bin/serial_logger
COPY --from=aqualinkd-build /home/AqualinkD/release/rs485mon /usr/local/bin/rs485mon
COPY --from=aqualinkd-build /home/AqualinkD/web/ /var/www/aqualinkd/
COPY --from=aqualinkd-build /home/AqualinkD/release/aqualinkd.conf /etc/aqualinkd.conf

Binary file not shown.

Binary file not shown.

View File

@ -35,7 +35,7 @@ web_directory=/var/www/aqualinkd/
# Also don't think setting a 12 when you have a 8 will give you 4 more accessories to control, it won't the
# panel information is needed as different panels use different bits within the RS protocol for status and key
# presses.
# serial_logger will get the panel type string if you don't know it, below are examples.
# rs485mon will get the panel type string if you don't know it, below are examples.
# Must be in format `XX-N ????` (XX=RS or PD, N=Circuits, ????=Combo or Only or Dual)
panel_type = RS-8 Combo
#panel_type = PD-8 Combo
@ -44,7 +44,7 @@ panel_type = RS-8 Combo
#panel_type = RS-4 Combo
#panel_type = RS-8 Only
#
# If serial_logger doesn't give you a type string in the format above, you can use the next options to set the specifics.
# If rs485mon doesn't give you a type string in the format above, you can use the next options to set the specifics.
#
# panel_type_size = (6, 8, 10, 12, 14 or 16) (Number of supported accessories / buttons)
# panel_type_combo = (yes or no) (combo panels support BOTH pool & spa)
@ -62,7 +62,7 @@ panel_type = RS-8 Combo
device_id=0xFF
# The ID of Jandy SerialInterface device. These is only one usable ID, if serial_logger
# The ID of Jandy SerialInterface device. These is only one usable ID, if rs485mon
# picks up your panel supports this, uncomment, as it will speed up heater setpoints & RS16 panels.
#rssa_device_id=0x48

View File

@ -10,6 +10,7 @@ PARENT_COMMAND=$(ps -o comm= $PPID 2>/dev/null)
SERVICE="aqualinkd"
BIN="aqualinkd"
RS485BIN="rs485mon"
CFG="aqualinkd.conf"
SRV="aqualinkd.service"
DEF="aqualinkd"
@ -22,7 +23,10 @@ DEFLocation="/etc/default"
WEBLocation="/var/www/aqualinkd/"
MDNSLocation="/etc/avahi/services/"
REQUIRED_GLIBC_VERSION="2.31"
SOURCEBIN=$BIN
SOURCERS485BIN=$RS485BIN
LOG_SYSTEMD=1 # 1=false in bash, 0=true
REMOUNT_RO=1
@ -34,7 +38,10 @@ _logfile=""
_frommake=$FALSE
_ignorearch=$FALSE
_nosystemd=$FALSE
_ignoreglibc=$FALSE
_installrs485mon=$TRUE
log()
{
@ -75,6 +82,7 @@ while [[ $# -gt 0 ]]; do
if [[ -n "$1" ]]; then
_ignorearch=$TRUE
SOURCEBIN=$BIN-$1
SOURCERS485BIN=$RS485BIN-$1
else
log "--arch requires parameter eg. ( --arch armhf | --arch arm64 )"
fi
@ -162,6 +170,7 @@ if [ "$PARENT_COMMAND" != "make" ] && [ "$_frommake" -eq $FALSE ] && [ "$_ignore
# Need to check BINEXISTS
if [ -f $BUILD/$SOURCEBIN$BINEXT ]; then
SOURCEBIN=$BIN$BINEXT
SOURCERS485BIN=$RS485BIN$BINEXT
elif [ -f $BUILD/$SOURCEBIN ]; then
# Not good
log "Can't find correct aqualinkd binary for $ARCH, '$BUILD/$SOURCEBIN$BINEXT' using '$BUILD/$SOURCEBIN' ";
@ -177,9 +186,10 @@ fi
## New for V3.0 check GLIBC version.
if [ "$_ignoreglibc" -eq $FALSE ]; then
# Check glib-c version.
REQUIRED_GLIBC_VERSION="2.31"
REQUIRED_GLIBC_MAJOR=2
REQUIRED_GLIBC_MINOR=31
# Extract the part BEFORE the first dot
REQUIRED_GLIBC_MAJOR="${REQUIRED_GLIBC_VERSION%.*}"
# Extract the part AFTER the first dot
REQUIRED_GLIBC_MINOR="${REQUIRED_GLIBC_VERSION#*.}"
CURRENT_GLIBC_VERSION_STRING=$(ldd --version 2>/dev/null | head -n 1 | awk '{print $NF}')
@ -219,6 +229,9 @@ if [ "$1" == "clean" ]; then
if [ -f $BINLocation/$BIN ]; then
rm -f $BINLocation/$BIN
fi
if [ -f $BINLocation/$RS485BIN ]; then
rm -f $BINLocation/$RS485BIN
fi
if [ -f $SRVLocation/$SRV ]; then
rm -f $SRVLocation/$SRV
fi
@ -275,8 +288,13 @@ fi
# copy files to locations, but only copy cfg if it doesn;t already exist
cp $BUILD/$SOURCEBIN $BINLocation/$BIN
cp $BUILD/$SRV $SRVLocation/$SRV
if [ "$_installrs485mon" -eq $TRUE ]; then
cp $BUILD/$SOURCERS485BIN $BINLocation/$RS485BIN
fi
if [ -f $CFGLocation/$CFG ]; then
log "AqualinkD config exists, did not copy new config, you may need to edit existing! $CFGLocation/$CFG"
else

1
release/rs485mon Symbolic link
View File

@ -0,0 +1 @@
./rs485mon-armhf

View File

@ -1 +0,0 @@
./serial_logger-armhf

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 %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);
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[0]=='\0'?_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[0]=='\0'?_aqconfig_.listen_address:iface->localurl), cline.url, cline.value);
}
}

View File

@ -873,7 +873,7 @@ void send_packet(int fd, unsigned char *packet, int length)
tcdrain(fd); // Make sure buffer has been sent.
//if (_aqconfig_.frame_delay > 0) {
#ifndef SERIAL_LOGGER
#ifndef RS485MON
if (_aqconfig_.frame_delay > 0) {
timespec_subtract(&elapsed_time, &now, &_last_serial_read_time);
LOG(RSTM_LOG, LOG_DEBUG, "Time from recv to send is %.3f sec\n",

View File

@ -11,7 +11,7 @@ const char *getJandyDeviceName(emulation_type etype);
#define CONNECTION_ERROR "ERROR No connection to RS control panel"
#ifdef AQ_MANAGER
#define CONNECTION_RUNNING_SLOG "Running serial_logger, this will take some time"
#define CONNECTION_RUNNING_SLOG "Running rs485mon, this will take some time"
#endif
//#define SERIAL_BLOCKING_TIME 50 // (1 to 255) in 1/10th second so 1 = 0.1 sec, 255 = 25.5 sec

View File

@ -62,7 +62,7 @@
#include "auto_configure.h"
#ifdef AQ_MANAGER
#include "serial_logger.h"
#include "rs485mon.h"
#endif
/*
@ -1211,13 +1211,13 @@ void main_loop()
#ifdef AQ_MANAGER
if (_aqualink_data.run_slogger) {
LOG(AQUA_LOG,LOG_WARNING, "Starting serial_logger, this will take some time!\n");
LOG(AQUA_LOG,LOG_WARNING, "Starting rs485mon, this will take some time!\n");
broadcast_aqualinkstate_error(CONNECTION_RUNNING_SLOG);
if (_aqualink_data.slogger_debug)
addDebugLogMask(SLOG_LOG);
serial_logger(rs_fd, _aqconfig_.serial_port, _aqualink_data.slogger_debug?LOG_DEBUG:getSystemLogLevel(), _aqualink_data.slogger_packets, _aqualink_data.slogger_ids);
rs485mon(rs_fd, _aqconfig_.serial_port, _aqualink_data.slogger_debug?LOG_DEBUG:getSystemLogLevel(), _aqualink_data.slogger_packets, _aqualink_data.slogger_ids);
_aqualink_data.run_slogger = false;
if (_aqualink_data.slogger_debug)

View File

@ -475,6 +475,37 @@ int build_color_lights_js(struct aqualinkdata *aqdata, char* buffer, int size)
return length;
}
int build_color_lights_json(struct aqualinkdata *aqdata, char* buffer, int size)
{
memset(&buffer[0], 0, size);
int length = 0;
int i, j;
length += sprintf(buffer+length, "\"light_programs\": {");
if ( _color_light_options[0][1] == NULL || strcmp(_color_light_options[0][1], "1") == 0) {
length += sprintf(buffer+length, "\"0\": [],");
i=1;
} else {
i=0;
}
for (; i < NUMBER_LIGHT_COLOR_TYPES; i++) {
length += sprintf(buffer+length, "\"%d\": [", i);
for (j=1; j < LIGHT_COLOR_OPTIONS; j++) { // Start a 1 since index 0 is blank
if (_color_light_options[i][j] != NULL)
length += sprintf(buffer+length, "\"%s%s\"%s", _color_light_options[i][j], (isShowMode(_color_light_options[i][j])?" - Show":""), (_color_light_options[i][j+1] != NULL)?",":"" );
}
//buffer[--length] = '\0';
length += sprintf(buffer+length, "],");
}
buffer[--length] = '\0';
length += sprintf(buffer+length, "}");
return length;
}
int build_color_light_jsonarray(int index, char* buffer, int size)
{
memset(&buffer[0], 0, size);

View File

@ -35,6 +35,7 @@ typedef enum clight_type {
const char *get_currentlight_mode_name(clight_detail light, emulation_type protocol);
const char *light_mode_name(clight_type type, int index, emulation_type protocol);
int build_color_lights_js(struct aqualinkdata *aqdata, char* buffer, int size);
int build_color_lights_json(struct aqualinkdata *aqdata, char* buffer, int size);
int build_color_light_jsonarray(int index, char* buffer, int size);
int dimmer_percent_to_mode_index(int value);
int dimmer_mode_to_percent(int value);

View File

@ -178,7 +178,7 @@ char *generate_mqtt_id() {
if (i < MQTT_ID_LEN) {
ID[i++] = '_';
const net_iface *info = get_first_valid_interface();
if (info->rawmac != NULL)
if (info->rawmac[0] != '\0')
sprintf(&ID[i], "%.*s", (MQTT_ID_LEN-i), info->rawmac);
else
sprintf(&ID[i], "%.*d", (MQTT_ID_LEN-i), getpid());

View File

@ -1142,7 +1142,7 @@ uriAtype action_URI(request_source from, const char *URI, int uri_length, float
return uActioned;
*/
} else if (strncmp(ri1, "seriallogger", 12) == 0 && from == NET_WS) { // Only valid from websocket.
LOG(NET_LOG,LOG_NOTICE, "Received request to run serial_logger!\n");
LOG(NET_LOG,LOG_NOTICE, "Received request to run rs485mon!\n");
//LOG(NET_LOG,LOG_NOTICE, "Received request ri1=%s, ri2=%s, ri3=%s value=%f\n",ri1,ri2,ri3,value);
_aqualink_data->slogger_packets = round(value);
if (ri2 != NULL) {
@ -1156,7 +1156,7 @@ uriAtype action_URI(request_source from, const char *URI, int uri_length, float
} else {
_aqualink_data->slogger_debug = false;
}
//LOG(NET_LOG,LOG_NOTICE, "Received request to run serial_logger (%d,%s,%s)!\n",
//LOG(NET_LOG,LOG_NOTICE, "Received request to run rs485mon (%d,%s,%s)!\n",
// _aqualink_data->slogger_packets,
// _aqualink_data->slogger_ids[0]!='\0'?_aqualink_data->slogger_ids:" ",
// _aqualink_data->slogger_debug?"debug":"" );
@ -1676,9 +1676,14 @@ void action_web_request(struct mg_connection *nc, struct mg_http_message *http_m
{
char message[JSON_BUFFER_SIZE];
DEBUG_TIMER_START(&tid2);
/*
build_dynamic_webconfig_js(_aqualink_data, message, JSON_BUFFER_SIZE);
DEBUG_TIMER_STOP(tid2, NET_LOG, "action_web_request() build_webconfig_js took");
mg_http_reply(nc, 200, CONTENT_JS, message);
*/
build_dynamic_webconfig_json(_aqualink_data, message, JSON_BUFFER_SIZE);
DEBUG_TIMER_STOP(tid2, NET_LOG, "action_web_request() build_webconfig_json took");
mg_http_reply(nc, 200, CONTENT_JSON, message);
}
break;
case uSchedules:
@ -1823,6 +1828,15 @@ void action_websocket_request(struct mg_connection *nc, struct mg_ws_message *wm
ws_send(nc, message);
}
break;
case uDynamicconf:
{
char message[JSON_BUFFER_SIZE];
DEBUG_TIMER_START(&tid2);
build_dynamic_webconfig_json(_aqualink_data, message, JSON_BUFFER_SIZE);
DEBUG_TIMER_STOP(tid2, NET_LOG, "action_web_request() build_webconfig_json took");
ws_send(nc, message);
}
break;
case uSimulator:
{
LOG(NET_LOG,LOG_DEBUG, "Request to start Simulator\n");

View File

@ -27,13 +27,13 @@
#include <time.h>
#include "rs_devices.h"
#include "serial_logger.h"
#include "rs485mon.h"
#include "aq_serial.h"
#include "utils.h"
#include "packetLogger.h"
#include "rs_msg_utils.h"
#ifdef SERIAL_LOGGER
#ifdef RS485MON
// Make us look like config.c when we load config.h so we get globals.
#define CONFIG_C
#endif
@ -43,7 +43,7 @@
#define PACKET_MAX 1200
#define PROBE_CYCLES 2
#define VERSION "serial_logger V2.11"
#define VERSION "rs485mon V2.12"
/*
typedef enum used {
@ -92,10 +92,10 @@ bool _playback_file = false;
int sl_timespec_subtract (struct timespec *result, const struct timespec *x, const struct timespec *y);
int _serial_logger(int rs_fd, char *port_name, int logPackets, int logLevel, bool panleProbe, bool rsSerialSpeedTest, bool errorMonitor, bool printAllIDs, bool timePackets);
int _rs485mon(int rs_fd, char *port_name, int logPackets, int logLevel, bool panleProbe, bool rsSerialSpeedTest, bool errorMonitor, bool printAllIDs, bool timePackets);
#ifdef SERIAL_LOGGER
#ifdef RS485MON
void broadcast_log(char *msg){
// Do nothing, just for utils.c to work.
}
@ -109,7 +109,7 @@ bool isAqualinkDStopping() {
return !_keepRunning;
}
#else
int serial_logger (int rs_fd, char *port_name, int logLevel, int slogger_packets, char *slogger_ids)
int rs485mon (int rs_fd, char *port_name, int logLevel, int slogger_packets, char *slogger_ids)
{
int packets=PACKET_MAX;
unsigned int n;
@ -140,11 +140,11 @@ int serial_logger (int rs_fd, char *port_name, int logLevel, int slogger_packets
}
if (slogger_packets > 0)
LOG(SLOG_LOG, LOG_NOTICE, "Running serial logger with %d pakets, loglevel %s\n",packets,elevel2text(logLevel>=LOG_NOTICE?logLevel:LOG_NOTICE) );
LOG(SLOG_LOG, LOG_NOTICE, "Running rs485mon with %d pakets, loglevel %s\n",packets,elevel2text(logLevel>=LOG_NOTICE?logLevel:LOG_NOTICE) );
else
LOG(SLOG_LOG, LOG_NOTICE, "Running serial logger (complete poll cycle), loglevel %s\n",elevel2text(logLevel>=LOG_NOTICE?logLevel:LOG_NOTICE) );
LOG(SLOG_LOG, LOG_NOTICE, "Running rs485mon (complete poll cycle), loglevel %s\n",elevel2text(logLevel>=LOG_NOTICE?logLevel:LOG_NOTICE) );
return _serial_logger(rs_fd, port_name, packets, (logLevel>=LOG_NOTICE?logLevel:LOG_NOTICE), true, false, false, false, false);
return _rs485mon(rs_fd, port_name, packets, (logLevel>=LOG_NOTICE?logLevel:LOG_NOTICE), true, false, false, false, false);
}
#endif
@ -529,7 +529,7 @@ bool filterMatch(unsigned char ID, unsigned char *packet_buffer, bool failNoFilt
return true;
}
#ifdef SERIAL_LOGGER
#ifdef RS485MON
void printHex(char *pk, int length)
{
@ -745,19 +745,19 @@ int main(int argc, char *argv[]) {
startPacketLogger();
_serial_logger(rs_fd, argv[1], logPackets, logLevel, panleProbe, rsSerialSpeedTest, errorMonitor, printAllIDs, timePackets);
_rs485mon(rs_fd, argv[1], logPackets, logLevel, panleProbe, rsSerialSpeedTest, errorMonitor, printAllIDs, timePackets);
stopPacketLogger();
close_serial_port(rs_fd);
}
#endif // SERIAL_LOGGER
#endif // RS485MON
int _serial_logger(int rs_fd, char *port_name, int logPackets, int logLevel, bool panleProbe, bool rsSerialSpeedTest, bool errorMonitor, bool printAllIDs, bool timePackets) {
int _rs485mon(int rs_fd, char *port_name, int logPackets, int logLevel, bool panleProbe, bool rsSerialSpeedTest, bool errorMonitor, bool printAllIDs, bool timePackets) {
int packet_length;
int last_packet_length = 0;
unsigned char packet_buffer[AQ_MAXPKTLEN];
@ -874,7 +874,7 @@ int _serial_logger(int rs_fd, char *port_name, int logPackets, int logLevel, boo
}
}
//LOG(SLOG_LOG, LOG_DEBUG_SERIAL, "Received Packet for ID 0x%02hhx of type %s\n", packet_buffer[PKT_DEST], get_packet_type(packet_buffer, packet_length));
#ifdef SERIAL_LOGGER
#ifdef RS485MON
if (logLevel > LOG_NOTICE)
printPacket(lastID, packet_buffer, packet_length, timePackets?extra_message:NULL);
#else
@ -944,7 +944,7 @@ int _serial_logger(int rs_fd, char *port_name, int logPackets, int logLevel, boo
}
#ifndef SERIAL_LOGGER
#ifndef RS485MON
if(received_packets%100==0) {
LOG(SLOG_LOG, LOG_NOTICE, "Read %d of %s%d packets\n", received_packets, probeCycle?"(max)":"" ,logPackets);
}
@ -961,7 +961,7 @@ int _serial_logger(int rs_fd, char *port_name, int logPackets, int logLevel, boo
received_packets = 0;
}
} else if (logLevel < LOG_DEBUG) {
#ifdef SERIAL_LOGGER
#ifdef RS485MON
advance_cursor();
#endif
}

20
source/rs485mon.h Normal file
View File

@ -0,0 +1,20 @@
#ifndef RS485MON_H_
#define RS485MON_H_
/*
int logPackets = PACKET_MAX;
int logLevel = LOG_NOTICE;
bool panleProbe = true;
bool rsSerialSpeedTest = false;
//bool serialBlocking = true;
bool errorMonitor = false;
*/
//int rs485mon(int rs_fd, char *port_name);
//int rs485mon(int rs_fd, char *port_name, int logPackets, int logLevel, bool panleProbe, bool rsSerialSpeedTest, bool errorMonitor);
//int rs485mon (int rs_fd, char *port_name, int logLevel);
int rs485mon (int rs_fd, char *port_name, int logLevel, int slogger_packets, char *slogger_ids);
void getPanelInfo(int rs_fd, unsigned char *packet_buffer, int packet_length);
#endif // SERIAL_LOGGER_H_

View File

@ -1,20 +0,0 @@
#ifndef SERIAL_LOGGER_H_
#define SERIAL_LOGGER_H_
/*
int logPackets = PACKET_MAX;
int logLevel = LOG_NOTICE;
bool panleProbe = true;
bool rsSerialSpeedTest = false;
//bool serialBlocking = true;
bool errorMonitor = false;
*/
//int serial_logger(int rs_fd, char *port_name);
//int serial_logger(int rs_fd, char *port_name, int logPackets, int logLevel, bool panleProbe, bool rsSerialSpeedTest, bool errorMonitor);
//int serial_logger (int rs_fd, char *port_name, int logLevel);
int serial_logger (int rs_fd, char *port_name, int logLevel, int slogger_packets, char *slogger_ids);
void getPanelInfo(int rs_fd, unsigned char *packet_buffer, int packet_length);
#endif // SERIAL_LOGGER_H_

View File

@ -358,10 +358,10 @@ const char *logmask2name(logmask_t from)
return "Simulator: ";
break;
case SLOG_LOG:
return "Serial Log:";
return "RS485mon: ";
break;
case IAQL_LOG:
return "iAqualink2: ";
return "iAqualink2:";
break;
case AQUA_LOG:
default:

View File

@ -41,6 +41,20 @@ int build_dynamic_webconfig_js(struct aqualinkdata *aqdata, char* buffer, int si
return length;
}
int build_dynamic_webconfig_json(struct aqualinkdata *aqdata, char* buffer, int size)
{
memset(&buffer[0], 0, size);
int length = 0;
length += sprintf(buffer+length, "{ \"type\": \"dynamicconfig\", \"enable_schedules\" : \"%s\",",(_aqconfig_.enable_scheduler)?"true":"false");
length += build_color_lights_json(aqdata, &buffer[length], size-length);
length += sprintf(buffer+length, "}");
return length;
}
char* find_nth_char(const char* str, int character, int n) {

View File

@ -4,6 +4,7 @@
int build_dynamic_webconfig_js(struct aqualinkdata *aqdata, char* buffer, int size);
int build_dynamic_webconfig_json(struct aqualinkdata *aqdata, char* buffer, int size);
int save_web_config_json(const char* inBuf, int inSize, char* outBuf, int outSize, struct aqualinkdata *aqdata);

File diff suppressed because it is too large Load Diff

View File

@ -271,7 +271,8 @@
"tile_settings": {
"turn_off_sensortiles": "true",
"show_vsp_gpm": "true",
"disable_off_icon_background": "true"
"disable_off_icon_background": "true",
"light_program_use_dropdown": "false"
},
"colors-dark-example": {
"body_background": "#121212",

View File

@ -4,15 +4,18 @@
<head>
<meta http-equiv='Content-Type' content='text/html; charset=windows-1252'>
<title>AqualinkD</title>
<meta name='viewport' content='width=device-width'>
<!-- <meta name='viewport' content='width=device-width'> -->
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name='mobile-web-app-capable' content='yes'>
<meta name='apple-mobile-web-app-capable' content='yes'>
<meta name='apple-mobile-web-app-status-bar-style' content='black'>
<link href='aqualinkd.png' rel='apple-touch-icon'>
<link href='aqualinkd.png' rel='icon'>
<!--<script src='config.js'></script>-->
<!--<script src='?command=dynamic_config'></script>-->
<script src='/api/dynamicconfig'></script>
<!--<script src='/api/dynamicconfig'></script>-->
<style>
:root {
--fonts: 'HelveticaNeue-Light', 'Helvetica Neue Light', 'Helvetica Neue', Helvetica, Arial, 'Lucida Grande', sans-serif;
@ -119,14 +122,14 @@
.opaque {
top: 0px;
left: 0px;
filter: alpha(opacity=60);
filter: opacity(60%);
opacity: 0.6;
}
.vopaque {
top: 0px;
left: 0px;
filter: alpha(opacity=40);
filter: opacity(40%);
opacity: 0.4;
}
@ -239,8 +242,8 @@
.hide {
display: none;
filter: alpha(opacity=0);
opacity: 0.0;
filter: opacity(0%);
}
.tile {
@ -253,20 +256,20 @@
padding: 5px;
height: var(--tile-width);
width: var(--tile-width);
filter: alpha(opacity=90);
filter: opacity(90%);
opacity: 0.9;
}
.on {
background-color: var(--tile_on_background);
color: var(--tile_on_text);
filter: alpha(opacity=100);
filter: opacity(100%);
opacity: 1.0;
}
.flash {
color: var(--tile_on_text);
filter: alpha(opacity=100);
filter: opacity(90%);
opacity: 0.9;
-webkit-animation-name: tile-flash;
/* Safari 4.0 - 8.0 */
@ -374,7 +377,7 @@
text-align: center;
vertical-align: middle;
line-height: var(--tile_icon-height);
filter: alpha(opacity=100);
filter: opacity(100%);
opacity: 1.0;
}
@ -712,28 +715,28 @@
.pane_close_button {
font-size: 10px !important;
font-weight: bold !important;
font-size: 10px !important;
font-weight: bold !important;
/*color: var(--body_text);*/
/*background-color: #7f8385 !important;*/
border: none !important;
color: rgb(0, 0, 0) !important;
padding: 2px 2px !important;
text-decoration: none !important;
margin: 2px 2px 2px 2px !important;
min-width: 18px !important;
border-radius: 2px !important;
height: 18px !important;
border: none !important;
color: rgb(0, 0, 0) !important;
padding: 2px 2px !important;
text-decoration: none !important;
margin: 2px 2px 2px 2px !important;
min-width: 18px !important;
border-radius: 2px !important;
height: 18px !important;
}
}
.pane_close_button_contaner {
position: absolute;
top: 0;
right: 0;
padding-top: 5px;
padding-right: 5px;
}
.pane_close_button_contaner {
position: absolute;
top: 0;
right: 0;
padding-top: 5px;
padding-right: 5px;
}
/*
.timedate {
@ -745,6 +748,9 @@
//'use strict';
var _config = {};
var _dynamicconfig = {};
//'{"enable_schedules" : "false","light_programs": {"0":[], '
var _aq_display_tile_size = 'small';
@ -758,6 +764,7 @@
var _scheduler_devices_json= [];
var _tile_line_char_limit = 0;
var _devices = [];
var _enable_schedules = false;
var _switchOnUri;
var _switchOffUri;
@ -879,6 +886,10 @@
if (! _config?.tile_settings?.link_spa_and_spa_heater) {
_config.tile_settings.link_spa_and_spa_heater = "false";
}
if (isConfigEnabled(_config?.tile_settings?.light_program_use_dropdown)) {
_lightProgramDropdown = true;
}
}
function isConfigEnabled(value) {
@ -921,7 +932,6 @@
setSizeSpecifics();
populateLightProgram(-1);
//populateLightProgram(0);
document.getElementById('thermostat_options').classList.remove("hide");
document.getElementById('swg_options').classList.remove("hide");
document.getElementById('pswitch_options').classList.remove("hide");
@ -971,6 +981,77 @@
}
function populateLightProgram(type=0, current_mode="") {
var light_program={};
if (type != -1) {
if ( typeof _dynamicconfig?.light_programs === 'undefined' || typeof _dynamicconfig?.light_programs[type] === 'undefined') {
console.log("WARNING: blank Ignoring call to populateLightProgram(), type="+type);
return;
} else {
light_program = _dynamicconfig.light_programs[type];
}
}
if (_lightProgramDropdown) {
option = document.getElementById('pswitch_option_list');
try {
option.innerHTML = '<option value="0">Light Program</option>';
fLen = light_program.length;
for (i = 0; i < fLen; i++) {
var opt = document.createElement('option');
opt.value = i + 1;
if (current_mode != "" && light_program[i].startsWith(current_mode)) {
opt.selected = true;
}
opt.innerHTML = light_program[i];
option.appendChild(opt);
}
} catch (e) {}
} else {
var tbody = document.getElementById('pswitch_table').getElementsByTagName('tbody')[0];
if (type == -1) {
// -1 is Just init, so create another row, just to delete later.
row = tbody.insertRow(2);
row.innerHTML = "<td align='center'>Solid Color</td><td align='center'>Light Show</td>";
//light_program = _light_program[0]; // Use aqualinkd light modes to set size below
light_program[0] = "blank";
light_program[1] = "blank - show";
}
var html1 = '';
var html2 = '';
var fLen = light_program.length;
var i;
var selected = "";
for (i = 0; i < fLen; i++) {
selected = "";
if (current_mode != "" && light_program[i].startsWith(current_mode)) {
selected = "checked";
}
if (light_program[i].endsWith(" - Show"))
html2 = html2 + "<div class='option_radiocontainer'><label><span class='radio'><input type='radio' name='light_program' value='" + (i+1) + "' "+selected+" onchange='updatePwsitchOptions(this, "+type+");'><span class='option_radio-value' aria-hidden='true'></span></span>" + light_program[i].substr(0, (light_program[i].length - 7)) + "</label></div>";
else
html1 = html1 + "<div class='option_radiocontainer'><label><span class='radio'><input type='radio' name='light_program' value='" + (i+1) + "' "+selected+" onchange='updatePwsitchOptions(this, "+type+");'><span class='option_radio-value' aria-hidden='true'></span></span>" + light_program[i] + "</label></div>";
}
var row;
row = tbody.deleteRow(2);
row = tbody.insertRow(2);
if (type == 10) {
row.innerHTML = "<td align='center'>Dimmer</td><td align='center'></td>";
} else {
row.innerHTML = "<td align='center'>Solid Color</td><td align='center'>Light Show</td>";
}
tbody.deleteRow(3);
row = tbody.insertRow(3);
row.innerHTML = "<td align='left' valign='top'>" + html1 + "</td><td align='left' valign='top'>" + html2 + "</td>";
}
}
/*
function populateLightProgram_old(type=0, current_mode="") {
console.log("WARNING: Ignoring call to populateLightProgram()");
return;
var light_program = _light_program[type];
if (_lightProgramDropdown) {
@ -1020,7 +1101,7 @@
row.innerHTML = "<td align='left' valign='top'>" + html1 + "</td><td align='left' valign='top'>" + html2 + "</td>";
}
}
*/
// Simply loop over each key/value in color jason array and set that property adding -- to the beginning of key
function setColors() {
@ -1106,6 +1187,9 @@
*/
_tile_line_char_limit = getComputedStyle(document.documentElement).getPropertyValue('--tile_name-charlimit');
if (_lightProgramDropdown == false && h < 570) {
_lightProgramDropdown = true;
}
window.addEventListener("orientationchange", function() {
var w = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
@ -1588,6 +1672,8 @@
return -1;
}
//function getTileS
function setThermostatTile(id, value, sp_value) {
setTileValue(id, value);
var tile;
@ -1941,13 +2027,15 @@
if (typeof object.type_ext !== 'undefined' && (object.type_ext == 'switch_program' || object.type_ext == 'light_dimmer')) {
if (typeof object.Light_Type !== 'undefined') {
document.getElementById(object.id).setAttribute('lighttype', object.Light_Type);
if (typeof object.Light_Program !== 'undefined') {
var light_mode = parseInt(object.Light_Program);
if ( object.Light_Type != "10" && object.type_ext != 'light_dimmer' ) {
if ( object.Light_Type != "11" && object.type_ext != 'light_dimmer' ) {
document.getElementById(object.id).setAttribute('spvalue', light_mode-1);
//console.log("Light_Program spvalue = "+document.getElementById(object.id).getAttribute('spvalue'));
} else if (object.Light_Type == "11") {
document.getElementById(object.id).setAttribute('spvalue', light_mode);
}
} else {
//console.log("Light_Program "+object.id+" object.Light_Program is null");
}
}
// Other switch_program types (other than light_type) GO HERE
@ -2404,8 +2492,10 @@
var state = oswitch?.checked;
if (type == 'switch_program') {
var mode=false;
if (_lightProgramDropdown) {
if (pswitch.selectedIndex > 0) {
//console.log("check "+(getTileSPvalue(id)+1) +" against "+pswitch.selectedIndex);
if (pswitch.selectedIndex > 0 && (getTileSPvalue(id)+1) != pswitch.selectedIndex) {
send_light_mode(pswitch.selectedIndex, id, pswitch.options[pswitch.selectedIndex].text);
mode=true;
}
@ -2415,6 +2505,7 @@
for (x = 0; x < radio.length; x++) {
if (radio[x].checked == true) {
//console.log("Light Current= "+(getTileSPvalue(id)+1)+" - "+getTileOnText(id)+" Selected="+radio[x].value+" - "+document.getElementById('pswitch_option_switch_text_value').innerHTML);
//console.log("check "+(getTileSPvalue(id)+1) +" against "+radio[x].value);
if (getTileSPvalue(id)+1 != radio[x].value) {
send_light_mode(radio[x].value, id, document.getElementById('pswitch_option_switch_text_value').innerHTML);
}
@ -2575,14 +2666,15 @@
var height = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
//console.log("height = "+height+" - "+caller.id);
//console.log("Height="+height+", computedwidth="+getComputedStyle(document.querySelector('.scheduler_pane')).width+", clientWidth="+document.documentElement.clientWidth+", innerWidth="+window.innerWidth);
if (typeof _enable_schedules === "undefined" || _enable_schedules != false)
{
if ( parseInt(getComputedStyle(document.querySelector('.scheduler_pane')).width) > Math.max(document.documentElement.clientWidth, window.innerWidth) ||
height < 300 ) {
//alert("Sorry, Scheduler won't fit on screen\nPlease use a different device");
//if ( parseInt(getComputedStyle(document.querySelector('.scheduler_pane')).width) > Math.max(document.documentElement.clientWidth, window.innerWidth) || height < 300 ) {
// Really bad check, but works. Should probably setup CSS variables for this.
if ( Math.max(document.documentElement.clientWidth, window.innerWidth) < 600 || height < 300) {
//alert("Sorry, Scheduler won't fit on screen\nPlease use a different device");
displayMessage("Scheduler won't fit on screen", 3);
//console.log("Height="+height+", computedwidth="+getComputedStyle(document.querySelector('.scheduler_pane')).width+", clientWidth="+document.documentElement.clientWidth+", innerWidth="+window.innerWidth);
return;
}
import("./cronstrue.min.js");
@ -2974,6 +3066,11 @@
*
*********************************************************************/
function update_dynamicconfig(data) {
_dynamicconfig = data;
_enable_schedules = isConfigEnabled(_dynamicconfig.enable_schedules);
}
function update_status(data) {
//console.log("Received Update Satus");
_aqualink_data = data;
@ -3083,30 +3180,35 @@
// If aqualinkd programmed light, need to convert int to text index, if not value is text
try {
var light_type = document.getElementById(obj.toString()).getAttribute('lighttype');
/*
if (light_type == "0") {
light_mode = parseInt(data.light_program_names[obj])-1;
light_mode = data.light_program_names[obj];
// For backward compatibility we could get a name here or number (number is is lights modes are in config.js vs aqualinkd.conf)
//console.log("Light "+light_mode);
if (! isNaN(light_mode)) {
light_mode_name = _light_program[light_type][light_mode];
//light_mode_name = _light_program[light_type][light_mode];
light_mode_name = _dynamicconfig?.light_programs[light_type][light_mode];
if (light_mode_name.endsWith(" - Show")) {
light_mode_name = light_mode_name.slice(0, -7);
}
}
} else if (/*light_type == 10 ||*/ light_type == 11) {
} else*/ if (/*light_type == 10 ||*/ light_type == 11) {
// Fo Dimmer Lights.
light_mode = parseInt(light_mode_name);
document.getElementById(obj.toString()).setAttribute('setpoint', light_mode);
} else {
light_mode = _light_program[light_type].findIndex(element => element.startsWith(light_mode_name))
//light_mode = _light_program[light_type].findIndex(element => element.startsWith(light_mode_name));
light_mode = _dynamicconfig?.light_programs[light_type].findIndex(element => element.startsWith(light_mode_name));
}
} catch (e) { /*console.log(e);*/ }
} catch (e) {}
if (light_mode_name != "-999%" && light_mode_name != "Off" && light_mode_name != "off")
setTileOnText(obj.toString(),light_mode_name);
try {
document.getElementById(obj.toString()).setAttribute('spvalue', light_mode);
//console.log(obj.toString()+" set spvalue attribute to "+light_mode);
//console.log("Light mode index "+light_mode+" - "+light_mode_name+" ----- "+_light_program[light_type][light_mode]);
} catch (e) { /*console.log(e);*/ }
@ -3269,6 +3371,7 @@
socket_di.onopen = function() {
// success!
get_devices();
get_dynamicconfig();
// Set recurring fetch every 1 minute
if (!window.devicesInterval) {
window.devicesInterval = setInterval(() => {get_devices();}, 60 * 1000);
@ -3293,6 +3396,8 @@
resetBackgroundSize();
} else if (data.type == 'schedules') {
cs_schedules(data);
} else if (data.type == 'dynamicconfig') {
update_dynamicconfig(data);
}
}
socket_di.onclose = function() {
@ -3324,6 +3429,13 @@
socket_di.send(JSON.stringify(msg));
}
function get_dynamicconfig() {
var msg = {
uri: "dynamicconfig"
};
socket_di.send(JSON.stringify(msg));
}
function get_schedules() {
var msg = {
uri: "schedules"
@ -3430,7 +3542,8 @@
function updatePwsitchOptions(source, light_type) {
if (source.type == 'radio') {
var modename = _light_program[light_type][source.value-1];
//var modename = _light_program[light_type][source.value-1];
var modename = _dynamicconfig?.light_programs[light_type][source.value-1];
if (modename.endsWith(" - Show"))
modename = modename.substr(0, (modename.length - 7));
document.getElementById('pswitch_option_switch_text_value').innerHTML = modename;
@ -3685,7 +3798,7 @@ function cs_synchronizeTableWidths() {
<tr>
<td colspan='2' align='center'>
<select id='pswitch_option_list' class='options_selector'>
<option value="0">Pool Light Program</option>
<option value="0">Light Program</option>
</select>
</td>
</tr>