Version 2.2.0c

pull/116/head
sfeakes 2020-07-26 14:28:58 -05:00
parent f4b7bd91ff
commit 6c9749f3e4
31 changed files with 1165 additions and 504 deletions

114
Makefile
View File

@ -1,45 +1,51 @@
# #
# Options # 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 # Valid flags for AQ_FLAGS
#AQ_DEBUG = true
AQ_RS16 = true AQ_RS16 = true
AQ_PDA = true AQ_PDA = true
AQ_ONETOUCH = true AQ_ONETOUCH = true
AQ_IAQTOUCH = true AQ_IAQTOUCH = true
#AQ_MEMCMP = true // Not implimented correctly yet. #AQ_MEMCMP = true // Not implimented correctly yet.
# 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: $(GLIBC_VERSION) )
# make EXFLAGS="-D BETA_PDA_AUTOLABEL" // Add compile flags
#
# define the C compiler to use # define the C compiler to use
CC = gcc CC = gcc
#LIBS := -lpthread -lm #LIBS := -lpthread -lm
LIBS := -l pthread -l m LIBS := -l pthread -l m
#LIBS := -lpthread -lwebsockets #LIBS := -l pthread -l m -static # Take out -static, just for dev
# debug of not # Standard compile flags
#DBG = -g -O0 -fsanitize=address GCCFLAGS = -Wall -O3
#GCCFLAGS = -Wall -O3 #GCCFLAGS = -O3
# USe below to remove unused functions and global variables.
#LFLAGS = -Wl,--gc-sections,--print-gc-sections
#GCCFLAGS = -Wall -ffunction-sections -fdata-sections
# define any compile-time flags
#GCCFLAGS = -Wall -O3 -Wextra #GCCFLAGS = -Wall -O3 -Wextra
#GCCFLAGS = -Wall -O3 #GCCFLAGS = -Wl,--gc-sections,--print-gc-sections
#GCCFLAGS = -Wall #GCCFLAGS = -Wall -O3 -ffunction-sections -fdata-sections
#CFLAGS = -Wall -g $(LIBS) # Standard debug flags
#CFLAGS = -Wall -g $(LIBS) -std=gnu11 DGCCFLAGS = -Wall -O0 -g
#CFLAGS = $(GCCFLAGS) $(DBG) $(AQ_FLAGS) $(LIBS) -D MG_DISABLE_MD5 -D MG_DISABLE_HTTP_DIGEST_AUTH -D MG_DISABLE_MD5 -D MG_DISABLE_JSON_RPC
CFLAGS = $(GCCFLAGS) $(DBG) $(LIBS) -D MG_DISABLE_MD5 -D MG_DISABLE_HTTP_DIGEST_AUTH -D MG_DISABLE_MD5 -D MG_DISABLE_JSON_RPC
# 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
# Add inputs and outputs from these tool invocations to the build variables
# define the C source files # define the C source files
#SRCS = aqualinkd.c utils.c config.c aq_serial.c init_buttons.c aq_programmer.c net_services.c json_messages.c pda.c pda_menu.c \ #SRCS = aqualinkd.c utils.c config.c aq_serial.c init_buttons.c aq_programmer.c net_services.c json_messages.c pda.c pda_menu.c \
@ -47,41 +53,41 @@ CFLAGS = $(GCCFLAGS) $(DBG) $(LIBS) -D MG_DISABLE_MD5 -D MG_DISABLE_HTTP_DIGEST_
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\ 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 mongoose.c devices_jandy.c packetLogger.c devices_pentair.c color_lights.c mongoose.c
DBG_SRC = timespec_subtract.c
AQ_FLAGS =
# Add source and flags depending on protocols to support.
ifeq ($(AQ_PDA), true) ifeq ($(AQ_PDA), true)
SRCS := $(SRCS) pda.c pda_menu.c pda_aq_programmer.c SRCS := $(SRCS) pda.c pda_menu.c pda_aq_programmer.c
CFLAGS := $(CFLAGS) -D AQ_PDA AQ_FLAGS := $(AQ_FLAGS) -D AQ_PDA
endif endif
ifeq ($(AQ_ONETOUCH), true) ifeq ($(AQ_ONETOUCH), true)
SRCS := $(SRCS) onetouch.c onetouch_aq_programmer.c SRCS := $(SRCS) onetouch.c onetouch_aq_programmer.c
CFLAGS := $(CFLAGS) -D AQ_ONETOUCH AQ_FLAGS := $(AQ_FLAGS) -D AQ_ONETOUCH
endif endif
ifeq ($(AQ_IAQTOUCH), true) ifeq ($(AQ_IAQTOUCH), true)
SRCS := $(SRCS) iaqtouch.c iaqtouch_aq_programmer.c SRCS := $(SRCS) iaqtouch.c iaqtouch_aq_programmer.c
CFLAGS := $(CFLAGS) -D AQ_IAQTOUCH AQ_FLAGS := $(AQ_FLAGS) -D AQ_IAQTOUCH
endif endif
ifeq ($(AQ_RS16), true) ifeq ($(AQ_RS16), true)
CFLAGS := $(CFLAGS) -D AQ_RS16 AQ_FLAGS := $(AQ_FLAGS) -D AQ_RS16
endif endif
ifeq ($(AQ_MEMCMP), true) ifeq ($(AQ_MEMCMP), true)
CFLAGS := $(CFLAGS) -D AQ_MEMCMP AQ_FLAGS := $(AQ_FLAGS) -D AQ_MEMCMP
endif endif
ifeq ($(AQ_DEBUG), true) # Put all flags together.
DEBUG=true CFLAGS = $(GCCFLAGS) $(AQ_FLAGS) $(MGFLAGS)
endif DFLAGS = $(DGCCFLAGS) $(AQ_FLAGS) $(MGFLAGS)
DBG_CFLAGS = $(DBGFLAGS) $(AQ_FLAGS) $(MGFLAGS)
# If run with `make DEBUG=true` add debug files and pass parameter for compile
ifeq ($(DEBUG), true)
SRCS := $(SRCS) $(DBG_SRC)
CFLAGS := -g -O0 $(CFLAGS) -D AQ_DEBUG
endif
# Other sources.
#DBG_SRC = timespec_subtract.c debug_timer.c
DBG_SRC = debug_timer.c
SL_SRC = serial_logger.c aq_serial.c utils.c packetLogger.c rs_msg_utils.c SL_SRC = serial_logger.c aq_serial.c utils.c packetLogger.c rs_msg_utils.c
LR_SRC = log_reader.c aq_serial.c utils.c packetLogger.c LR_SRC = log_reader.c aq_serial.c utils.c packetLogger.c
PL_EXSRC = aq_serial.c PL_EXSRC = aq_serial.c
@ -89,6 +95,7 @@ PL_EXOBJ = aq_serial_player.o
PL_SRC := $(filter-out aq_serial.c, $(SRCS)) PL_SRC := $(filter-out aq_serial.c, $(SRCS))
OBJS = $(SRCS:.c=.o) OBJS = $(SRCS:.c=.o)
DBG_OBJS = $(DBG_SRC:.c=.o)
SL_OBJS = $(SL_SRC:.c=.o) SL_OBJS = $(SL_SRC:.c=.o)
LR_OBJS = $(LR_SRC:.c=.o) LR_OBJS = $(LR_SRC:.c=.o)
@ -99,27 +106,45 @@ MAIN = ./release/aqualinkd
SLOG = ./release/serial_logger SLOG = ./release/serial_logger
LOGR = ./release/log_reader LOGR = ./release/log_reader
PLAY = ./release/aqualinkd-player PLAY = ./release/aqualinkd-player
DEBG = ./release/aqualinkd-debug
all: $(MAIN) all: $(MAIN)
@echo: $(MAIN) have been compiled $(info $(MAIN) has been compiled)
# debug, Just change compile flags and call MAIN
debug: CFLAGS = $(DFLAGS)
debug: $(MAIN)
$(info $(MAIN) has been compiled)
$(MAIN): $(OBJS) $(MAIN): $(OBJS)
$(CC) $(CFLAGS) $(INCLUDES) -o $(MAIN) $(OBJS) $(LFLAGS) $(LIBS) $(CC) $(CFLAGS) $(INCLUDES) -o $(MAIN) $(OBJS) $(LIBS)
$(info $(MAIN) has been compiled)
slog: $(SLOG) slog: $(SLOG)
@echo: $(SLOG) have been compiled $(info $(SLOG) has been compiled)
$(SLOG): CFLAGS := $(CFLAGS) -D SERIAL_LOGGER
$(SLOG): $(SL_OBJS) $(SLOG): $(SL_OBJS)
$(CC) $(CFLAGS) $(INCLUDES) -o $(SLOG) $(SL_OBJS) -D SERIAL_LOGGER $(CC) $(CFLAGS) $(INCLUDES) -o $(SLOG) $(SL_OBJS)
# Shouldn't need to use any of these options unless you're developing.
aqdebug: $(DEBG)
$(info $(DEBG) has been compiled)
$(DEBG): CFLAGS = $(DBG_CFLAGS)
$(DEBG): $(OBJS) $(DBG_OBJS)
$(CC) $(CFLAGS) $(INCLUDES) -o $(DEBG) $(OBJS) $(DBG_OBJS) $(DBGFLAGS) $(LIBS)
logr: $(LOGR) logr: $(LOGR)
@echo: $(LOGR) have been compiled $(info $(LOGR) has been compiled)
$(LOGR): $(LR_OBJS) $(LOGR): $(LR_OBJS)
$(CC) $(CFLAGS) $(INCLUDES) -o $(LOGR) $(LR_OBJS) $(CC) $(CFLAGS) $(INCLUDES) -o $(LOGR) $(LR_OBJS)
player: $(PLAY) player: $(PLAY)
@echo: $(PLAY) have been compiled $(info $(PLAY) has been compiled)
$(PL_EXOBJ): $(PL_EXSRC) $(PL_EXOBJ): $(PL_EXSRC)
$(CC) $(CFLAGS) -D PLAYBACK_MODE $(INCLUDES) -c $(PL_EXSRC) -o $(PL_EXOBJ) $(CC) $(CFLAGS) -D PLAYBACK_MODE $(INCLUDES) -c $(PL_EXSRC) -o $(PL_EXOBJ)
@ -127,6 +152,7 @@ $(PL_EXOBJ): $(PL_EXSRC)
$(PLAY): $(PL_OBJS) $(PL_EXOBJ) $(PLAY): $(PL_OBJS) $(PL_EXOBJ)
$(CC) $(CFLAGS) $(INCLUDES) -o $(PLAY) $(PL_OBJS) $(PL_EXOBJ) $(CC) $(CFLAGS) $(INCLUDES) -o $(PLAY) $(PL_OBJS) $(PL_EXOBJ)
# Fog github publishing
.PHONY: git .PHONY: git
git: clean $(MAIN) $(SLOG) git: clean $(MAIN) $(SLOG)
./release/git_version.sh ./release/git_version.sh
@ -141,8 +167,8 @@ git: clean $(MAIN) $(SLOG)
.PHONY: clean .PHONY: clean
clean: clean:
$(RM) *.o *~ $(MAIN) $(MAIN_U) $(PLAY) $(PL_EXOBJ) $(RM) *.o *~ $(MAIN) $(MAIN_U) $(PLAY) $(PL_EXOBJ) $(DEBG)
$(RM) $(wildcard *.o) $(wildcard *~) $(MAIN) $(MAIN_U) $(PLAY) $(PL_EXOBJ) $(LOGR) $(PLAY) $(RM) $(wildcard *.o) $(wildcard *~) $(MAIN) $(MAIN_U) $(PLAY) $(PL_EXOBJ) $(LOGR) $(PLAY) $(DEBG)
depend: $(SRCS) depend: $(SRCS)
makedepend $(INCLUDES) $^ makedepend $(INCLUDES) $^

View File

@ -76,13 +76,18 @@ Designed to mimic AqualinkRS6 All Button keypad and (like the keypad) is used to
* Allow selecting of pre-defined VSP programs * Allow selecting of pre-defined VSP programs
* Timed based actions (undecided on cron & AqualinkD or use Jandy programs ) * Timed based actions (undecided on cron & AqualinkD or use Jandy programs )
* Put back some form of Jandy panel simulator. (existing was removed in V2.2.0) * Put back some form of Jandy panel simulator. (existing was removed in V2.2.0)
* RS Serial protocol. AqualinkD has all Jandy control protocols except RS Serial. * Add RS Serial protocol. AqualinkD has all Jandy control protocols except RS Serial.
* Update homekit-aqualinkd to use new API & features. * Update homekit-aqualinkd to use new API & features.
* Add light programming to Aqualink Touch protocol.
# Update in (Pre) Release 2.2.0b # Update in (Pre) Release 2.2.0c
* Cleaned up Makefile (and adding debug timings).
* Changed loggin infrastructure.
* Added expermental options for Pi4.
* 2.2.0a (had some issues with compiler optimisation), please don't use or compile yourself. * 2.2.0a (had some issues with compiler optimisation), please don't use or compile yourself.
* Fixed RS-4 bug. * Fixed RS-4 panel bug.
* Increased timeout for startup probe * Fixed some AqualinkTouch programming issues.
* Increased timeout for startup probe.
* This release WILL require you to make aqualinkd.conf changes. <b>Make sure to read wiki section https://github.com/sfeakes/AqualinkD/wiki#Version_2</b> * This release WILL require you to make aqualinkd.conf changes. <b>Make sure to read wiki section https://github.com/sfeakes/AqualinkD/wiki#Version_2</b>
* Extensive work to reduce CPU cycles and unnesessary logic. * Extensive work to reduce CPU cycles and unnesessary logic.
* iAqualink Touch protocol supported for VSP & extended programming. * iAqualink Touch protocol supported for VSP & extended programming.

File diff suppressed because it is too large Load Diff

View File

