Release 2.3.1

pull/229/head v2.3.1
sfeakes 2023-06-19 19:15:45 -05:00
parent 7fa7b558e5
commit 78fe018e70
22 changed files with 740 additions and 742 deletions

230
Makefile
View File

@ -1,3 +1,211 @@
#
# Options
#
# make // standard everything
# make debug // Give standard binary just with debugging
# make aqdebug // Compile with extra aqualink debug information like timings
# make slog // Serial logger
# make <other> // not documenting
#
# Valid flags for AQ_FLAGS
AQ_RS16 = true
AQ_PDA = true
AQ_ONETOUCH = true
AQ_IAQTOUCH = true
#AQ_MEMCMP = true // Not implimented correctly yet.
# Turn off threadded net services
AQ_NO_THREAD_NETSERVICE = false
# define the C compiler to use
CC = gcc
#LIBS := -lpthread -lm
LIBS := -l pthread -l m
#LIBS := -l pthread -l m -static # Take out -static, just for dev
# Standard compile flags
GCCFLAGS = -Wall -O3
#GCCFLAGS = -O3
#GCCFLAGS = -Wall -O3 -Wextra
#GCCFLAGS = -Wl,--gc-sections,--print-gc-sections
#GCCFLAGS = -Wall -O3 -ffunction-sections -fdata-sections
# Standard debug flags
DGCCFLAGS = -Wall -O0 -g
# Aqualink Debug flags
#DBGFLAGS = -g -O0 -Wall -fsanitize=address -D AQ_DEBUG -D AQ_TM_DEBUG
DBGFLAGS = -g -O0 -Wall -D AQ_DEBUG -D AQ_TM_DEBUG
# Mongoose flags
#MGFLAGS = -D MG_DISABLE_MD5 -D MG_DISABLE_HTTP_DIGEST_AUTH -D MG_DISABLE_MD5 -D MG_DISABLE_JSON_RPC
# Mongoose 6.18 flags
MGFLAGS = -D MG_ENABLE_HTTP_SSI=0 -D MG_ENABLE_DIRECTORY_LISTING=0 -D MG_ENABLE_HTTP_CGI=0
#MGFLAGS =
# Detect OS and set some specifics
ifeq ($(OS),Windows_NT)
# Windows Make.
RM = del /Q
MKDIR = mkdir
FixPath = $(subst /,\,$1)
else
UNAME_S := $(shell uname -s)
# Linux
ifeq ($(UNAME_S),Linux)
RM = rm -f
MKDIR = mkdir -p
FixPath = $1
# Get some system information
PI_OS_VERSION = $(shell cat /etc/os-release | grep VERSION= | cut -d\" -f2)
$(info OS: $(PI_OS_VERSION) )
GLIBC_VERSION = $(shell ldd --version | grep ldd)
$(info GLIBC build with: $(GLIBC_VERSION) )
$(info GLIBC Prefered : 2.24-11+deb9u1 2.24 )
endif
# OSX
ifeq ($(UNAME_S),Darwin)
endif
endif
# Main source files
SRCS = aqualinkd.c utils.c config.c aq_serial.c aq_panel.c aq_programmer.c net_services.c json_messages.c rs_msg_utils.c\
devices_jandy.c packetLogger.c devices_pentair.c color_lights.c serialadapter.c aq_timer.c aq_scheduler.c web_config.c\
mongoose.c
AQ_FLAGS =
# Add source and flags depending on protocols to support.
ifeq ($(AQ_PDA), true)
SRCS := $(SRCS) pda.c pda_menu.c pda_aq_programmer.c
AQ_FLAGS := $(AQ_FLAGS) -D AQ_PDA
endif
ifeq ($(AQ_ONETOUCH), true)
SRCS := $(SRCS) onetouch.c onetouch_aq_programmer.c
AQ_FLAGS := $(AQ_FLAGS) -D AQ_ONETOUCH
endif
ifeq ($(AQ_IAQTOUCH), true)
SRCS := $(SRCS) iaqtouch.c iaqtouch_aq_programmer.c
AQ_FLAGS := $(AQ_FLAGS) -D AQ_IAQTOUCH
endif
ifeq ($(AQ_RS16), true)
AQ_FLAGS := $(AQ_FLAGS) -D AQ_RS16
endif
ifeq ($(AQ_MEMCMP), true)
AQ_FLAGS := $(AQ_FLAGS) -D AQ_MEMCMP
endif
ifeq ($(AQ_NO_THREAD_NETSERVICE), true)
AQ_FLAGS := $(AQ_FLAGS) -D AQ_NO_THREAD_NETSERVICE
endif
# Put all flags together.
CFLAGS = $(GCCFLAGS) $(AQ_FLAGS) $(MGFLAGS)
DFLAGS = $(DGCCFLAGS) $(AQ_FLAGS) $(MGFLAGS)
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
# Build durectories
OBJ_DIR := ./build
DBG_OBJ_DIR := $(OBJ_DIR)/debug
SL_OBJ_DIR := $(OBJ_DIR)/slog
# Object files
OBJ_FILES := $(patsubst %.c,$(OBJ_DIR)/%.o,$(SRCS))
DBG_OBJ_FILES := $(patsubst %.c,$(DBG_OBJ_DIR)/%.o,$(DBG_SRC))
SL_OBJ_FILES := $(patsubst %.c,$(SL_OBJ_DIR)/%.o,$(SL_SRC))
# define the executable file
MAIN = ./release/aqualinkd
SLOG = ./release/serial_logger
DEBG = ./release/aqualinkd-debug
#LOGR = ./release/log_reader
#PLAY = ./release/aqualinkd-player
# Rules to pass to make.
all: $(MAIN) $(SLOG)
$(info $(MAIN) has been compiled)
$(info $(SLOG) has been compiled)
slog: $(SLOG)
$(info $(SLOG) has been compiled)
aqdebug: $(DEBG)
$(info $(DEBG) has been compiled)
#debug, Just change compile flags and call MAIN
debug: CFLAGS = $(DFLAGS)
debug: $(MAIN) $(SLOG)
$(info $(MAIN) has been compiled (** DEBUG **))
$(info $(SLOG) has been compiled (** DEBUG **))
install: $(MAIN)
./release/install.sh
# Rules to compile
$(OBJ_DIR)/%.o: %.c | $(OBJ_DIR)
$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $<
$(DBG_OBJ_DIR)/%.o: %.c | $(DBG_OBJ_DIR)
$(CC) $(DBG_CFLAGS) $(INCLUDES) -c -o $@ $<
$(SL_OBJ_DIR)/%.o: %.c | $(SL_OBJ_DIR)
$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $<
# Rules to link
$(MAIN): $(OBJ_FILES)
$(CC) $(CFLAGS) $(INCLUDES) $(LIBS) -o $@ $^
$(DEBG): $(DBG_OBJ_FILES)
$(CC) $(DBG_CFLAGS) $(INCLUDES) $(LIBS) -o $@ $^
$(SLOG): CFLAGS := $(CFLAGS) -D SERIAL_LOGGER
$(SLOG): $(SL_OBJ_FILES)
$(CC) $(CFLAGS) $(INCLUDES) $(LIBS) -o $@ $^
# Rules to make object directories.
$(OBJ_DIR):
$(MKDIR) $@
$(SL_OBJ_DIR):
$(MKDIR) $@
$(DBG_OBJ_DIR):
$(MKDIR) $@
# Clean rules
.PHONY: clean
clean:
$(RM) *.o *~ $(MAIN) $(MAIN_U) $(PLAY) $(PL_EXOBJ) $(DEBG)
$(RM) $(wildcard *.o) $(wildcard *~) $(OBJ_FILES) $(DBG_OBJ_FILES) $(SL_OBJ_FILES) $(MAIN) $(MAIN_U) $(PLAY) $(PL_EXOBJ) $(LOGR) $(PLAY) $(DEBG)
define DO_NOT_USE
# OLD MAKEFILE, STILL NEED TO MOVE THE BELOW OVER TO NEW Makefile
LOGR = ./release/log_reader
PLAY = ./release/aqualinkd-player
#
# Options
#
@ -48,7 +256,9 @@ DGCCFLAGS = -Wall -O0 -g
DBGFLAGS = -g -O0 -Wall -D AQ_DEBUG -D AQ_TM_DEBUG
# Mongoose flags
MGFLAGS = -D MG_DISABLE_MD5 -D MG_DISABLE_HTTP_DIGEST_AUTH -D MG_DISABLE_MD5 -D MG_DISABLE_JSON_RPC
#MGFLAGS = -D MG_DISABLE_MD5 -D MG_DISABLE_HTTP_DIGEST_AUTH -D MG_DISABLE_MD5 -D MG_DISABLE_JSON_RPC
# Mongoose 6.18 flags
MGFLAGS = -D MG_ENABLE_HTTP_SSI=0 -D MG_ENABLE_DIRECTORY_LISTING=0 -D MG_ENABLE_HTTP_CGI=0
#MGFLAGS =
# define the C source files
@ -56,7 +266,8 @@ MGFLAGS = -D MG_DISABLE_MD5 -D MG_DISABLE_HTTP_DIGEST_AUTH -D MG_DISABLE_MD5 -D
# pda_aq_programmer.c devices_jandy.c onetouch.c onetouch_aq_programmer.c packetLogger.c devices_pentair.c color_lights.c mongoose.c
SRCS = aqualinkd.c utils.c config.c aq_serial.c aq_panel.c aq_programmer.c net_services.c json_messages.c rs_msg_utils.c\
devices_jandy.c packetLogger.c devices_pentair.c color_lights.c serialadapter.c aq_timer.c aq_scheduler.c web_config.c mongoose.c
devices_jandy.c packetLogger.c devices_pentair.c color_lights.c serialadapter.c aq_timer.c aq_scheduler.c web_config.c\
mongoose.c
AQ_FLAGS =
@ -110,6 +321,7 @@ SL_OBJS = $(SL_SRC:.c=.o)
LR_OBJS = $(LR_SRC:.c=.o)
PL_OBJS = $(PL_SRC:.c=.o)
# define the executable file
MAIN = ./release/aqualinkd
SLOG = ./release/serial_logger
@ -117,8 +329,10 @@ LOGR = ./release/log_reader
PLAY = ./release/aqualinkd-player
DEBG = ./release/aqualinkd-debug
all: $(MAIN)
all: $(MAIN) $(SLOG)
$(info $(MAIN) has been compiled)
$(info $(SLOG) has been compiled)
# debug, Just change compile flags and call MAIN
debug: CFLAGS = $(DFLAGS)
@ -134,7 +348,8 @@ slog: $(SLOG)
$(SLOG): CFLAGS := $(CFLAGS) -D SERIAL_LOGGER
$(SLOG): $(SL_OBJS)
$(CC) $(CFLAGS) $(INCLUDES) -o $(SLOG) $(SL_OBJS)
# $(CC) $(CFLAGS) $(INCLUDES) -o $(SLOG) $(SL_OBJS)
$(CC) $(INCLUDES) -o $(SLOG) $(SL_OBJS)
#.PHONY: clean_slog_o
@ -181,7 +396,8 @@ git: clean $(MAIN) $(SLOG)
# the rule(a .c file) and $@: the name of the target of the rule (a .o file)
# (see the gnu make manual section about automatic variables)
.c.o:
$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@
$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@
.PHONY: clean
clean:
@ -194,3 +410,7 @@ depend: $(SRCS)
install: $(MAIN)
./release/install.sh
endef

View File

@ -78,11 +78,9 @@ Designed to mimic AqualinkRS6 All Button keypad and (like the keypad) is used to
* Allow selecting of pre-defined VSP programs (Aqualink Touch & OneTouch protocols.)
* Add set time to OneTouch protocol.
# Update in Release 2.3.0f (pre release)
* This is pre-release, please treat it as such.
* Proceed with caution on PDA panels <i>I have not been able to test it fully on all variants</i> and you may need to go back to your current (or previous) version of AqualinkD
# Update in Release 2.3.1
* Changed a lot of logic around different protocols.
* Added low latency support for ITDI usb driver.
* Added low latency support for FTDI usb driver.
* AqualinkD will find out the fastest way to change something depending on the protocols available.
* Added scheduler (click time in web ui). supports full calendar year (ie seasons), See wiki for details.
* Added timers for devices (ie can turn on Pump for x minutes), Long press on device in WebUI.
@ -97,6 +95,8 @@ Designed to mimic AqualinkRS6 All Button keypad and (like the keypad) is used to
* Fix bug in IntelliBrite color lights
* Install script checks for cron and it's config (needed for scheduler)
* serial-logger will now give recommended values for aqualinkd.conf
* Lock the serial port to stop duplicate process conflict.
* Lots of code cleanup & modifying ready for AqualinkD Management console in a future release.
# Update in Release 2.2.2
* Fixed some Web UI bugs

View File

@ -368,6 +368,33 @@ int set_port_low_latency(int fd, const char* tty)
return 0;
}
#include <sys/file.h>
int lock_port(int fd, const char* tty)
{
if (ioctl (fd, TIOCEXCL) < 0) {
LOG(RSSD_LOG,LOG_ERR, "Can't put (%s) into exclusive mode (%d): %s\n", tty,errno, strerror( errno ));
return -1;
}
if (flock(fd, LOCK_EX | LOCK_NB) < 0) {
LOG(RSSD_LOG,LOG_ERR, "Can't lock (%s) (%d): %s\n", tty,errno, strerror( errno ));
return -1;
}
return 0;
}
int unlock_port(int fd)
{
if (flock(fd, LOCK_UN) < 0) {
LOG(RSSD_LOG,LOG_ERR, "Can't unlock serial port (%d): %s\n",errno, strerror( errno ));
return -1;
}
return 0;
}
// https://www.cmrr.umn.edu/~strupp/serial.html#2_5_2
// http://unixwiz.net/techtips/termios-vmin-vtime.html
//#define OLD_SERIAL_INIT
@ -396,6 +423,11 @@ int _init_serial_port(const char* tty, bool blocking, bool readahead)
return -1;
}
if ( lock_port(fd, tty) < 0) {
//LOG(RSSD_LOG,LOG_ERR, "Unable to lock port: %s, error %d\n", tty, errno);
return -1;
}
if (_aqconfig_.ftdi_low_latency)
set_port_low_latency(fd, tty);
@ -448,7 +480,7 @@ int _init_serial_port(const char* tty, bool blocking, bool readahead)
return -1;
}
LOG(RSSD_LOG,LOG_INFO, "Set serial port %s I/O %s attributes\n",tty,_blocking_mode?"blocking":"non blocking");
LOG(RSSD_LOG,LOG_INFO, "Port %s set I/O %s attributes\n",tty,_blocking_mode?"blocking":"non blocking");
return fd;
}
@ -520,6 +552,7 @@ void close_blocking_serial_port()
/* close tty port */
void close_serial_port(int fd)
{
unlock_port(fd);
tcsetattr(fd, TCSANOW, &_oldtio);
close(fd);
LOG(RSSD_LOG,LOG_DEBUG_SERIAL, "Closed serial port\n");

View File

@ -87,7 +87,18 @@ void intHandler(int sig_num)
_keepRunning = false;
if (sig_num == SIGRESTART) {
_restart = true;
// If we are deamonized, we need to use the system
if (_aqconfig_.deamonize) {
if(fork() == 0) {
sleep(2);
char *newargv[] = {"/bin/systemctl", "restart", "aqualinkd", NULL};
char *newenviron[] = { NULL };
execve(newargv[0], newargv, newenviron);
exit (EXIT_SUCCESS);
}
} else {
_restart = true;
}
}
//LOG(AQUA_LOG,LOG_NOTICE, "Stopping!\n");
//if (dummy){}// stop compile warnings
@ -1128,6 +1139,7 @@ int startup(char *self, char *cfgFile)
_cfgFile = cfgFile;
//initButtons(&_aqualink_data);
clearDebugLogMask();
read_config(&_aqualink_data, cfgFile);
// Sanity check on Device ID's against panel type
@ -1791,8 +1803,14 @@ void main_loop()
logPacketRead(packet_buffer, packet_length);
}
if (!_aqconfig_.prioritize_ack)
if (!_aqconfig_.prioritize_ack) {
_aqualink_data.updated = process_packet(packet_buffer, packet_length);
} else {
// If we did not process the packet, above we need to record it for the caculate_ack_packet call.
// Should find a better place to put this, but since prioritize_ack is expermental it's ok for now.
// NSF The exact same needs to be done for onetouch / iaqtouch and probably rssaadapter.
_aqualink_data.last_packet_type = packet_buffer[PKT_CMD];
}
#ifdef AQ_PDA
if (isPDA_PANEL)
caculate_ack_packet(rs_fd, packet_buffer, AQUAPDA);
@ -1807,17 +1825,18 @@ void main_loop()
}
else if (packet_length > 0 && isRSSA_ENABLED && packet_buffer[PKT_DEST] == _aqconfig_.rssa_device_id && getProtocolType(packet_buffer) == JANDY) {
if (_aqconfig_.prioritize_ack) {
_aqualink_data.updated = process_rssadapter_packet(packet_buffer, packet_length, &_aqualink_data);
caculate_ack_packet(rs_fd, packet_buffer, RSSADAPTER);
_aqualink_data.updated = process_rssadapter_packet(packet_buffer, packet_length, &_aqualink_data);
} else {
caculate_ack_packet(rs_fd, packet_buffer, RSSADAPTER);
_aqualink_data.updated = process_rssadapter_packet(packet_buffer, packet_length, &_aqualink_data);
caculate_ack_packet(rs_fd, packet_buffer, RSSADAPTER);
}
DEBUG_TIMER_STOP(_rs_packet_timer,AQUA_LOG,"SerialAdapter Emulation Processed packet in");
}
#ifdef AQ_ONETOUCH
else if (packet_length > 0 && isONET_ENABLED && packet_buffer[PKT_DEST] == _aqconfig_.extended_device_id && getProtocolType(packet_buffer) == JANDY) {
if (_aqconfig_.prioritize_ack) {
set_onetouch_lastmsg(packet_buffer[PKT_CMD]);
caculate_ack_packet(rs_fd, packet_buffer, ONETOUCH);
_aqualink_data.updated = process_onetouch_packet(packet_buffer, packet_length, &_aqualink_data);
} else {
@ -1830,8 +1849,9 @@ void main_loop()
#ifdef AQ_IAQTOUCH
else if (packet_length > 0 && isIAQT_ENABLED && packet_buffer[PKT_DEST] == _aqconfig_.extended_device_id && getProtocolType(packet_buffer) == JANDY) {
if (_aqconfig_.prioritize_ack) {
caculate_ack_packet(rs_fd, packet_buffer, IAQTOUCH);
_aqualink_data.updated = process_iaqtouch_packet(packet_buffer, packet_length, &_aqualink_data);
set_iaqtouch_lastmsg(packet_buffer[PKT_CMD]);
caculate_ack_packet(rs_fd, packet_buffer, IAQTOUCH);
_aqualink_data.updated = process_iaqtouch_packet(packet_buffer, packet_length, &_aqualink_data);
} else {
_aqualink_data.updated = process_iaqtouch_packet(packet_buffer, packet_length, &_aqualink_data);
caculate_ack_packet(rs_fd, packet_buffer, IAQTOUCH);

View File

@ -69,6 +69,8 @@ void init_parameters (struct aqconfig * parms)
_tmpPanel->combo = true;
_tmpPanel->dual = false;
clearDebugLogMask();
//int i;
//char *p;
//parms->rs_panel_size = 8;

View File

@ -83,6 +83,11 @@ unsigned char iaqtLastMsg()
return _lastMsgType;
}
void set_iaqtouch_lastmsg(unsigned char msgtype)
{
_lastMsgType = msgtype;
}
bool wasiaqtThreadKickTypePage()
{
switch(_lastMsgType) {
@ -608,8 +613,8 @@ bool process_iaqtouch_packet(unsigned char *packet, int length, struct aqualinkd
//debuglogPacket(IAQT_LOG ,packet, length);
_lastMsgType = packet[PKT_CMD];
//_lastMsgType = packet[PKT_CMD];
set_iaqtouch_lastmsg(packet[PKT_CMD]);
//debuglogPacket(IAQT_LOG ,packet, length);
//beautifyPacket(buff, packet, length);
//LOG(IAQT_LOG,LOG_DEBUG, "%s", buff);

View File

@ -25,6 +25,8 @@ 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);
void set_iaqtouch_lastmsg(unsigned char msgtype);
// This should be moved to aq_serial once finished.
#define PKT_IAQT_BUTINDX 4
#define PKT_IAQT_BUTSTATE 5

View File

@ -80,8 +80,9 @@ int build_logmsg_JSON(char *dest, const char *src, int dest_len, int src_len)
int length = sprintf(dest, "{\"logmsg\":\"");
length += json_chars(dest+length, src, (dest_len-20), src_len);
length += sprintf(dest+length, "\"}");
dest[length] = '\n';
dest[length+1] = '\0';
dest[length] = '\0';
//dest[length] = '\n';
//dest[length+1] = '\0';
return length;
}
@ -473,6 +474,64 @@ int build_device_JSON(struct aqualinkdata *aqdata, char* buffer, int size, bool
//return length;
}
int logmaskjsonobject(int16_t flag, char* buffer)
{
int length = sprintf(buffer, "{\"name\":\"%s\",\"id\":\"%d\",\"set\":\"%s\"},", logmask2name(flag), flag,(isDebugLogMaskSet(flag)?JSON_ON:JSON_OFF));
return length;
}
int logleveljsonobject(int level, char* buffer)
{
int length = sprintf(buffer, "{\"name\":\"%s\",\"id\":\"%d\",\"set\":\"%s\"},", loglevel2name(level), level,(getSystemLogLevel()==level?JSON_ON:JSON_OFF));
return length;
}
int build_aqualink_aqmanager_JSON(struct aqualinkdata *aqdata, char* buffer, int size)
{
memset(&buffer[0], 0, size);
int length = 0;
length += sprintf(buffer+length, "{\"type\": \"aqmanager\"");
length += sprintf(buffer+length, ",\"deamonized\": \"%s\"", (_aqconfig_.deamonize?JSON_ON:JSON_OFF) );
/*
length += sprintf(buffer+length, ",\"panel_type\":\"%s\"",getPanelString());
length += sprintf(buffer+length, ",\"version\":\"%s\"",aqdata->version );//8157 REV MMM",
length += sprintf(buffer+length, ",\"aqualinkd_version\":\"%s\"", AQUALINKD_VERSION ); //1.0b,
*/
//length += sprintf(buffer+length, ",\"logging2file\": \"%s\"",islogFileReady()?JSON_ON:JSON_OFF);
length += sprintf(buffer+length, ",\"logfileready\": \"%s\"",islogFileReady()?JSON_ON:JSON_OFF);
length += sprintf(buffer+length, ",\"logfilename\": \"%s\"",_aqconfig_.log_file);
length += sprintf(buffer+length, ",\"debugmasks\":[");
length += logmaskjsonobject(AQUA_LOG, buffer+length);
length += logmaskjsonobject(NET_LOG, buffer+length);
length += logmaskjsonobject(AQRS_LOG, buffer+length);
length += logmaskjsonobject(ONET_LOG, buffer+length);
length += logmaskjsonobject(IAQT_LOG, buffer+length);
length += logmaskjsonobject(PDA_LOG, buffer+length);
length += logmaskjsonobject(RSSA_LOG, buffer+length);
length += logmaskjsonobject(DJAN_LOG, buffer+length);
length += logmaskjsonobject(DPEN_LOG, buffer+length);
length += logmaskjsonobject(RSSD_LOG, buffer+length);
length += logmaskjsonobject(PROG_LOG, buffer+length);
length += logmaskjsonobject(DBGT_LOG, buffer+length);
length += logmaskjsonobject(TIMR_LOG, buffer+length);
if (buffer[length-1] == ',')
length--;
length += sprintf(buffer+length, "]");
length += sprintf(buffer+length, ",\"loglevels\":[");
length += logleveljsonobject(LOG_DEBUG_SERIAL, buffer+length);
length += logleveljsonobject(LOG_DEBUG, buffer+length);
length += logleveljsonobject(LOG_INFO, buffer+length);
length += logleveljsonobject(LOG_NOTICE, buffer+length);
length += logleveljsonobject(LOG_WARNING, buffer+length);
length += logleveljsonobject(LOG_ERR, buffer+length);
if (buffer[length-1] == ',')
length--;
length += sprintf(buffer+length, "]");
length += sprintf(buffer+length, "}");
return length;
}
int build_aqualink_status_JSON(struct aqualinkdata *aqdata, char* buffer, int size)
{
//strncpy(buffer, test_message, strlen(test_message)+1);

View File

@ -53,6 +53,7 @@ int build_mqtt_status_JSON(char* buffer, int size, int idx, int nvalue, float se
bool parseJSONmqttrequest(const char *str, size_t len, int *idx, int *nvalue, char *svalue);
int build_aqualink_error_status_JSON(char* buffer, int size, char *msg);
int build_mqtt_status_message_JSON(char* buffer, int size, int idx, int nvalue, char *svalue);
int build_aqualink_aqmanager_JSON(struct aqualinkdata *aqdata, char* buffer, int size);
//int build_device_JSON(struct aqualinkdata *aqdata, int programable_switch, char* buffer, int size, bool homekit);
//int build_device_JSON(struct aqualinkdata *aqdata, int programable_switch1, int programable_switch2, char* buffer, int size, bool homekit);
int build_device_JSON(struct aqualinkdata *aqdata, char* buffer, int size, bool homekit);

View File

@ -43,6 +43,10 @@
#ifdef AQ_PDA
#include "pda.h"
#endif
// NSF remove once aqmanager is released.
#define INCLUDE_OLD_DEBUG_HTML
/*
#if defined AQ_DEBUG || defined AQ_TM_DEBUG
#include "timespec_subtract.h"
@ -59,13 +63,6 @@ static bool _keepNetServicesRunning = false;
static struct mg_mgr _mgr;
static int _mqtt_exit_flag = false;
// Will remove this once we deprecate V1 API's
#ifdef INCLUDE_V1_API
void OLD_action_web_request(struct mg_connection *nc, struct http_message *http_msg);
void OLD_action_websocket_request(struct mg_connection *nc, struct websocket_message *wm);
#endif
#ifndef MG_DISABLE_MQTT
void start_mqtt(struct mg_mgr *mgr);
static struct aqualinkdata _last_mqtt_aqualinkdata;
@ -142,30 +139,70 @@ void _broadcast_aqualinkstate_error(struct mg_connection *nc, char *msg)
// Maybe enhacment in future to sent error messages to MQTT
}
#define MAX_LOGSTACK 30
#define WS_LOG_LENGTH 200
char _logstack[MAX_LOGSTACK][WS_LOG_LENGTH];
int _logstack_place=0;
pthread_mutex_t logmsg_mutex;
// Send log message to any aqManager websocket.
void _broadcast_logs(struct mg_connection *nc, char *msg) {
char message[LOGBUFFER];
void _ws_send_logmsg(struct mg_connection *nc, char *msg) {
struct mg_connection *c;
for (c = mg_next(nc->mgr, NULL); c != NULL; c = mg_next(nc->mgr, c)) {
if (is_websocket(c) && is_websocket_aqmanager(c)) {
build_logmsg_JSON(message, msg, LOGBUFFER, strlen(msg));
ws_send(c, message);
ws_send(c, msg);
}
}
}
void broadcast_logs(char *msg) {
void send_ws_logmessages()
{
pthread_mutex_lock(&logmsg_mutex);
// This pulls them off in the wrong order.
while (_logstack_place > 0) {
_ws_send_logmsg(_mgr.active_connections, _logstack[0]);
memmove(&_logstack[0], &_logstack[1], WS_LOG_LENGTH * _logstack_place ) ;
_logstack_place--;
}
pthread_mutex_unlock(&logmsg_mutex);
}
// This needs to be thread safe.
void broadcast_log(char *msg) {
// NSF This causes mongoose to core dump after a period of time due to number of messages
// so remove until get time to update to new mongoose version.
return;
//return;
#ifdef AQ_NO_THREAD_NETSERVICE
if (_keepNetServicesRunning && !_aqconfig_.thread_netservices && _aqualink_data->aqManagerActive)
{
char message[WS_LOG_LENGTH];
build_logmsg_JSON(message, msg, WS_LOG_LENGTH, strlen(msg));
_ws_send_logmsg(_mgr.active_connections , message);
return;
}
#endif
// See if we have and manager runnig first so we return ASAP.
// Since this get's galled long before net_Services is started, also check we are running.
// Since this get's called long before net_Services is started, also check we are running.
if (_keepNetServicesRunning && _net_thread_id != 0 && _aqualink_data->aqManagerActive)
_broadcast_logs(_mgr.active_connections, msg);
{
pthread_mutex_lock(&logmsg_mutex);
if (_logstack_place < MAX_LOGSTACK)
{
//printf("**** Add message %s\n",msg);
// This need mutex lock on _logstack
build_logmsg_JSON(_logstack[_logstack_place++], msg, WS_LOG_LENGTH, strlen(msg) );
} else {
// Need to figure this out, can't send error message as that will put us in a infinate loop.
fprintf(stderr, "*** ERROR Log queue full ***\n");
// Use the last message to let UI know
build_logmsg_JSON(_logstack[MAX_LOGSTACK-1], "Error: *** Logs truncated, see server to complete list of message ***\n", LOGBUFFER, strlen(msg) );
}
pthread_mutex_unlock(&logmsg_mutex);
}
}
void _broadcast_aqualinkstate(struct mg_connection *nc)
@ -655,51 +692,6 @@ void mqtt_broadcast_aqualinkstate(struct mg_connection *nc)
}
//
/*
void set_light_mode(char *value, int button)
{
int i;
clight_detail *light = NULL;
#ifdef AQ_PDA
if (isPDA_PANEL) {
LOG(NET_LOG,LOG_ERR, "Light mode control not supported in PDA mode\n");
return;
}
#endif
for (i=0; i < _aqualink_data->num_lights; i++) {
if (&_aqualink_data->aqbuttons[button] == _aqualink_data->lights[i].button) {
// Found the programmable light
light = &_aqualink_data->lights[i];
break;
}
}
if (light == NULL) {
LOG(NET_LOG,LOG_ERR, "Light mode control not configured for button %d\n",button);
return;
}
char buf[LIGHT_MODE_BUFER];
if (light->lightType == LC_PROGRAMABLE ) {
// 5 below is light index, need to look this up so it's not hard coded.
sprintf(buf, "%-5s%-5d%-5d%-5d%.2f",value,
button,
_aqconfig_.light_programming_initial_on,
_aqconfig_.light_programming_initial_off,
_aqconfig_.light_programming_mode );
//LOG(NET_LOG,LOG_NOTICE, "WEB: requset light mode %s\n", buf);
aq_programmer(AQ_SET_LIGHTPROGRAM_MODE, buf, _aqualink_data);
} else {
sprintf(buf, "%-5s%-5d%-5d",value, button, light->lightType);
aq_programmer(AQ_SET_LIGHTCOLOR_MODE, buf, _aqualink_data);
}
}
*/
typedef enum {uActioned, uBad, uDevices, uStatus, uHomebridge, uDynamicconf, uDebugStatus, uDebugDownload, uSimulator, uSchedules, uSetSchedules, uAQmanager} uriAtype;
//typedef enum {NET_MQTT=0, NET_API, NET_WS, DZ_MQTT} netRequest;
const char actionName[][5] = {"MQTT", "API", "WS", "DZ"};
@ -713,43 +705,7 @@ const char actionName[][5] = {"MQTT", "API", "WS", "DZ"};
#define NOCHANGE_IGNORING "No change, device is already in that state"
#define UNKNOWN_REQUEST "Didn't understand request"
/*
void create_program_request(request_source requester, action_type type, int value, int id) // id is only valid for PUMP RPM
{
//panel_device_request(struct aqualinkdata *aqdata, action_type type, int deviceIndex, int value, int subIndex, request_source source);
//panel_device_request(_aqualink_data, type, id, value, requester);
if (_aqualink_data->unactioned.type != NO_ACTION && type != _aqualink_data->unactioned.type)
LOG(NET_LOG,LOG_ERR, "%s: About to overwrite unactioned panel program\n",actionName[requester]);
if (type == POOL_HTR_SETOINT || type == SPA_HTR_SETOINT || type == FREEZE_SETPOINT || type == SWG_SETPOINT ) {
_aqualink_data->unactioned.value = setpoint_check(type, value, _aqualink_data);
if (value != _aqualink_data->unactioned.value)
LOG(NET_LOG,LOG_NOTICE, "%s: requested setpoint value %d is invalid, change to %d\n",actionName[requester], value, _aqualink_data->unactioned.value);
} else if (type == PUMP_RPM) {
//_aqualink_data->unactioned.value = RPM_check(_aqualink_data->pumps[id].pumpType , value, _aqualink_data);
_aqualink_data->unactioned.value = value;
//if (value != _aqualink_data->unactioned.value)
// LOG(NET_LOG,LOG_NOTICE, "%s: requested Pump value %d is invalid, change to %d\n",actionName[requester], value, _aqualink_data->unactioned.value);
} else if (type == PUMP_VSPROGRAM) {
//_aqualink_data->unactioned.value = value;
//if (value != _aqualink_data->unactioned.value)
LOG(NET_LOG,LOG_ERR, "%s: requested Pump vsp program is not implimented yet\n",actionName[requester], value, _aqualink_data->unactioned.value);
} else {
// SWG_BOOST & PUMP_RPM
_aqualink_data->unactioned.value = value;
}
_aqualink_data->unactioned.type = type;
_aqualink_data->unactioned.id = id; // This is only valid for pump.
if (requester == NET_MQTT) // We can get multiple MQTT requests from some, so this will wait for last one to come in.
time(&_aqualink_data->unactioned.requested);
else
_aqualink_data->unactioned.requested = 0;
}
*/
#ifdef AQ_PDA
void create_PDA_on_off_request(aqkey *button, bool isON)
@ -767,71 +723,6 @@ void create_PDA_on_off_request(aqkey *button, bool isON)
}
#endif
/*
bool create_panel_request(request_source requester, int buttonIndex, int value, bool timer) {
//if (timer)
// return panel_device_request(_aqualink_data, TIMER, buttonIndex, value, requester);
//else
// return panel_device_request(_aqualink_data, ON_OFF, buttonIndex, value, requester);
// if value = 0 is OFF,
// if value = 1 is ON if (timer = false).
// if value > 0 (timer should be true, and vaue is duration).
if ((_aqualink_data->aqbuttons[buttonIndex].led->state == OFF && value == 0) ||
(value > 0 && (_aqualink_data->aqbuttons[buttonIndex].led->state == ON || _aqualink_data->aqbuttons[buttonIndex].led->state == FLASH ||
_aqualink_data->aqbuttons[buttonIndex].led->state == ENABLE))) {
LOG(NET_LOG, LOG_INFO, "%s: received '%s' for '%s', already '%s', Ignoring\n", actionName[requester], (value == 0 ? "OFF" : "ON"), _aqualink_data->aqbuttons[buttonIndex].name, (value == 0 ? "OFF" : "ON"));
//return false;
} else {
LOG(NET_LOG, LOG_INFO, "%s: received '%s' for '%s', turning '%s'\n", actionName[requester], (value == 0 ? "OFF" : "ON"), _aqualink_data->aqbuttons[buttonIndex].name, (value == 0 ? "OFF" : "ON"));
#ifdef AQ_PDA
if (isPDA_PANEL) {
char msg[PTHREAD_ARG];
sprintf(msg, "%-5d%-5d", buttonIndex, (value == 0 ? OFF : ON));
aq_programmer(AQ_PDA_DEVICE_ON_OFF, msg, _aqualink_data);
} else
#endif
{
// Check for panel programmable light. if so simple ON isn't going to work well
// Could also add "light mode" check, as this is only valid for panel configured light not aqualinkd configured light.
if ((_aqualink_data->aqbuttons[buttonIndex].special_mask & PROGRAM_LIGHT) == PROGRAM_LIGHT && _aqualink_data->aqbuttons[buttonIndex].led->state == OFF) {
// OK Programable light, and no light mode selected. Now let's work out best way to turn it on. serial_adapter protocol will to it without questions,
// all other will require programmig.
if (isRSSA_ENABLED) {
set_aqualink_rssadapter_aux_state(buttonIndex, true);
} else {
set_light_mode("0", buttonIndex); // 0 means use current light mode
}
} else {
aq_send_cmd(_aqualink_data->aqbuttons[buttonIndex].code);
}
// Pre set device to state, next status will correct if state didn't take, but this will stop multiple ON messages setting on/off
#ifdef PRESTATE_ONOFF
if ((_aqualink_data->aqbuttons[buttonIndex].code == KEY_POOL_HTR || _aqualink_data->aqbuttons[buttonIndex].code == KEY_SPA_HTR ||
_aqualink_data->aqbuttons[buttonIndex].code == KEY_SOLAR_HTR) &&
value > 0) {
_aqualink_data->aqbuttons[buttonIndex].led->state = ENABLE; // if heater and set to on, set pre-status to enable.
//_aqualink_data->updated = true;
} else if (isRSSA_ENABLED || ((_aqualink_data->aqbuttons[buttonIndex].special_mask & PROGRAM_LIGHT) != PROGRAM_LIGHT)) {
_aqualink_data->aqbuttons[buttonIndex].led->state = (value == 0 ? OFF : ON); // as long as it's not programmable light , pre-set to on/off
//_aqualink_data->updated = true;
}
#endif
}
}
// If it's a timer, start the timer
if (timer) {
start_timer(_aqualink_data, &_aqualink_data->aqbuttons[buttonIndex], value);
}
return true;
}
*/
//uriAtype action_URI(char *from, const char *URI, int uri_length, float value, bool convertTemp) {
//uriAtype action_URI(netRequest from, const char *URI, int uri_length, float value, bool convertTemp) {
@ -891,11 +782,34 @@ uriAtype action_URI(request_source from, const char *URI, int uri_length, float
return uSchedules;
} else if (strncmp(ri1, "simulator", 9) == 0 && from == NET_WS) { // Only valid from websocket.
return uSimulator;
} else if (strncmp(ri1, "aqmanager", 9) == 0 && from == NET_WS) { // Only valid from websocket.
return uAQmanager;
} else if (strncmp(ri1, "rawcommand", 10) == 0 && from == NET_WS) { // Only valid from websocket.
aq_send_cmd((unsigned char)value);
return uActioned;
} else if (strncmp(ri1, "aqmanager", 9) == 0 && from == NET_WS) { // Only valid from websocket.
return uAQmanager;
} else if (strncmp(ri1, "setloglevel", 11) == 0 && from == NET_WS) { // Only valid from websocket.
setSystemLogLevel(round(value));
return uAQmanager; // Want to resent updated status
} else if (strncmp(ri1, "addlogmask", 10) == 0 && from == NET_WS) { // Only valid from websocket.
addDebugLogMask(round(value));
return uAQmanager; // Want to resent updated status
} else if (strncmp(ri1, "removelogmask", 13) == 0 && from == NET_WS) { // Only valid from websocket.
removeDebugLogMask(round(value));
return uAQmanager; // Want to resent updated status
} else if (strncmp(ri1, "log2file", 5) == 0) {
if (ri2 != NULL && strncmp(ri2, "start", 5) == 0) {
startInlineLog2File();
} else if (ri2 != NULL && strncmp(ri2, "stop", 4) == 0) {
stopInlineLog2File();
} else if (ri2 != NULL && strncmp(ri2, "clean", 5) == 0) {
cleanInlineLogFile();
} else if (ri2 != NULL && strncmp(ri2, "download", 8) == 0) {
return uDebugDownload;
}
return uAQmanager; // Want to resent updated status
// BELOW IS FOR OLD DEBUG.HTML, Need to remove in future release
#ifdef INCLUDE_OLD_DEBUG_HTML
} else if (strncmp(ri1, "debug", 5) == 0) {
if (ri2 != NULL && strncmp(ri2, "start", 5) == 0) {
startInlineDebug();
@ -909,14 +823,18 @@ uriAtype action_URI(request_source from, const char *URI, int uri_length, float
cleanInlineDebug();
} else if (ri2 != NULL && strncmp(ri2, "download", 8) == 0) {
return uDebugDownload;
} else if (ri2 != NULL && strncmp(ri2, "stop", 4) == 0) {
}
}
return uDebugStatus;
#endif
// couple of debug items for testing
} else if (strncmp(ri1, "restart", 13) == 0) {
} else if (strncmp(ri1, "restart", 13) == 0 && from == NET_WS) { // Only valid from websocket.
/*
LOG(NET_LOG,LOG_NOTICE, "Received restart request!\n");
raise(SIGRESTART);
return uActioned;
*/
LOG(NET_LOG,LOG_WARNING, "Received restart request, not implimented in this release!\n");
return uBad;
} else if (strncmp(ri1, "set_date_time", 13) == 0) {
//aq_programmer(AQ_SET_TIME, NULL, _aqualink_data);
panel_device_request(_aqualink_data, DATE_TIME, 0, 0, from);
@ -1137,7 +1055,7 @@ uriAtype action_URI(request_source from, const char *URI, int uri_length, float
return rtn;
}
for (i=0; i < _aqualink_data->total_buttons; i++) {
for (i=0; i < _aqualink_data->total_buttons && found==false; i++) {
// If Label = "Spa", "Spa_Heater" will turn on "Spa", so need to check '/' on label as next character
if (strncmp(ri1, _aqualink_data->aqbuttons[i].name, strlen(_aqualink_data->aqbuttons[i].name)) == 0 ||
(strncmp(ri1, _aqualink_data->aqbuttons[i].label, strlen(_aqualink_data->aqbuttons[i].label)) == 0 && ri1[strlen(_aqualink_data->aqbuttons[i].label)] == '/'))
@ -1146,19 +1064,6 @@ uriAtype action_URI(request_source from, const char *URI, int uri_length, float
//create_panel_request(from, i, value, istimer);
panel_device_request(_aqualink_data, atype, i, value, from);
//LOG(NET_LOG,LOG_INFO, "%s: MATCH %s to topic %.*s\n",from,_aqualink_data->aqbuttons[i].name,uri_length, URI);
// Message is either a 1 or 0 for on or off
//int status = atoi(msg->payload.p);
/*
if ( value > 1 || value < 0) {
LOG(NET_LOG,LOG_WARNING, "%s: URI %s has invalid value %.2f\n",actionName[from], URI, value);
*rtnmsg = INVALID_VALUE;
rtn = uBad;
}
if (timer > 0) {
create_panel_request(from, i, timer, true);
} else {
create_panel_request(from, i, value, false);
}*/
}
}
if(!found) {
@ -1279,14 +1184,7 @@ void action_web_request(struct mg_connection *nc, struct http_message *http_msg)
// If we have a get request, pass it
if (strncmp(http_msg->uri.p, "/api", 4 ) != 0) {
if (strstr(http_msg->method.p, "GET") && http_msg->query_string.len > 0) {
#ifdef INCLUDE_V1_API
LOG(NET_LOG,LOG_WARNING, "WEB: Old stanza, using old method to action\n");
DEBUG_TIMER_START(&tid);
OLD_action_web_request(nc, http_msg);
DEBUG_TIMER_STOP(tid, NET_LOG, "action_web_request() serve Old stanza took");
#else
LOG(NET_LOG,LOG_ERR, "WEB: Old API stanza requested, ignoring client request\n");
#endif
} else {
DEBUG_TIMER_START(&tid);
mg_serve_http(nc, http_msg, _http_server_opts);
@ -1373,6 +1271,7 @@ void action_web_request(struct mg_connection *nc, struct http_message *http_msg)
mg_send(nc, message, size);
}
break;
#ifdef INCLUDE_OLD_DEBUG_HTML
case uDebugStatus:
{
char message[JSON_BUFFER_SIZE];
@ -1381,6 +1280,7 @@ void action_web_request(struct mg_connection *nc, struct http_message *http_msg)
mg_send(nc, message, size);
}
break;
#endif
case uDebugDownload:
mg_http_serve_file(nc, http_msg, getInlineLogFName(), mg_mk_str("text/plain"), mg_mk_str(""));
break;
@ -1439,13 +1339,8 @@ void action_websocket_request(struct mg_connection *nc, struct websocket_message
}
if (uri == NULL) {
#ifdef INCLUDE_V1_API
LOG(NET_LOG,LOG_WARNING, "WS: Old stanza, using old method to action\n");
return OLD_action_websocket_request(nc, wm);
#else
LOG(NET_LOG,LOG_ERR, "WEB: Old websocket stanza requested, ignoring client request\n");
return;
#endif
}
switch ( action_URI(NET_WS, uri, strlen(uri), (value!=NULL?atof(value):TEMP_UNKNOWN), false, &msg)) {
@ -1478,7 +1373,7 @@ void action_websocket_request(struct mg_connection *nc, struct websocket_message
_aqualink_data->simulate_panel = true;
DEBUG_TIMER_START(&tid);
char message[JSON_BUFFER_SIZE];
build_aqualink_status_JSON(_aqualink_data, message, JSON_BUFFER_SIZE); // Should change this to simulator.
build_aqualink_status_JSON(_aqualink_data, message, JSON_BUFFER_SIZE);
DEBUG_TIMER_STOP(tid, NET_LOG, "action_websocket_request() build_aqualink_status_JSON took");
ws_send(nc, message);
}
@ -1490,7 +1385,8 @@ void action_websocket_request(struct mg_connection *nc, struct websocket_message
_aqualink_data->aqManagerActive = true;
DEBUG_TIMER_START(&tid);
char message[JSON_BUFFER_SIZE];
build_aqualink_status_JSON(_aqualink_data, message, JSON_BUFFER_SIZE); // Should change this to simulator.
//build_aqualink_status_JSON(_aqualink_data, message, JSON_BUFFER_SIZE);
build_aqualink_aqmanager_JSON(_aqualink_data, message, JSON_BUFFER_SIZE);
DEBUG_TIMER_STOP(tid, NET_LOG, "action_websocket_request() build_aqualink_status_JSON took");
ws_send(nc, message);
}
@ -1829,13 +1725,17 @@ void *net_services_thread( void *ptr )
while (_keepNetServicesRunning == true)
{
//poll_net_services(&_mgr, 10);
mg_mgr_poll(&_mgr, 100);
// Shorten poll cycle when logging messages to WS
mg_mgr_poll(&_mgr, (_aqualink_data->aqManagerActive)?5:100);
//mg_mgr_poll(&_mgr, 100);
if (aqdata->updated == true /*|| _broadcast == true*/) {
//LOG(NET_LOG,LOG_DEBUG, "********** Broadcast ************\n");
_broadcast_aqualinkstate(_mgr.active_connections);
aqdata->updated = false;
//_broadcast = false;
}
if (_aqualink_data->aqManagerActive) {
send_ws_logmessages();
}
}
@ -1949,462 +1849,4 @@ bool start_net_services(/*struct mg_mgr *mgr, */struct aqualinkdata *aqdata)
return true;
}
#endif
#ifdef INCLUDE_V1_API
/* OLD Functions to be deprecated */
int getTempforMeteohub(char *buffer)
{
int length = 0;
if (_aqualink_data->air_temp != TEMP_UNKNOWN)
length += sprintf(buffer+length, "t0 %d\n",(int)degFtoC(_aqualink_data->air_temp)*10);
else
length += sprintf(buffer+length, "t0 \n");
if (_aqualink_data->pool_temp != TEMP_UNKNOWN)
length += sprintf(buffer+length, "t1 %d\n",(int)degFtoC(_aqualink_data->pool_temp)*10);
else
length += sprintf(buffer+length, "t1 \n");
return strlen(buffer);
}
/* Leave the old API / web function intact until we deprecate */
void OLD_action_web_request(struct mg_connection *nc, struct http_message *http_msg) {
// struct http_message *http_msg = (struct http_message *)ev_data;
if (getLogLevel(NET_LOG) >= LOG_WARNING) { // Simply for log message, check we are at
// this log level before running all this
// junk
char *uri = (char *)malloc(http_msg->uri.len + http_msg->query_string.len + 2);
strncpy(uri, http_msg->uri.p, http_msg->uri.len + http_msg->query_string.len + 1);
uri[http_msg->uri.len + http_msg->query_string.len + 1] = '\0';
LOG(NET_LOG,LOG_WARNING, "URI request: '%s'\n", uri);
free(uri);
}
// If we have a get request, pass it
if (strstr(http_msg->method.p, "GET") && http_msg->query_string.len > 0) {
char command[20];
mg_get_http_var(&http_msg->query_string, "command", command, sizeof(command));
LOG(NET_LOG,LOG_INFO, "WEB: Message command='%s'\n", command);
if (strcmp(command, "dynamic_config") == 0) {
char data[JSON_BUFFER_SIZE];
int size = build_color_lights_js(_aqualink_data, data, JSON_BUFFER_SIZE);
mg_send_head(nc, 200, size, CONTENT_JS);
mg_send(nc, data, size);
} else
// if (strstr(http_msg->query_string.p, "command=status")) {
if (strcmp(command, "status") == 0) {
char data[JSON_STATUS_SIZE];
int size = build_aqualink_status_JSON(_aqualink_data, data, JSON_STATUS_SIZE);
mg_send_head(nc, 200, size, CONTENT_JSON);
mg_send(nc, data, size);
//} else if (strstr(http_msg->query_string.p, "command=mhstatus")) {
} else if (strcmp(command, "mhstatus") == 0) {
char data[20];
int size = getTempforMeteohub(data);
mg_send_head(nc, 200, size, CONTENT_TEXT);
mg_send(nc, data, size);
} else if (strcmp(command, "poollightmode") == 0) {
LOG(NET_LOG,LOG_ERR, "WEB: poollightmode taken out for update (forgot to put it back)\n");
/*
char value[20];
mg_get_http_var(&http_msg->query_string, "value", value, sizeof(value));
//aq_programmer(AQ_SET_COLORMODE, value, _aqualink_data);
set_light_mode(value, _aqconfig_.light_programming_button_pool);
mg_send_head(nc, 200, strlen(GET_RTN_OK), CONTENT_TEXT);
mg_send(nc, GET_RTN_OK, strlen(GET_RTN_OK));
*/
} else if (strcmp(command, "spalightmode") == 0) {
LOG(NET_LOG,LOG_ERR, "WEB: spalightmode taken out for update (forgot to put it back)\n");
/*
char value[20];
mg_get_http_var(&http_msg->query_string, "value", value, sizeof(value));
//aq_programmer(AQ_SET_COLORMODE, value, _aqualink_data);
set_light_mode(value, _aqconfig_.light_programming_button_spa);
mg_send_head(nc, 200, strlen(GET_RTN_OK), CONTENT_TEXT);
mg_send(nc, GET_RTN_OK, strlen(GET_RTN_OK));
*/
} else if (strcmp(command, "diag") == 0) {
aq_programmer(AQ_GET_DIAGNOSTICS_MODEL, NULL, _aqualink_data);
mg_send_head(nc, 200, strlen(GET_RTN_OK), CONTENT_TEXT);
mg_send(nc, GET_RTN_OK, strlen(GET_RTN_OK));
} else if (strcmp(command, "swg_percent") == 0) {
char value[20];
mg_get_http_var(&http_msg->query_string, "value", value, sizeof(value));
aq_programmer(AQ_SET_SWG_PERCENT, value, _aqualink_data);
LOG(NET_LOG,LOG_INFO, "Web: request to set SWG to %s\n", value);
mg_send_head(nc, 200, strlen(GET_RTN_OK), CONTENT_TEXT);
mg_send(nc, GET_RTN_OK, strlen(GET_RTN_OK));
} else if (strcmp(command, "pool_htr_set_pnt") == 0) {
char value[20];
mg_get_http_var(&http_msg->query_string, "value", value, sizeof(value));
aq_programmer(AQ_SET_POOL_HEATER_TEMP, value, _aqualink_data);
LOG(NET_LOG,LOG_INFO, "Web: request to set Pool heater to %s\n", value);
mg_send_head(nc, 200, strlen(GET_RTN_OK), CONTENT_TEXT);
mg_send(nc, GET_RTN_OK, strlen(GET_RTN_OK));
} else if (strcmp(command, "spa_htr_set_pnt") == 0) {
char value[20];
mg_get_http_var(&http_msg->query_string, "value", value, sizeof(value));
aq_programmer(AQ_SET_SPA_HEATER_TEMP, value, _aqualink_data);
LOG(NET_LOG,LOG_INFO, "Web: request to set Spa heater to %s\n", value);
mg_send_head(nc, 200, strlen(GET_RTN_OK), CONTENT_TEXT);
mg_send(nc, GET_RTN_OK, strlen(GET_RTN_OK));
} else if (strcmp(command, "frz_protect_set_pnt") == 0) {
char value[20];
mg_get_http_var(&http_msg->query_string, "value", value, sizeof(value));
aq_programmer(AQ_SET_FRZ_PROTECTION_TEMP, value, _aqualink_data);
LOG(NET_LOG,LOG_INFO, "Web: request to set Freeze protect to %s\n", value);
mg_send_head(nc, 200, strlen(GET_RTN_OK), CONTENT_TEXT);
mg_send(nc, GET_RTN_OK, strlen(GET_RTN_OK));
/*
} else if (strcmp(command, "extended_device_prg") == 0) {
char value[20];
char message[JSON_LABEL_SIZE];
mg_get_http_var(&http_msg->query_string, "value", value, sizeof(value));
bool prg = request2bool(value);
if (prg && !onetouch_enabled())
prg = false; // Ignore request if onetouch is not enabeled
set_extended_device_id_programming(prg);
sprintf(message,"{\"extended_device_prg\":\"%s\"}", bool2text(prg));
mg_send_head(nc, 200, strlen(message), CONTENT_JSON);
mg_send(nc, message, strlen(message));
*/
} else if (strcmp(command, "devices") == 0) {
char message[JSON_BUFFER_SIZE];
int size = build_device_JSON(_aqualink_data, message, JSON_BUFFER_SIZE, false);
mg_send_head(nc, 200, size, CONTENT_JSON);
mg_send(nc, message, size);
} else if (strcmp(command, "homebridge") == 0) {
char message[JSON_BUFFER_SIZE];
int size = build_device_JSON(_aqualink_data, message, JSON_BUFFER_SIZE, true);
mg_send_head(nc, 200, size, CONTENT_JSON);
mg_send(nc, message, size);
} else if (strcmp(command, "setconfigprm") == 0) {
char value[20];
char param[30];
char *webrtn;
mg_get_http_var(&http_msg->query_string, "param", param, sizeof(param));
mg_get_http_var(&http_msg->query_string, "value", value, sizeof(value));
if (setConfigValue(_aqualink_data, param, value)) {
webrtn = GET_RTN_OK;
LOG(NET_LOG,LOG_INFO, "Web: request to config %s to %s\n", param, value);
} else {
webrtn = GET_RTN_ERROR;
LOG(NET_LOG,LOG_ERR, "Web: request to config %s to %s failed\n", param, value);
}
mg_send_head(nc, 200, strlen(webrtn), CONTENT_TEXT);
mg_send(nc, webrtn, strlen(webrtn));
} else if (strcmp(command, "writeconfig") == 0) {
if (writeCfg (_aqualink_data)) {
mg_send_head(nc, 200, strlen(GET_RTN_OK), CONTENT_TEXT);
mg_send(nc, GET_RTN_OK, strlen(GET_RTN_OK));
} else {
mg_send_head(nc, 200, strlen(GET_RTN_ERROR), CONTENT_TEXT);
mg_send(nc, GET_RTN_ERROR, strlen(GET_RTN_ERROR));
}
} else if (strcmp(command, "debug") == 0) {
char value[80];
char *rtn;
mg_get_http_var(&http_msg->query_string, "value", value, sizeof(value));
if (strcmp(value, "start") == 0) {
startInlineDebug();
rtn = GET_RTN_OK;
LOG(NET_LOG,LOG_DEBUG, "WEB: Started inline debug mode\n");
} else if (strcmp(value, "stop") == 0) {
LOG(NET_LOG,LOG_DEBUG, "WEB: Stoped inline debug mode\n");
stopInlineDebug();
rtn = GET_RTN_OK;
} else if (strcmp(value, "serialstart") == 0) {
startInlineSerialDebug();
LOG(NET_LOG,LOG_DEBUG, "WEB: Started inline debug mode\n");
rtn = GET_RTN_OK;
} else if (strcmp(value, "serialstop") == 0) {
LOG(NET_LOG,LOG_DEBUG, "WEB: Stoped inline debug mode\n");
stopInlineDebug();
rtn = GET_RTN_OK;
} else if (strcmp(value, "status") == 0) {
snprintf(value,80,"{\"sLevel\":\"%s\", \"iLevel\":%d, \"logReady\":\"%s\"}\n",elevel2text(getLogLevel(NET_LOG)),getLogLevel(NET_LOG),islogFileReady()?"true":"false" );
mg_send_head(nc, 200, strlen(value), "Content-Type: text/json");
mg_send(nc, value, strlen(value));
return;
//rtn = value;
} else if (strcmp(value, "clean") == 0) {
cleanInlineDebug();
rtn = GET_RTN_OK;
} else if (strcmp(value, "download") == 0) {
mg_http_serve_file(nc, http_msg, getInlineLogFName(), mg_mk_str("text/plain"), mg_mk_str(""));
return;
} else {
rtn = GET_RTN_UNKNOWN;
}
mg_send_head(nc, 200, strlen(rtn), CONTENT_TEXT);
mg_send(nc, rtn, strlen(rtn));
} else if (strncmp(command, "Pump_", 5) == 0) {
// Set Pump RPM
bool found = false;
int pumpIndex = atoi(command+5); // Check for 0
char value[10];
mg_get_http_var(&http_msg->query_string, "value", value, sizeof(value));
int rpm = atoi(value);
// Check for pumpIndex = 0 (BAD) and check RPM Value
//printf("******** ADD CHECK FOR PUMP & RPM HERE ********\n");
int pi;
for (pi=0; pi < _aqualink_data->num_pumps; pi++) {
if (_aqualink_data->pumps[pi].pumpIndex == pumpIndex) {
LOG(NET_LOG,LOG_NOTICE, "WEB: request to change pump %d to %d\n",pumpIndex+1, round(rpm));
_aqualink_data->unactioned.type = PUMP_RPM;
_aqualink_data->unactioned.value = round(rpm);
_aqualink_data->unactioned.id = pumpIndex;
found=true;
break;
}
}
if(!found)
LOG(NET_LOG,LOG_ERR, "WEB: Didn't find pump %d from command %s\n",pumpIndex,command);
} else {
int i;
for (i = 0; i < _aqualink_data->total_buttons; i++) {
if (strcmp(command, _aqualink_data->aqbuttons[i].name) == 0) {
char value[20];
char *rtn;
mg_get_http_var(&http_msg->query_string, "value", value, sizeof(value));
// LOG(NET_LOG,LOG_INFO, "Web Message command='%s'\n",command);
// aq_programmer(AQ_SEND_CMD, (char
// *)&_aqualink_data->aqbuttons[i].code, _aqualink_data);
LOG(NET_LOG,LOG_DEBUG, "WEB: Message request '%s' change state to '%s'\n", command, value);
#ifdef AQ_PDA
if (isPDA_PANEL) {
char msg[PTHREAD_ARG];
sprintf(msg, "%-5d%-5d",i, (strcmp(value, "on") == 0)?ON:OFF);
//printf("******* '%s' ********\n",msg);
aq_programmer(AQ_PDA_DEVICE_ON_OFF, msg, _aqualink_data);
rtn = GET_RTN_OK;
}
else
#endif
if (strcmp(value, "on") == 0) {
if (_aqualink_data->aqbuttons[i].led->state == OFF || _aqualink_data->aqbuttons[i].led->state == FLASH) {
//aq_programmer(AQ_SEND_CMD, (char *)&_aqualink_data->aqbuttons[i].code, _aqualink_data);
aq_send_cmd(_aqualink_data->aqbuttons[i].code);
rtn = GET_RTN_OK;
LOG(NET_LOG,LOG_INFO, "WEB: turn ON '%s' changed state to '%s'\n", command, value);
} else {
rtn = GET_RTN_NOT_CHANGED;
LOG(NET_LOG,LOG_INFO, "WEB: '%s' is already on '%s', current state %d\n", command, value, _aqualink_data->aqbuttons[i].led->state);
}
} else if (strcmp(value, "off") == 0) {
if (_aqualink_data->aqbuttons[i].led->state == ON ||
_aqualink_data->aqbuttons[i].led->state == ENABLE ||
_aqualink_data->aqbuttons[i].led->state == FLASH) {
//aq_programmer(AQ_SEND_CMD, (char *)&_aqualink_data->aqbuttons[i].code, _aqualink_data);
aq_send_cmd(_aqualink_data->aqbuttons[i].code);
rtn = GET_RTN_OK;
LOG(NET_LOG,LOG_INFO, "WEB: turn Off '%s' changed state to '%s'\n", command, value);
} else {
rtn = GET_RTN_NOT_CHANGED;
LOG(NET_LOG,LOG_INFO, "WEB: '%s' is already off '%s', current state %d\n", command, value, _aqualink_data->aqbuttons[i].led->state);
}
} else { // Blind switch
//aq_programmer(AQ_SEND_CMD, (char *)&_aqualink_data->aqbuttons[i].code, _aqualink_data);
aq_send_cmd(_aqualink_data->aqbuttons[i].code);
rtn = GET_RTN_OK;
LOG(NET_LOG,LOG_INFO, "WEB: '%s' blindly changed state\n", command, value);
}
LOG(NET_LOG,LOG_DEBUG, "WEB: On=%d, Off=%d, Enable=%d, Flash=%d\n", ON, OFF, ENABLE, FLASH);
// NSF change OK and 2 below to a constant
mg_send_head(nc, 200, strlen(rtn), CONTENT_TEXT);
mg_send(nc, rtn, strlen(rtn));
// NSF place check we found command here
}
}
}
// If we get here, got a bad query
mg_send_head(nc, 200, strlen(GET_RTN_UNKNOWN), CONTENT_TEXT);
mg_send(nc, GET_RTN_UNKNOWN, strlen(GET_RTN_UNKNOWN));
} else {
//struct mg_serve_http_opts opts;
//memset(&opts, 0, sizeof(opts)); // Reset all options to defaults
//opts.document_root = _web_root; // Serve files from the current directory
// LOG(NET_LOG,LOG_DEBUG, "Doc root=%s\n",opts.document_root);
mg_serve_http(nc, http_msg, _http_server_opts);
}
}
void OLD_action_websocket_request(struct mg_connection *nc, struct websocket_message *wm) {
char buffer[100];
struct JSONwebrequest request;
#ifdef AQ_PDA
// Any websocket request means UI is active, so don't let AqualinkD go to sleep if in PDA mode
if (isPDA_PANEL)
pda_reset_sleep();
#endif
strncpy(buffer, (char *)wm->data, wm->size);
buffer[wm->size] = '\0';
// LOG(NET_LOG,LOG_DEBUG, "buffer '%s'\n", buffer);
parseJSONwebrequest(buffer, &request);
LOG(NET_LOG,LOG_INFO, "WS: Message - Key '%s' Value '%s' | Key2 '%s' Value2 '%s'\n", request.first.key, request.first.value, request.second.key,
request.second.value);
/*
if (strcmp(request.first.key, "raw") == 0 || strcmp(request.first.key, "simulator") == 0 )
_aqualink_data->simulate_panel = true;
else
_aqualink_data->simulate_panel = false;
*/
if (strcmp(request.first.key, "raw") == 0) {
_aqualink_data->simulate_panel = true;
LOG(NET_LOG,LOG_NOTICE, "WS: Send raw command to controller %s\n",request.first.value);
unsigned int n;
sscanf(request.first.value, "0x%2x", &n);
//aq_programmer(AQ_SEND_CMD, (char *)&n, NULL);
aq_send_cmd((unsigned char)n);
//char message[JSON_LABEL_SIZE*10];
//build_device_JSON(_aqualink_data, _aqconfig_.light_programming_button, message, JSON_LABEL_SIZE*10);
//ws_send(nc, message);
} else if (strcmp(request.first.key, "mode") == 0) {
//if (strcmp(request.first.value, "onetouchraw") == 0) {
// set_websocket_RSraw(nc);
// }
} else if (strcmp(request.first.key, "command") == 0) {
_aqualink_data->simulate_panel = false;
if (strcmp(request.first.value, "GET_AUX_LABELS") == 0) {
char labels[JSON_LABEL_SIZE];
build_aux_labels_JSON(_aqualink_data, labels, JSON_LABEL_SIZE);
ws_send(nc, labels);
} else if (strcmp(request.first.value, "GET_DEVICES") == 0) {
char message[JSON_BUFFER_SIZE];
build_device_JSON(_aqualink_data, message, JSON_BUFFER_SIZE, false);
ws_send(nc, message);
} else if ( strcmp(request.first.value, "simulator") == 0) {
_aqualink_data->simulate_panel = true;
LOG(NET_LOG,LOG_INFO, "WS: Set Simulator mode\n");
char labels[JSON_LABEL_SIZE];
build_aux_labels_JSON(_aqualink_data, labels, JSON_LABEL_SIZE);
ws_send(nc, labels);
} else if ( strcmp(request.first.value, SWG_BOOST_TOPIC) == 0) {
//LOG(NET_LOG,LOG_INFO, "Boost\n");
if (request.second.value != NULL)
_aqualink_data->unactioned.value = request2bool(request.second.value);
else
_aqualink_data->unactioned.value = !_aqualink_data->boost;
_aqualink_data->unactioned.type = SWG_BOOST;
} else { // Search for value in command list
int i;
for (i = 0; i < _aqualink_data->total_buttons; i++) {
if (strcmp(request.first.value, _aqualink_data->aqbuttons[i].name) == 0) {
LOG(NET_LOG,LOG_INFO, "WS: button '%s' pressed\n",_aqualink_data->aqbuttons[i].name);
#ifdef AQ_PDA
if (isPDA_PANEL) {
char msg[PTHREAD_ARG];
sprintf(msg, "%-5d%-5d",i, (_aqualink_data->aqbuttons[i].led->state!=OFF)?OFF:ON);
aq_programmer(AQ_PDA_DEVICE_ON_OFF, msg, _aqualink_data);
} else
#endif
{
LOG(NET_LOG,LOG_DEBUG, "WS: request 0x%02hhx to be sent to controller\n",_aqualink_data->aqbuttons[i].code);
aq_send_cmd(_aqualink_data->aqbuttons[i].code);
}
break;
// NSF place check we found command here
}
}
}
} else if (strcmp(request.first.key, "parameter") == 0) {
_aqualink_data->simulate_panel = false;
if (strcmp(request.first.value, "FRZ_PROTECT") == 0 || strcmp(request.first.value, FREEZE_PROTECT) == 0) {
aq_programmer(AQ_SET_FRZ_PROTECTION_TEMP, request.second.value, _aqualink_data);
} else if (strcmp(request.first.value, "POOL_HTR") == 0 || strcmp(request.first.value, BTN_POOL_HTR) == 0 ) {
aq_programmer(AQ_SET_POOL_HEATER_TEMP, request.second.value, _aqualink_data);
} else if (strcmp(request.first.value, "SPA_HTR") == 0 || strcmp(request.first.value, BTN_SPA_HTR) == 0) {
aq_programmer(AQ_SET_SPA_HEATER_TEMP, request.second.value, _aqualink_data);
} else if (strcmp(request.first.value, SWG_TOPIC) == 0) {
//aq_programmer(AQ_SET_SWG_PERCENT, request.second.value, _aqualink_data);
int value = setpoint_check(SWG_SETPOINT, atoi(request.second.value), _aqualink_data);
if (_aqualink_data->ar_swg_device_status == SWG_STATUS_OFF ) {
// SWG is off, can't set %, so delay the set until it's on.
_aqualink_data->swg_delayed_percent = value;
} else {
aq_programmer(AQ_SET_SWG_PERCENT, request.second.value, _aqualink_data);
_aqualink_data->swg_percent = value; // Set the value as if it's already been set, just incase it's 0 as we won't get that message, or will update next time
}
//} else if (strcmp(request.first.value, "POOL_LIGHT_MODE") == 0) {
// set_light_mode(request.second.value, _aqconfig_.light_programming_button_pool);
} else if (strcmp(request.first.value, "LIGHT_MODE") == 0) {
// second is mode & third is button_id
int i;
for (i = 0; i < _aqualink_data->total_buttons; i++) {
// NSF I could pull the text here for the real light color name. 4th value in json
if (strcmp(request.third.value, _aqualink_data->aqbuttons[i].name) == 0) {
//set_light_mode(request.second.value, i);
panel_device_request(_aqualink_data, LIGHT_MODE, i, request.second.value, NET_API);
break;
}
}
//set_light_mode(request.second.value, 0);
} else {
int i;
bool found = false;
for (i = 0; i < _aqualink_data->total_buttons; i++) {
if (strcmp(request.first.value, _aqualink_data->aqbuttons[i].name) == 0) {
int pi;
LOG(NET_LOG,LOG_INFO, "WS: button parameter request '%s' '%s'\n",_aqualink_data->aqbuttons[i].name, request.second.value);
for (pi=0; pi < _aqualink_data->num_pumps; pi++) {
if (_aqualink_data->pumps[pi].button == &_aqualink_data->aqbuttons[i]) {
LOG(NET_LOG,LOG_NOTICE, "WS: request to change pump %d %s to %s\n",pi+1, _aqualink_data->aqbuttons[i].name, request.second.value);
_aqualink_data->unactioned.type = PUMP_RPM;
_aqualink_data->unactioned.value = atoi(request.second.value);
_aqualink_data->unactioned.id = _aqualink_data->pumps[pi].pumpIndex;
found=true;
break;
}
}
}
}
if (!found)
LOG(NET_LOG,LOG_DEBUG, "WS: Unknown parameter %s\n", request.first.value);
}
}
}
#endif // INCLUDE_V1_API
#endif

View File

@ -29,7 +29,7 @@ void stop_net_services();
time_t poll_net_services(int timeout_ms);
void broadcast_aqualinkstate();
void broadcast_aqualinkstate_error(char *msg);
void broadcast_logs(char *msg);
void broadcast_log(char *msg);
//#endif

View File

@ -604,6 +604,11 @@ unsigned char *last_onetouch_packet()
return &_last_msg_type;
}
void set_onetouch_lastmsg(unsigned char msgtype)
{
_last_msg_type = msgtype;
}
bool process_onetouch_packet(unsigned char *packet, int length, struct aqualinkdata *aq_data)
{
static bool filling_menu = false;
@ -651,7 +656,8 @@ bool process_onetouch_packet(unsigned char *packet, int length, struct aqualinkd
_last_kick_type = KICKT_CMD;
}
*/
_last_msg_type = packet[PKT_CMD];
//_last_msg_type = packet[PKT_CMD];
set_onetouch_lastmsg(packet[PKT_CMD]);
// Receive 0x04 for System menu (before 0x02)
// Receive 0x04 for startup menu (before 0x02)

View File

@ -72,7 +72,7 @@ char *onetouch_menu_hlightchars(int *len);
int onetouch_menu_find_index(char *text);
int ot_atoi(const char* str);
int ot_strcmp(const char *s1, const char *s2);
void set_onetouch_lastmsg(unsigned char msgtype);

Binary file not shown.

Binary file not shown.

View File

@ -26,6 +26,7 @@
#include <fcntl.h>
#include <time.h>
#include "serial_logger.h"
#include "aq_serial.h"
#include "utils.h"
#include "packetLogger.h"
@ -38,7 +39,7 @@
#define SLOG_MAX 80
#define PACKET_MAX 600
#define VERSION "serial_logger V1.7"
#define VERSION "serial_logger V1.8"
/*
typedef enum used {
@ -83,7 +84,8 @@ bool _playback_file = false;
int timespec_subtract (struct timespec *result, const struct timespec *x, const struct timespec *y);
void broadcast_logs(char *msg){
#ifdef SERIAL_LOGGER
void broadcast_log(char *msg){
// Do nothing, just for utils.c to work.
}
@ -93,6 +95,7 @@ void intHandler(int dummy) {
if (_playback_file) // If we are reading file, loop is irevelent
exit(0);
}
#endif
#define MASTER " <-- Master control panel"
#define SWG " <-- Salt Water Generator (Aquarite mode)"
@ -389,30 +392,37 @@ void getPanelInfo(int rs_fd, unsigned char *packet_buffer, int packet_length)
}
}
#ifdef SERIAL_LOGGER
int main(int argc, char *argv[]) {
int rs_fd;
int packet_length;
int last_packet_length = 0;
unsigned char packet_buffer[AQ_MAXPKTLEN];
unsigned char last_packet_buffer[AQ_MAXPKTLEN];
unsigned char lastID = 0x00;
//int packet_length;
//int last_packet_length = 0;
//unsigned char packet_buffer[AQ_MAXPKTLEN];
//unsigned char last_packet_buffer[AQ_MAXPKTLEN];
//unsigned char lastID = 0x00;
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;
//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;
bool panleProbe = true;
bool rsSerialSpeedTest = false;
bool serialBlocking = true;
bool errorMonitor = false;
struct timespec start_time;
struct timespec end_time;
struct timespec elapsed;
int blankReads = 0;
//struct timespec start_time;
//struct timespec end_time;
//struct timespec elapsed;
//int blankReads = 0;
//bool returnError = false;
//bool monitorOnly = false;
//bool playback_file = false;
@ -424,6 +434,7 @@ int main(int argc, char *argv[]) {
_aqconfig_.readahead_b4_write = false;
_aqconfig_.log_protocol_packets = false;
_aqconfig_.log_raw_bytes = false;
_aqconfig_.ftdi_low_latency = true;
printf("AqualinkD %s\n",VERSION);
@ -437,9 +448,9 @@ int main(int argc, char *argv[]) {
//fprintf(stderr, "Optional parameters are -d (debug) & -p <number> (log # packets) & -i <ID> & -r (raw) ie:=\n\t%s /dev/ttyUSB0 -d -p 1000 -i 0x08\n\n", argv[0]);
fprintf(stderr, "Optional parameters are :-\n");
fprintf(stderr, "\t-n (Do not probe panel for type/rev info)\n");
fprintf(stderr, "\t-d (debug)\n");
fprintf(stderr, "\t-d (debug / print messages)\n");
fprintf(stderr, "\t-p <number> (# packets to log, default=%d)\n",PACKET_MAX);
fprintf(stderr, "\t-i <ID> (just log these ID's, can use multiple -i)\n");
fprintf(stderr, "\t-i <ID> (just log specific ID, can use multiple -i. will also force -d switc)\n");
fprintf(stderr, "\t-r (raw)\n");
fprintf(stderr, "\t-s (Serial Speed Test / OS caching issues)\n");
fprintf(stderr, "\t-lpack (log RS packets to %s)\n",RS485LOGFILE);
@ -495,6 +506,12 @@ int main(int argc, char *argv[]) {
rs_fd = init_serial_port(argv[1]);
else
rs_fd = init_blocking_serial_port(argv[1]);
if (rs_fd < 0) {
LOG(RSSD_LOG, LOG_ERR, "Unable to open port: %s\n", argv[1]);
displayLastSystemError(argv[1]);
return -1;
}
}
signal(SIGINT, intHandler);
@ -514,7 +531,37 @@ int main(int argc, char *argv[]) {
printf("Please wait.");
startPacketLogger();
//startPacketLogging(true,true);
serial_logger(rs_fd, argv[1], logPackets, logLevel, panleProbe, rsSerialSpeedTest, errorMonitor);
stopPacketLogger();
close_serial_port(rs_fd);
}
#endif // SERIAL_LOGGER
int serial_logger(int rs_fd, char *port_name, int logPackets, int logLevel, bool panleProbe, bool rsSerialSpeedTest, bool errorMonitor) {
int packet_length;
int last_packet_length = 0;
unsigned char packet_buffer[AQ_MAXPKTLEN];
unsigned char last_packet_buffer[AQ_MAXPKTLEN];
unsigned char lastID = 0x00;
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;
struct timespec start_time;
struct timespec end_time;
struct timespec elapsed;
int blankReads = 0;
bool returnError = false;
clock_gettime(CLOCK_REALTIME, &start_time);
@ -527,12 +574,14 @@ int main(int argc, char *argv[]) {
if (packet_length == AQSERR_READ) {
// Unrecoverable read error. Force an attempt to reconnect.
LOG(RSSD_LOG, LOG_ERR, "ERROR, on serial port! Please check %s\n",argv[1]);
LOG(RSSD_LOG, LOG_ERR, "ERROR, on serial port! Please check %s\n",port_name);
_keepRunning = false;
returnError = true;
} else if (packet_length == AQSERR_TIMEOUT) {
// Unrecoverable read error. Force an attempt to reconnect.
LOG(RSSD_LOG, LOG_ERR, "ERROR, Timeout on serial port, nothing read! Please check %s\n",argv[1]);
LOG(RSSD_LOG, LOG_ERR, "ERROR, Timeout on serial port, nothing read! Please check %s\n",port_name);
_keepRunning = false;
returnError = true;
} else if (packet_length < 0) {
// Error condition
if (errorMonitor && last_packet_length > 0) { // Error packet wwould have already been printed.
@ -545,8 +594,9 @@ int main(int argc, char *argv[]) {
} else if (packet_length == 0) {
// Nothing read
if (++blankReads > (rsSerialSpeedTest?100000000:1000) ) {
LOG(RSSD_LOG, LOG_ERR, "ERROR, too many blank reads! Please check %s\n",argv[1]);
LOG(RSSD_LOG, LOG_ERR, "ERROR, too many blank reads! Please check %s\n",port_name);
_keepRunning = false;
returnError = true;
}
//if (!rsSerialSpeedTest)
delay(1);
@ -646,10 +696,16 @@ int main(int argc, char *argv[]) {
clock_gettime(CLOCK_REALTIME, &end_time);
stopPacketLogger();
//stopPacketLogger();
if (errorMonitor) {
// Reset and close the port.
//close_serial_port(rs_fd);
// If we were monitoring errors, or filtering messages, or no panel probe, don;t print details
if (errorMonitor || panleProbe==false || _filters > 0) {
return 0;
} else if (returnError) {
return 1;
}
timespec_subtract(&elapsed, &end_time, &start_time);
@ -760,4 +816,69 @@ int timespec_subtract (struct timespec *result, const struct timespec *x, const
/* Return 1 if result is negative. */
return x->tv_sec < tmp.tv_sec;
}
}
/*********************************************
// Notes on PC Dock
To start download.
Jandy To 0x58 of type Probe | HEX: 0x10|0x02|0x58|0x00|0x6a|0x10|0x03|
Jandy From 0x58 of type Unknown '0x19' | HEX: 0x10|0x02|0x00|0x19|0x00|0x00|0x2b|0x10|0x03|
Then the download is a lot of these.
Jandy To 0x58 of type Unknown '0x1a' | HEX: 0x10|0x02|0x58|0x1a|0x00|0x00|0x00|0x00|0x3c|0x00|0x00|0x64|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x05|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x29|0x10|0x03|
Jandy From 0x58 of type Unknown '0x19' | HEX: 0x10|0x02|0x00|0x19|0x01|0x00|0x2c|0x10|0x03|
Jandy To 0x58 of type Unknown '0x1a' | HEX: 0x10|0x02|0x58|0x1a|0x01|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x85|0x10|0x03|
Jandy From 0x58 of type Unknown '0x19' | HEX: 0x10|0x02|0x00|0x19|0x02|0x00|0x2d|0x10|0x03|
Jandy To 0x58 of type Unknown '0x1a' | HEX: 0x10|0x02|0x58|0x1a|0x02|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x86|0x10|0x03|
Jandy From 0x58 of type Unknown '0x19' | HEX: 0x10|0x02|0x00|0x19|0x03|0x00|0x2e|0x10|0x03|
Jandy To 0x58 of type Unknown '0x1a' | HEX: 0x10|0x02|0x58|0x1a|0x03|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x01|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x04|0x00|0x22|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0xae|0x10|0x03|
Jandy From 0x58 of type Unknown '0x19' | HEX: 0x10|0x02|0x00|0x19|0x04|0x00|0x2f|0x10|0x03|
Jandy To 0x58 of type Unknown '0x1a' | HEX: 0x10|0x02|0x58|0x1a|0x04|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0x4f|0x10|0x03|
Jandy From 0x58 of type Unknown '0x19' | HEX: 0x10|0x02|0x00|0x19|0x05|0x00|0x30|0x10|0x03|
Jandy To 0x58 of type Unknown '0x1a' | HEX: 0x10|0x02|0x58|0x1a|0x05|0x00|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0xff|0x49|0x10|0x03|
Jandy From 0x58 of type Unknown '0x19' | HEX: 0x10|0x02|0x00|0x19|0x06|0x00|0x31|0x10|0x03|
End of download is (Not sure how it knows to send ACK and not 0x19 reply)
Jandy To 0x58 of type Unknown '0x1a' | HEX: 0x10|0x02|0x58|0x1a|0x56|0x00|0x4d|0xc2|0x31|0x42|0x41|0x36|0x32|0x38|0x32|0x35|0x42|0x37|0x43|0x36|0x39|0x41|0x34|0x43|0x43|0x36|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0xff|0xff|0xff|0x52|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x4f|0x10|0x03|
Jandy From 0x58 of type Ack | HEX: 0x10|0x02|0x00|0x01|0x57|0x00|0x6a|0x10|0x03|
To start upload
Jandy To 0x58 of type Probe | HEX: 0x10|0x02|0x58|0x00|0x6a|0x10|0x03|
Jandy From 0x58 of type Unknown '0x17' | HEX: 0x10|0x02|0x00|0x17|0x29|0x10|0x03|
Jandy To 0x58 of type Unknown '0x19' | HEX: 0x10|0x02|0x58|0x19|0x00|0x00|0x83|0x10|0x03|
Jandy From 0x58 of type Unknown '0x1a' | HEX: 0x10|0x02|0x00|0x1a|0x00|0x00|0x00|0x00|0x3c|0x00|0x00|0x64|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x05|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0xd1|0x10|0x03|
Jandy To 0x58 of type Unknown '0x19' | HEX: 0x10|0x02|0x58|0x19|0x01|0x00|0x84|0x10|0x03|
Jandy From 0x58 of type Unknown '0x1a' | HEX: 0x10|0x02|0x00|0x1a|0x01|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x2d|0x10|0x03|
Jandy To 0x58 of type Unknown '0x19' | HEX: 0x10|0x02|0x58|0x19|0x02|0x00|0x85|0x10|0x03|
Jandy From 0x58 of type Unknown '0x1a' | HEX: 0x10|0x02|0x00|0x1a|0x02|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x2e|0x10|0x03|
Jandy To 0x58 of type Unknown '0x19' | HEX: 0x10|0x02|0x58|0x19|0x03|0x00|0x86|0x10|0x03|
Jandy From 0x58 of type Unknown '0x1a' | HEX: 0x10|0x02|0x00|0x1a|0x03|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x01|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x04|0x00|0x22|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x56|0x10|0x03|
Not sure on end, kind-a looks like control panel sends probe back.
Jandy To 0x58 of type Unknown '0x19' | HEX: 0x10|0x02|0x58|0x19|0x55|0x00|0xd8|0x10|0x03|
Jandy From 0x58 of type Unknown '0x1a' | HEX: 0x10|0x02|0x00|0x1a|0x55|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x01|0x00|0x01|0x00|0x57|0x50|0x77|0x72|0x20|0x43|0x6e|0x74|0x72|0x20|0x42|0x00|0x00|0x58|0x01|0xff|0x17|0x00|0x00|0x6c|0x17|0x00|0x00|0x6c|0x17|0x00|0x00|0x6c|0x17|0x00|0x00|0x6c|0x20|0x20|0x20|0x20|0x20|0x20|0x20|0x20|0x20|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0xb0|0x10|0x03|
Jandy To 0x58 of type Unknown '0x19' | HEX: 0x10|0x02|0x58|0x19|0x56|0x00|0xd9|0x10|0x03|
Jandy From 0x58 of type Unknown '0x1a' | HEX: 0x10|0x02|0x00|0x1a|0x56|0x00|0x4d|0xc2|0x31|0x42|0x41|0x36|0x32|0x38|0x32|0x35|0x42|0x37|0x43|0x36|0x39|0x41|0x34|0x43|0x43|0x36|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0xff|0xff|0xff|0x52|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0xf7|0x10|0x03|
Jandy To 0x58 of type Probe | HEX: 0x10|0x02|0x58|0x00|0x6a|0x10|0x03|
Jandy From 0x58 of type Unknown '0x1a' | HEX: 0x10|0x02|0x00|0x1a|0x56|0x00|0x4d|0xc2|0x31|0x42|0x41|0x36|0x32|0x38|0x32|0x35|0x42|0x37|0x43|0x36|0x39|0x41|0x34|0x43|0x43|0x36|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0xff|0xff|0xff|0x52|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0xf7|0x10|0x03|
Jandy To 0x58 of type Probe | HEX: 0x10|0x02|0x58|0x00|0x6a|0x10|0x03|
Jandy From 0x58 of type Unknown '0x1a' | HEX: 0x10|0x02|0x00|0x1a|0x56|0x00|0x4d|0xc2|0x31|0x42|0x41|0x36|0x32|0x38|0x32|0x35|0x42|0x37|0x43|0x36|0x39|0x41|0x34|0x43|0x43|0x36|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0xff|0xff|0xff|0x52|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0xf7|0x10|0x03|
********************************************/

16
serial_logger.h Normal file
View File

@ -0,0 +1,16 @@
#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);
#endif // SERIAL_LOGGER_H_

View File

@ -195,23 +195,25 @@ void get_aqualink_rssadapter_setpoints() {
push_rssa_cmd(getPoolSP2);
}
void setLEDstate( aqled *led, unsigned char state, struct aqualinkdata *aq_data)
// Return true if we change the state.
bool setLEDstate( aqled *led, unsigned char state, struct aqualinkdata *aq_data)
{
if (state == 0x00) {
if (led->state != OFF) {
led->state = OFF;
aq_data->updated = true;
return true;
}
} else if (state == 0x01) {
if (led->state != ON) {
led->state = ON;
aq_data->updated = true;
return true;
}
}
// Should also add FLASH and ENABLE.
//_aqualink_data.aqbuttons[13].led->state = OFF;
//
//
return false;
}
bool process_rssadapter_packet(unsigned char *packet, int length, struct aqualinkdata *aq_data) {
@ -271,37 +273,42 @@ bool process_rssadapter_packet(unsigned char *packet, int length, struct aqualin
if (packet[6] == 0x01) {
LOG(RSSA_LOG,LOG_INFO,"Units are Deg C\n");
aq_data->temp_units = CELSIUS;
rtn = true;
} else if (packet[6] == 0x00) {
LOG(RSSA_LOG,LOG_INFO,"Units are Deg F\n");
aq_data->temp_units = FAHRENHEIT;
rtn = true;
} else {
LOG(RSSA_LOG,LOG_ERR,"Units are Unknown\n");
}
} else if (packet[4] == RS_SA_POOLSP) {
LOG(RSSA_LOG,LOG_INFO,"Pool SP is %d\n", packet[6]);
aq_data->pool_htr_set_point = (int) packet[6];
rtn = true;
} else if (packet[4] == RS_SA_SPASP) {
LOG(RSSA_LOG,LOG_INFO,"Spa SP is %d\n", packet[6]);
aq_data->spa_htr_set_point = (int) packet[6];
rtn = true;
} else if (packet[4] == RS_SA_POOLSP2) {
LOG(RSSA_LOG,LOG_INFO,"Pool SP2 is %d\n", packet[6]);
aq_data->spa_htr_set_point = (int) packet[6];
rtn = true;
} else if (packet[4] == 0x03) {
// These are device status messages
#ifdef AQ_RS16
if (packet[7] == RS_SA_AUX12) {
LOG(RSSA_LOG,LOG_INFO,"AUX12 %d\n", packet[6]);
setLEDstate(aq_data->aqbuttons[13].led, packet[6], aq_data);
rtn = setLEDstate(aq_data->aqbuttons[13].led, packet[6], aq_data);
//_aqualink_data.aqbuttons[13].led->state = OFF;
} else if (packet[7] == RS_SA_AUX13) {
LOG(RSSA_LOG,LOG_INFO,"AUX13 %d\n", packet[6]);
setLEDstate(aq_data->aqbuttons[14].led, packet[6], aq_data);
rtn = setLEDstate(aq_data->aqbuttons[14].led, packet[6], aq_data);
} else if (packet[7] == RS_SA_AUX14) {
LOG(RSSA_LOG,LOG_INFO,"AUX14 %d\n", packet[6]);
setLEDstate(aq_data->aqbuttons[15].led, packet[6], aq_data);
rtn = setLEDstate(aq_data->aqbuttons[15].led, packet[6], aq_data);
} else if (packet[7] == RS_SA_AUX15) {
LOG(RSSA_LOG,LOG_INFO,"AUX15 %d\n", packet[6]);
setLEDstate(aq_data->aqbuttons[16].led, packet[6], aq_data);
rtn = setLEDstate(aq_data->aqbuttons[16].led, packet[6], aq_data);
}
#endif
}
@ -359,6 +366,9 @@ unsigned char AllButton2RSsrialAdapter(unsigned char abcmd)
#ifdef DO_NOT_COMPILE
/
//*********************************************
// Notes on protocol for Serial Adapter.
/*
@ -1285,6 +1295,9 @@ Solar Heat Off
Debug: RS Serial: To 0x00 of type Ack | HEX: 0x10|0x02|0x00|0x01|0x00|0x12|0x25|0x10|0x03|
Debug: RS Serial: To 0x48 of type RSSA DevStatus | HEX: 0x10|0x02|0x48|0x13|0x03|0x00|0x00|0x12|0x82|0x10|0x03|
*/
#endif

83
utils.c
View File

@ -46,7 +46,7 @@
// Since this get's compiled without net_services for serial_logger
// pre-define this here rather than include netservices.h
void broadcast_logs(char *msg);
void broadcast_log(char *msg);
static bool _daemonise = false;
static bool _log2file = false;
@ -79,6 +79,14 @@ void setLoggingPrms(int level , bool deamonized, char* log_file, char *error_mes
}
}
void setSystemLogLevel( int level)
{
_log_level = level;
}
int getSystemLogLevel()
{
return _log_level;
}
int getLogLevel(int16_t from)
{
@ -93,7 +101,38 @@ int getLogLevel(int16_t from)
return _log_level;
}
void startInlineLog2File()
{
_log2file = true;
if (_log_filename == NULL)
_log_filename = DEFAULT_LOG_FILE;
}
void stopInlineLog2File()
{
_log2file = _cfg_log2file;
}
char *getInlineLogFName()
{
return _log_filename;
}
void cleanInlineLogFile() {
if (_log_filename != NULL) {
fclose(fopen(_log_filename, "w"));
}
}
bool islogFileReady()
{
if (_log_filename != NULL) {
struct stat st;
stat(_log_filename, &st);
if ( st.st_size > 0)
return true;
}
return false;
}
#ifdef INCLUDE_OLD_DEBUG_HTML
void startInlineDebug()
{
_log_level = LOG_DEBUG;
@ -115,30 +154,13 @@ void stopInlineDebug()
_log_level = _cfg_log_level;
_log2file = _cfg_log2file;
}
char *getInlineLogFName()
{
return _log_filename;
}
bool islogFileReady()
{
if (_log_filename != NULL) {
struct stat st;
stat(_log_filename, &st);
if ( st.st_size > 0)
return true;
}
return false;
}
void cleanInlineDebug() {
if (_log_filename != NULL) {
fclose(fopen(_log_filename, "w"));
}
}
#endif
/*
* This function reports the error and
@ -216,6 +238,14 @@ int text2elevel(char* level)
return LOG_ERR;
}
const char* loglevel2name(int level)
{
if (level == LOG_DEBUG_SERIAL)
return "Debug Serial:";
return elevel2text(level);
}
const char* logmask2name(int16_t from)
{
switch (from) {
@ -415,6 +445,16 @@ void removeDebugLogMask(int16_t flag)
_logforcemask &= ~flag;
}
void clearDebugLogMask()
{
_logforcemask = 0;
}
bool isDebugLogMaskSet(int16_t flag)
{
return _logforcemask & flag;
}
void _LOG(int16_t from, int msg_level, char * message);
/*
@ -435,7 +475,6 @@ void logMessage(int msg_level, const char *format, ...)
}
*/
void LOG(int16_t from, int msg_level, const char * format, ...)
{
//printf("msg_level=%d _log_level=%d mask=%d\n",msg_level,_log_level,(_logforcemask & from));
@ -513,7 +552,7 @@ void _LOG(int16_t from, int msg_level, char *message)
*/
// Send logs to any websocket that's interested.
broadcast_logs(message);
broadcast_log(message);
// Sent the log to the UI if configured.
if (msg_level <= LOG_ERR && _loq_display_message != NULL) {

26
utils.h
View File

@ -5,6 +5,9 @@
#ifndef UTILS_H_
#define UTILS_H_
// In future release, delete this and all code, it's been replaced with aqmanager
#define INCLUDE_OLD_DEBUG_HTML
#define LOG_DEBUG_SERIAL 8
#ifndef EXIT_SUCCESS
@ -17,9 +20,9 @@
#define FALSE 0
#endif
#define LOGBUFFER 1024
#define LOGBUFFER 256
#define MAXLEN 256
//#define MAXLEN 256
//#define round(a) (int) (a+0.5) // 0 decimal places (doesn't work for negative numbers)
#define round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5))
@ -55,6 +58,8 @@ typedef enum
//void setLoggingPrms(int level , bool deamonized, char* log_file);
void setLoggingPrms(int level , bool deamonized, char* log_file, char *error_messages);
int getLogLevel(int16_t from);
int getSystemLogLevel();
void setSystemLogLevel( int level);
void daemonise ( char *pidFile, void (*main_function)(void) );
//void debugPrint (char *format, ...);
void displayLastSystemError (const char *on_what);
@ -62,6 +67,10 @@ void displayLastSystemError (const char *on_what);
void addDebugLogMask(int16_t flag);
void removeDebugLogMask(int16_t flag);
void clearDebugLogMask();
bool isDebugLogMaskSet(int16_t flag);
const char* logmask2name(int16_t mask);
const char* loglevel2name(int level);
//#define logMessage(msg_level, format, ...) LOG (1, msg_level, format, ##__VA_ARGS__)
@ -93,13 +102,22 @@ char* stristr(const char* haystack, const char* needle);
char *prittyString(char *str);
//void writePacketLog(char *buff);
//void closePacketLog();
void startInlineLog2File();
void stopInlineLog2File();
void cleanInlineLogFile();
#ifdef INCLUDE_OLD_DEBUG_HTML
void startInlineDebug();
void startInlineSerialDebug();
void stopInlineDebug();
void startInlineSerialDebug();
void cleanInlineDebug();
#endif
char *getInlineLogFName();
bool islogFileReady();
const char *logmask2name(int16_t from);
//const char *logmask2name(int16_t from);
//#ifndef _UTILS_C_
extern bool _daemon_;

View File

@ -1,4 +1,4 @@
#define AQUALINKD_NAME "Aqualink Daemon"
#define AQUALINKD_VERSION "2.3.0f"
#define AQUALINKD_VERSION "2.3.1"

View File

@ -1872,7 +1872,8 @@
case "switch":
if (deviceobj.type_ext == "switch_vsp") {
if (deviceobj.Pump_Type == "vfPump") {
html = html + '<option value="' + V_RPM + '" ' + cs_isSelected("RPM", val1, val2) + '>RPM</option><option value="' + V_GPM + '" ' + cs_isSelected("GPM", val1, val2) + '>GPM</option>';
//html = html + '<option value="' + V_RPM + '" ' + cs_isSelected("RPM", val1, val2) + '>RPM</option><option value="' + V_GPM + '" ' + cs_isSelected("GPM", val1, val2) + '>GPM</option>';
html = html + '<option value="' + V_GPM + '" ' + cs_isSelected("GPM", val1, val2) + '>GPM</option>';
} else {
html = html + '<option value="' + V_RPM + '" ' + cs_isSelected("RPM", val1, val2) + '>RPM</option>';
}