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
#
# make // standard everything
# make debug // Give standard binary just with debugging
# make aqdebug // Compile with extra aqualink debug information like timings
# make slog // Serial logger
# make <other> // not documenting
#
# Valid flags for AQ_FLAGS
#AQ_DEBUG = true
AQ_RS16 = true
AQ_PDA = true
AQ_ONETOUCH = true
AQ_IAQTOUCH = true
#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
CC = gcc
#LIBS := -lpthread -lm
LIBS := -l pthread -l m
#LIBS := -lpthread -lwebsockets
#LIBS := -l pthread -l m -static # Take out -static, just for dev
# debug of not
#DBG = -g -O0 -fsanitize=address
#GCCFLAGS = -Wall -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
# Standard compile flags
GCCFLAGS = -Wall -O3
#GCCFLAGS = -O3
#GCCFLAGS = -Wall -O3 -Wextra
#GCCFLAGS = -Wall -O3
#GCCFLAGS = -Wall
#GCCFLAGS = -Wl,--gc-sections,--print-gc-sections
#GCCFLAGS = -Wall -O3 -ffunction-sections -fdata-sections
#CFLAGS = -Wall -g $(LIBS)
#CFLAGS = -Wall -g $(LIBS) -std=gnu11
#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
# Standard debug flags
DGCCFLAGS = -Wall -O0 -g
# Aqualink Debug flags
#DBGFLAGS = -g -O0 -Wall -fsanitize=address -D AQ_DEBUG -D AQ_TM_DEBUG
DBGFLAGS = -g -O0 -Wall -D AQ_DEBUG -D AQ_TM_DEBUG
# Mongoose flags
MGFLAGS = -D MG_DISABLE_MD5 -D MG_DISABLE_HTTP_DIGEST_AUTH -D MG_DISABLE_MD5 -D MG_DISABLE_JSON_RPC
# Add inputs and outputs from these tool invocations to the build variables
# 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 \
@ -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\
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)
SRCS := $(SRCS) pda.c pda_menu.c pda_aq_programmer.c
CFLAGS := $(CFLAGS) -D AQ_PDA
AQ_FLAGS := $(AQ_FLAGS) -D AQ_PDA
endif
ifeq ($(AQ_ONETOUCH), true)
SRCS := $(SRCS) onetouch.c onetouch_aq_programmer.c
CFLAGS := $(CFLAGS) -D AQ_ONETOUCH
AQ_FLAGS := $(AQ_FLAGS) -D AQ_ONETOUCH
endif
ifeq ($(AQ_IAQTOUCH), true)
SRCS := $(SRCS) iaqtouch.c iaqtouch_aq_programmer.c
CFLAGS := $(CFLAGS) -D AQ_IAQTOUCH
AQ_FLAGS := $(AQ_FLAGS) -D AQ_IAQTOUCH
endif
ifeq ($(AQ_RS16), true)
CFLAGS := $(CFLAGS) -D AQ_RS16
AQ_FLAGS := $(AQ_FLAGS) -D AQ_RS16
endif
ifeq ($(AQ_MEMCMP), true)
CFLAGS := $(CFLAGS) -D AQ_MEMCMP
AQ_FLAGS := $(AQ_FLAGS) -D AQ_MEMCMP
endif
ifeq ($(AQ_DEBUG), true)
DEBUG=true
endif
# 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
# Put all flags together.
CFLAGS = $(GCCFLAGS) $(AQ_FLAGS) $(MGFLAGS)
DFLAGS = $(DGCCFLAGS) $(AQ_FLAGS) $(MGFLAGS)
DBG_CFLAGS = $(DBGFLAGS) $(AQ_FLAGS) $(MGFLAGS)
# 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
LR_SRC = log_reader.c aq_serial.c utils.c packetLogger.c
PL_EXSRC = aq_serial.c
@ -89,6 +95,7 @@ PL_EXOBJ = aq_serial_player.o
PL_SRC := $(filter-out aq_serial.c, $(SRCS))
OBJS = $(SRCS:.c=.o)
DBG_OBJS = $(DBG_SRC:.c=.o)
SL_OBJS = $(SL_SRC:.c=.o)
LR_OBJS = $(LR_SRC:.c=.o)
@ -99,27 +106,45 @@ MAIN = ./release/aqualinkd
SLOG = ./release/serial_logger
LOGR = ./release/log_reader
PLAY = ./release/aqualinkd-player
DEBG = ./release/aqualinkd-debug
all: $(MAIN)
@echo: $(MAIN) have been compiled
all: $(MAIN)
$(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)
$(CC) $(CFLAGS) $(INCLUDES) -o $(MAIN) $(OBJS) $(LFLAGS) $(LIBS)
$(CC) $(CFLAGS) $(INCLUDES) -o $(MAIN) $(OBJS) $(LIBS)
$(info $(MAIN) has been compiled)
slog: $(SLOG)
@echo: $(SLOG) have been compiled
$(info $(SLOG) has been compiled)
$(SLOG): CFLAGS := $(CFLAGS) -D SERIAL_LOGGER
$(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)
@echo: $(LOGR) have been compiled
$(info $(LOGR) has been compiled)
$(LOGR): $(LR_OBJS)
$(CC) $(CFLAGS) $(INCLUDES) -o $(LOGR) $(LR_OBJS)
player: $(PLAY)
@echo: $(PLAY) have been compiled
$(info $(PLAY) has been compiled)
$(PL_EXOBJ): $(PL_EXSRC)
$(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)
$(CC) $(CFLAGS) $(INCLUDES) -o $(PLAY) $(PL_OBJS) $(PL_EXOBJ)
# Fog github publishing
.PHONY: git
git: clean $(MAIN) $(SLOG)
./release/git_version.sh
@ -141,8 +167,8 @@ git: clean $(MAIN) $(SLOG)
.PHONY: clean
clean:
$(RM) *.o *~ $(MAIN) $(MAIN_U) $(PLAY) $(PL_EXOBJ)
$(RM) $(wildcard *.o) $(wildcard *~) $(MAIN) $(MAIN_U) $(PLAY) $(PL_EXOBJ) $(LOGR) $(PLAY)
$(RM) *.o *~ $(MAIN) $(MAIN_U) $(PLAY) $(PL_EXOBJ) $(DEBG)
$(RM) $(wildcard *.o) $(wildcard *~) $(MAIN) $(MAIN_U) $(PLAY) $(PL_EXOBJ) $(LOGR) $(PLAY) $(DEBG)
depend: $(SRCS)
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
* 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)
* 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.
* 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.
* Fixed RS-4 bug.
* Increased timeout for startup probe
* Fixed RS-4 panel bug.
* 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>
* Extensive work to reduce CPU cycles and unnesessary logic.
* 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
} program_type;
struct programmingThreadCtrl {
pthread_t thread_id;
//void *thread_args;

View File

@ -33,7 +33,10 @@
//#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
@ -306,8 +309,75 @@ Open and Initialize the serial communications port to the Aqualink RS8 device.
Arg is tty or port designation string
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)
{
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 DATABITS = CS8;
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
_blocking_mode = blocking;
//int fd = open(tty, O_RDWR | O_NOCTTY | O_NONBLOCK);
int fd = open(tty, O_RDWR | O_NOCTTY | O_NONBLOCK | O_NDELAY);
if (fd < 0) {
@ -323,13 +395,22 @@ int init_serial_port(const char* tty)
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);
fcntl(fd, F_SETFL, flags | O_NONBLOCK | O_NDELAY);
newtio.c_cc[VMIN]= 0;
newtio.c_cc[VTIME]= 1;
LOG(RSSD_LOG,LOG_DEBUG_SERIAL, "Set serial port %s to non blocking mode\n",tty);
if (_blocking_mode) {
// http://unixwiz.net/techtips/termios-vmin-vtime.html
// Not designed behaviour, but it's what we need.
fcntl(fd, F_SETFL, 0);
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
// set new port settings for canonical input processing
@ -341,11 +422,20 @@ int init_serial_port(const char* tty)
tcflush(fd, TCIFLUSH);
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;
}
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 */
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.
// 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
@ -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)
{
if (_aqconfig_.readahead_b4_write) {
unsigned char byte;
int r;
//int j=0;
do {
//j++;
r = read(fd, &byte, 1);
//printf("*** Peek Read %d 0x%02hhx ***\n",r,byte);
if (r==1 && byte != 0x00) {
LOG(RSSD_LOG,LOG_ERR, "SERIOUS ERROR on RS485, AqualinkD was too slow in replying to message! (please check OS for performance issues)\n");
return;
}
} while (r==1 && byte==0x00);
}
if (_blocking_mode) {
write(fd, packet, length);
} else {
if (_aqconfig_.readahead_b4_write) {
unsigned char byte;
int bytesRead;
// int j=0;
do {
// j++;
bytesRead = read(fd, &byte, 1);
// printf("*** Peek Read %d 0x%02hhx ***\n",r,byte);
if (bytesRead == 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;
for (i=0; i<length; i += nwrite) {
nwrite = write(fd, packet + i, length - i);
if (nwrite < 0)
LOG(RSSD_LOG,LOG_ERR, "write to serial port failed\n");
}
/*
#ifdef AQ_DEBUG
// Need to take this out for release
if ( getLogLevel(RSSD_LOG) >= LOG_DEBUG) {
debuglogPacket(&packet[1], length-2);
}
#endif
*/
return;
}
} while (bytesRead == 1 && byte == 0x00);
}
int nwrite, i;
for (i = 0; i < length; i += nwrite) {
nwrite = write(fd, packet + i, length - i);
if (nwrite < 0)
LOG(RSSD_LOG, LOG_ERR, "write to serial port failed\n");
}
} // _blockine_mode
/*
#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) {
// Packet is padded with 0x00, so discard for logging
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) {
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 &&
jandyPacketStarted == false &&

View File

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

View File

@ -8,7 +8,7 @@
#include "aq_programmer.h"
#include "aq_panel.h"
#define DEFAULT_MG_NET_WAIT 2
#define DEFAULT_POLL_SPEED 2
#define TIME_CHECK_INTERVAL 3600
#define ACCEPTABLE_TIME_DIFF 120
@ -19,6 +19,10 @@
#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
/*

View File

@ -49,29 +49,41 @@
#include "iaqtouch_aq_programmer.h"
#include "version.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"
//#define AQ_DEBUG_TIME_ACK
#endif
*/
//#define DEFAULT_CONFIG_FILE "./aqualinkd.conf"
static volatile bool _keepRunning = true;
//static struct aqconfig _aqconfig_;
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
void main_loop();
void intHandler(int dummy)
{
_keepRunning = false;
LOG(AQUA_LOG,LOG_NOTICE, "Stopping!");
if (dummy){}// stop compile warnings
LOG(AQUA_LOG,LOG_NOTICE, "Stopping!\n");
//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()
@ -307,11 +319,11 @@ void _processMessage(char *message, bool reset)
_aqualink_data.frz_protect_state = OFF;
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
}
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"
if ((msg_loop & MSG_SWG) != MSG_SWG && _aqualink_data.aqbuttons[PUMP_INDEX].led->state == 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 ( (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 ) {
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)
_aqualink_data.aqbuttons[13].led->state = OFF;
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);
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);
}
@ -911,6 +927,10 @@ int main(int argc, char *argv[])
_aqualink_data.num_pumps = 0;
_aqualink_data.num_lights = 0;
#ifdef AQ_TM_DEBUG
addDebugLogMask(DBGT_LOG);
init_aqd_timer(); // Must clear timers.
#endif
// Any debug logging masks
//addDebugLogMask(IAQT_LOG);
//addDebugLogMask(ONET_LOG);
@ -1002,8 +1022,8 @@ int main(int argc, char *argv[])
#if defined AQ_ONETOUCH || defined AQ_IAQTOUCH
if (_aqconfig_.extended_device_id != 0x00) {
if (_aqconfig_.extended_device_id >= 0x30 && _aqconfig_.extended_device_id <= 0x33 ||
_aqconfig_.extended_device_id >= 0x40 && _aqconfig_.extended_device_id <= 0x43) {
if ( (_aqconfig_.extended_device_id >= 0x30 && _aqconfig_.extended_device_id <= 0x33) ||
(_aqconfig_.extended_device_id >= 0x40 && _aqconfig_.extended_device_id <= 0x43) ) {
// We are good
} 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);
@ -1100,8 +1120,28 @@ int main(int argc, char *argv[])
if (_aqconfig_.readahead_b4_write == true)
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)
LOG(AQUA_LOG,LOG_NOTICE, "Network Poll Speed = %d\n", _aqconfig_.net_poll_wait);
if (_aqconfig_.rs_poll_speed != DEFAULT_POLL_SPEED)
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 < _aqualink_data.total_buttons; i++)
@ -1162,10 +1202,12 @@ void caculate_ack_packet(int rs_fd, unsigned char *packet_buffer, emulation_type
switch (source) {
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));
//DEBUG_TIMER_STOP(_rs_packet_timer,AQUA_LOG,"AllButton Emulation type Processed packet in");
break;
#ifdef AQ_ONETOUCH
case ONETOUCH:
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;
#endif
#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);
rem_iaqt_control_cmd(cmd);
}
//DEBUG_TIMER_STOP(_rs_packet_timer,AQUA_LOG,"AquaTouch Emulation type Processed packet in");
break;
#endif
#ifdef AQ_PDA
@ -1188,20 +1231,24 @@ void caculate_ack_packet(int rs_fd, unsigned char *packet_buffer, emulation_type
} else {
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;
#endif
default:
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;
}
#ifdef AQ_DEBUG_TIME_ACK
/*
#ifdef AQ_TM_DEBUG
static struct timespec now;
static struct timespec elapsed;
clock_gettime(CLOCK_REALTIME, &now);
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
*/
}
/*
@ -1364,9 +1411,18 @@ void main_loop()
signal(SIGINT, intHandler);
signal(SIGTERM, intHandler);
signal(SIGQUIT, intHandler);
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);
#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.
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);
} 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);
} 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);
return;
}
@ -1484,11 +1540,11 @@ void main_loop()
else if (packet_length <= 0) {
blank_read++;
//printf("Blank Reads %d\n",blank_read);
delay(200);
delay(2);
}
else if (packet_length > 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) {
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
stopPacketLogger();
close_serial_port(rs_fd);
mg_mgr_free(&mgr);
//mg_mgr_free(&mgr);
stop_net_services(&mgr);
return;
}
}
@ -1515,14 +1572,16 @@ void main_loop()
*
*/
//int max_blank_read = 0;
_aqconfig_.readahead_b4_write = read_ahead;
LOG(AQUA_LOG,LOG_NOTICE, "Starting communication with Control Panel\n");
int blank_read_reconnect = MAX_ZERO_READ_BEFORE_RECONNECT;
// Not the best way to do this, but ok for moment
if (_aqconfig_.net_poll_wait <= 1)
blank_read_reconnect = MAX_ZERO_READ_BEFORE_RECONNECT * 10;
//if (_aqconfig_.net_poll_wait <= 1)
// blank_read_reconnect = MAX_ZERO_READ_BEFORE_RECONNECT;
blank_read = 0;
// OK, Now go into infinate loop
@ -1531,6 +1590,7 @@ void main_loop()
//printf("%d ",blank_read);
while ((rs_fd < 0 || blank_read >= blank_read_reconnect) && _keepRunning == true)
{
printf("rs_fd =% d\n",rs_fd);
if (rs_fd < 0)
{
// sleep(1);
@ -1545,8 +1605,13 @@ void main_loop()
{
LOG(AQUA_LOG,LOG_ERR, "Aqualink daemon looks like serial error, resetting.\n");
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;
}
@ -1563,14 +1628,16 @@ void main_loop()
}
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++;
}
else if (packet_length > 0)
{
#ifdef AQ_DEBUG_TIME_ACK
clock_gettime(CLOCK_REALTIME, &_rs_packet_readitme);
#endif
DEBUG_TIMER_START(&_rs_packet_timer);
blank_read = 0;
//changed = false;
@ -1586,17 +1653,21 @@ void main_loop()
else
#endif
caculate_ack_packet(rs_fd, packet_buffer, ALLBUTTON);
DEBUG_TIMER_STOP(_rs_packet_timer,AQUA_LOG,"AllButton Emulation Processed packet in");
}
#ifdef AQ_ONETOUCH
else if (packet_length > 0 && isONET_ENABLED && packet_buffer[PKT_DEST] == _aqconfig_.extended_device_id && getProtocolType(packet_buffer) == JANDY) {
_aqualink_data.updated = process_onetouch_packet(packet_buffer, packet_length, &_aqualink_data);
caculate_ack_packet(rs_fd, packet_buffer, ONETOUCH);
DEBUG_TIMER_STOP(_rs_packet_timer,AQUA_LOG,"OneTouch Emulation Processed packet in");
}
#endif
#ifdef AQ_IAQTOUCH
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);
caculate_ack_packet(rs_fd, packet_buffer, IAQTOUCH);
DEBUG_TIMER_STOP(_rs_packet_timer,AQUA_LOG,"AquaTouch Emulation Processed packet in");
}
#endif
else if (packet_length > 0 && _aqconfig_.read_all_devices == true)
@ -1644,19 +1715,24 @@ void main_loop()
//broadcast_aqualinkstate(mgr.active_connections);
_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) {
broadcast_aqualinkstate(mgr.active_connections);
_aqualink_data.updated = false;
//_aqualink_data.updated = false;
}
}
//mg_mgr_poll(&mgr, 10);
//mg_mgr_poll(&mgr, 5);
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.
//mg_mgr_poll(&mgr, packet_length>0?0:_aqconfig_.net_poll_wait); // Don;t wait if we read something.
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);
// Any unactioned commands
@ -1671,20 +1747,22 @@ void main_loop()
}
}
//tcdrain(rs_fd); // Make sure buffer has been sent.
//delay(10);
}
//if (_aqconfig_.debug_RSProtocol_packets) stopPacketLogger();
stopPacketLogger();
// Stop network
stop_net_services(&mgr);
// Reset and close the port.
close_serial_port(rs_fd);
// Clear webbrowser
mg_mgr_free(&mgr);
//mg_mgr_free(&mgr);
// NSF need to run through config memory and clean up.
LOG(AQUA_LOG,LOG_NOTICE, "Exit!\n");
exit(EXIT_FAILURE);
}