@ -74,6 +74,7 @@ typedef enum {
AQ_SET_IAQTOUCH_SET_TIME AQ_SET_IAQTOUCH_SET_TIME
} program_type; } program_type;
struct programmingThreadCtrl { struct programmingThreadCtrl {
pthread_t thread_id; pthread_t thread_id;
//void *thread_args; //void *thread_args;

View File

@ -33,7 +33,10 @@
//#define USE_AQ_SERIAL_OLD //#define USE_AQ_SERIAL_OLD
//#define BLOCKING_MODE
static bool _blocking_mode = false;
int _blocking_fds = -1;
#ifndef USE_AQ_SERIAL_OLD // Substansial changes to core component, make sure we can role back easily #ifndef USE_AQ_SERIAL_OLD // Substansial changes to core component, make sure we can role back easily
@ -306,8 +309,75 @@ Open and Initialize the serial communications port to the Aqualink RS8 device.
Arg is tty or port designation string Arg is tty or port designation string
returns the file descriptor returns the file descriptor
*/ */
//#define TXDEN_DUMMY_RS485_MODE
#ifdef TXDEN_DUMMY_RS485_MODE
#include <linux/serial.h>
/* RS485 ioctls: */
#define TIOCGRS485 0x542E
#define TIOCSRS485 0x542F
int init_serial_port_Pi(const char* tty)
{
struct serial_rs485 rs485conf = {0};
//int fd = open(tty, O_RDWR | O_NOCTTY | O_NONBLOCK);
int fd = open(tty, O_RDWR);
if (fd < 0) {
LOG(RSSD_LOG,LOG_ERR, "Unable to open port: %s\n", tty);
return -1;
}
LOG(RSSD_LOG,LOG_DEBUG_SERIAL, "Openeded serial port %s\n",tty);
if (ioctl (fd, TIOCGRS485, &rs485conf) < 0) {
LOG(RSSD_LOG,LOG_ERR, "Error reading ioctl port (%d): %s\n", errno, strerror( errno ));
return -1;
}
LOG(RSSD_LOG,LOG_DEBUG, "Port currently RS485 mode is %s\n", (rs485conf.flags & SER_RS485_ENABLED) ? "set" : "NOT set");
/* Enable RS485 mode: */
rs485conf.flags |= SER_RS485_ENABLED;
/* Set logical level for RTS pin equal to 1 when sending: */
rs485conf.flags |= SER_RS485_RTS_ON_SEND;
/* or, set logical level for RTS pin equal to 0 when sending: */
//rs485conf.flags &= ~(SER_RS485_RTS_ON_SEND);
/* Set logical level for RTS pin equal to 1 after sending: */
rs485conf.flags |= SER_RS485_RTS_AFTER_SEND;
/* or, set logical level for RTS pin equal to 0 after sending: */
//rs485conf.flags &= ~(SER_RS485_RTS_AFTER_SEND);
/* Set this flag if you want to receive data even whilst sending data */
//rs485conf.flags |= SER_RS485_RX_DURING_TX;
if (ioctl (fd, TIOCSRS485, &rs485conf) < 0) {
LOG(RSSD_LOG,LOG_ERR, "Unable to set port to RS485 %s (%d): %s\n", tty, errno, strerror( errno ));
return -1;
}
return fd;
}
#endif
int _init_serial_port(const char* tty, bool blocking);
int init_serial_port(const char* tty) int init_serial_port(const char* tty)
{ {
return _init_serial_port(tty, false);
}
int init_blocking_serial_port(const char* tty)
{
_blocking_fds = _init_serial_port(tty, true);
return _blocking_fds;
}
int _init_serial_port(const char* tty, bool blocking)
{
long BAUD = B9600; long BAUD = B9600;
long DATABITS = CS8; long DATABITS = CS8;
long STOPBITS = 0; long STOPBITS = 0;
@ -316,6 +386,8 @@ int init_serial_port(const char* tty)
struct termios newtio; //place for old and new port settings for serial port struct termios newtio; //place for old and new port settings for serial port
_blocking_mode = blocking;
//int fd = open(tty, O_RDWR | O_NOCTTY | O_NONBLOCK); //int fd = open(tty, O_RDWR | O_NOCTTY | O_NONBLOCK);
int fd = open(tty, O_RDWR | O_NOCTTY | O_NONBLOCK | O_NDELAY); int fd = open(tty, O_RDWR | O_NOCTTY | O_NONBLOCK | O_NDELAY);
if (fd < 0) { if (fd < 0) {
@ -323,13 +395,22 @@ int init_serial_port(const char* tty)
return -1; return -1;
} }
LOG(RSSD_LOG,LOG_DEBUG_SERIAL, "Openeded serial port %s\n",tty); LOG(RSSD_LOG,LOG_DEBUG, "Openeded serial port %s\n",tty);
int flags = fcntl(fd, F_GETFL, 0); if (_blocking_mode) {
fcntl(fd, F_SETFL, flags | O_NONBLOCK | O_NDELAY); // http://unixwiz.net/techtips/termios-vmin-vtime.html
newtio.c_cc[VMIN]= 0; // Not designed behaviour, but it's what we need.
newtio.c_cc[VTIME]= 1; fcntl(fd, F_SETFL, 0);
LOG(RSSD_LOG,LOG_DEBUG_SERIAL, "Set serial port %s to non blocking mode\n",tty); newtio.c_cc[VMIN]= 1;
newtio.c_cc[VTIME]= 0;
LOG(RSSD_LOG,LOG_DEBUG, "Set serial port %s to blocking mode\n",tty);
} else {
int flags = fcntl(fd, F_GETFL, 0);
fcntl(fd, F_SETFL, flags | O_NONBLOCK | O_NDELAY);
newtio.c_cc[VMIN]= 0;
newtio.c_cc[VTIME]= 1;
LOG(RSSD_LOG,LOG_DEBUG, "Set serial port %s to non blocking mode\n",tty);
}
tcgetattr(fd, &_oldtio); // save current port settings tcgetattr(fd, &_oldtio); // save current port settings
// set new port settings for canonical input processing // set new port settings for canonical input processing
@ -341,11 +422,20 @@ int init_serial_port(const char* tty)
tcflush(fd, TCIFLUSH); tcflush(fd, TCIFLUSH);
tcsetattr(fd, TCSANOW, &newtio); tcsetattr(fd, TCSANOW, &newtio);
LOG(RSSD_LOG,LOG_DEBUG_SERIAL, "Set serial port %s io attributes\n",tty); LOG(RSSD_LOG,LOG_DEBUG, "Set serial port %s io attributes\n",tty);
return fd; return fd;
} }
void close_blocking_serial_port()
{
if (_blocking_fds > 0) {
LOG(RSSD_LOG,LOG_INFO, "Forcing close of blocking serial port, ignore following read errors\n");
close_serial_port(_blocking_fds);
} else {
LOG(RSSD_LOG,LOG_ERR, "Didn't find valid blocking serial port file descripter\n");
}
}
/* close tty port */ /* close tty port */
void close_serial_port(int fd) void close_serial_port(int fd)
{ {
@ -355,11 +445,6 @@ void close_serial_port(int fd)
} }
// Send an ack packet to the Aqualink RS8 master device. // Send an ack packet to the Aqualink RS8 master device.
// fd: the file descriptor of the serial port connected to the device // fd: the file descriptor of the serial port connected to the device
// command: the command byte to send to the master device, NUL if no command // command: the command byte to send to the master device, NUL if no command
@ -530,35 +615,45 @@ void send_command(int fd, unsigned char *packet_buffer, int size)
void send_packet(int fd, unsigned char *packet, int length) void send_packet(int fd, unsigned char *packet, int length)
{ {
if (_aqconfig_.readahead_b4_write) { if (_blocking_mode) {
unsigned char byte; write(fd, packet, length);
int r; } else {
//int j=0; if (_aqconfig_.readahead_b4_write) {
do { unsigned char byte;
//j++; int bytesRead;
r = read(fd, &byte, 1); // int j=0;
//printf("*** Peek Read %d 0x%02hhx ***\n",r,byte); do {
if (r==1 && byte != 0x00) { // j++;
LOG(RSSD_LOG,LOG_ERR, "SERIOUS ERROR on RS485, AqualinkD was too slow in replying to message! (please check OS for performance issues)\n"); bytesRead = read(fd, &byte, 1);
return; // printf("*** Peek Read %d 0x%02hhx ***\n",r,byte);
} if (bytesRead == 1 && byte != 0x00) {
} while (r==1 && byte==0x00); LOG(RSSD_LOG, LOG_ERR, "ERROR on RS485, AqualinkD was too slow in replying to message! (please check for performance issues)\n");
} do { // Just play catchup
bytesRead = read(fd, &byte, 1);
// if (bytesRead==1) { LOG(RSSD_LOG,LOG_ERR, "Error Cleanout read 0x%02hhx\n",byte); }
} while (bytesRead == 1);
int nwrite, i; return;
for (i=0; i<length; i += nwrite) { }
nwrite = write(fd, packet + i, length - i); } while (bytesRead == 1 && byte == 0x00);
if (nwrite < 0) }
LOG(RSSD_LOG,LOG_ERR, "write to serial port failed\n");
} int nwrite, i;
/* for (i = 0; i < length; i += nwrite) {
#ifdef AQ_DEBUG nwrite = write(fd, packet + i, length - i);
// Need to take this out for release if (nwrite < 0)
if ( getLogLevel(RSSD_LOG) >= LOG_DEBUG) { LOG(RSSD_LOG, LOG_ERR, "write to serial port failed\n");
debuglogPacket(&packet[1], length-2); }
} } // _blockine_mode
#endif
*/ /*
#ifdef AQ_DEBUG
// Need to take this out for release
if ( getLogLevel(RSSD_LOG) >= LOG_DEBUG) {
debuglogPacket(&packet[1], length-2);
}
#endif
*/
if ( getLogLevel(RSSD_LOG) >= LOG_DEBUG_SERIAL) { if ( getLogLevel(RSSD_LOG) >= LOG_DEBUG_SERIAL) {
// Packet is padded with 0x00, so discard for logging // Packet is padded with 0x00, so discard for logging
LOG(RSSD_LOG,LOG_DEBUG_SERIAL, "Serial write %d bytes\n",length-2); LOG(RSSD_LOG,LOG_DEBUG_SERIAL, "Serial write %d bytes\n",length-2);
@ -634,6 +729,7 @@ int _get_packet(int fd, unsigned char* packet, bool rawlog)
while (!endOfPacket) { while (!endOfPacket) {
bytesRead = read(fd, &byte, 1); bytesRead = read(fd, &byte, 1);
//printf("Read %d 0x%02hhx err=%d\n",bytesRead,byte,errno);
//if (bytesRead < 0 && errno == EAGAIN && packetStarted == FALSE && lastByteDLE == FALSE) { //if (bytesRead < 0 && errno == EAGAIN && packetStarted == FALSE && lastByteDLE == FALSE) {
if (bytesRead < 0 && errno == EAGAIN && if (bytesRead < 0 && errno == EAGAIN &&
jandyPacketStarted == false && jandyPacketStarted == false &&

View File

@ -425,7 +425,9 @@ typedef enum {
int init_serial_port(const char* tty); int init_serial_port(const char* tty);
int init_blocking_serial_port(const char* tty);
void close_serial_port(int file_descriptor); void close_serial_port(int file_descriptor);
void close_blocking_serial_port();
//#ifdef AQ_PDA //#ifdef AQ_PDA
//void set_pda_mode(bool mode); //void set_pda_mode(bool mode);
//bool pda_mode(); //bool pda_mode();

View File

@ -8,7 +8,7 @@
#include "aq_programmer.h" #include "aq_programmer.h"
#include "aq_panel.h" #include "aq_panel.h"
#define DEFAULT_MG_NET_WAIT 2 #define DEFAULT_POLL_SPEED 2
#define TIME_CHECK_INTERVAL 3600 #define TIME_CHECK_INTERVAL 3600
#define ACCEPTABLE_TIME_DIFF 120 #define ACCEPTABLE_TIME_DIFF 120
@ -19,6 +19,10 @@
#define MAX_ZERO_READ_BEFORE_RECONNECT 10000 // 2k normally #define MAX_ZERO_READ_BEFORE_RECONNECT 10000 // 2k normally
void intHandler(int dummy);
// There are cases where SWG will read 80% in allbutton and 0% in onetouch/aqualinktouch, this will compile that in or our
//#define READ_SWG_FROM_EXTENDED_ID
//#define TOTAL_BUTTONS 12 //#define TOTAL_BUTTONS 12
/* /*

View File

@ -49,29 +49,41 @@
#include "iaqtouch_aq_programmer.h" #include "iaqtouch_aq_programmer.h"
#include "version.h" #include "version.h"
#include "rs_msg_utils.h" #include "rs_msg_utils.h"
#include "debug_timer.h"
#ifdef AQ_DEBUG /*
#if defined AQ_DEBUG || defined AQ_TM_DEBUG
#include "timespec_subtract.h" #include "timespec_subtract.h"
//#define AQ_DEBUG_TIME_ACK
#endif #endif
*/
//#define DEFAULT_CONFIG_FILE "./aqualinkd.conf" //#define DEFAULT_CONFIG_FILE "./aqualinkd.conf"
static volatile bool _keepRunning = true; static volatile bool _keepRunning = true;
//static struct aqconfig _aqconfig_; //static struct aqconfig _aqconfig_;
static struct aqualinkdata _aqualink_data; static struct aqualinkdata _aqualink_data;
#ifdef AQ_DEBUG_TIME_ACK
struct timespec _rs_packet_readitme; #ifdef AQ_TM_DEBUG
//struct timespec _rs_packet_readitme;
int _rs_packet_timer;
#endif #endif
void main_loop(); void main_loop();
void intHandler(int dummy) void intHandler(int dummy)
{ {
_keepRunning = false; _keepRunning = false;
LOG(AQUA_LOG,LOG_NOTICE, "Stopping!"); LOG(AQUA_LOG,LOG_NOTICE, "Stopping!\n");
if (dummy){}// stop compile warnings //if (dummy){}// stop compile warnings
// In blocking mode, die as cleanly as possible.
if (_aqconfig_.rs_poll_speed < 0) {
stopPacketLogger();
// This should force port to close and do somewhat gracefull exit.
close_blocking_serial_port();
//exit(-1);
}
} }
void processLEDstate() void processLEDstate()
@ -307,11 +319,11 @@ void _processMessage(char *message, bool reset)
_aqualink_data.frz_protect_state = OFF; _aqualink_data.frz_protect_state = OFF;
if ((msg_loop & MSG_SERVICE) != MSG_SERVICE && if ((msg_loop & MSG_SERVICE) != MSG_SERVICE &&
(msg_loop & MSG_SERVICE) != MSG_TIMEOUT ) { (msg_loop & MSG_TIMEOUT) != MSG_TIMEOUT ) {
_aqualink_data.service_mode_state = OFF; // IF we get this message then Service / Timeout is off _aqualink_data.service_mode_state = OFF; // IF we get this message then Service / Timeout is off
} }
if ((msg_loop & MSG_SWG_DEVICE) != MSG_SWG_DEVICE) { if ( ((msg_loop & MSG_SWG_DEVICE) != MSG_SWG_DEVICE) && _aqualink_data.swg_led_state != LED_S_UNKNOWN) {
// No Additional SWG devices messages like "no flow" // No Additional SWG devices messages like "no flow"
if ((msg_loop & MSG_SWG) != MSG_SWG && _aqualink_data.aqbuttons[PUMP_INDEX].led->state == OFF ) if ((msg_loop & MSG_SWG) != MSG_SWG && _aqualink_data.aqbuttons[PUMP_INDEX].led->state == OFF )
setSWGdeviceStatus(&_aqualink_data, ALLBUTTON, SWG_STATUS_OFF); setSWGdeviceStatus(&_aqualink_data, ALLBUTTON, SWG_STATUS_OFF);
@ -362,7 +374,7 @@ void _processMessage(char *message, bool reset)
//if ( _aqconfig_.rs_panel_size >= 16) { //if ( _aqconfig_.rs_panel_size >= 16) {
//if ( (int)PANEL_SIZE >= 16) { // NSF No idea why this fails on RS-4, but it does. Come back and find out why //if ( (int)PANEL_SIZE >= 16) { // NSF No idea why this fails on RS-4, but it does. Come back and find out why
if ( PANEL_SIZE() >= 16 ) { if ( PANEL_SIZE() >= 16 ) {
printf("Panel size %d What the fuck am I doing here\n",PANEL_SIZE()); //printf("Panel size %d What the fuck am I doing here\n",PANEL_SIZE());
if ((msg_loop & MSG_RS13BUTTON) != MSG_RS13BUTTON) if ((msg_loop & MSG_RS13BUTTON) != MSG_RS13BUTTON)
_aqualink_data.aqbuttons[13].led->state = OFF; _aqualink_data.aqbuttons[13].led->state = OFF;
if ((msg_loop & MSG_RS14BUTTON) != MSG_RS14BUTTON) if ((msg_loop & MSG_RS14BUTTON) != MSG_RS14BUTTON)
@ -533,7 +545,11 @@ void _processMessage(char *message, bool reset)
LOG(AQRS_LOG,LOG_NOTICE, "RS time is NOT accurate '%s %s', re-setting on controller!\n", _aqualink_data.time, _aqualink_data.date); LOG(AQRS_LOG,LOG_NOTICE, "RS time is NOT accurate '%s %s', re-setting on controller!\n", _aqualink_data.time, _aqualink_data.date);
aq_programmer(AQ_SET_TIME, NULL, &_aqualink_data); aq_programmer(AQ_SET_TIME, NULL, &_aqualink_data);
} }
else else if (_initWithRS == false || _aqconfig_.sync_panel_time == false)
{
LOG(AQRS_LOG,LOG_DEBUG, "RS time '%s %s' not checking\n", _aqualink_data.time, _aqualink_data.date);
}
else if (_initWithRS == true)
{ {
LOG(AQRS_LOG,LOG_DEBUG, "RS time is accurate '%s %s'\n", _aqualink_data.time, _aqualink_data.date); LOG(AQRS_LOG,LOG_DEBUG, "RS time is accurate '%s %s'\n", _aqualink_data.time, _aqualink_data.date);
} }
@ -911,6 +927,10 @@ int main(int argc, char *argv[])
_aqualink_data.num_pumps = 0; _aqualink_data.num_pumps = 0;
_aqualink_data.num_lights = 0; _aqualink_data.num_lights = 0;
#ifdef AQ_TM_DEBUG
addDebugLogMask(DBGT_LOG);
init_aqd_timer(); // Must clear timers.
#endif
// Any debug logging masks // Any debug logging masks
//addDebugLogMask(IAQT_LOG); //addDebugLogMask(IAQT_LOG);
//addDebugLogMask(ONET_LOG); //addDebugLogMask(ONET_LOG);
@ -1002,8 +1022,8 @@ int main(int argc, char *argv[])
#if defined AQ_ONETOUCH || defined AQ_IAQTOUCH #if defined AQ_ONETOUCH || defined AQ_IAQTOUCH
if (_aqconfig_.extended_device_id != 0x00) { if (_aqconfig_.extended_device_id != 0x00) {
if (_aqconfig_.extended_device_id >= 0x30 && _aqconfig_.extended_device_id <= 0x33 || if ( (_aqconfig_.extended_device_id >= 0x30 && _aqconfig_.extended_device_id <= 0x33) ||
_aqconfig_.extended_device_id >= 0x40 && _aqconfig_.extended_device_id <= 0x43) { (_aqconfig_.extended_device_id >= 0x40 && _aqconfig_.extended_device_id <= 0x43) ) {
// We are good // We are good
} else { } else {
LOG(AQUA_LOG,LOG_ERR, "Extended Device ID 0x%02hhx does not match OneTouch or AqualinkTouch ID, please check config!\n", _aqconfig_.extended_device_id); LOG(AQUA_LOG,LOG_ERR, "Extended Device ID 0x%02hhx does not match OneTouch or AqualinkTouch ID, please check config!\n", _aqconfig_.extended_device_id);
@ -1100,8 +1120,28 @@ int main(int argc, char *argv[])
if (_aqconfig_.readahead_b4_write == true) if (_aqconfig_.readahead_b4_write == true)
LOG(AQUA_LOG,LOG_NOTICE, "Serial Read Ahead Write = %s\n", bool2text(_aqconfig_.readahead_b4_write)); LOG(AQUA_LOG,LOG_NOTICE, "Serial Read Ahead Write = %s\n", bool2text(_aqconfig_.readahead_b4_write));
if (_aqconfig_.net_poll_wait != DEFAULT_MG_NET_WAIT) if (_aqconfig_.rs_poll_speed != DEFAULT_POLL_SPEED)
LOG(AQUA_LOG,LOG_NOTICE, "Network Poll Speed = %d\n", _aqconfig_.net_poll_wait); LOG(AQUA_LOG,LOG_NOTICE, "RS Poll Speed = %d\n", _aqconfig_.rs_poll_speed);
if (_aqconfig_.thread_netservices)
LOG(AQUA_LOG,LOG_NOTICE, "Thread Network Services = %s\n", bool2text(_aqconfig_.thread_netservices));
if (_aqconfig_.rs_poll_speed < 0 && !_aqconfig_.thread_netservices) {
LOG(AQUA_LOG,LOG_WARNING, "Negative RS Poll Speed is only valid when using Thread Network Services, resetting to %d\n",DEFAULT_POLL_SPEED);
_aqconfig_.rs_poll_speed = DEFAULT_POLL_SPEED;
}
if (_aqconfig_.rs_poll_speed < 0 && _aqconfig_.readahead_b4_write) {
LOG(AQUA_LOG,LOG_WARNING, "Serial Read Ahead Write is not valid when using Negative RS Poll Speed, turning Serial Read Ahead Write off\n");
_aqconfig_.readahead_b4_write = false;
}
if (_aqconfig_.rs_poll_speed < 0) {
LOG(AQUA_LOG,LOG_WARNING, "**************************************************************************************************\n");
LOG(AQUA_LOG,LOG_WARNING, "* RS Poll Speed of %d is expermental, this put's USB in complete blocking mode *\n",_aqconfig_.rs_poll_speed);
LOG(AQUA_LOG,LOG_WARNING, "* if USB becomes unstable / connection to panel lost, AqualinkD may need to be killed manually *\n");
LOG(AQUA_LOG,LOG_WARNING, "* eg:- sudo kill -9 <list of aqualinkd process ID's> *\n");
LOG(AQUA_LOG,LOG_WARNING, "**************************************************************************************************\n");
}
//for (i = 0; i < TOTAL_BUTONS; i++) //for (i = 0; i < TOTAL_BUTONS; i++)
for (i = 0; i < _aqualink_data.total_buttons; i++) for (i = 0; i < _aqualink_data.total_buttons; i++)
@ -1162,10 +1202,12 @@ void caculate_ack_packet(int rs_fd, unsigned char *packet_buffer, emulation_type
switch (source) { switch (source) {
case ALLBUTTON: case ALLBUTTON:
send_extended_ack(rs_fd, (packet_buffer[PKT_CMD]==CMD_MSG_LONG?ACK_SCREEN_BUSY_SCROLL:ACK_NORMAL), pop_aq_cmd(&_aqualink_data)); send_extended_ack(rs_fd, (packet_buffer[PKT_CMD]==CMD_MSG_LONG?ACK_SCREEN_BUSY_SCROLL:ACK_NORMAL), pop_aq_cmd(&_aqualink_data));
//DEBUG_TIMER_STOP(_rs_packet_timer,AQUA_LOG,"AllButton Emulation type Processed packet in");
break; break;
#ifdef AQ_ONETOUCH #ifdef AQ_ONETOUCH
case ONETOUCH: case ONETOUCH:
send_extended_ack(rs_fd, ACK_ONETOUCH, pop_ot_cmd(packet_buffer[PKT_CMD])); send_extended_ack(rs_fd, ACK_ONETOUCH, pop_ot_cmd(packet_buffer[PKT_CMD]));
//DEBUG_TIMER_STOP(_rs_packet_timer,AQUA_LOG,"OneTouch Emulation type Processed packet in");
break; break;
#endif #endif
#ifdef AQ_IAQTOUCH #ifdef AQ_IAQTOUCH
@ -1178,6 +1220,7 @@ void caculate_ack_packet(int rs_fd, unsigned char *packet_buffer, emulation_type
send_jandy_command(rs_fd, cmd, size); send_jandy_command(rs_fd, cmd, size);
rem_iaqt_control_cmd(cmd); rem_iaqt_control_cmd(cmd);
} }
//DEBUG_TIMER_STOP(_rs_packet_timer,AQUA_LOG,"AquaTouch Emulation type Processed packet in");
break; break;
#endif #endif
#ifdef AQ_PDA #ifdef AQ_PDA
@ -1188,20 +1231,24 @@ void caculate_ack_packet(int rs_fd, unsigned char *packet_buffer, emulation_type
} else { } else {
send_extended_ack(rs_fd, ACK_PDA, pop_aq_cmd(&_aqualink_data)); send_extended_ack(rs_fd, ACK_PDA, pop_aq_cmd(&_aqualink_data));
} }
//DEBUG_TIMER_STOP(_rs_packet_timer,AQUA_LOG,"PDA Emulation type Processed packet in");
break; break;
#endif #endif
default: default:
LOG(AQUA_LOG,LOG_WARNING, "Can't caculate ACK, No idea what packet this source packet was for!\n"); LOG(AQUA_LOG,LOG_WARNING, "Can't caculate ACK, No idea what packet this source packet was for!\n");
//DEBUG_TIMER_STOP(_rs_packet_timer,AQUA_LOG,"Unknown Emulation type Processed packet in");
break; break;
} }
#ifdef AQ_DEBUG_TIME_ACK /*
#ifdef AQ_TM_DEBUG
static struct timespec now; static struct timespec now;
static struct timespec elapsed; static struct timespec elapsed;
clock_gettime(CLOCK_REALTIME, &now); clock_gettime(CLOCK_REALTIME, &now);
timespec_subtract(&elapsed, &now, &_rs_packet_readitme); timespec_subtract(&elapsed, &now, &_rs_packet_readitme);
LOG(AQUA_LOG,LOG_NOTICE, "Packet processed in %d.%02ld sec (%08ld ns)\n", elapsed.tv_sec, elapsed.tv_nsec / 1000000L, elapsed.tv_nsec); LOG(AQUA_LOG,LOG_NOTICE, "Emulation type %d. Processed packet in %d.%02ld sec (%08ld ns)\n",source, elapsed.tv_sec, elapsed.tv_nsec / 1000000L, elapsed.tv_nsec);
#endif #endif
*/
} }
/* /*
@ -1364,9 +1411,18 @@ void main_loop()
signal(SIGINT, intHandler); signal(SIGINT, intHandler);
signal(SIGTERM, intHandler); signal(SIGTERM, intHandler);
signal(SIGQUIT, intHandler);
int blank_read = 0; int blank_read = 0;
rs_fd = init_serial_port(_aqconfig_.serial_port); if (_aqconfig_.rs_poll_speed < 0)
rs_fd = init_blocking_serial_port(_aqconfig_.serial_port);
else
rs_fd = init_serial_port(_aqconfig_.serial_port);
if (rs_fd == -1) {
LOG(AQUA_LOG,LOG_ERR, "Error Aqualink setting serial port: %s\n", _aqconfig_.serial_port);
exit(EXIT_FAILURE);
}
LOG(AQUA_LOG,LOG_NOTICE, "Listening to Aqualink RS8 on serial port: %s\n", _aqconfig_.serial_port); LOG(AQUA_LOG,LOG_NOTICE, "Listening to Aqualink RS8 on serial port: %s\n", _aqconfig_.serial_port);
#ifdef AQ_PDA #ifdef AQ_PDA
@ -1434,11 +1490,11 @@ void main_loop()
// Loop until we get the probe messages, that means we didn;t start too soon after last shutdown. // Loop until we get the probe messages, that means we didn;t start too soon after last shutdown.
while ( (got_probe == false || got_probe_extended == false ) && _keepRunning == true) while ( (got_probe == false || got_probe_extended == false ) && _keepRunning == true)
{ {
if (blank_read == 10) { if (blank_read == MAX_ZERO_READ_BEFORE_RECONNECT) {
LOG(AQUA_LOG,LOG_ERR, "Nothing read on '%s', are you sure that's right?\n",_aqconfig_.serial_port); LOG(AQUA_LOG,LOG_ERR, "Nothing read on '%s', are you sure that's right?\n",_aqconfig_.serial_port);
} else if (blank_read == 50) { } else if (blank_read == MAX_ZERO_READ_BEFORE_RECONNECT*2) {
LOG(AQUA_LOG,LOG_ERR, "Nothing read on '%s', are you sure that's right?\n",_aqconfig_.serial_port); LOG(AQUA_LOG,LOG_ERR, "Nothing read on '%s', are you sure that's right?\n",_aqconfig_.serial_port);
} else if (blank_read == 150) { } else if (blank_read == MAX_ZERO_READ_BEFORE_RECONNECT*3) {
LOG(AQUA_LOG,LOG_ERR, "I'm done, exiting, please check '%s'\n",_aqconfig_.serial_port); LOG(AQUA_LOG,LOG_ERR, "I'm done, exiting, please check '%s'\n",_aqconfig_.serial_port);
return; return;
} }
@ -1484,11 +1540,11 @@ void main_loop()
else if (packet_length <= 0) { else if (packet_length <= 0) {
blank_read++; blank_read++;
//printf("Blank Reads %d\n",blank_read); //printf("Blank Reads %d\n",blank_read);
delay(200); delay(2);
} }
else if (packet_length > 0) { else if (packet_length > 0) {
blank_read = 0; blank_read = 0;
if (i++ > 1000) { // 1000 packets without a probe to BOTH ID's, give up config is wrong if (i++ > 1000) {
if(!got_probe) { if(!got_probe) {
LOG(AQUA_LOG,LOG_ERR, "No probe on '0x%02hhx', giving up! (please check config)\n",_aqconfig_.device_id); LOG(AQUA_LOG,LOG_ERR, "No probe on '0x%02hhx', giving up! (please check config)\n",_aqconfig_.device_id);
} }
@ -1499,7 +1555,8 @@ void main_loop()
#endif #endif
stopPacketLogger(); stopPacketLogger();
close_serial_port(rs_fd); close_serial_port(rs_fd);
mg_mgr_free(&mgr); //mg_mgr_free(&mgr);
stop_net_services(&mgr);
return; return;
} }
} }
@ -1515,14 +1572,16 @@ void main_loop()
* *
*/ */
//int max_blank_read = 0;
_aqconfig_.readahead_b4_write = read_ahead; _aqconfig_.readahead_b4_write = read_ahead;
LOG(AQUA_LOG,LOG_NOTICE, "Starting communication with Control Panel\n"); LOG(AQUA_LOG,LOG_NOTICE, "Starting communication with Control Panel\n");
int blank_read_reconnect = MAX_ZERO_READ_BEFORE_RECONNECT; int blank_read_reconnect = MAX_ZERO_READ_BEFORE_RECONNECT;
// Not the best way to do this, but ok for moment // Not the best way to do this, but ok for moment
if (_aqconfig_.net_poll_wait <= 1) //if (_aqconfig_.net_poll_wait <= 1)
blank_read_reconnect = MAX_ZERO_READ_BEFORE_RECONNECT * 10; // blank_read_reconnect = MAX_ZERO_READ_BEFORE_RECONNECT;
blank_read = 0; blank_read = 0;
// OK, Now go into infinate loop // OK, Now go into infinate loop
@ -1531,6 +1590,7 @@ void main_loop()
//printf("%d ",blank_read); //printf("%d ",blank_read);
while ((rs_fd < 0 || blank_read >= blank_read_reconnect) && _keepRunning == true) while ((rs_fd < 0 || blank_read >= blank_read_reconnect) && _keepRunning == true)
{ {
printf("rs_fd =% d\n",rs_fd);
if (rs_fd < 0) if (rs_fd < 0)
{ {
// sleep(1); // sleep(1);
@ -1545,8 +1605,13 @@ void main_loop()
{ {
LOG(AQUA_LOG,LOG_ERR, "Aqualink daemon looks like serial error, resetting.\n"); LOG(AQUA_LOG,LOG_ERR, "Aqualink daemon looks like serial error, resetting.\n");
close_serial_port(rs_fd); close_serial_port(rs_fd);
if (_aqconfig_.rs_poll_speed < 0)
rs_fd = init_blocking_serial_port(_aqconfig_.serial_port);
else
rs_fd = init_serial_port(_aqconfig_.serial_port);
} }
rs_fd = init_serial_port(_aqconfig_.serial_port);
blank_read = 0; blank_read = 0;
} }
@ -1563,14 +1628,16 @@ void main_loop()
} }
else if (packet_length == 0) else if (packet_length == 0)
{ {
//LOG(AQUA_LOG,LOG_DEBUG_SERIAL, "Nothing read on serial\n"); //if (blank_read > max_blank_read) {
// LOG(AQUA_LOG,LOG_NOTICE, "Nothing read on serial %d\n",blank_read);
// max_blank_read = blank_read;
//}
blank_read++; blank_read++;
} }
else if (packet_length > 0) else if (packet_length > 0)
{ {
#ifdef AQ_DEBUG_TIME_ACK DEBUG_TIMER_START(&_rs_packet_timer);
clock_gettime(CLOCK_REALTIME, &_rs_packet_readitme);
#endif
blank_read = 0; blank_read = 0;
//changed = false; //changed = false;
@ -1586,17 +1653,21 @@ void main_loop()
else else
#endif #endif
caculate_ack_packet(rs_fd, packet_buffer, ALLBUTTON); caculate_ack_packet(rs_fd, packet_buffer, ALLBUTTON);
DEBUG_TIMER_STOP(_rs_packet_timer,AQUA_LOG,"AllButton Emulation Processed packet in");
} }
#ifdef AQ_ONETOUCH #ifdef AQ_ONETOUCH
else if (packet_length > 0 && isONET_ENABLED && packet_buffer[PKT_DEST] == _aqconfig_.extended_device_id && getProtocolType(packet_buffer) == JANDY) { else if (packet_length > 0 && isONET_ENABLED && packet_buffer[PKT_DEST] == _aqconfig_.extended_device_id && getProtocolType(packet_buffer) == JANDY) {
_aqualink_data.updated = process_onetouch_packet(packet_buffer, packet_length, &_aqualink_data); _aqualink_data.updated = process_onetouch_packet(packet_buffer, packet_length, &_aqualink_data);
caculate_ack_packet(rs_fd, packet_buffer, ONETOUCH); caculate_ack_packet(rs_fd, packet_buffer, ONETOUCH);
DEBUG_TIMER_STOP(_rs_packet_timer,AQUA_LOG,"OneTouch Emulation Processed packet in");
} }
#endif #endif
#ifdef AQ_IAQTOUCH #ifdef AQ_IAQTOUCH
else if (packet_length > 0 && isIAQT_ENABLED && packet_buffer[PKT_DEST] == _aqconfig_.extended_device_id && getProtocolType(packet_buffer) == JANDY) { else if (packet_length > 0 && isIAQT_ENABLED && packet_buffer[PKT_DEST] == _aqconfig_.extended_device_id && getProtocolType(packet_buffer) == JANDY) {
_aqualink_data.updated = process_iaqtouch_packet(packet_buffer, packet_length, &_aqualink_data); _aqualink_data.updated = process_iaqtouch_packet(packet_buffer, packet_length, &_aqualink_data);
caculate_ack_packet(rs_fd, packet_buffer, IAQTOUCH); caculate_ack_packet(rs_fd, packet_buffer, IAQTOUCH);
DEBUG_TIMER_STOP(_rs_packet_timer,AQUA_LOG,"AquaTouch Emulation Processed packet in");
} }
#endif #endif
else if (packet_length > 0 && _aqconfig_.read_all_devices == true) else if (packet_length > 0 && _aqconfig_.read_all_devices == true)
@ -1644,19 +1715,24 @@ void main_loop()
//broadcast_aqualinkstate(mgr.active_connections); //broadcast_aqualinkstate(mgr.active_connections);
_aqualink_data.updated = true; _aqualink_data.updated = true;
} }
} }
DEBUG_TIMER_STOP(_rs_packet_timer,AQUA_LOG,"Processed (readonly) packet in");
} else {
DEBUG_TIMER_CLEAR(_rs_packet_timer); // Clear timer, no need to print anything
} }
if (_aqualink_data.updated) { if (_aqualink_data.updated) {
broadcast_aqualinkstate(mgr.active_connections); broadcast_aqualinkstate(mgr.active_connections);
_aqualink_data.updated = false; //_aqualink_data.updated = false;
} }
} }
//mg_mgr_poll(&mgr, 10); //mg_mgr_poll(&mgr, 10);
//mg_mgr_poll(&mgr, 5); //mg_mgr_poll(&mgr, 5);
mg_mgr_poll(&mgr, packet_length>0?0:_aqconfig_.net_poll_wait); // Don;t wait if we read something. //mg_mgr_poll(&mgr, packet_length>0?0:_aqconfig_.net_poll_wait); // Don;t wait if we read something.
//tcdrain(rs_fd); // Make sure buffer has been sent. poll_net_services(&mgr, packet_length>0?0:_aqconfig_.rs_poll_speed); // Don;t wait if we read something.
tcdrain(rs_fd); // Make sure buffer has been sent.
//mg_mgr_poll(&mgr, 0); //mg_mgr_poll(&mgr, 0);
// Any unactioned commands // Any unactioned commands
@ -1671,20 +1747,22 @@ void main_loop()
} }
} }
//tcdrain(rs_fd); // Make sure buffer has been sent. //tcdrain(rs_fd); // Make sure buffer has been sent.
//delay(10); //delay(10);
} }
//if (_aqconfig_.debug_RSProtocol_packets) stopPacketLogger(); //if (_aqconfig_.debug_RSProtocol_packets) stopPacketLogger();
stopPacketLogger(); stopPacketLogger();
// Stop network
stop_net_services(&mgr);
// Reset and close the port. // Reset and close the port.
close_serial_port(rs_fd); close_serial_port(rs_fd);
// Clear webbrowser // Clear webbrowser
mg_mgr_free(&mgr); //mg_mgr_free(&mgr);
// NSF need to run through config memory and clean up. // NSF need to run through config memory and clean up.
LOG(AQUA_LOG,LOG_NOTICE, "Exit!\n"); LOG(AQUA_LOG,LOG_NOTICE, "Exit!\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }

View File

@ -123,7 +123,8 @@ void init_parameters (struct aqconfig * parms)
parms->log_raw_RS_bytes = false; parms->log_raw_RS_bytes = false;
parms->readahead_b4_write = false; parms->readahead_b4_write = false;
parms->sync_panel_time = true; parms->sync_panel_time = true;
parms->net_poll_wait = DEFAULT_MG_NET_WAIT; parms->rs_poll_speed = DEFAULT_POLL_SPEED;
parms->thread_netservices = false;
generate_mqtt_id(parms->mqtt_ID, MQTT_ID_LEN); generate_mqtt_id(parms->mqtt_ID, MQTT_ID_LEN);
} }
@ -517,7 +518,14 @@ bool setConfigValue(struct aqualinkdata *aqdata, char *param, char *value) {
_aqconfig_.sync_panel_time = text2bool(value); _aqconfig_.sync_panel_time = text2bool(value);
rtn=true; rtn=true;
} else if (strncasecmp (param, "network_poll_speed", 18) == 0) { } else if (strncasecmp (param, "network_poll_speed", 18) == 0) {
_aqconfig_.net_poll_wait = strtoul(value, NULL, 10); LOG(AQUA_LOG,LOG_WARNING, "Config error, 'network_poll_speed' is no longer supported, using value for 'rs_poll_speed'\n");
_aqconfig_.rs_poll_speed = strtoul(value, NULL, 10);
rtn=true;
} else if (strncasecmp (param, "rs_poll_speed", 13) == 0) {
_aqconfig_.rs_poll_speed = strtoul(value, NULL, 10);
rtn=true;
} else if (strncasecmp (param, "thread_netservices", 18) == 0) {
_aqconfig_.thread_netservices = text2bool(value);
rtn=true; rtn=true;
} }

View File

@ -73,7 +73,8 @@ struct aqconfig
bool readahead_b4_write; bool readahead_b4_write;
bool mqtt_timed_update; bool mqtt_timed_update;
bool sync_panel_time; bool sync_panel_time;
int net_poll_wait; int rs_poll_speed;
bool thread_netservices;
}; };
#ifndef CONFIG_C #ifndef CONFIG_C

119
debug_timer.c Normal file
View File

@ -0,0 +1,119 @@
#ifdef AQ_TM_DEBUG
#include <stdio.h>
#include <string.h>
#include "debug_timer.h"
#include "utils.h"
//#include "timespec_subtract.h"
#define NUM_DEBUG_TIMERS 10
static struct timespec _start_time[NUM_DEBUG_TIMERS];
static int _timeid=0;
void init_aqd_timer(int *timeid)
{
int i=0;
for(i=0; i < NUM_DEBUG_TIMERS; i++) {
_start_time[i].tv_sec = 0;
_start_time[i].tv_nsec = 0;
}
}
void start_aqd_timer(int *id)
{
bool maxloop=false;
// Just a sanity check, should be redundant.
if (_timeid >= NUM_DEBUG_TIMERS)
_timeid = 0;
while (_start_time[_timeid].tv_sec != 0 && _start_time[_timeid].tv_nsec != 0) {
if (++_timeid >= NUM_DEBUG_TIMERS) {
if (maxloop) { // Means we ranover loop twice
LOG(DBGT_LOG,LOG_ERR,"Ranout of debug timers\n");
*id = -1;
return;
} else {
_timeid = 0;
maxloop=true;
}
}
}
clock_gettime(CLOCK_REALTIME, &_start_time[_timeid++]);
*id = _timeid-1;
//return _timeid-1;
}
void clear_aqd_timer(int timeid) {
_start_time[timeid].tv_sec = 0;
_start_time[timeid].tv_nsec = 0;
}
void stop_aqd_timer(int timeid, int16_t from, char *message)
{
if (timeid < 0 || timeid >= NUM_DEBUG_TIMERS) {
LOG(from,LOG_ERR,"Invalid timeid '%d' for message '%s'\n", timeid, message);
return;
}
static struct timespec now;
static struct timespec elapsed;
clock_gettime(CLOCK_REALTIME, &now);
timespec_subtract(&elapsed, &now, &_start_time[timeid]);
//DBGT_LOG
//LOG(from,LOG_NOTICE, "%s %d.%02ld sec (%08ld ns)\n", message, elapsed.tv_sec, elapsed.tv_nsec / 1000000L, elapsed.tv_nsec);
LOG(DBGT_LOG,LOG_DEBUG, "%s %s %d.%02ld sec (%08ld ns)\n", logmask2name(from), message, elapsed.tv_sec, elapsed.tv_nsec / 1000000L, elapsed.tv_nsec);
// We've used it so free it.
clear_aqd_timer(timeid);
}
/* Copyright (c) 1991, 1999 Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*
* You are free to use this software under the terms of the GNU General
* Public License, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*/
/* Based on https://www.gnu.org/software/libc/manual/html_node/Elapsed-Time.html
Subtract the struct timespec values X and Y,
storing the result in RESULT.
Return 1 if the difference is negative, otherwise 0. */
//#include <string.h>
//#include "timespec_subtract.h"
int timespec_subtract (struct timespec *result, const struct timespec *x,
const struct timespec *y)
{
struct timespec tmp;
memcpy (&tmp, y, sizeof(struct timespec));
/* Perform the carry for the later subtraction by updating y. */
if (x->tv_nsec < tmp.tv_nsec)
{
int nsec = (tmp.tv_nsec - x->tv_nsec) / 1000000000 + 1;
tmp.tv_nsec -= 1000000000 * nsec;
tmp.tv_sec += nsec;
}
if (x->tv_nsec - tmp.tv_nsec > 1000000000)
{
int nsec = (x->tv_nsec - tmp.tv_nsec) / 1000000000;
tmp.tv_nsec += 1000000000 * nsec;
tmp.tv_sec -= nsec;
}
/* Compute the time remaining to wait.
tv_nsec is certainly positive. */
result->tv_sec = x->tv_sec - tmp.tv_sec;
result->tv_nsec = x->tv_nsec - tmp.tv_nsec;
/* Return 1 if result is negative. */
return x->tv_sec < tmp.tv_sec;
}
#endif