View File

@ -123,7 +123,8 @@ void init_parameters (struct aqconfig * parms)
parms->log_raw_RS_bytes = false;
parms->readahead_b4_write = false;
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);
}
@ -517,7 +518,14 @@ bool setConfigValue(struct aqualinkdata *aqdata, char *param, char *value) {
_aqconfig_.sync_panel_time = text2bool(value);
rtn=true;
} 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;
}

View File

@ -73,7 +73,8 @@ struct aqconfig
bool readahead_b4_write;
bool mqtt_timed_update;
bool sync_panel_time;
int net_poll_wait;
int rs_poll_speed;
bool thread_netservices;
};
#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->swg_percent = 101;
}
return true;
}
// 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) {
int i;
//int i;
struct iaqt_page_button *buttons;
// NSF Need to merge this from iaqtFindButtonByLabel function
@ -398,17 +398,7 @@ void passDeviceStatusPage(struct aqualinkdata *aq_data)
pump = NULL;
}
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.
} else if (rsm_strcmp(_deviceStatus[i],"Chemlink") == 0) {
if (rsm_strcmp(_deviceStatus[i],"Chemlink") == 0) {
/* Info: = Chemlink 1
Info: = ORP 750/PH 7.0 */
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]);
}
}
#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
}
@ -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)
{
static int cnt = 0;
char buff[1024];
//char buff[1024];
if (packet[PKT_CMD] == CMD_IAQ_PAGE_START) {
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
if (packet[3] == 0x30) {
// Load status page every 1000 messages
//if (cnt++ > 50 && in_iaqt_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 ) {
if (cnt++ > REQUEST_STATUS_POLL_COUNT && in_programming_mode(aq_data) == false ) {
iaqt_queue_cmd(KEY_IAQTCH_STATUS);
//aq_programmer(AQ_GET_IAQTOUCH_VSP_ASSIGNMENT, NULL, aq_data);
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;
}
@ -592,7 +592,7 @@ bool process_iaqtouch_packet(unsigned char *packet, int length, struct aqualinkd
_lastMsgType = packet[PKT_CMD];
debuglogPacket(IAQT_LOG ,packet, length);
//debuglogPacket(IAQT_LOG ,packet, length);
//beautifyPacket(buff, packet, length);
//LOG(IAQT_LOG,LOG_DEBUG, "%s", buff);

View File

@ -31,6 +31,7 @@
#include "aq_panel.h"
#include "config.h"
#include "devices_jandy.h"
#include "packetLogger.h"
// 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");
*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;
}
@ -145,9 +154,12 @@ bool waitfor_iaqt_ctrl_queue2empty()
int i=0;
while ( (_iaqt_control_cmd_len >0 ) && ( i++ < 20) ) {
LOG(IAQT_LOG,LOG_DEBUG, "Waiting for commandset to send\n");
delay(50);
}
LOG(IAQT_LOG,LOG_DEBUG, "Wait for commandset over!\n");
if (_iaqt_control_cmd_len > 0 ) {
LOG(IAQT_LOG,LOG_WARNING, "iAQ Touch Send control command Queue did not empty, timeout\n");
return false;
@ -167,11 +179,13 @@ unsigned const char waitfor_iaqt_nextPage(struct aqualinkdata *aq_data) {
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);
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);
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.
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);
//printf("\n");
//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)
return;
return false;
_iaqt_control_cmd[0] = DEV_MASTER;
_iaqt_control_cmd[1] = 0x24;
_iaqt_control_cmd[2] = 0x31;
_iaqt_control_cmd_len = char2iaqtRSset(&_iaqt_control_cmd[3], str, strlen(str));
// Need to bad time for some reason not yet known
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|
// From position 11 (8 without pre) add 0x30|0x32|0x00
_iaqt_control_cmd[++_iaqt_control_cmd_len] = 0x30;
_iaqt_control_cmd[++_iaqt_control_cmd_len] = 0x32;
_iaqt_control_cmd[++_iaqt_control_cmd_len] = 0x00;
_iaqt_control_cmd_len += 3;
_iaqt_control_cmd[9] = 0x30;
_iaqt_control_cmd[10] = 0x32;
_iaqt_control_cmd[11] = 0x00;
}
// 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++)
@ -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.
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);
f_end:
//goto_iaqt_page(IAQ_PAGE_HOME, aq_data);
// Go to status page on startup to read devices
goto_iaqt_page(IAQ_PAGE_STATUS, aq_data);
f_end:
goto_iaqt_page(IAQ_PAGE_HOME, aq_data);
cleanAndTerminateThread(threadCtrl);
// 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;
}
// THIS IS NOT FINISHED.
void *get_aqualink_iaqtouch_aux_labels( void *ptr )
{
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 06| Aux6 Aux6 No
* Info: Table Messages 07| Aux7 Aux7 No
*
* Info: Table Messages ??| Aux B7 Aux B7 No
*/
const char *buf;
int aux;
@ -624,9 +648,10 @@ void *get_aqualink_iaqtouch_aux_labels( void *ptr )
for(i=1; i < PANEL_SIZE(); i++)
{
buf = iaqtGetTableInfoLine(i);
LOG(IAQT_LOG,LOG_INFO, "From Messages %.2d| %s\n",i,buf);
//printf("**** BUF '%s'\n",aux,buf);
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:
@ -915,9 +940,9 @@ void *set_aqualink_iaqtouch_time( void *ptr )
struct aqualinkdata *aq_data = threadCtrl->aq_data;
struct iaqt_page_button *button;
char buf[20];
int len;
//int len;
int i;
bool AM;
//bool AM;
waitForSingleThreadOrTerminate(threadCtrl, AQ_SET_IAQTOUCH_SET_TIME);
@ -945,9 +970,13 @@ void *set_aqualink_iaqtouch_time( void *ptr )
send_aqt_cmd(button->keycode);
waitfor_iaqt_queue2empty();
// Queue the date string
queue_iaqt_control_command_str(icct_setdate, buf);
LOG(IAQT_LOG,LOG_DEBUG, "Set date to %s\n",buf);
waitfor_iaqt_ctrl_queue2empty();
if ( queue_iaqt_control_command_str(icct_setdate, buf)) {
LOG(IAQT_LOG,LOG_NOTICE, "Set date to %s\n",buf);
waitfor_iaqt_ctrl_queue2empty();
} else {
LOG(IAQT_LOG,LOG_ERR, "Failed to queue commandset for setting date\n");
}
} else {
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
strftime(buf, 20, "%I:%M", result);
queue_iaqt_control_command_str(icct_settime, buf);
LOG(IAQT_LOG,LOG_DEBUG, "Set time to %s\n",buf);
waitfor_iaqt_ctrl_queue2empty();
if (queue_iaqt_control_command_str(icct_settime, buf)) {
LOG(IAQT_LOG,LOG_NOTICE, "Set time to %s\n",buf);
waitfor_iaqt_ctrl_queue2empty();
} else {
LOG(IAQT_LOG,LOG_ERR, "Failed to queue commandset for setting time\n");
}
f_end:

View File

@ -35,19 +35,21 @@
#include "aq_mqtt.h"
#include "devices_jandy.h"
#include "color_lights.h"
#include "debug_timer.h"
#ifdef AQ_PDA
#include "pda.h"
#endif
#ifdef AQ_DEBUG
/*
#if defined AQ_DEBUG || defined AQ_TM_DEBUG
#include "timespec_subtract.h"
//#define AQ_NET_TIMER
//#define AQ_TM_DEBUG
#endif
*/
//static struct aqconfig *_aqconfig_;
static struct aqualinkdata *_aqualink_data;
static char *_web_root;
//static char *_web_root;
static int _mqtt_exit_flag = false;
@ -64,49 +66,21 @@ void mqtt_broadcast_aqualinkstate(struct mg_connection *nc);
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 const char *s_http_port = "8080";
static struct mg_serve_http_opts _http_server_opts;
static void signal_handler(int sig_num) {
signal(sig_num, signal_handler); // Reinstantiate signal handler
s_signal_received = sig_num;
static void net_signal_handler(int 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) {
nc->flags |= MG_F_USER_2;
}
/*
static int is_websocket_RSraw(const struct mg_connection *nc) {
return nc->flags & MG_F_USER_2;
}
*/
static int is_mqtt(const struct mg_connection *nc) {
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);
}
void broadcast_aqualinkstate_error(struct mg_connection *nc, char *msg)
void _broadcast_aqualinkstate_error(struct mg_connection *nc, char *msg)
{
struct mg_connection *c;
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
}
void broadcast_aqualinkstate(struct mg_connection *nc)
void _broadcast_aqualinkstate(struct mg_connection *nc)
{
static int mqtt_count=0;
struct mg_connection *c;
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);
#ifdef AQ_MEMCMP
if ( memcmp(_aqualink_data, &_last_mqtt_aqualinkdata, sizeof(struct aqualinkdata) ) == 0) {
LOG(NET_LOG,LOG_NOTICE, "**********Structure buffs the same, ignoring request************\n");
DEBUG_TIMER_CLEAR(&tid);
return;
}
#endif
@ -185,6 +167,8 @@ void broadcast_aqualinkstate(struct mg_connection *nc)
memcpy(&_last_mqtt_aqualinkdata, _aqualink_data, sizeof(struct aqualinkdata));
#endif
DEBUG_TIMER_STOP(tid, NET_LOG, "broadcast_aqualinkstate() completed, took ");
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.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);
else
_aqualink_data->unactioned.requested = 0;
@ -771,7 +755,7 @@ uriAtype action_URI(netRequest from, const char *URI, int uri_length, float valu
return uBad;
}
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);
else
_aqualink_data->unactioned.requested = 0;
@ -938,8 +922,12 @@ uriAtype action_URI(netRequest from, const char *URI, int uri_length, float valu
return rtn;
}
void action_mqtt_message(struct mg_connection *nc, struct mg_mqtt_message *msg) {
char *rtnmsg;
#ifdef AQ_TM_DEBUG
int tid;
#endif
//unsigned int i;
//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.
@ -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);
DEBUG_TIMER_START(&tid);
//Need to do this in a better manor, but for present it's ok.
static char tmp[20];
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;
int offset = strlen(_aqconfig_.mqtt_aq_topic)+1;
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) {
LOG(NET_LOG,LOG_INFO, "Message body:\n'%.*s'\n", body->len, body->p);
// 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) {
char *msg = NULL;
// struct http_message *http_msg = (struct http_message *)ev_data;
#ifdef AQ_NET_TIMER
#ifdef AQ_TM_DEBUG
int tid;
int tid2;
#endif
DEBUG_TIMER_START(&tid);
//DEBUG_TIMER_START(&tid);
if (getLogLevel(NET_LOG) >= LOG_INFO) { // Simply for log message, check we are at
// this log level before running all this
// 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);
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);
@ -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 (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");
DEBUG_TIMER_START(&tid);
OLD_action_web_request(nc, http_msg);
DEBUG_TIMER_STOP(tid, NET_LOG, "action_web_request() serve Old stanza took");
} else {
DEBUG_TIMER_START(&tid);
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 {
char buf[50];
float value;
float value = 0;
DEBUG_TIMER_START(&tid);
// 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];
DEBUG_TIMER_START(&tid2);
build_device_JSON(_aqualink_data, message, JSON_BUFFER_SIZE, false);
DEBUG_TIMER_STOP(tid2, "action_web_request build_device_JSON took");
mg_send_head(nc, 200, strlen(message), CONTENT_JSON);
mg_send(nc, message, strlen(message));
int size = build_device_JSON(_aqualink_data, message, JSON_BUFFER_SIZE, false);
DEBUG_TIMER_STOP(tid2, NET_LOG, "action_web_request() build_device_JSON took");
mg_send_head(nc, 200, size, CONTENT_JSON);
mg_send(nc, message, size);
}
break;
case uHomebridge:
{
char message[JSON_BUFFER_SIZE];
build_device_JSON(_aqualink_data, message, JSON_BUFFER_SIZE, true);
mg_send_head(nc, 200, strlen(message), CONTENT_JSON);
mg_send(nc, message, strlen(message));
int size = build_device_JSON(_aqualink_data, message, JSON_BUFFER_SIZE, true);
mg_send_head(nc, 200, size, CONTENT_JSON);
mg_send(nc, message, size);
}
break;
case uStatus:
{
char message[JSON_BUFFER_SIZE];
DEBUG_TIMER_START(&tid2);
build_aqualink_status_JSON(_aqualink_data, message, JSON_BUFFER_SIZE);
DEBUG_TIMER_STOP(tid2, "action_web_request build_aqualink_status_JSON took");
mg_send_head(nc, 200, strlen(message), CONTENT_JSON);
mg_send(nc, message, strlen(message));
int size = build_aqualink_status_JSON(_aqualink_data, message, JSON_BUFFER_SIZE);
DEBUG_TIMER_STOP(tid2, NET_LOG, "action_web_request() build_aqualink_status_JSON took");
mg_send_head(nc, 200, size, CONTENT_JSON);
mg_send(nc, message, size);
}
break;
case uDynamicconf:
{
char message[JSON_BUFFER_SIZE];
DEBUG_TIMER_START(&tid2);
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(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));
}
sprintf(buf, "action_web_request serve api request '%.*s' took",http_msg->uri.len, http_msg->uri.p);
DEBUG_TIMER_STOP(tid, buf);
sprintf(buf, "action_web_request() request '%.*s' took",http_msg->uri.len, http_msg->uri.p);
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 *value = NULL;
char *msg = NULL;
#ifdef AQ_NET_TIMER
#ifdef AQ_TM_DEBUG
int tid;
#endif
#ifdef AQ_PDA
@ -1156,7 +1150,7 @@ void action_websocket_request(struct mg_connection *nc, struct websocket_message
DEBUG_TIMER_START(&tid);
char message[JSON_BUFFER_SIZE];
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);
}
break;
@ -1165,7 +1159,7 @@ void action_websocket_request(struct mg_connection *nc, struct websocket_message
DEBUG_TIMER_START(&tid);
char 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);
}
break;
@ -1231,7 +1225,7 @@ static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
struct http_message *http_msg;
struct websocket_message *ws_msg;
char aq_topic[30];
#ifdef AQ_NET_TIMER
#ifdef AQ_TM_DEBUG
int tid;
#endif
//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;
DEBUG_TIMER_START(&tid);
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");
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;
DEBUG_TIMER_START(&tid);
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;
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);
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) {
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) {
LOG(NET_LOG,LOG_ERR, "Failed to create MQTT listener to %s\n", _aqconfig_.mqtt_server);
} else {
int i;
//int i;
#ifdef AQ_MEMCMP
memset(&_last_mqtt_aqualinkdata, 0, sizeof (struct aqualinkdata));
#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_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;
_aqualink_data = aqdata;
//_aqconfig_ = aqconfig;
signal(SIGTERM, signal_handler);
signal(SIGINT, signal_handler);
signal(SIGTERM, net_signal_handler);
signal(SIGINT, net_signal_handler);
setvbuf(stdout, 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));
} else {
struct mg_serve_http_opts opts;
//struct mg_serve_http_opts opts;
//memset(&opts, 0, sizeof(opts)); // Reset all options to defaults
//opts.document_root = _web_root; // Serve files from the current directory
// LOG(NET_LOG,LOG_DEBUG, "Doc root=%s\n",opts.document_root);

View File

@ -16,6 +16,8 @@
//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);
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_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:
log_heater_setpoints(aq_data);
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);
}
}
#ifdef READ_SWG_FROM_EXTENDED_ID
} else if (rsm_strcmp(_menu[2],"AQUAPURE") == 0) {
/* Info: OneTouch Menu Line 0 = Equipment Status
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);
}
#endif
} else if (rsm_strcmp(_menu[2],"Chemlink") == 0) {
/* Info: OneTouch Menu Line 0 = Equipment Status
Info: OneTouch Menu Line 1 =

View File

@ -767,7 +767,7 @@ void *set_aqualink_onetouch_swg_percent( void *ptr )
int diff;
int i;
int len;
unsigned char direction;
unsigned char direction = KEY_ONET_UP;
waitForSingleThreadOrTerminate(threadCtrl, AQ_SET_ONETOUCH_SWG_PERCENT);
int val = atoi((char*)threadCtrl->thread_args);
@ -808,7 +808,7 @@ void *set_aqualink_onetouch_swg_percent( void *ptr )
i=0;
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);
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");
delay(50);
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;
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 {
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
{
char labelBuff[AQ_MSGLEN + 1];
char labelBuff[AQ_MSGLEN + 2];
strncpy(labelBuff, msg, AQ_MSGLEN + 1);
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_sub_topic = domoticz/out
#mqtt_aq_topic = aqualinkd
# MQTT will only post updated information, this option AqualinkD will re-post all MQTT information every ~5 minutes.
#mqtt_timed_update = no
# Please see forum for this, only set to yes when logging information to support
# new devices. Inflrmation will be written to /tmp/RS485.log
#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
#thread_netservices = yes
#rs_poll_speed = -1
# 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
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
cp $BUILD/$BIN $BINLocation/$BIN
cp $BUILD/$SRV $SRVLocation/$SRV
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
cp $BUILD/$CFG $CFGLocation/$CFG
fi
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
cp $BUILD/$DEF.defaults $DEFLocation/$DEF
fi
@ -70,7 +93,7 @@ if [ ! -d "$WEBLocation" ]; then
fi
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
else
cp -r $BUILD/../web/* $WEBLocation
@ -83,5 +106,7 @@ systemctl daemon-reload
if [ $SERVICE_EXISTS -eq 0 ]; then
echo "Starting daemon $SERVICE"
systemctl start $SERVICE
else
echo "Please edit $CFGLocation/$CFG, then start AqualinkD service"
fi

Binary file not shown.

View File

@ -73,7 +73,7 @@ bool _playback_file = false;
void intHandler(int dummy) {
_keepRunning = false;
logMessage(LOG_NOTICE, "Stopping!");
LOG(RSSD_LOG, LOG_NOTICE, "Stopping!");
if (_playback_file) // If we are reading file, loop is irevelent
exit(0);
}
@ -320,6 +320,7 @@ int main(int argc, char *argv[]) {
int logLevel = LOG_NOTICE;
bool rsRawDebug = false;
bool panleProbe = true;
bool rsSerialSpeedTest = false;
//bool playback_file = false;
//int logLevel;
@ -345,6 +346,7 @@ int main(int argc, char *argv[]) {
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-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, "\nie:\t%s /dev/ttyUSB0 -d -p 1000 -i 0x08 -i 0x0a\n\n", argv[0]);
return 1;
@ -372,6 +374,8 @@ int main(int argc, char *argv[]) {
rsRawDebug = true;
} else if (strcmp(argv[i], "-n") == 0) {
panleProbe = false;
} else if (strcmp(argv[i], "-s") == 0) {
rsSerialSpeedTest = true;
}
}
@ -380,7 +384,7 @@ int main(int argc, char *argv[]) {
if (_playback_file) {
rs_fd = open(argv[1], O_RDONLY | O_NOCTTY | O_NONBLOCK | O_NDELAY);
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]);
return -1;
}
@ -414,7 +418,7 @@ int main(int argc, char *argv[]) {
// Nothing read
} 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)
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*/) {
//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++) {
if (slog[i].ID == lastID) {
slog[i].inuse = true;
@ -477,6 +481,18 @@ int main(int argc, char *argv[]) {
}*/
// 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) {
@ -500,7 +516,7 @@ int main(int argc, char *argv[]) {
LOG(RSSD_LOG, LOG_NOTICE, "Jandy ID's found\n");
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" : "");
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",

86
utils.c
View File

@ -143,7 +143,8 @@ void displayLastSystemError (const char *on_what)
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 ();
}
}
@ -208,6 +209,43 @@ int text2elevel(char* level)
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)
{
time_t now;
@ -354,6 +392,7 @@ void addDebugLogMask(int16_t flag)
void _LOG(int16_t from, int msg_level, char * message);
/*
void logMessage(int msg_level, const char *format, ...)
{
if (msg_level > _log_level) {
@ -369,7 +408,7 @@ void logMessage(int msg_level, const char *format, ...)
_LOG(AQUA_LOG, msg_level, buffer);
}
*/
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;
@ -404,36 +443,9 @@ void _LOG(int16_t from, int msg_level, char * message)
message[i+1] = '\0';
}
switch (from) {
case NET_LOG:
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;
}
//strncpy(&message[9], logmask2name(from), 11); // Will give compiller warning as doesn;t realise we are copying into middle of string.
memcpy(&message[9], logmask2name(from), 11);
// Logging has not been setup yet, so STD error & syslog
if (_log_level == -1) {
fprintf (stderr, message);
@ -512,7 +524,7 @@ void daemonise (char *pidFile, void (*main_function) (void))
/* Check we are root */
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);
}
@ -523,7 +535,7 @@ void daemonise (char *pidFile, void (*main_function) (void))
//if (EWOULDBLOCK == errno)
//; // another instance is running
//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);
}
@ -541,12 +553,12 @@ void daemonise (char *pidFile, void (*main_function) (void))
fp = fopen (pidFile, "w");
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
fprintf(fp, "%d", process_id);
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
exit (EXIT_SUCCESS);
}