25
debug_timer.h Normal file
View File

@ -0,0 +1,25 @@
#ifndef DEBUG_TIMER_H_
#define DEBUG_TIMER_H_
#ifdef AQ_TM_DEBUG
#include <time.h>
#include <stdint.h>
void init_aqd_timer();
int timespec_subtract (struct timespec *result, const struct timespec *x, const struct timespec *y);
void stop_aqd_timer(int timeid, int16_t from, char *message);
void start_aqd_timer(int *timeid);
void clear_aqd_timer(int timeid);
#define DEBUG_TIMER_START(x) start_aqd_timer(x)
#define DEBUG_TIMER_STOP(x, y, z) stop_aqd_timer(x, y, z)
#define DEBUG_TIMER_CLEAR(x) clear_aqd_timer(x)
//#define DEBUG_TIMER_START1() int t; start_aqd_timer(&t)
//#define DEBUG_TIMER_STOP1(y, z) stop_aqd_timer(t, y, z)
#else
#define DEBUG_TIMER_START(x)
#define DEBUG_TIMER_STOP(x, y, z)
#define DEBUG_TIMER_CLEAR(x)
#endif
#endif //DEBUG_TIMER_H_

View File

@ -173,6 +173,8 @@ bool setSWGboost(struct aqualinkdata *aqdata, bool on) {
aqdata->boost = true; aqdata->boost = true;
aqdata->swg_percent = 101; aqdata->swg_percent = 101;
} }
return true;
} }
// Only change SWG percent if we are not in SWG programming // Only change SWG percent if we are not in SWG programming

View File