View File

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

View File

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

View File

@ -1485,6 +1485,8 @@
get_devices();
// Set another load 1 minute from now just incase the server hasn't got all the devices yet
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) {
document.getElementById("header").classList.remove("error");
@ -1523,6 +1525,17 @@
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) {
var _cmd = {};
_cmd.command = cmd;

View File

@ -278,7 +278,7 @@
for (var obj in data['devices']) {
if (document.getElementById(data['devices'][obj].id) == null) {
_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]);
}
}
@ -321,6 +321,10 @@
function createTile(object) {
if (object.name == 'NONE')
return;
if (typeof devices !== 'undefined' && devices.indexOf(object.id) < 0) {
return;
}
//if (ignore_devices.indexOf(object.id) >= 0)
// return;
var table = document.getElementById("deviceList");
@ -339,13 +343,14 @@
cell3.setAttribute('align', 'right');
//cell3.setAttribute('cellpadding', '0');
cell4.setAttribute('align', 'right');
if (object.type == 'switch') {
if (object.type == 'switch' /*&& object.type_ext != "switch_program"*/) {
row.deleteCell(2);
row.deleteCell(1);
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>";
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);
cell2.setAttribute('colspan', '2');
//cell2.setAttribute('width', '100%');
@ -364,6 +369,7 @@
}
} catch (e) {}
setButton(object.id, object.state);
*/
} else if (object.type == 'value') {
row.deleteCell(2);
row.deleteCell(1);
@ -414,19 +420,29 @@
switch (source.getAttribute("type")) {
case "range":
cmd.parameter = source.id.substr(7); // remove 'slider_'
cmd.value = source.value;
if ( source.id.includes("SWG") ) {
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;
case "checkbox":
cmd.uri = source.id.substr(7)+"/set";
cmd.value = source.checked?"1":"0";
//name = source.id.substr(11); //remove 'btn-toggle-''
//state = source.checked?"on":"off";
cmd.command = source.id.substr(7);
//cmd.command = source.id.substr(7);
break;
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_''
cmd.parameter = 'LIGHT_MODE';
//cmd.parameter = 'LIGHT_MODE';
cmd.value = source.value;
cmd.button = source.id.substr(9); // remove 'selector_'
//cmd.button = source.id.substr(9); // remove 'selector_'
break;
}
//console.log(source);
@ -564,7 +580,8 @@
function get_devices() {
var msg = {
command: "GET_DEVICES"
//command: "GET_DEVICES"
uri: "devices"
};
socket_di.send(JSON.stringify(msg));
}