@ -120,7 +120,7 @@ const char *iaqtGetTableInfoLine(int index) {
} }
struct iaqt_page_button *iaqtFindButtonByIndex(int index) { struct iaqt_page_button *iaqtFindButtonByIndex(int index) {
int i; //int i;
struct iaqt_page_button *buttons; struct iaqt_page_button *buttons;
// NSF Need to merge this from iaqtFindButtonByLabel function // NSF Need to merge this from iaqtFindButtonByLabel function
@ -398,17 +398,7 @@ void passDeviceStatusPage(struct aqualinkdata *aq_data)
pump = NULL; pump = NULL;
} }
if (rsm_strcmp(_deviceStatus[i],"AQUAPURE") == 0) { if (rsm_strcmp(_deviceStatus[i],"Chemlink") == 0) {
//aq_data->swg_percent = rsm_atoi(&_deviceStatus[i][9]);
if (changeSWGpercent(aq_data, rsm_atoi(&_deviceStatus[i][9])))
LOG(IAQT_LOG,LOG_DEBUG, "Set swg %% to %d from message'%s'\n",aq_data->swg_percent,_deviceStatus[i]);
} else if (rsm_strcmp(_deviceStatus[i],"salt") == 0) {
aq_data->swg_ppm = rsm_atoi(&_deviceStatus[i][5]);
LOG(IAQT_LOG,LOG_DEBUG, "Set swg PPM to %d from message'%s'\n",aq_data->swg_ppm,_deviceStatus[i]);
} else if (rsm_strcmp(_deviceStatus[i],"Boost Pool") == 0) {
aq_data->boost = true;
// Let RS pickup time remaing message.
} else if (rsm_strcmp(_deviceStatus[i],"Chemlink") == 0) {
/* Info: = Chemlink 1 /* Info: = Chemlink 1
Info: = ORP 750/PH 7.0 */ Info: = ORP 750/PH 7.0 */
i++; i++;
@ -423,6 +413,19 @@ void passDeviceStatusPage(struct aqualinkdata *aq_data)
LOG(IAQT_LOG,LOG_INFO, "Set Cemlink ORP = %d PH = %f from message '%s'\n",orp,ph,_deviceStatus[i]); LOG(IAQT_LOG,LOG_INFO, "Set Cemlink ORP = %d PH = %f from message '%s'\n",orp,ph,_deviceStatus[i]);
} }
} }
#ifdef READ_SWG_FROM_EXTENDED_ID
else if (rsm_strcmp(_deviceStatus[i],"AQUAPURE") == 0) {
//aq_data->swg_percent = rsm_atoi(&_deviceStatus[i][9]);
if (changeSWGpercent(aq_data, rsm_atoi(&_deviceStatus[i][9])))
LOG(IAQT_LOG,LOG_DEBUG, "Set swg %% to %d from message'%s'\n",aq_data->swg_percent,_deviceStatus[i]);
} else if (rsm_strcmp(_deviceStatus[i],"salt") == 0) {
aq_data->swg_ppm = rsm_atoi(&_deviceStatus[i][5]);
LOG(IAQT_LOG,LOG_DEBUG, "Set swg PPM to %d from message'%s'\n",aq_data->swg_ppm,_deviceStatus[i]);
} else if (rsm_strcmp(_deviceStatus[i],"Boost Pool") == 0) {
aq_data->boost = true;
// Let RS pickup time remaing message.
}
#endif
} // for } // for
} }
@ -502,12 +505,12 @@ void processPage(struct aqualinkdata *aq_data)
} }
} }
#define REQUEST_STATUS_POLL_COUNT 50
bool process_iaqtouch_packet(unsigned char *packet, int length, struct aqualinkdata *aq_data) bool process_iaqtouch_packet(unsigned char *packet, int length, struct aqualinkdata *aq_data)
{ {
static int cnt = 0; static int cnt = 0;
char buff[1024]; //char buff[1024];
if (packet[PKT_CMD] == CMD_IAQ_PAGE_START) { if (packet[PKT_CMD] == CMD_IAQ_PAGE_START) {
LOG(IAQT_LOG,LOG_DEBUG, "Turning IAQ SEND off\n"); LOG(IAQT_LOG,LOG_DEBUG, "Turning IAQ SEND off\n");
@ -571,20 +574,17 @@ bool process_iaqtouch_packet(unsigned char *packet, int length, struct aqualinkd
// Standard ack/poll not interested in printing or kicking threads // Standard ack/poll not interested in printing or kicking threads
if (packet[3] == 0x30) { if (packet[3] == 0x30) {
// Load status page every 1000 messages // Load status page every 1000 messages
//if (cnt++ > 50 && in_iaqt_programming_mode(aq_data) == false ) { if (cnt++ > REQUEST_STATUS_POLL_COUNT && in_programming_mode(aq_data) == false ) {
// Let's not confuse any message data, only grab status if not in any from of programming mode
/*
if (cnt++ == 50 && in_programming_mode(aq_data) == false ) {
//iaqt_queue_cmd(KEY_IAQTCH_STATUS);
//aq_programmer(AQ_GET_IAQTOUCH_VSP_ASSIGNMENT, NULL, aq_data);
//cnt = 0;
queueGetProgramData(IAQTOUCH, aq_data);
}
else*/ if (cnt++ > 100 && in_programming_mode(aq_data) == false ) {
iaqt_queue_cmd(KEY_IAQTCH_STATUS); iaqt_queue_cmd(KEY_IAQTCH_STATUS);
//aq_programmer(AQ_GET_IAQTOUCH_VSP_ASSIGNMENT, NULL, aq_data); //aq_programmer(AQ_GET_IAQTOUCH_VSP_ASSIGNMENT, NULL, aq_data);
cnt = 0; cnt = 0;
} else if (in_programming_mode(aq_data) == true) {
// Set count to something close to above, so we will pull latest info once programming has finished.
// This is goot for VSP GPM programming as it takes number of seconds to register once finished programming.
// -5 seems to be too quick for VSP/GPM so using 10
cnt = REQUEST_STATUS_POLL_COUNT - 10;
} }
return false; return false;
} }
@ -592,7 +592,7 @@ bool process_iaqtouch_packet(unsigned char *packet, int length, struct aqualinkd
_lastMsgType = packet[PKT_CMD]; _lastMsgType = packet[PKT_CMD];
debuglogPacket(IAQT_LOG ,packet, length); //debuglogPacket(IAQT_LOG ,packet, length);
//beautifyPacket(buff, packet, length); //beautifyPacket(buff, packet, length);
//LOG(IAQT_LOG,LOG_DEBUG, "%s", buff); //LOG(IAQT_LOG,LOG_DEBUG, "%s", buff);

View File

@ -31,6 +31,7 @@
#include "aq_panel.h" #include "aq_panel.h"
#include "config.h" #include "config.h"
#include "devices_jandy.h" #include "devices_jandy.h"
#include "packetLogger.h"
// System Page is obfiously fixed and not dynamic loaded, so set buttons to stop confustion. // System Page is obfiously fixed and not dynamic loaded, so set buttons to stop confustion.
@ -131,6 +132,14 @@ int ref_iaqt_control_cmd(unsigned char **cmd)
{ {
//printf("*********** GET READY SENDING CONTROL ****************\n"); //printf("*********** GET READY SENDING CONTROL ****************\n");
*cmd = _iaqt_control_cmd; *cmd = _iaqt_control_cmd;
if ( getLogLevel(IAQT_LOG) >= LOG_DEBUG ) {
char buff[1000];
//sprintf("Sending control command:")
beautifyPacket(buff, _iaqt_control_cmd, _iaqt_control_cmd_len);
LOG(IAQT_LOG,LOG_DEBUG, "iAQ Touch sending commandsed : %s\n", buff);
}
return _iaqt_control_cmd_len; return _iaqt_control_cmd_len;
} }
@ -145,9 +154,12 @@ bool waitfor_iaqt_ctrl_queue2empty()
int i=0; int i=0;
while ( (_iaqt_control_cmd_len >0 ) && ( i++ < 20) ) { while ( (_iaqt_control_cmd_len >0 ) && ( i++ < 20) ) {
LOG(IAQT_LOG,LOG_DEBUG, "Waiting for commandset to send\n");
delay(50); delay(50);
} }
LOG(IAQT_LOG,LOG_DEBUG, "Wait for commandset over!\n");
if (_iaqt_control_cmd_len > 0 ) { if (_iaqt_control_cmd_len > 0 ) {
LOG(IAQT_LOG,LOG_WARNING, "iAQ Touch Send control command Queue did not empty, timeout\n"); LOG(IAQT_LOG,LOG_WARNING, "iAQ Touch Send control command Queue did not empty, timeout\n");
return false; return false;
@ -167,11 +179,13 @@ unsigned const char waitfor_iaqt_nextPage(struct aqualinkdata *aq_data) {
while( ++i <= numMessageReceived) while( ++i <= numMessageReceived)
{ {
LOG(IAQT_LOG,LOG_DEBUG, "waitfor_iaqt_nextPage (%d of %d)\n",i,numMessageReceived); //LOG(IAQT_LOG,LOG_DEBUG, "waitfor_iaqt_nextPage (%d of %d)\n",i,numMessageReceived);
pthread_cond_wait(&aq_data->active_thread.thread_cond, &aq_data->active_thread.thread_mutex); pthread_cond_wait(&aq_data->active_thread.thread_cond, &aq_data->active_thread.thread_mutex);
if(wasiaqtThreadKickTypePage()) break; if(wasiaqtThreadKickTypePage()) break;
} }
LOG(IAQT_LOG,LOG_DEBUG, "waitfor_iaqt_nextPage finished in (%d of %d)\n",i,numMessageReceived);
pthread_mutex_unlock(&aq_data->active_thread.thread_mutex); pthread_mutex_unlock(&aq_data->active_thread.thread_mutex);
if(wasiaqtThreadKickTypePage()) if(wasiaqtThreadKickTypePage())
@ -225,30 +239,32 @@ void queue_iaqt_control_command(iaqtControlCmdYype type, int num) {
// Tell the control panel we are ready to send this shit. // Tell the control panel we are ready to send this shit.
send_aqt_cmd(ACK_CMD_READY_CTRL); send_aqt_cmd(ACK_CMD_READY_CTRL);
LOG(IAQT_LOG,LOG_DEBUG, "Queued extended commandsed of length %d\n",_iaqt_control_cmd_len);
//printHex(packets, 19); //printHex(packets, 19);
//printf("\n"); //printf("\n");
//send_jandy_command(NULL, packets, cnt); //send_jandy_command(NULL, packets, cnt);
} }
void queue_iaqt_control_command_str(iaqtControlCmdYype type, char *str) { bool queue_iaqt_control_command_str(iaqtControlCmdYype type, char *str) {
if (waitfor_iaqt_ctrl_queue2empty() == false) if (waitfor_iaqt_ctrl_queue2empty() == false)
return; return false;
_iaqt_control_cmd[0] = DEV_MASTER; _iaqt_control_cmd[0] = DEV_MASTER;
_iaqt_control_cmd[1] = 0x24; _iaqt_control_cmd[1] = 0x24;
_iaqt_control_cmd[2] = 0x31; _iaqt_control_cmd[2] = 0x31;
_iaqt_control_cmd_len = char2iaqtRSset(&_iaqt_control_cmd[3], str, strlen(str)); _iaqt_control_cmd_len = char2iaqtRSset(&_iaqt_control_cmd[3], str, strlen(str));
// Need to bad time for some reason not yet known // Need to bad time for some reason not yet known
if (type == icct_settime) { if (type == icct_settime) {
//Debug: RS Serial: To 0x00 of type iAq pBut | HEX: 0x10|0x02|0x00|0x24|0x31|0x30|0x31|0x3a|0x30|0x31|0x00|0x30|0x32|0x00|0xcd|0xcd|0xcd|0xcd|0xcd|0xcd|0xcd|0x60|0x10|0x03| //Debug: RS Serial: To 0x00 of type iAq pBut | HEX: 0x10|0x02|0x00|0x24|0x31|0x30|0x31|0x3a|0x30|0x31|0x00|0x30|0x32|0x00|0xcd|0xcd|0xcd|0xcd|0xcd|0xcd|0xcd|0x60|0x10|0x03|
// From position 11 (8 without pre) add 0x30|0x32|0x00 // From position 11 (8 without pre) add 0x30|0x32|0x00
_iaqt_control_cmd[++_iaqt_control_cmd_len] = 0x30; _iaqt_control_cmd_len += 3;
_iaqt_control_cmd[++_iaqt_control_cmd_len] = 0x32; _iaqt_control_cmd[9] = 0x30;
_iaqt_control_cmd[++_iaqt_control_cmd_len] = 0x00; _iaqt_control_cmd[10] = 0x32;
_iaqt_control_cmd[11] = 0x00;
} }
// Pad with 0xcd for some reason. // Pad with 0xcd for some reason.
for(_iaqt_control_cmd_len = _iaqt_control_cmd_len+3; _iaqt_control_cmd_len <= 18; _iaqt_control_cmd_len++) for(_iaqt_control_cmd_len = _iaqt_control_cmd_len+3; _iaqt_control_cmd_len <= 18; _iaqt_control_cmd_len++)
@ -256,6 +272,9 @@ void queue_iaqt_control_command_str(iaqtControlCmdYype type, char *str) {
// Tell the control panel we are ready to send this shit. // Tell the control panel we are ready to send this shit.
send_aqt_cmd(ACK_CMD_READY_CTRL); send_aqt_cmd(ACK_CMD_READY_CTRL);
return true;
//debuglogPacket()
} }
@ -464,9 +483,11 @@ void *set_aqualink_iaqtouch_pump_rpm( void *ptr )
*/ */
//send_aqt_cmd(0x80); //send_aqt_cmd(0x80);
f_end: // Go to status page on startup to read devices
//goto_iaqt_page(IAQ_PAGE_HOME, aq_data);
goto_iaqt_page(IAQ_PAGE_STATUS, aq_data); goto_iaqt_page(IAQ_PAGE_STATUS, aq_data);
f_end:
goto_iaqt_page(IAQ_PAGE_HOME, aq_data);
cleanAndTerminateThread(threadCtrl); cleanAndTerminateThread(threadCtrl);
// just stop compiler error, ptr is not valid as it's just been freed // just stop compiler error, ptr is not valid as it's just been freed
@ -594,6 +615,7 @@ void *get_aqualink_iaqtouch_setpoints( void *ptr )
return ptr; return ptr;
} }
// THIS IS NOT FINISHED.
void *get_aqualink_iaqtouch_aux_labels( void *ptr ) void *get_aqualink_iaqtouch_aux_labels( void *ptr )
{ {
struct programmingThreadCtrl *threadCtrl; struct programmingThreadCtrl *threadCtrl;
@ -616,6 +638,8 @@ void *get_aqualink_iaqtouch_aux_labels( void *ptr )
* Info: Table Messages 05| Aux5 Aux5 No * Info: Table Messages 05| Aux5 Aux5 No
* Info: Table Messages 06| Aux6 Aux6 No * Info: Table Messages 06| Aux6 Aux6 No
* Info: Table Messages 07| Aux7 Aux7 No * Info: Table Messages 07| Aux7 Aux7 No
*
* Info: Table Messages ??| Aux B7 Aux B7 No
*/ */
const char *buf; const char *buf;
int aux; int aux;
@ -624,9 +648,10 @@ void *get_aqualink_iaqtouch_aux_labels( void *ptr )
for(i=1; i < PANEL_SIZE(); i++) for(i=1; i < PANEL_SIZE(); i++)
{ {
buf = iaqtGetTableInfoLine(i); buf = iaqtGetTableInfoLine(i);
LOG(IAQT_LOG,LOG_INFO, "From Messages %.2d| %s\n",i,buf);
//printf("**** BUF '%s'\n",aux,buf); //printf("**** BUF '%s'\n",aux,buf);
aux = rsm_atoi(buf + 3); aux = rsm_atoi(buf + 3);
printf("**** AUX %d = '%s'\n",aux,buf + 5); LOG(IAQT_LOG,LOG_INFO, "**** AUX %d = '%s'\n",aux,buf + 5);
} }
f_end: f_end:
@ -915,9 +940,9 @@ void *set_aqualink_iaqtouch_time( void *ptr )
struct aqualinkdata *aq_data = threadCtrl->aq_data; struct aqualinkdata *aq_data = threadCtrl->aq_data;
struct iaqt_page_button *button; struct iaqt_page_button *button;
char buf[20]; char buf[20];
int len; //int len;
int i; int i;
bool AM; //bool AM;
waitForSingleThreadOrTerminate(threadCtrl, AQ_SET_IAQTOUCH_SET_TIME); waitForSingleThreadOrTerminate(threadCtrl, AQ_SET_IAQTOUCH_SET_TIME);
@ -945,9 +970,13 @@ void *set_aqualink_iaqtouch_time( void *ptr )
send_aqt_cmd(button->keycode); send_aqt_cmd(button->keycode);
waitfor_iaqt_queue2empty(); waitfor_iaqt_queue2empty();
// Queue the date string // Queue the date string
queue_iaqt_control_command_str(icct_setdate, buf); if ( queue_iaqt_control_command_str(icct_setdate, buf)) {
LOG(IAQT_LOG,LOG_DEBUG, "Set date to %s\n",buf); LOG(IAQT_LOG,LOG_NOTICE, "Set date to %s\n",buf);
waitfor_iaqt_ctrl_queue2empty(); waitfor_iaqt_ctrl_queue2empty();
} else {
LOG(IAQT_LOG,LOG_ERR, "Failed to queue commandset for setting date\n");
}
} else { } else {
LOG(IAQT_LOG,LOG_DEBUG, "Date %s is accurate, not changing\n",button->name); LOG(IAQT_LOG,LOG_DEBUG, "Date %s is accurate, not changing\n",button->name);
} }
@ -977,9 +1006,12 @@ void *set_aqualink_iaqtouch_time( void *ptr )
// Print HH:MM into string // Print HH:MM into string
strftime(buf, 20, "%I:%M", result); strftime(buf, 20, "%I:%M", result);
queue_iaqt_control_command_str(icct_settime, buf); if (queue_iaqt_control_command_str(icct_settime, buf)) {
LOG(IAQT_LOG,LOG_DEBUG, "Set time to %s\n",buf); LOG(IAQT_LOG,LOG_NOTICE, "Set time to %s\n",buf);
waitfor_iaqt_ctrl_queue2empty(); waitfor_iaqt_ctrl_queue2empty();
} else {
LOG(IAQT_LOG,LOG_ERR, "Failed to queue commandset for setting time\n");
}
f_end: f_end:

View File

@ -35,19 +35,21 @@
#include "aq_mqtt.h" #include "aq_mqtt.h"
#include "devices_jandy.h" #include "devices_jandy.h"
#include "color_lights.h" #include "color_lights.h"
#include "debug_timer.h"
#ifdef AQ_PDA #ifdef AQ_PDA
#include "pda.h" #include "pda.h"
#endif #endif
#ifdef AQ_DEBUG /*
#if defined AQ_DEBUG || defined AQ_TM_DEBUG
#include "timespec_subtract.h" #include "timespec_subtract.h"
//#define AQ_NET_TIMER //#define AQ_TM_DEBUG
#endif #endif
*/
//static struct aqconfig *_aqconfig_; //static struct aqconfig *_aqconfig_;
static struct aqualinkdata *_aqualink_data; static struct aqualinkdata *_aqualink_data;
static char *_web_root; //static char *_web_root;
static int _mqtt_exit_flag = false; static int _mqtt_exit_flag = false;
@ -64,49 +66,21 @@ void mqtt_broadcast_aqualinkstate(struct mg_connection *nc);
void reset_last_mqtt_status(); void reset_last_mqtt_status();
#ifdef AQ_NET_TIMER
static struct timespec _start_time[5];
static int _timeid=0;
void start_net_timer(int *timeid)
{
if (_timeid >= 5)
_timeid = 0;
clock_gettime(CLOCK_REALTIME, &_start_time[_timeid++]);
*timeid = _timeid-1;
//return _timeid-1;
}
void stop_net_timer(int timeid, char *message)
{
if (timeid < 0 || timeid >= 5) {
LOG(NET_LOG,LOG_ERR,"Invalid timeid '%d' for message '%s'\n", timeid, message);
return;
}
static struct timespec now;
static struct timespec elapsed;
clock_gettime(CLOCK_REALTIME, &now);
timespec_subtract(&elapsed, &now, &_start_time[timeid]);
LOG(NET_LOG,LOG_NOTICE, "%s %d.%02ld sec (%08ld ns)\n", message, elapsed.tv_sec, elapsed.tv_nsec / 1000000L, elapsed.tv_nsec);
}
#define DEBUG_TIMER_START(x) start_net_timer(x)
#define DEBUG_TIMER_STOP(x, y) stop_net_timer(x, y)
#else
#define DEBUG_TIMER_START(x)
#define DEBUG_TIMER_STOP(x, y)
#endif
static sig_atomic_t s_signal_received = 0; static sig_atomic_t s_signal_received = 0;
//static const char *s_http_port = "8080"; //static const char *s_http_port = "8080";
static struct mg_serve_http_opts _http_server_opts; static struct mg_serve_http_opts _http_server_opts;
static void signal_handler(int sig_num) { static void net_signal_handler(int sig_num) {
signal(sig_num, signal_handler); // Reinstantiate signal handler
s_signal_received = sig_num; if (!_aqconfig_.thread_netservices) {
signal(sig_num, net_signal_handler); // Reinstantiate signal handler to aqualinkd.c
s_signal_received = sig_num;
} else {
intHandler(sig_num); // Force signal handler to aqualinkd.c
}
} }
@ -116,9 +90,11 @@ static int is_websocket(const struct mg_connection *nc) {
static void set_websocket_RSraw(struct mg_connection *nc) { static void set_websocket_RSraw(struct mg_connection *nc) {
nc->flags |= MG_F_USER_2; nc->flags |= MG_F_USER_2;
} }
/*
static int is_websocket_RSraw(const struct mg_connection *nc) { static int is_websocket_RSraw(const struct mg_connection *nc) {
return nc->flags & MG_F_USER_2; return nc->flags & MG_F_USER_2;
} }
*/
static int is_mqtt(const struct mg_connection *nc) { static int is_mqtt(const struct mg_connection *nc) {
return nc->flags & MG_F_USER_1; return nc->flags & MG_F_USER_1;
} }
@ -135,7 +111,7 @@ static void ws_send(struct mg_connection *nc, char *msg)
//LOG(NET_LOG,LOG_DEBUG, "WS: Sent %d characters '%s'\n",size, msg); //LOG(NET_LOG,LOG_DEBUG, "WS: Sent %d characters '%s'\n",size, msg);
} }
void broadcast_aqualinkstate_error(struct mg_connection *nc, char *msg) void _broadcast_aqualinkstate_error(struct mg_connection *nc, char *msg)
{ {
struct mg_connection *c; struct mg_connection *c;
char data[JSON_STATUS_SIZE]; char data[JSON_STATUS_SIZE];
@ -148,16 +124,22 @@ void broadcast_aqualinkstate_error(struct mg_connection *nc, char *msg)
// Maybe enhacment in future to sent error messages to MQTT // Maybe enhacment in future to sent error messages to MQTT
} }
void broadcast_aqualinkstate(struct mg_connection *nc) void _broadcast_aqualinkstate(struct mg_connection *nc)
{ {
static int mqtt_count=0; static int mqtt_count=0;
struct mg_connection *c; struct mg_connection *c;
char data[JSON_STATUS_SIZE]; char data[JSON_STATUS_SIZE];
#ifdef AQ_TM_DEBUG
int tid;
#endif
DEBUG_TIMER_START(&tid);
build_aqualink_status_JSON(_aqualink_data, data, JSON_STATUS_SIZE); build_aqualink_status_JSON(_aqualink_data, data, JSON_STATUS_SIZE);
#ifdef AQ_MEMCMP #ifdef AQ_MEMCMP
if ( memcmp(_aqualink_data, &_last_mqtt_aqualinkdata, sizeof(struct aqualinkdata) ) == 0) { if ( memcmp(_aqualink_data, &_last_mqtt_aqualinkdata, sizeof(struct aqualinkdata) ) == 0) {
LOG(NET_LOG,LOG_NOTICE, "**********Structure buffs the same, ignoring request************\n"); LOG(NET_LOG,LOG_NOTICE, "**********Structure buffs the same, ignoring request************\n");
DEBUG_TIMER_CLEAR(&tid);
return; return;
} }
#endif #endif
@ -185,6 +167,8 @@ void broadcast_aqualinkstate(struct mg_connection *nc)
memcpy(&_last_mqtt_aqualinkdata, _aqualink_data, sizeof(struct aqualinkdata)); memcpy(&_last_mqtt_aqualinkdata, _aqualink_data, sizeof(struct aqualinkdata));
#endif #endif
DEBUG_TIMER_STOP(tid, NET_LOG, "broadcast_aqualinkstate() completed, took ");
return; return;
} }
@ -678,7 +662,7 @@ void create_program_request(netRequest requester, action_type type, int value, i
_aqualink_data->unactioned.type = type; _aqualink_data->unactioned.type = type;
_aqualink_data->unactioned.id = id; // This is only valid for pump. _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. 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); time(&_aqualink_data->unactioned.requested);
else else
_aqualink_data->unactioned.requested = 0; _aqualink_data->unactioned.requested = 0;
@ -771,7 +755,7 @@ uriAtype action_URI(netRequest from, const char *URI, int uri_length, float valu
return uBad; return uBad;
} }
rtn = uActioned; rtn = uActioned;
if (from = NET_MQTT) // We can get multiple MQTT requests for if (from == NET_MQTT) // We can get multiple MQTT requests for
time(&_aqualink_data->unactioned.requested); time(&_aqualink_data->unactioned.requested);
else else
_aqualink_data->unactioned.requested = 0; _aqualink_data->unactioned.requested = 0;
@ -938,8 +922,12 @@ uriAtype action_URI(netRequest from, const char *URI, int uri_length, float valu
return rtn; return rtn;
} }
void action_mqtt_message(struct mg_connection *nc, struct mg_mqtt_message *msg) { void action_mqtt_message(struct mg_connection *nc, struct mg_mqtt_message *msg) {
char *rtnmsg; char *rtnmsg;
#ifdef AQ_TM_DEBUG
int tid;
#endif
//unsigned int i; //unsigned int i;
//LOG(NET_LOG,LOG_DEBUG, "MQTT: topic %.*s %.2f\n",msg->topic.len, msg->topic.p, atof(msg->payload.p)); //LOG(NET_LOG,LOG_DEBUG, "MQTT: topic %.*s %.2f\n",msg->topic.len, msg->topic.p, atof(msg->payload.p));
// If message doesn't end in set we don't care about it. // If message doesn't end in set we don't care about it.
@ -949,6 +937,7 @@ void action_mqtt_message(struct mg_connection *nc, struct mg_mqtt_message *msg)
} }
LOG(NET_LOG,LOG_DEBUG, "MQTT: topic %.*s %.*s\n",msg->topic.len, msg->topic.p, msg->payload.len, msg->payload.p); LOG(NET_LOG,LOG_DEBUG, "MQTT: topic %.*s %.*s\n",msg->topic.len, msg->topic.p, msg->payload.len, msg->payload.p);
DEBUG_TIMER_START(&tid);
//Need to do this in a better manor, but for present it's ok. //Need to do this in a better manor, but for present it's ok.
static char tmp[20]; static char tmp[20];
strncpy(tmp, msg->payload.p, msg->payload.len); strncpy(tmp, msg->payload.p, msg->payload.len);
@ -959,8 +948,13 @@ void action_mqtt_message(struct mg_connection *nc, struct mg_mqtt_message *msg)
bool convert = (_aqualink_data->temp_units != CELSIUS && _aqconfig_.convert_mqtt_temp)?true:false; bool convert = (_aqualink_data->temp_units != CELSIUS && _aqconfig_.convert_mqtt_temp)?true:false;
int offset = strlen(_aqconfig_.mqtt_aq_topic)+1; int offset = strlen(_aqconfig_.mqtt_aq_topic)+1;
action_URI(NET_MQTT, &msg->topic.p[offset], msg->topic.len - offset, value, convert, &rtnmsg); action_URI(NET_MQTT, &msg->topic.p[offset], msg->topic.len - offset, value, convert, &rtnmsg);
DEBUG_TIMER_STOP(tid, NET_LOG, "action_mqtt_message() completed, took ");
} }
float pass_mg_body(struct mg_str *body) { float pass_mg_body(struct mg_str *body) {
LOG(NET_LOG,LOG_INFO, "Message body:\n'%.*s'\n", body->len, body->p); LOG(NET_LOG,LOG_INFO, "Message body:\n'%.*s'\n", body->len, body->p);
// Quick n dirty pass value from either of below. // Quick n dirty pass value from either of below.
@ -985,13 +979,12 @@ float pass_mg_body(struct mg_str *body) {
void action_web_request(struct mg_connection *nc, struct http_message *http_msg) { void action_web_request(struct mg_connection *nc, struct http_message *http_msg) {
char *msg = NULL; char *msg = NULL;
// struct http_message *http_msg = (struct http_message *)ev_data; // struct http_message *http_msg = (struct http_message *)ev_data;
#ifdef AQ_NET_TIMER #ifdef AQ_TM_DEBUG
int tid; int tid;
int tid2; int tid2;
#endif #endif
DEBUG_TIMER_START(&tid); //DEBUG_TIMER_START(&tid);
if (getLogLevel(NET_LOG) >= LOG_INFO) { // Simply for log message, check we are at if (getLogLevel(NET_LOG) >= LOG_INFO) { // Simply for log message, check we are at
// this log level before running all this // this log level before running all this
// junk // junk
@ -1001,7 +994,7 @@ void action_web_request(struct mg_connection *nc, struct http_message *http_msg)
LOG(NET_LOG,LOG_INFO, "URI request: '%s'\n", uri); LOG(NET_LOG,LOG_INFO, "URI request: '%s'\n", uri);
free(uri); free(uri);
} }
DEBUG_TIMER_STOP(tid, "action_web_request debug print crap took"); //DEBUG_TIMER_STOP(tid, NET_LOG, "action_web_request debug print crap took");
//LOG(NET_LOG,LOG_INFO, "Message request:\n'%.*s'\n", http_msg->message.len, http_msg->message.p); //LOG(NET_LOG,LOG_INFO, "Message request:\n'%.*s'\n", http_msg->message.len, http_msg->message.p);
@ -1009,16 +1002,18 @@ void action_web_request(struct mg_connection *nc, struct http_message *http_msg)
if (strncmp(http_msg->uri.p, "/api", 4 ) != 0) { if (strncmp(http_msg->uri.p, "/api", 4 ) != 0) {
if (strstr(http_msg->method.p, "GET") && http_msg->query_string.len > 0) { if (strstr(http_msg->method.p, "GET") && http_msg->query_string.len > 0) {
LOG(NET_LOG,LOG_WARNING, "WEB: Old stanza, using old method to action\n"); 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); OLD_action_web_request(nc, http_msg);
DEBUG_TIMER_STOP(tid, NET_LOG, "action_web_request() serve Old stanza took");
} else { } else {
DEBUG_TIMER_START(&tid); DEBUG_TIMER_START(&tid);
mg_serve_http(nc, http_msg, _http_server_opts); mg_serve_http(nc, http_msg, _http_server_opts);
DEBUG_TIMER_STOP(tid, "action_web_request serve file took"); DEBUG_TIMER_STOP(tid, NET_LOG, "action_web_request() serve file took");
} }
//} else if (strstr(http_msg->method.p, "PUT")) { //} else if (strstr(http_msg->method.p, "PUT")) {
} else { } else {
char buf[50]; char buf[50];
float value; float value = 0;
DEBUG_TIMER_START(&tid); DEBUG_TIMER_START(&tid);
// If query string. // If query string.
@ -1041,35 +1036,36 @@ void action_web_request(struct mg_connection *nc, struct http_message *http_msg)
{ {
char message[JSON_BUFFER_SIZE]; char message[JSON_BUFFER_SIZE];
DEBUG_TIMER_START(&tid2); DEBUG_TIMER_START(&tid2);
build_device_JSON(_aqualink_data, message, JSON_BUFFER_SIZE, false); int size = build_device_JSON(_aqualink_data, message, JSON_BUFFER_SIZE, false);
DEBUG_TIMER_STOP(tid2, "action_web_request build_device_JSON took"); DEBUG_TIMER_STOP(tid2, NET_LOG, "action_web_request() build_device_JSON took");
mg_send_head(nc, 200, strlen(message), CONTENT_JSON); mg_send_head(nc, 200, size, CONTENT_JSON);
mg_send(nc, message, strlen(message)); mg_send(nc, message, size);
} }
break; break;
case uHomebridge: case uHomebridge:
{ {
char message[JSON_BUFFER_SIZE]; char message[JSON_BUFFER_SIZE];
build_device_JSON(_aqualink_data, message, JSON_BUFFER_SIZE, true); int size = build_device_JSON(_aqualink_data, message, JSON_BUFFER_SIZE, true);
mg_send_head(nc, 200, strlen(message), CONTENT_JSON); mg_send_head(nc, 200, size, CONTENT_JSON);
mg_send(nc, message, strlen(message)); mg_send(nc, message, size);
} }
break; break;
case uStatus: case uStatus:
{ {
char message[JSON_BUFFER_SIZE]; char message[JSON_BUFFER_SIZE];
DEBUG_TIMER_START(&tid2); DEBUG_TIMER_START(&tid2);
build_aqualink_status_JSON(_aqualink_data, message, JSON_BUFFER_SIZE); int size = build_aqualink_status_JSON(_aqualink_data, message, JSON_BUFFER_SIZE);
DEBUG_TIMER_STOP(tid2, "action_web_request build_aqualink_status_JSON took"); DEBUG_TIMER_STOP(tid2, NET_LOG, "action_web_request() build_aqualink_status_JSON took");
mg_send_head(nc, 200, strlen(message), CONTENT_JSON); mg_send_head(nc, 200, size, CONTENT_JSON);
mg_send(nc, message, strlen(message)); mg_send(nc, message, size);
} }
break;
case uDynamicconf: case uDynamicconf:
{ {
char message[JSON_BUFFER_SIZE]; char message[JSON_BUFFER_SIZE];
DEBUG_TIMER_START(&tid2); DEBUG_TIMER_START(&tid2);
int size = build_color_lights_js(_aqualink_data, message, JSON_BUFFER_SIZE); int size = build_color_lights_js(_aqualink_data, message, JSON_BUFFER_SIZE);
DEBUG_TIMER_STOP(tid2, "action_web_request build_color_lights_js took"); DEBUG_TIMER_STOP(tid2, NET_LOG, "action_web_request() build_color_lights_js took");
mg_send_head(nc, 200, size, CONTENT_JS); mg_send_head(nc, 200, size, CONTENT_JS);
mg_send(nc, message, size); mg_send(nc, message, size);
} }
@ -1101,12 +1097,10 @@ void action_web_request(struct mg_connection *nc, struct http_message *http_msg)
mg_send(nc, GET_RTN_UNKNOWN, strlen(GET_RTN_UNKNOWN)); mg_send(nc, GET_RTN_UNKNOWN, strlen(GET_RTN_UNKNOWN));
} }
sprintf(buf, "action_web_request serve api request '%.*s' took",http_msg->uri.len, http_msg->uri.p); sprintf(buf, "action_web_request() request '%.*s' took",http_msg->uri.len, http_msg->uri.p);
DEBUG_TIMER_STOP(tid, buf);
DEBUG_TIMER_STOP(tid, NET_LOG, buf);
} }
} }
@ -1117,7 +1111,7 @@ void action_websocket_request(struct mg_connection *nc, struct websocket_message
char *uri = NULL; char *uri = NULL;
char *value = NULL; char *value = NULL;
char *msg = NULL; char *msg = NULL;
#ifdef AQ_NET_TIMER #ifdef AQ_TM_DEBUG
int tid; int tid;
#endif #endif
#ifdef AQ_PDA #ifdef AQ_PDA
@ -1156,7 +1150,7 @@ void action_websocket_request(struct mg_connection *nc, struct websocket_message
DEBUG_TIMER_START(&tid); DEBUG_TIMER_START(&tid);
char message[JSON_BUFFER_SIZE]; char message[JSON_BUFFER_SIZE];
build_device_JSON(_aqualink_data, message, JSON_BUFFER_SIZE, false); build_device_JSON(_aqualink_data, message, JSON_BUFFER_SIZE, false);
DEBUG_TIMER_STOP(tid, "action_websocket_request build_device_JSON took"); DEBUG_TIMER_STOP(tid, NET_LOG, "action_websocket_request() build_device_JSON took");
ws_send(nc, message); ws_send(nc, message);
} }
break; break;
@ -1165,7 +1159,7 @@ void action_websocket_request(struct mg_connection *nc, struct websocket_message
DEBUG_TIMER_START(&tid); DEBUG_TIMER_START(&tid);
char message[JSON_BUFFER_SIZE]; char message[JSON_BUFFER_SIZE];
build_aqualink_status_JSON(_aqualink_data, message, JSON_BUFFER_SIZE); build_aqualink_status_JSON(_aqualink_data, message, JSON_BUFFER_SIZE);
DEBUG_TIMER_STOP(tid, "action_websocket_request build_aqualink_status_JSON took"); DEBUG_TIMER_STOP(tid, NET_LOG, "action_websocket_request() build_aqualink_status_JSON took");
ws_send(nc, message); ws_send(nc, message);
} }
break; break;
@ -1231,7 +1225,7 @@ static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
struct http_message *http_msg; struct http_message *http_msg;
struct websocket_message *ws_msg; struct websocket_message *ws_msg;
char aq_topic[30]; char aq_topic[30];
#ifdef AQ_NET_TIMER #ifdef AQ_TM_DEBUG
int tid; int tid;
#endif #endif
//static double last_control_time; //static double last_control_time;
@ -1243,7 +1237,7 @@ static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
http_msg = (struct http_message *)ev_data; http_msg = (struct http_message *)ev_data;
DEBUG_TIMER_START(&tid); DEBUG_TIMER_START(&tid);
action_web_request(nc, http_msg); action_web_request(nc, http_msg);
DEBUG_TIMER_STOP(tid, "WEB Request took"); DEBUG_TIMER_STOP(tid, NET_LOG, "WEB Request action_web_request() took");
LOG(NET_LOG,LOG_DEBUG, "Served WEB request\n"); LOG(NET_LOG,LOG_DEBUG, "Served WEB request\n");
break; break;
@ -1257,7 +1251,7 @@ static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
ws_msg = (struct websocket_message *)ev_data; ws_msg = (struct websocket_message *)ev_data;
DEBUG_TIMER_START(&tid); DEBUG_TIMER_START(&tid);
action_websocket_request(nc, ws_msg); action_websocket_request(nc, ws_msg);
DEBUG_TIMER_STOP(tid, "Websocket Request took"); DEBUG_TIMER_STOP(tid, NET_LOG, "Websocket Request action_websocket_request() took");
break; break;
case MG_EV_CLOSE: case MG_EV_CLOSE:
@ -1350,7 +1344,7 @@ static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
{ {
DEBUG_TIMER_START(&tid); DEBUG_TIMER_START(&tid);
action_mqtt_message(nc, mqtt_msg); action_mqtt_message(nc, mqtt_msg);
DEBUG_TIMER_STOP(tid, "MQTT Request took"); DEBUG_TIMER_STOP(tid, NET_LOG, "MQTT Request action_mqtt_message() took");
} }
if (_aqconfig_.mqtt_dz_sub_topic != NULL && strncmp(mqtt_msg->topic.p, _aqconfig_.mqtt_dz_sub_topic, strlen(_aqconfig_.mqtt_dz_sub_topic)) == 0) { if (_aqconfig_.mqtt_dz_sub_topic != NULL && strncmp(mqtt_msg->topic.p, _aqconfig_.mqtt_dz_sub_topic, strlen(_aqconfig_.mqtt_dz_sub_topic)) == 0) {
action_domoticz_mqtt_message(nc, mqtt_msg); action_domoticz_mqtt_message(nc, mqtt_msg);
@ -1386,7 +1380,7 @@ void start_mqtt(struct mg_mgr *mgr) {
if (mg_connect(mgr, _aqconfig_.mqtt_server, ev_handler) == NULL) { if (mg_connect(mgr, _aqconfig_.mqtt_server, ev_handler) == NULL) {
LOG(NET_LOG,LOG_ERR, "Failed to create MQTT listener to %s\n", _aqconfig_.mqtt_server); LOG(NET_LOG,LOG_ERR, "Failed to create MQTT listener to %s\n", _aqconfig_.mqtt_server);
} else { } else {
int i; //int i;
#ifdef AQ_MEMCMP #ifdef AQ_MEMCMP
memset(&_last_mqtt_aqualinkdata, 0, sizeof (struct aqualinkdata)); memset(&_last_mqtt_aqualinkdata, 0, sizeof (struct aqualinkdata));
#endif #endif
@ -1397,13 +1391,13 @@ void start_mqtt(struct mg_mgr *mgr) {
//bool start_web_server(struct mg_mgr *mgr, struct aqualinkdata *aqdata, char *port, char* web_root) { //bool start_web_server(struct mg_mgr *mgr, struct aqualinkdata *aqdata, char *port, char* web_root) {
//bool start_net_services(struct mg_mgr *mgr, struct aqualinkdata *aqdata, struct aqconfig *aqconfig) { //bool start_net_services(struct mg_mgr *mgr, struct aqualinkdata *aqdata, struct aqconfig *aqconfig) {
bool start_net_services(struct mg_mgr *mgr, struct aqualinkdata *aqdata) { bool _start_net_services(struct mg_mgr *mgr, struct aqualinkdata *aqdata) {
struct mg_connection *nc; struct mg_connection *nc;
_aqualink_data = aqdata; _aqualink_data = aqdata;
//_aqconfig_ = aqconfig; //_aqconfig_ = aqconfig;
signal(SIGTERM, signal_handler); signal(SIGTERM, net_signal_handler);
signal(SIGINT, signal_handler); signal(SIGINT, net_signal_handler);
setvbuf(stdout, NULL, _IOLBF, 0); setvbuf(stdout, NULL, _IOLBF, 0);
setvbuf(stderr, NULL, _IOLBF, 0); setvbuf(stderr, NULL, _IOLBF, 0);
@ -1440,6 +1434,119 @@ bool start_net_services(struct mg_mgr *mgr, struct aqualinkdata *aqdata) {
} }
/**********************************************************************************************
* Thread Net Services
*
*/
pthread_t _net_thread_id;
bool _keepNetServicesRunning = true;
//volatile bool _broadcast = false; // This is redundent when most the fully threadded rather than option.
void *net_services_thread( void *ptr )
{
struct aqualinkdata *aqdata = (struct aqualinkdata *) ptr;
struct mg_mgr mgr;
_start_net_services(&mgr, aqdata);
while (_keepNetServicesRunning == true)
{
//poll_net_services(&mgr, 10);
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;
}
}
LOG(NET_LOG,LOG_NOTICE, "Stopping network services thread\n");
mg_mgr_free(&mgr);
pthread_exit(0);
}
bool start_net_services(struct mg_mgr *mgr, struct aqualinkdata *aqdata)
{
if ( ! _aqconfig_.thread_netservices) {
return _start_net_services(mgr, aqdata);
}
LOG(NET_LOG,LOG_NOTICE, "Starting network services thread\n");
if( pthread_create( &_net_thread_id , NULL , net_services_thread, (void*)aqdata) < 0) {
LOG(NET_LOG, LOG_ERR, "could not create network thread\n");
return false;
}
pthread_detach(_net_thread_id);
return true;
}
time_t poll_net_services(struct mg_mgr *mgr, int timeout_ms)
{
if (timeout_ms < 0)
timeout_ms = 0;
if ( ! _aqconfig_.thread_netservices) {
return mg_mgr_poll(mgr, timeout_ms);
}
if (timeout_ms > 5)
delay(5);
else if (timeout_ms > 0)
delay(timeout_ms);
//LOG(NET_LOG,LOG_NOTICE, "Poll network services\n");
return 0;
}
void broadcast_aqualinkstate(struct mg_connection *nc)
{
if ( ! _aqconfig_.thread_netservices) {
_broadcast_aqualinkstate(nc);
_aqualink_data->updated = false;
return;
}
//_broadcast = true;
//LOG(NET_LOG,LOG_NOTICE, "Broadcast status to network\n");
}
void broadcast_aqualinkstate_error(struct mg_connection *nc, char *msg)
{
if ( ! _aqconfig_.thread_netservices) {
return _broadcast_aqualinkstate_error(nc, msg);
}
LOG(NET_LOG,LOG_NOTICE, "Broadcast error to network\n");
}
void stop_net_services(struct mg_mgr *mgr) {
if ( ! _aqconfig_.thread_netservices) {
mg_mgr_free(mgr);
return;
}
_keepNetServicesRunning = false;
return;
}
@ -1713,7 +1820,7 @@ LOG(NET_LOG,LOG_ERR, "WEB: spalightmode taken out for update (forgot to put it b
mg_send(nc, GET_RTN_UNKNOWN, strlen(GET_RTN_UNKNOWN)); mg_send(nc, GET_RTN_UNKNOWN, strlen(GET_RTN_UNKNOWN));
} else { } else {
struct mg_serve_http_opts opts; //struct mg_serve_http_opts opts;
//memset(&opts, 0, sizeof(opts)); // Reset all options to defaults //memset(&opts, 0, sizeof(opts)); // Reset all options to defaults
//opts.document_root = _web_root; // Serve files from the current directory //opts.document_root = _web_root; // Serve files from the current directory
// LOG(NET_LOG,LOG_DEBUG, "Doc root=%s\n",opts.document_root); // LOG(NET_LOG,LOG_DEBUG, "Doc root=%s\n",opts.document_root);

View File

@ -16,6 +16,8 @@
//bool start_web_server(struct mg_mgr *mgr, struct aqualinkdata *aqdata, char *port, char* web_root); //bool start_web_server(struct mg_mgr *mgr, struct aqualinkdata *aqdata, char *port, char* web_root);
//bool start_net_services(struct mg_mgr *mgr, struct aqualinkdata *aqdata, struct aqconfig *aqconfig); //bool start_net_services(struct mg_mgr *mgr, struct aqualinkdata *aqdata, struct aqconfig *aqconfig);
bool start_net_services(struct mg_mgr *mgr, struct aqualinkdata *aqdata); bool start_net_services(struct mg_mgr *mgr, struct aqualinkdata *aqdata);
void stop_net_services(struct mg_mgr *mgr);
time_t poll_net_services(struct mg_mgr *mgr, int timeout_ms);
void broadcast_aqualinkstate(struct mg_connection *nc); void broadcast_aqualinkstate(struct mg_connection *nc);
void broadcast_aqualinkstate_error(struct mg_connection *nc, char *msg); void broadcast_aqualinkstate_error(struct mg_connection *nc, char *msg);

View File

@ -124,6 +124,9 @@ void log_programming_information(struct aqualinkdata *aq_data)
case OTM_SET_TEMP: case OTM_SET_TEMP:
log_heater_setpoints(aq_data); log_heater_setpoints(aq_data);
break; break;
default:
// No need to do anything yet
break;
} }
} }
@ -346,6 +349,7 @@ bool log_qeuiptment_status(struct aqualinkdata *aq_data)
//printf ("Set Pump Type to %d\n",aq_data->pumps[i].pumpType); //printf ("Set Pump Type to %d\n",aq_data->pumps[i].pumpType);
} }
} }
#ifdef READ_SWG_FROM_EXTENDED_ID
} else if (rsm_strcmp(_menu[2],"AQUAPURE") == 0) { } else if (rsm_strcmp(_menu[2],"AQUAPURE") == 0) {
/* Info: OneTouch Menu Line 0 = Equipment Status /* Info: OneTouch Menu Line 0 = Equipment Status
Info: OneTouch Menu Line 1 = Info: OneTouch Menu Line 1 =
@ -367,7 +371,7 @@ bool log_qeuiptment_status(struct aqualinkdata *aq_data)
} }
LOG(ONET_LOG,LOG_INFO, "OneTouch PPM = %d\n",ppm); LOG(ONET_LOG,LOG_INFO, "OneTouch PPM = %d\n",ppm);
} }
#endif
} else if (rsm_strcmp(_menu[2],"Chemlink") == 0) { } else if (rsm_strcmp(_menu[2],"Chemlink") == 0) {
/* Info: OneTouch Menu Line 0 = Equipment Status /* Info: OneTouch Menu Line 0 = Equipment Status
Info: OneTouch Menu Line 1 = Info: OneTouch Menu Line 1 =

View File

@ -767,7 +767,7 @@ void *set_aqualink_onetouch_swg_percent( void *ptr )
int diff; int diff;
int i; int i;
int len; int len;
unsigned char direction; unsigned char direction = KEY_ONET_UP;
waitForSingleThreadOrTerminate(threadCtrl, AQ_SET_ONETOUCH_SWG_PERCENT); waitForSingleThreadOrTerminate(threadCtrl, AQ_SET_ONETOUCH_SWG_PERCENT);
int val = atoi((char*)threadCtrl->thread_args); int val = atoi((char*)threadCtrl->thread_args);
@ -808,7 +808,7 @@ void *set_aqualink_onetouch_swg_percent( void *ptr )
i=0; i=0;
char *st = onetouch_menu_hlightchars(&len); char *st = onetouch_menu_hlightchars(&len);
LOG(ONET_LOG,LOG_DEBUG, "** OneTouch set SWG Percent highlighted='%.*s' len=%d st=%s\n", len, st, len, st); LOG(ONET_LOG,LOG_DEBUG, "** OneTouch set SWG Percent highlighted='%.*s' len=%d st=%s\n", len, st, len, st);
while (len > 5 || len < 0 && i < 5) { while (len > 5 || (len < 0 && i < 5)) {
LOG(ONET_LOG,LOG_DEBUG, "** OneTouch set SWG Percent highlighted waiting again\n"); LOG(ONET_LOG,LOG_DEBUG, "** OneTouch set SWG Percent highlighted waiting again\n");
delay(50); delay(50);
waitForOT_MessageTypes(aq_data,CMD_PDA_HIGHLIGHTCHARS,0x00,5); // CMD_PDA_0x04 is just a packer. waitForOT_MessageTypes(aq_data,CMD_PDA_HIGHLIGHTCHARS,0x00,5); // CMD_PDA_0x04 is just a packer.

View File

@ -98,7 +98,7 @@ int _beautifyPacket(char *buff, unsigned char *packet_buffer, int packet_length,
int cnt = 0; int cnt = 0;
if (_includePentair) { if (_includePentair) {
cnt = sprintf(buff, "%s%8.8s Packet | HEX: ",(error?"BAD PACKET ":""),getProtocolType(packet_buffer)==JANDY?"Jandy":"Pentair"); cnt = sprintf(buff, "%s%8.8s Packet | HEX: ",(error?"BAD PACKET ":""),getProtocolType(packet_buffer)==PENTAIR?"Pentair":"Jandy");
} else { } else {
cnt = sprintf(buff, "%sTo 0x%02hhx of type %8.8s | HEX: ",(error?"BAD PACKET ":""), packet_buffer[PKT_DEST], get_packet_type(packet_buffer, packet_length)); cnt = sprintf(buff, "%sTo 0x%02hhx of type %8.8s | HEX: ",(error?"BAD PACKET ":""), packet_buffer[PKT_DEST], get_packet_type(packet_buffer, packet_length));
} }

2
pda.c
View File

@ -200,7 +200,7 @@ void pass_pda_equiptment_status_item(char *msg)
} }
else else
{ {
char labelBuff[AQ_MSGLEN + 1]; char labelBuff[AQ_MSGLEN + 2];
strncpy(labelBuff, msg, AQ_MSGLEN + 1); strncpy(labelBuff, msg, AQ_MSGLEN + 1);
msg = stripwhitespace(labelBuff); msg = stripwhitespace(labelBuff);

Binary file not shown.

View File

@ -105,14 +105,18 @@ report_zero_pool_temp = no
#mqtt_dz_pub_topic = domoticz/in #mqtt_dz_pub_topic = domoticz/in
#mqtt_dz_sub_topic = domoticz/out #mqtt_dz_sub_topic = domoticz/out
#mqtt_aq_topic = aqualinkd #mqtt_aq_topic = aqualinkd
# MQTT will only post updated information, this option AqualinkD will re-post all MQTT information every ~5 minutes. # MQTT will only post updated information, this option AqualinkD will re-post all MQTT information every ~5 minutes.
#mqtt_timed_update = no #mqtt_timed_update = no
# Please see forum for this, only set to yes when logging information to support # Please see forum for this, only set to yes when logging information to support
# new devices. Inflrmation will be written to /tmp/RS485.log # new devices. Inflrmation will be written to /tmp/RS485.log
#debug_RSProtocol_packets = no #debug_RSProtocol_packets = no
# Not documented, only use if asked to for problem solving purposes.
# Not documented, or expermental. Only use if asked to for problem solving purposes.
#serial_readahead_b4_write = yes #serial_readahead_b4_write = yes
#thread_netservices = yes
#rs_poll_speed = -1
# Put AqualinkD to sleep when in PDA mode after inactivity. # Put AqualinkD to sleep when in PDA mode after inactivity.

View File

@ -38,19 +38,42 @@ command -v systemctl >/dev/null 2>&1 || { echo "This script needs systemd's syst
systemctl stop $SERVICE > /dev/null 2>&1 systemctl stop $SERVICE > /dev/null 2>&1
SERVICE_EXISTS=$(echo $?) SERVICE_EXISTS=$(echo $?)
# Clean everything if requested.
if [ "$1" == "clean" ]; then
echo "Deleting install"
systemctl disable $SERVICE > /dev/null 2>&1
if [ -f $BINLocation/$BIN ]; then
rm -f $BINLocation/$BIN
fi
if [ -f $SRVLocation/$SRV ]; then
rm -f $SRVLocation/$SRV
fi
if [ -f $CFGLocation/$CFG ]; then
rm -f $CFGLocation/$CFG
fi
if [ -f $DEFLocation/$DEF ]; then
rm -f $DEFLocation/$DEF
fi
if [ -d $WEBLocation ]; then
rm -rf $WEBLocation
fi
systemctl daemon-reload
exit
fi
# copy files to locations, but only copy cfg if it doesn;t already exist # copy files to locations, but only copy cfg if it doesn;t already exist
cp $BUILD/$BIN $BINLocation/$BIN cp $BUILD/$BIN $BINLocation/$BIN
cp $BUILD/$SRV $SRVLocation/$SRV cp $BUILD/$SRV $SRVLocation/$SRV
if [ -f $CFGLocation/$CFG ]; then if [ -f $CFGLocation/$CFG ]; then
echo "Config exists, did not copy new config, you may need to edit existing! $CFGLocation/$CFG" echo "AqualinkD config exists, did not copy new config, you may need to edit existing! $CFGLocation/$CFG"
else else
cp $BUILD/$CFG $CFGLocation/$CFG cp $BUILD/$CFG $CFGLocation/$CFG
fi fi
if [ -f $DEFLocation/$DEF ]; then if [ -f $DEFLocation/$DEF ]; then
echo "Defaults exists, did not copy new defaults to $DEFLocation/$DEF" echo "AqualinkD defaults exists, did not copy new defaults to $DEFLocation/$DEF"
else else
cp $BUILD/$DEF.defaults $DEFLocation/$DEF cp $BUILD/$DEF.defaults $DEFLocation/$DEF
fi fi
@ -70,7 +93,7 @@ if [ ! -d "$WEBLocation" ]; then
fi fi
if [ -f "$WEBLocation/config.js" ]; then if [ -f "$WEBLocation/config.js" ]; then
echo "$WEBLocation/config.js exists, did not copy overight, please make sure to update manually" echo "AqualinkD web config exists, did not copy new config, you may need to edit existing $WEBLocation/config.js "
rsync -avq --exclude='config.js' $BUILD/../web/* $WEBLocation rsync -avq --exclude='config.js' $BUILD/../web/* $WEBLocation
else else
cp -r $BUILD/../web/* $WEBLocation cp -r $BUILD/../web/* $WEBLocation
@ -83,5 +106,7 @@ systemctl daemon-reload
if [ $SERVICE_EXISTS -eq 0 ]; then if [ $SERVICE_EXISTS -eq 0 ]; then
echo "Starting daemon $SERVICE" echo "Starting daemon $SERVICE"
systemctl start $SERVICE systemctl start $SERVICE
else
echo "Please edit $CFGLocation/$CFG, then start AqualinkD service"
fi fi

Binary file not shown.

View File

@ -73,7 +73,7 @@ bool _playback_file = false;
void intHandler(int dummy) { void intHandler(int dummy) {
_keepRunning = false; _keepRunning = false;
logMessage(LOG_NOTICE, "Stopping!"); LOG(RSSD_LOG, LOG_NOTICE, "Stopping!");
if (_playback_file) // If we are reading file, loop is irevelent if (_playback_file) // If we are reading file, loop is irevelent
exit(0); exit(0);
} }
@ -320,6 +320,7 @@ int main(int argc, char *argv[]) {
int logLevel = LOG_NOTICE; int logLevel = LOG_NOTICE;
bool rsRawDebug = false; bool rsRawDebug = false;
bool panleProbe = true; bool panleProbe = true;
bool rsSerialSpeedTest = false;
//bool playback_file = false; //bool playback_file = false;
//int logLevel; //int logLevel;
@ -345,6 +346,7 @@ int main(int argc, char *argv[]) {
fprintf(stderr, "\t-p <number> (log # packets)\n"); fprintf(stderr, "\t-p <number> (log # packets)\n");
fprintf(stderr, "\t-i <ID> (just log these ID's, can use multiple -i)\n"); fprintf(stderr, "\t-i <ID> (just log these ID's, can use multiple -i)\n");
fprintf(stderr, "\t-r (raw)\n"); fprintf(stderr, "\t-r (raw)\n");
fprintf(stderr, "\t-s (Serial Speed Test)\n");
fprintf(stderr, "\t-rsrd (log raw RS bytes to %s)\n",RS485BYTELOGFILE); fprintf(stderr, "\t-rsrd (log raw RS bytes to %s)\n",RS485BYTELOGFILE);
fprintf(stderr, "\nie:\t%s /dev/ttyUSB0 -d -p 1000 -i 0x08 -i 0x0a\n\n", argv[0]); fprintf(stderr, "\nie:\t%s /dev/ttyUSB0 -d -p 1000 -i 0x08 -i 0x0a\n\n", argv[0]);
return 1; return 1;
@ -372,6 +374,8 @@ int main(int argc, char *argv[]) {
rsRawDebug = true; rsRawDebug = true;
} else if (strcmp(argv[i], "-n") == 0) { } else if (strcmp(argv[i], "-n") == 0) {
panleProbe = false; panleProbe = false;
} else if (strcmp(argv[i], "-s") == 0) {
rsSerialSpeedTest = true;
} }
} }
@ -380,7 +384,7 @@ int main(int argc, char *argv[]) {
if (_playback_file) { if (_playback_file) {
rs_fd = open(argv[1], O_RDONLY | O_NOCTTY | O_NONBLOCK | O_NDELAY); rs_fd = open(argv[1], O_RDONLY | O_NOCTTY | O_NONBLOCK | O_NDELAY);
if (rs_fd < 0) { if (rs_fd < 0) {
logMessage(LOG_ERR, "Unable to open file: %s\n", argv[1]); LOG(RSSD_LOG, LOG_ERR, "Unable to open file: %s\n", argv[1]);
displayLastSystemError(argv[1]); displayLastSystemError(argv[1]);
return -1; return -1;
} }
@ -414,7 +418,7 @@ int main(int argc, char *argv[]) {
// Nothing read // Nothing read
} else if (packet_length > 0) { } else if (packet_length > 0) {
//logMessage(LOG_DEBUG_SERIAL, "Received Packet for ID 0x%02hhx of type %s\n", packet_buffer[PKT_DEST], get_packet_type(packet_buffer, packet_length)); //LOG(RSSD_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));
if (logLevel > LOG_NOTICE) if (logLevel > LOG_NOTICE)
printPacket(lastID, packet_buffer, packet_length); printPacket(lastID, packet_buffer, packet_length);
@ -448,7 +452,7 @@ int main(int argc, char *argv[]) {
} }
if (packet_buffer[PKT_DEST] == DEV_MASTER /*&& packet_buffer[PKT_CMD] == CMD_ACK*/) { if (packet_buffer[PKT_DEST] == DEV_MASTER /*&& packet_buffer[PKT_CMD] == CMD_ACK*/) {
//logMessage(LOG_NOTICE, "ID is in use 0x%02hhx %x\n", lastID, lastID); //LOG(RSSD_LOG, LOG_NOTICE, "ID is in use 0x%02hhx %x\n", lastID, lastID);
for (i = 0; i <= sindex; i++) { for (i = 0; i <= sindex; i++) {
if (slog[i].ID == lastID) { if (slog[i].ID == lastID) {
slog[i].inuse = true; slog[i].inuse = true;
@ -477,6 +481,18 @@ int main(int argc, char *argv[]) {
}*/ }*/
// NSF // NSF
// Test Serial speed & caching
if (rsSerialSpeedTest) {
if (rsRawDebug)
packet_length = get_packet_lograw(rs_fd, packet_buffer);
else
packet_length = get_packet(rs_fd, packet_buffer);
if (packet_length > 0) {
LOG(RSSD_LOG, LOG_ERR, "SERIOUS RS485 ERROR, Slow serial port read detected, (check RS485 adapteer / os performance / USB serial speed\n");
}
}
} }
if (logPackets != 0 && received_packets >= logPackets) { if (logPackets != 0 && received_packets >= logPackets) {
@ -500,7 +516,7 @@ int main(int argc, char *argv[]) {
LOG(RSSD_LOG, LOG_NOTICE, "Jandy ID's found\n"); LOG(RSSD_LOG, LOG_NOTICE, "Jandy ID's found\n");
for (i = 0; i < sindex; i++) { for (i = 0; i < sindex; i++) {
//logMessage(LOG_NOTICE, "ID 0x%02hhx is %s %s\n", slog[i].ID, (slog[i].inuse == true) ? "in use" : "not used", //LOG(RSSD_LOG, LOG_NOTICE, "ID 0x%02hhx is %s %s\n", slog[i].ID, (slog[i].inuse == true) ? "in use" : "not used",
// (slog[i].inuse == false && canUse(slog[i].ID) == true)? " <-- can use for Aqualinkd" : ""); // (slog[i].inuse == false && canUse(slog[i].ID) == true)? " <-- can use for Aqualinkd" : "");
if (logLevel >= LOG_DEBUG || slog[i].inuse == true || canUse(slog[i].ID) == true) { if (logLevel >= LOG_DEBUG || slog[i].inuse == true || canUse(slog[i].ID) == true) {
LOG(RSSD_LOG, LOG_NOTICE, "ID 0x%02hhx is %s %s\n", slog[i].ID, (slog[i].inuse == true) ? "in use" : "not used", LOG(RSSD_LOG, LOG_NOTICE, "ID 0x%02hhx is %s %s\n", slog[i].ID, (slog[i].inuse == true) ? "in use" : "not used",

86
utils.c
View File

@ -143,7 +143,8 @@ void displayLastSystemError (const char *on_what)
if (_daemonise == TRUE) if (_daemonise == TRUE)
{ {
logMessage (LOG_ERR, "%d : %s", errno, on_what); //logMessage (LOG_ERR, "%d : %s", errno, on_what);
LOG(AQUA_LOG, LOG_ERR, "%d : %s", errno, on_what);
closelog (); closelog ();
} }
} }
@ -208,6 +209,43 @@ int text2elevel(char* level)
return LOG_ERR; return LOG_ERR;
} }
const char* logmask2name(int16_t from)
{
switch (from) {
case NET_LOG:
return "NetService:";
break;
case AQRS_LOG:
return "RS Allbtn: ";
break;
case ONET_LOG:
return "One Touch: ";
break;
case IAQT_LOG:
return "iAQ Touch: ";
break;
case PDA_LOG:
return "PDA: ";
break;
case DJAN_LOG:
return "JandyDvce: ";
break;
case DPEN_LOG:
return "PentaDvce: ";
break;
case RSSD_LOG:
return "RS Serial: ";
break;
case DBGT_LOG:
return "AQ Timing: ";
break;
case AQUA_LOG:
default:
return "AqualinkD: ";
break;
}
}
void timestamp(char* time_string) void timestamp(char* time_string)
{ {
time_t now; time_t now;
@ -354,6 +392,7 @@ void addDebugLogMask(int16_t flag)
void _LOG(int16_t from, int msg_level, char * message); void _LOG(int16_t from, int msg_level, char * message);
/*
void logMessage(int msg_level, const char *format, ...) void logMessage(int msg_level, const char *format, ...)
{ {
if (msg_level > _log_level) { if (msg_level > _log_level) {
@ -369,7 +408,7 @@ void logMessage(int msg_level, const char *format, ...)
_LOG(AQUA_LOG, msg_level, buffer); _LOG(AQUA_LOG, msg_level, buffer);
} }
*/
void LOG(int16_t from, int msg_level, const char * format, ...) void LOG(int16_t from, int msg_level, const char * format, ...)
{ {
@ -388,7 +427,7 @@ void LOG(int16_t from, int msg_level, const char * format, ...)
} }
void _LOG(int16_t from, int msg_level, char * message) void _LOG(int16_t from, int msg_level, char *message)
{ {
int i; int i;
@ -404,36 +443,9 @@ void _LOG(int16_t from, int msg_level, char * message)
message[i+1] = '\0'; message[i+1] = '\0';
} }
switch (from) { //strncpy(&message[9], logmask2name(from), 11); // Will give compiller warning as doesn;t realise we are copying into middle of string.
case NET_LOG: memcpy(&message[9], logmask2name(from), 11);
strncpy(&message[9], "NetService:", 11);
break;
case AQRS_LOG:
strncpy(&message[9], "RS Allbtn: ", 11);
break;
case ONET_LOG:
strncpy(&message[9], "One Touch: ", 11);
break;
case IAQT_LOG:
strncpy(&message[9], "iAQ Touch: ", 11);
break;
case PDA_LOG:
strncpy(&message[9], "PDA: ", 11);
break;
case DJAN_LOG:
strncpy(&message[9], "JandyDvce: ", 11);
break;
case DPEN_LOG:
strncpy(&message[9], "PentaDvce: ", 11);
break;
case RSSD_LOG:
strncpy(&message[9], "RS Serial: ", 11);
break;
case AQUA_LOG:
default:
strncpy(&message[9], "AqualinkD: ", 11);
break;
}
// Logging has not been setup yet, so STD error & syslog // Logging has not been setup yet, so STD error & syslog
if (_log_level == -1) { if (_log_level == -1) {
fprintf (stderr, message); fprintf (stderr, message);
@ -512,7 +524,7 @@ void daemonise (char *pidFile, void (*main_function) (void))
/* Check we are root */ /* Check we are root */
if (getuid() != 0) if (getuid() != 0)
{ {
logMessage(LOG_ERR,"Can only be run as root\n"); LOG(AQUA_LOG, LOG_ERR,"Can only be run as root\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@ -523,7 +535,7 @@ void daemonise (char *pidFile, void (*main_function) (void))
//if (EWOULDBLOCK == errno) //if (EWOULDBLOCK == errno)
//; // another instance is running //; // another instance is running
//fputs ("\nAnother instance is already running\n", stderr); //fputs ("\nAnother instance is already running\n", stderr);
logMessage(LOG_ERR,"\nAnother instance is already running\n"); LOG(AQUA_LOG, LOG_ERR,"\nAnother instance is already running\n");
exit (EXIT_FAILURE); exit (EXIT_FAILURE);
} }
@ -541,12 +553,12 @@ void daemonise (char *pidFile, void (*main_function) (void))
fp = fopen (pidFile, "w"); fp = fopen (pidFile, "w");
if (fp == NULL) if (fp == NULL)
logMessage(LOG_ERR,"can't write to PID file %s",pidFile); LOG(AQUA_LOG, LOG_ERR,"can't write to PID file %s",pidFile);
else else
fprintf(fp, "%d", process_id); fprintf(fp, "%d", process_id);
fclose (fp); fclose (fp);
logMessage (LOG_DEBUG, "process_id of child process %d \n", process_id); LOG(AQUA_LOG, LOG_DEBUG, "process_id of child process %d \n", process_id);
// return success in exit status // return success in exit status
exit (EXIT_SUCCESS); exit (EXIT_SUCCESS);
} }

View File

@ -35,6 +35,8 @@
#define DPEN_LOG (1 << 7) // Pentair Device #define DPEN_LOG (1 << 7) // Pentair Device
// misc // misc
#define RSSD_LOG (1 << 8) // Serial #define RSSD_LOG (1 << 8) // Serial
#define PROG_LOG (1 << 9) // Programmer
#define DBGT_LOG (1 << 10) // Debug Timer
/* /*
typedef enum typedef enum
{ {
@ -51,7 +53,11 @@ void displayLastSystemError (const char *on_what);
void addDebugLogMask(int16_t flag); void addDebugLogMask(int16_t flag);
//#define logMessage(msg_level, format, ...) LOG (1, msg_level, format, ##__VA_ARGS__) //#define logMessage(msg_level, format, ...) LOG (1, msg_level, format, ##__VA_ARGS__)
void logMessage(int level, const char *format, ...);
//void logMessage(int level, const char *format, ...);
//void LOG(int from, int level, char *format, ...); //void LOG(int from, int level, char *format, ...);
void LOG(int16_t from, int msg_level, const char *format, ...); void LOG(int16_t from, int msg_level, const char *format, ...);
@ -82,6 +88,7 @@ void stopInlineDebug();
void cleanInlineDebug(); void cleanInlineDebug();
char *getInlineLogFName(); char *getInlineLogFName();
bool islogFileReady(); bool islogFileReady();
const char *logmask2name(int16_t from);
//#ifndef _UTILS_C_ //#ifndef _UTILS_C_
extern bool _daemon_; extern bool _daemon_;

View File

@ -1,4 +1,4 @@
#define AQUALINKD_NAME "Aqualink Daemon" #define AQUALINKD_NAME "Aqualink Daemon"
#define AQUALINKD_VERSION "2.2.0b" #define AQUALINKD_VERSION "2.2.0c"

View File

@ -1485,6 +1485,8 @@
get_devices(); get_devices();
// Set another load 1 minute from now just incase the server hasn't got all the devices yet // Set another load 1 minute from now just incase the server hasn't got all the devices yet
window.setTimeout(get_devices, (60 * 1000)); window.setTimeout(get_devices, (60 * 1000));
// Get Status just incase control panel hasn't connected yet
get_status();
} }
socket_di.onmessage = function got_packet(msg) { socket_di.onmessage = function got_packet(msg) {
document.getElementById("header").classList.remove("error"); document.getElementById("header").classList.remove("error");
@ -1523,6 +1525,17 @@
socket_di.send(JSON.stringify(msg)); socket_di.send(JSON.stringify(msg));
} }
function get_status() {
/*
var msg = {
command: "GET_DEVICES"
};*/
var msg = {
uri: "status"
};
socket_di.send(JSON.stringify(msg));
}
function send_command(cmd, value=null) { function send_command(cmd, value=null) {
var _cmd = {}; var _cmd = {};
_cmd.command = cmd; _cmd.command = cmd;

View File

@ -278,7 +278,7 @@
for (var obj in data['devices']) { for (var obj in data['devices']) {
if (document.getElementById(data['devices'][obj].id) == null) { if (document.getElementById(data['devices'][obj].id) == null) {
_displayNames[data['devices'][obj].id.replace("Aux_", "AUX")] = data['devices'][obj].name; _displayNames[data['devices'][obj].id.replace("Aux_", "AUX")] = data['devices'][obj].name;
//console.log("Create " + data['devices'][obj].id); console.log("Create " + data['devices'][obj].id);
createTile(data['devices'][obj]); createTile(data['devices'][obj]);
} }
} }
@ -321,6 +321,10 @@
function createTile(object) { function createTile(object) {
if (object.name == 'NONE') if (object.name == 'NONE')
return; return;
if (typeof devices !== 'undefined' && devices.indexOf(object.id) < 0) {
return;
}
//if (ignore_devices.indexOf(object.id) >= 0) //if (ignore_devices.indexOf(object.id) >= 0)
// return; // return;
var table = document.getElementById("deviceList"); var table = document.getElementById("deviceList");
@ -339,13 +343,14 @@
cell3.setAttribute('align', 'right'); cell3.setAttribute('align', 'right');
//cell3.setAttribute('cellpadding', '0'); //cell3.setAttribute('cellpadding', '0');
cell4.setAttribute('align', 'right'); cell4.setAttribute('align', 'right');
if (object.type == 'switch') { if (object.type == 'switch' /*&& object.type_ext != "switch_program"*/) {
row.deleteCell(2); row.deleteCell(2);
row.deleteCell(1); row.deleteCell(1);
cell1.setAttribute('colspan', '3'); cell1.setAttribute('colspan', '3');
cell4.innerHTML = "<div id='"+object.id+"'><input id='switch-"+object.id+"' name='"+object.id+"' class='switch switch-btn' type='checkbox' onclick='update(this);'><label for='switch-"+object.id+"'></label></div>"; cell4.innerHTML = "<div id='"+object.id+"'><input id='switch-"+object.id+"' name='"+object.id+"' class='switch switch-btn' type='checkbox' onclick='update(this);'><label for='switch-"+object.id+"'></label></div>";
setButton(object.id, object.state); setButton(object.id, object.state);
} else if (object.type == 'switch_program') { /* //Removing light program, too much for simple interface
} else if (object.type == 'switch' && object.type_ext == 'switch_program') {
row.deleteCell(2); row.deleteCell(2);
cell2.setAttribute('colspan', '2'); cell2.setAttribute('colspan', '2');
//cell2.setAttribute('width', '100%'); //cell2.setAttribute('width', '100%');
@ -364,6 +369,7 @@
} }
} catch (e) {} } catch (e) {}
setButton(object.id, object.state); setButton(object.id, object.state);
*/
} else if (object.type == 'value') { } else if (object.type == 'value') {
row.deleteCell(2); row.deleteCell(2);
row.deleteCell(1); row.deleteCell(1);
@ -414,19 +420,29 @@
switch (source.getAttribute("type")) { switch (source.getAttribute("type")) {
case "range": case "range":
cmd.parameter = source.id.substr(7); // remove 'slider_' if ( source.id.includes("SWG") ) {
cmd.value = source.value; cmd.uri = source.id.substr(7)+"/percent/set";
cmd.value = source.value;
} else {
cmd.uri = source.id.substr(7)+"/setpoint/set";
//cmd.parameter = source.id.substr(7); // remove 'slider_'
cmd.value = source.value;
}
break; break;
case "checkbox": case "checkbox":
cmd.uri = source.id.substr(7)+"/set";
cmd.value = source.checked?"1":"0";
//name = source.id.substr(11); //remove 'btn-toggle-'' //name = source.id.substr(11); //remove 'btn-toggle-''
//state = source.checked?"on":"off"; //state = source.checked?"on":"off";
cmd.command = source.id.substr(7); //cmd.command = source.id.substr(7);
break; break;
default: // type is null because it's a selector default: // type is null because it's a selector
cmd.uri = source.id.substr(9)+"/program/set";
cmd.button = source.id.substr(9);
//name = source.id.substr(9); //remove 'selector_'' //name = source.id.substr(9); //remove 'selector_''
cmd.parameter = 'LIGHT_MODE'; //cmd.parameter = 'LIGHT_MODE';
cmd.value = source.value; cmd.value = source.value;
cmd.button = source.id.substr(9); // remove 'selector_' //cmd.button = source.id.substr(9); // remove 'selector_'
break; break;
} }
//console.log(source); //console.log(source);
@ -564,7 +580,8 @@
function get_devices() { function get_devices() {
var msg = { var msg = {
command: "GET_DEVICES" //command: "GET_DEVICES"
uri: "devices"
}; };
socket_di.send(JSON.stringify(msg)); socket_di.send(JSON.stringify(msg));
} }