mirror of https://github.com/sfeakes/AqualinkD.git
commit
a033fc3fbf
14
Makefile
14
Makefile
|
@ -14,7 +14,8 @@ AQ_PDA = true
|
|||
AQ_ONETOUCH = true
|
||||
AQ_IAQTOUCH = true
|
||||
AQ_MANAGER =true
|
||||
AQ_RS_EXTRA_OPTS = false
|
||||
#AQ_RS_EXTRA_OPTS = false
|
||||
#AQ_CONTAINER = false // this is for compiling for containers
|
||||
#AQ_MEMCMP = true // Not implimented correctly yet.
|
||||
|
||||
# Turn off threadded net services
|
||||
|
@ -75,7 +76,7 @@ endif
|
|||
# Main source files
|
||||
SRCS = aqualinkd.c utils.c config.c aq_serial.c aq_panel.c aq_programmer.c net_services.c json_messages.c rs_msg_utils.c\
|
||||
devices_jandy.c packetLogger.c devices_pentair.c color_lights.c serialadapter.c aq_timer.c aq_scheduler.c web_config.c\
|
||||
serial_logger.c mongoose.c timespec_subtract.c
|
||||
serial_logger.c mongoose.c simulator.c timespec_subtract.c
|
||||
|
||||
|
||||
AQ_FLAGS =
|
||||
|
@ -130,6 +131,7 @@ DBG_CFLAGS = $(DBGFLAGS) $(AQ_FLAGS) $(MGFLAGS)
|
|||
# Other sources.
|
||||
DBG_SRC = $(SRCS) debug_timer.c
|
||||
SL_SRC = serial_logger.c aq_serial.c utils.c packetLogger.c rs_msg_utils.c timespec_subtract.c
|
||||
#MG_SRC = mongoose.c
|
||||
|
||||
# Build durectories
|
||||
OBJ_DIR := ./build
|
||||
|
@ -140,7 +142,7 @@ SL_OBJ_DIR := $(OBJ_DIR)/slog
|
|||
OBJ_FILES := $(patsubst %.c,$(OBJ_DIR)/%.o,$(SRCS))
|
||||
DBG_OBJ_FILES := $(patsubst %.c,$(DBG_OBJ_DIR)/%.o,$(DBG_SRC))
|
||||
SL_OBJ_FILES := $(patsubst %.c,$(SL_OBJ_DIR)/%.o,$(SL_SRC))
|
||||
|
||||
#MG_OBJ_FILES := $(patsubst %.c,$(OBJ_DIR)/%.o,$(MG_SRC))
|
||||
|
||||
# define the executable file
|
||||
MAIN = ./release/aqualinkd
|
||||
|
@ -161,6 +163,12 @@ slog: $(SLOG)
|
|||
aqdebug: $(DEBG)
|
||||
$(info $(DEBG) has been compiled)
|
||||
|
||||
# Container, add container flag and compile
|
||||
container: CFLAGS := $(CFLAGS) -D AQ_CONTAINER
|
||||
container: $(MAIN) $(SLOG)
|
||||
$(info $(MAIN) has been compiled (** For Container use **))
|
||||
$(info $(SLOG) has been compiled (** For Container use **))
|
||||
|
||||
#debug, Just change compile flags and call MAIN
|
||||
debug: CFLAGS = $(DFLAGS)
|
||||
debug: $(MAIN) $(SLOG)
|
||||
|
|
26
README.md
26
README.md
|
@ -56,9 +56,10 @@ https://github.com/sfeakes/AqualinkD/wiki/Jandy-Aqualink-RS485-protocol
|
|||
</td></tr>
|
||||
</table>
|
||||
|
||||
### Simulator
|
||||
Designed to mimic AqualinkRS6 All Button keypad and (like the keypad) is used to fully configure the master control panel<br>
|
||||
<img src="extras/simulator.png?raw=true" width="550">
|
||||
### Simulators
|
||||
Designed to mimic AqualinkRS devices, used to fully configure the master control panel<br>
|
||||
<img src="extras/onetouch_sim.png?raw=true">
|
||||
<img src="extras/allbutton_sim.png?raw=true">
|
||||
|
||||
### In Apple Home app.
|
||||
<img src="extras/HomeKit2.png?raw=true" width="800"></img>
|
||||
|
@ -71,13 +72,26 @@ Designed to mimic AqualinkRS6 All Button keypad and (like the keypad) is used to
|
|||
## All Web interfaces.
|
||||
* http://aqualink.ip/ <- (Standard WEB UI
|
||||
* http://aqualink.ip/simple.html <- (Simple opion if you don't like the above)
|
||||
* http://aqualink.ip/simulator.html <- (RS8 All Button Control Panel simulator)
|
||||
* http://aqualink.ip/debug.html <- (Turn on/off debug/serial debug & download logs)
|
||||
* http://aqualink.ip/simulator.html <- (Displays all simulators in one page with tabs)
|
||||
* http://aqualink.ip/aqmanager.html <- (Manage AqualinkD configuration & runtime)
|
||||
* http://aqualink.ip/allbutton_sim.html <- (All Button Simulator)
|
||||
* http://aqualink.ip/onetouch_sim.html <- (One Touch Simulator)
|
||||
* http://aqualink.ip/aquapda_sim.html <- (PDA simulator)
|
||||
#<a name="release"></a>
|
||||
# ToDo (future release)
|
||||
* Allow selecting of pre-defined VSP programs (Aqualink Touch & OneTouch protocols.)
|
||||
* Add set time to OneTouch protocol.
|
||||
* Publish AqualinkD Management console. (Configure, Restart, run serial_logger) within AqualinkD.
|
||||
* Update AqualinkD Management console to manage configuration
|
||||
* Create iAqualink Touch Simulator
|
||||
|
||||
# Update in Release 2.3.4
|
||||
* Changes for Docker
|
||||
* Updated simulator code base and added new simulators for AllButton, OneTouch & PDA.
|
||||
* <aqualinkd.ip>/allbutton_sim.html
|
||||
* <aqualinkd.ip>/onetouch_sim.html
|
||||
* <aqualinkd.ip>/aquapda_sim.html
|
||||
* On PDA only panel AqualinkD has to share the same ID with the PDA simulator. There for AqualinkD will not respond to commands while simulator is active.
|
||||
* Now you can completley program the control panel with the simulators removing the need to have Jandy device.
|
||||
|
||||
# Update in Release 2.3.3
|
||||
* Introduced Aqualink Manager UI http://aqualink.ip/aqmanager.html
|
||||
|
|
|
@ -29,12 +29,14 @@
|
|||
#define LIGHT_MODE_BUFER PTHREAD_ARG
|
||||
|
||||
typedef enum emulation_type{
|
||||
SIM_NONE = -1,
|
||||
ALLBUTTON,
|
||||
RSSADAPTER,
|
||||
ONETOUCH,
|
||||
IAQTOUCH,
|
||||
AQUAPDA, // AQUAPALM and PDA are taken as specific type.
|
||||
JANDY_DEVICE // Very rarley used.
|
||||
JANDY_DEVICE, // Very rarley used.
|
||||
SIMULATOR
|
||||
} emulation_type;
|
||||
|
||||
typedef enum {
|
||||
|
|
|
@ -38,7 +38,11 @@ Example /etc/cron.d/aqualinkd
|
|||
*/
|
||||
|
||||
bool remount_root_ro(bool readonly) {
|
||||
// NSF Check if config is RO_ROOT set
|
||||
|
||||
#ifdef AQ_CONTAINER
|
||||
// In container this is pointless
|
||||
return false;
|
||||
#endif
|
||||
|
||||
if (readonly) {
|
||||
LOG(SCHD_LOG,LOG_INFO, "reMounting root RO\n");
|
||||
|
|
48
aq_serial.c
48
aq_serial.c
|
@ -336,30 +336,15 @@ int _init_serial_port(const char* tty, bool blocking, bool readahead);
|
|||
int init_serial_port(const char* tty)
|
||||
{
|
||||
#ifdef AQ_NO_THREAD_NETSERVICE
|
||||
if (_aqconfig_.rs_poll_speed < 0)
|
||||
return init_blocking_serial_port(_aqconfig_.serial_port);
|
||||
else if (_aqconfig_.readahead_b4_write)
|
||||
return init_readahead_serial_port(_aqconfig_.serial_port);
|
||||
else
|
||||
return init_serial_port(_aqconfig_.serial_port);
|
||||
#elif AQ_RS_EXTRA_OPTS
|
||||
if (_aqconfig_.readahead_b4_write)
|
||||
return init_readahead_serial_port(_aqconfig_.serial_port);
|
||||
else
|
||||
if (_aqconfig_.rs_poll_speed < 0) {
|
||||
return init_blocking_serial_port(_aqconfig_.serial_port);
|
||||
}
|
||||
#else
|
||||
return init_blocking_serial_port(_aqconfig_.serial_port);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#ifdef AQ_RS_EXTRA_OPTS
|
||||
int init_readahead_serial_port(const char* tty)
|
||||
{
|
||||
return _init_serial_port(tty, false, true);
|
||||
}
|
||||
#endif
|
||||
|
||||
int init_blocking_serial_port(const char* tty)
|
||||
{
|
||||
_blocking_fds = _init_serial_port(tty, true, false);
|
||||
|
@ -767,14 +752,6 @@ void send_packet(int fd, unsigned char *packet, int length)
|
|||
if (nwrite != length)
|
||||
LOG(RSSD_LOG, LOG_ERR, "write to serial port failed\n");
|
||||
} else {
|
||||
#ifdef AQ_RS_EXTRA_OPTS
|
||||
if (_aqconfig_.readahead_b4_write) {
|
||||
if (cleanOutSerial(fd, false) != 0x00) {
|
||||
LOG(RSSD_LOG, LOG_ERR, "ERROR on RS485, AqualinkD was too slow in replying to message! (please check for performance issues)\n");
|
||||
cleanOutSerial(fd, true);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
int nwrite, i;
|
||||
for (i = 0; i < length; i += nwrite) {
|
||||
nwrite = write(fd, packet + i, length - i);
|
||||
|
@ -1026,25 +1003,8 @@ int get_packet(int fd, unsigned char* packet)
|
|||
|
||||
// Clean out rest of buffer, make sure their is nothing else
|
||||
/* Doesn't work for shit due to probe message speed, need to come back and re-think
|
||||
if (_aqconfig_.readahead_b4_write) {
|
||||
if (endOfPacket == true) {
|
||||
do {
|
||||
bytesRead = read(fd, &byte, 1);
|
||||
//if (bytesRead==1) { LOG(RSSD_LOG,LOG_ERR, "Cleanout buffer read 0x%02hhx\n",byte); }
|
||||
if (bytesRead==1 && byte != 0x00) {
|
||||
LOG(RSSD_LOG,LOG_ERR, "SERIOUS ERROR on RS485, AqualinkD caught packet collision on bus, ignoring!\n");
|
||||
LOG(RSSD_LOG,LOG_ERR, "Error Cleanout read 0x%02hhx\n",byte);
|
||||
// Run the buffer out
|
||||
do {
|
||||
bytesRead = read(fd, &byte, 1);
|
||||
if (bytesRead==1) { LOG(RSSD_LOG,LOG_ERR, "Error Cleanout read 0x%02hhx\n",byte); }
|
||||
} while (bytesRead==1);
|
||||
return 0;
|
||||
}
|
||||
} while (bytesRead==1);
|
||||
}
|
||||
}
|
||||
*/
|
||||
*/
|
||||
|
||||
//LOG(RSSD_LOG,LOG_DEBUG, "Serial checksum, length %d got 0x%02hhx expected 0x%02hhx\n", index, packet[index-3], generate_checksum(packet, index));
|
||||
if (jandyPacketStarted) {
|
||||
if (check_jandy_checksum(packet, index) != true){
|
||||
|
|
|
@ -458,7 +458,7 @@ typedef enum {
|
|||
|
||||
int init_serial_port(const char* tty);
|
||||
int init_blocking_serial_port(const char* tty);
|
||||
int init_readahead_serial_port(const char* tty);
|
||||
//int init_readahead_serial_port(const char* tty);
|
||||
|
||||
void close_serial_port(int file_descriptor);
|
||||
void close_blocking_serial_port();
|
||||
|
|
21
aqualink.h
21
aqualink.h
|
@ -138,6 +138,16 @@ typedef enum pump_type {
|
|||
} pump_type;
|
||||
*/
|
||||
|
||||
/*
|
||||
typedef enum simulator_type {
|
||||
SIM_NONE,
|
||||
SIM_ALLB,
|
||||
SIM_ONET,
|
||||
SIM_PDA,
|
||||
SIM_IAQT
|
||||
} simulator_type;
|
||||
*/
|
||||
|
||||
#define PUMP_PRIMING -1
|
||||
#define PUMP_OFFLINE -2
|
||||
#define PUMP_ERROR -3
|
||||
|
@ -227,7 +237,16 @@ struct aqualinkdata
|
|||
//unsigned short total_ordered_buttons;
|
||||
unsigned char last_packet_type;
|
||||
int swg_delayed_percent;
|
||||
bool simulate_panel;
|
||||
//bool simulate_panel; // NSF remove in future
|
||||
unsigned char simulator_packet[AQ_MAXPKTLEN+1];
|
||||
bool simulator_packet_updated;
|
||||
int simulator_packet_length;
|
||||
|
||||
//bool simulator_active; // should be redundant with other two
|
||||
unsigned char simulator_id;
|
||||
//simulator_type simulator_active;
|
||||
emulation_type simulator_active;
|
||||
|
||||
bool aqManagerActive;
|
||||
int open_websockets;
|
||||
struct programmingthread active_thread;
|
||||
|
|
154
aqualinkd.c
154
aqualinkd.c
|
@ -50,6 +50,7 @@
|
|||
#include "version.h"
|
||||
#include "rs_msg_utils.h"
|
||||
#include "serialadapter.h"
|
||||
#include "simulator.h"
|
||||
#include "debug_timer.h"
|
||||
|
||||
#ifdef AQ_MANAGER
|
||||
|
@ -743,7 +744,8 @@ void _processMessage(char *message, bool reset)
|
|||
{
|
||||
LOG(AQRS_LOG,LOG_DEBUG_SERIAL, "Ignoring '%s'\n", msg);
|
||||
//_aqualink_data.display_message = msg;
|
||||
if (in_programming_mode(&_aqualink_data) == false && _aqualink_data.simulate_panel == false &&
|
||||
//if (in_programming_mode(&_aqualink_data) == false && _aqualink_data.simulate_panel == false &&
|
||||
if (in_programming_mode(&_aqualink_data) == false &&
|
||||
stristr(msg, "JANDY AquaLinkRS") == NULL &&
|
||||
//stristr(msg, "PUMP O") == NULL &&// Catch 'PUMP ON' and 'PUMP OFF' but not 'PUMP WILL TURN ON'
|
||||
strncasecmp(msg, "PUMP O", 6) != 0 &&// Catch 'PUMP ON' and 'PUMP OFF' but not 'PUMP WILL TURN ON'
|
||||
|
@ -1059,7 +1061,6 @@ int main(int argc, char *argv[])
|
|||
char defaultCfg[] = "./aqualinkd.conf";
|
||||
char *cfgFile;
|
||||
|
||||
|
||||
//printf ("TIMER = %d\n",TIMR_LOG);
|
||||
|
||||
#ifdef AQ_MEMCMP
|
||||
|
@ -1137,7 +1138,7 @@ int main(int argc, char *argv[])
|
|||
else if (strcmp(argv[i], "-rsrd") == 0)
|
||||
{
|
||||
_cmdln_lograwRS485 = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set this here, so it doesn;t get reset if the manager restarts the AqualinkD process.
|
||||
|
@ -1316,14 +1317,6 @@ int startup(char *self, char *cfgFile)
|
|||
if (READ_RSDEV_SWG && _aqconfig_.swg_zero_ignore != DEFAULT_SWG_ZERO_IGNORE_COUNT)
|
||||
LOG(AQUA_LOG,LOG_NOTICE, "Ignore SWG 0 msg count = %d\n", _aqconfig_.swg_zero_ignore);
|
||||
|
||||
|
||||
#ifdef AQ_RS_EXTRA_OPTS
|
||||
if (_aqconfig_.readahead_b4_write == true)
|
||||
LOG(AQUA_LOG,LOG_NOTICE, "Serial Read Ahead Write = %s\n", bool2text(_aqconfig_.readahead_b4_write));
|
||||
if (_aqconfig_.prioritize_ack == true)
|
||||
LOG(AQUA_LOG,LOG_NOTICE, "Serial Prioritize Ack = %s\n", bool2text(_aqconfig_.prioritize_ack));
|
||||
#endif
|
||||
|
||||
if (_aqconfig_.ftdi_low_latency == true)
|
||||
LOG(AQUA_LOG,LOG_NOTICE, "Serial FTDI low latency = %s\n", bool2text(_aqconfig_.ftdi_low_latency));
|
||||
|
||||
|
@ -1342,13 +1335,6 @@ int startup(char *self, char *cfgFile)
|
|||
LOG(AQUA_LOG,LOG_NOTICE, "RS Poll Speed = %d\n", _aqconfig_.rs_poll_speed);
|
||||
#endif
|
||||
|
||||
#if defined AQ_RS_EXTRA_OPTS && defined AQ_NO_THREAD_NETSERVICE
|
||||
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;
|
||||
}
|
||||
#endif
|
||||
|
||||
//for (i = 0; i < TOTAL_BUTONS; i++)
|
||||
for (i = 0; i < _aqualink_data.total_buttons; i++)
|
||||
{
|
||||
|
@ -1451,6 +1437,20 @@ void caculate_ack_packet(int rs_fd, unsigned char *packet_buffer, emulation_type
|
|||
//DEBUG_TIMER_STOP(_rs_packet_timer,AQUA_LOG,"PDA Emulation type Processed packet in");
|
||||
break;
|
||||
#endif
|
||||
case SIMULATOR:
|
||||
if (_aqualink_data.simulator_active == ALLBUTTON) {
|
||||
send_extended_ack(rs_fd, (packet_buffer[PKT_CMD]==CMD_MSG_LONG?ACK_SCREEN_BUSY_SCROLL:ACK_NORMAL), pop_simulator_cmd(packet_buffer[PKT_CMD]));
|
||||
} else if (_aqualink_data.simulator_active == ONETOUCH) {
|
||||
send_extended_ack(rs_fd, ACK_ONETOUCH, pop_simulator_cmd(packet_buffer[PKT_CMD]));
|
||||
} else if (_aqualink_data.simulator_active == IAQTOUCH) {
|
||||
LOG(SIM_LOG,LOG_WARNING, "IAQTOUCH not implimented yet!\n");
|
||||
} else if (_aqualink_data.simulator_active == AQUAPDA) {
|
||||
send_extended_ack(rs_fd, ACK_PDA, pop_simulator_cmd(packet_buffer[PKT_CMD]));
|
||||
} else {
|
||||
LOG(SIM_LOG,LOG_ERR, "No idea on this protocol (%d), not implimented!!!\n",_aqualink_data.simulator_active);
|
||||
}
|
||||
break;
|
||||
|
||||
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");
|
||||
|
@ -1507,7 +1507,7 @@ void main_loop()
|
|||
int blank_read_reconnect = MAX_ZERO_READ_BEFORE_RECONNECT_BLOCKING; // Will get reset if non blocking
|
||||
|
||||
sprintf(_aqualink_data.last_display_message, "%s", "Connecting to Control Panel");
|
||||
_aqualink_data.simulate_panel = false;
|
||||
//_aqualink_data.simulate_panel = false;
|
||||
_aqualink_data.active_thread.thread_id = 0;
|
||||
_aqualink_data.air_temp = TEMP_UNKNOWN;
|
||||
_aqualink_data.pool_temp = TEMP_UNKNOWN;
|
||||
|
@ -1528,6 +1528,8 @@ void main_loop()
|
|||
_aqualink_data.open_websockets = 0;
|
||||
_aqualink_data.ph = TEMP_UNKNOWN;
|
||||
_aqualink_data.orp = TEMP_UNKNOWN;
|
||||
_aqualink_data.simulator_id = NUL;
|
||||
_aqualink_data.simulator_active = SIM_NONE;
|
||||
|
||||
pthread_mutex_init(&_aqualink_data.active_thread.thread_mutex, NULL);
|
||||
pthread_cond_init(&_aqualink_data.active_thread.thread_cond, NULL);
|
||||
|
@ -1563,8 +1565,10 @@ void main_loop()
|
|||
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_ERR, "Error Aqualink setting serial port: %s\n", _aqconfig_.serial_port);
|
||||
#ifndef AQ_CONTAINER
|
||||
exit(EXIT_FAILURE);
|
||||
#endif
|
||||
}
|
||||
LOG(AQUA_LOG,LOG_NOTICE, "Listening to Aqualink RS8 on serial port: %s\n", _aqconfig_.serial_port);
|
||||
|
||||
|
@ -1634,16 +1638,15 @@ void main_loop()
|
|||
LOG(AQUA_LOG,LOG_NOTICE, "Waiting for Control Panel probe\n");
|
||||
i=0;
|
||||
|
||||
// Turn off read ahead while dealing with probes
|
||||
#ifdef AQ_RS_EXTRA_OPTS
|
||||
bool read_ahead = _aqconfig_.readahead_b4_write;
|
||||
_aqconfig_.readahead_b4_write = false;
|
||||
#endif
|
||||
// Loop until we get the probe messages, that means we didn;t start too soon after last shutdown.
|
||||
while ( (got_probe == false || got_probe_rssa == false || got_probe_extended == false ) && _keepRunning == true)
|
||||
{
|
||||
if (blank_read == blank_read_reconnect) {
|
||||
LOG(AQUA_LOG,LOG_ERR, "Nothing read on '%s', are you sure that's right?\n",_aqconfig_.serial_port);
|
||||
#ifdef AQ_CONTAINER
|
||||
// Reset blank reads here, we want to ignore TTY errors in container to keep it running
|
||||
blank_read = 1;
|
||||
#endif
|
||||
} else if (blank_read == blank_read_reconnect*2) {
|
||||
LOG(AQUA_LOG,LOG_ERR, "I'm done, exiting, please check '%s'\n",_aqconfig_.serial_port);
|
||||
stopPacketLogger();
|
||||
|
@ -1749,11 +1752,6 @@ void main_loop()
|
|||
*
|
||||
*/
|
||||
|
||||
//int max_blank_read = 0;
|
||||
#ifdef AQ_RS_EXTRA_OPTS
|
||||
_aqconfig_.readahead_b4_write = read_ahead;
|
||||
#endif
|
||||
|
||||
LOG(AQUA_LOG,LOG_NOTICE, "Starting communication with Control Panel\n");
|
||||
|
||||
// Not the best way to do this, but ok for moment
|
||||
|
@ -1819,7 +1817,6 @@ void main_loop()
|
|||
#ifdef AQ_NO_THREAD_NETSERVICE
|
||||
if (_aqconfig_.rs_poll_speed < 0) {
|
||||
#else
|
||||
//if (!_aqconfig_.readahead_b4_write) {
|
||||
if (serial_blockingmode() && (packet_length == AQSERR_READ || packet_length == AQSERR_TIMEOUT) ) {
|
||||
#endif
|
||||
LOG(AQUA_LOG,LOG_ERR, "Nothing read on blocking serial port\n");
|
||||
|
@ -1843,80 +1840,73 @@ void main_loop()
|
|||
blank_read = 0;
|
||||
//changed = false;
|
||||
|
||||
if (_aqualink_data.simulator_active != SIM_NONE) {
|
||||
// Check if we have a valid connection
|
||||
if ( _aqualink_data.simulator_id != NUL && packet_buffer[PKT_DEST] == _aqualink_data.simulator_id) {
|
||||
// Action comand and Send to web
|
||||
processSimulatorPacket(packet_buffer, packet_length, &_aqualink_data);
|
||||
caculate_ack_packet(rs_fd, packet_buffer, SIMULATOR);
|
||||
DEBUG_TIMER_STOP(_rs_packet_timer,AQUA_LOG,"Simulator Emulation Processed packet in");
|
||||
}
|
||||
else if ( _aqualink_data.simulator_id == NUL
|
||||
&& packet_buffer[PKT_CMD] == CMD_PROBE
|
||||
&& packet_buffer[PKT_DEST] != _aqconfig_.device_id // Check no conflicting id's
|
||||
#if defined AQ_ONETOUCH || defined AQ_IAQTOUCH
|
||||
&& packet_buffer[PKT_DEST] != _aqconfig_.extended_device_id // Check no conflicting id's
|
||||
#endif
|
||||
)
|
||||
{
|
||||
if (is_simulator_packet(&_aqualink_data, packet_buffer, packet_length)) {
|
||||
_aqualink_data.simulator_id = packet_buffer[PKT_DEST];
|
||||
// reply to probe
|
||||
LOG(SIM_LOG,LOG_NOTICE, "Got probe on '0x%02hhx', using for simulator ID\n",packet_buffer[PKT_DEST]);
|
||||
processSimulatorPacket(packet_buffer, packet_length, &_aqualink_data);
|
||||
caculate_ack_packet(rs_fd, packet_buffer, SIMULATOR);
|
||||
} else {
|
||||
LOG(SIM_LOG,LOG_INFO, "Got probe on '0x%02hhx' Still waiting for valid simulator probe\n",packet_buffer[PKT_DEST]);
|
||||
}
|
||||
DEBUG_TIMER_STOP(_rs_packet_timer,AQUA_LOG,"Simulator Emulation Processed packet in");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (packet_length > 0 && packet_buffer[PKT_DEST] == _aqconfig_.device_id && getProtocolType(packet_buffer) == JANDY)
|
||||
{
|
||||
if (getLogLevel(AQUA_LOG) >= LOG_DEBUG) {
|
||||
LOG(AQUA_LOG,LOG_DEBUG, "RS received packet of type %s length %d\n", get_packet_type(packet_buffer, packet_length), packet_length);
|
||||
logPacketRead(packet_buffer, packet_length);
|
||||
}
|
||||
#ifdef AQ_RS_EXTRA_OPTS
|
||||
// If we did not process the packet, above we need to record it for the caculate_ack_packet call.
|
||||
// Should find a better place to put this, but since prioritize_ack is expermental it's ok for now.
|
||||
// NSF We shouldn;t need to do the same for rssa / onetouch / iaqtouch and probably rssaadapter since they don;t queue commands & programming commands.
|
||||
if (_aqconfig_.prioritize_ack) {
|
||||
_aqualink_data.last_packet_type = packet_buffer[PKT_CMD];
|
||||
else
|
||||
#endif
|
||||
_aqualink_data.updated = process_packet(packet_buffer, packet_length);
|
||||
_aqualink_data.updated = process_packet(packet_buffer, packet_length);
|
||||
|
||||
#ifdef AQ_PDA
|
||||
if (isPDA_PANEL)
|
||||
caculate_ack_packet(rs_fd, packet_buffer, AQUAPDA);
|
||||
if (isPDA_PANEL) {
|
||||
// If we are in simulator mode, the sim has already send the ack
|
||||
if (_aqualink_data.simulator_active == SIM_NONE) {
|
||||
caculate_ack_packet(rs_fd, packet_buffer, AQUAPDA);
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
caculate_ack_packet(rs_fd, packet_buffer, ALLBUTTON);
|
||||
|
||||
#ifdef AQ_RS_EXTRA_OPTS
|
||||
if (_aqconfig_.prioritize_ack)
|
||||
_aqualink_data.updated = process_packet(packet_buffer, packet_length);
|
||||
#endif
|
||||
DEBUG_TIMER_STOP(_rs_packet_timer,AQUA_LOG,"AllButton Emulation Processed packet in");
|
||||
}
|
||||
else if (packet_length > 0 && isRSSA_ENABLED && packet_buffer[PKT_DEST] == _aqconfig_.rssa_device_id && getProtocolType(packet_buffer) == JANDY) {
|
||||
#ifdef AQ_RS_EXTRA_OPTS
|
||||
if (_aqconfig_.prioritize_ack) {
|
||||
caculate_ack_packet(rs_fd, packet_buffer, RSSADAPTER);
|
||||
_aqualink_data.updated = process_rssadapter_packet(packet_buffer, packet_length, &_aqualink_data);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
_aqualink_data.updated = process_rssadapter_packet(packet_buffer, packet_length, &_aqualink_data);
|
||||
caculate_ack_packet(rs_fd, packet_buffer, RSSADAPTER);
|
||||
}
|
||||
_aqualink_data.updated = process_rssadapter_packet(packet_buffer, packet_length, &_aqualink_data);
|
||||
caculate_ack_packet(rs_fd, packet_buffer, RSSADAPTER);
|
||||
DEBUG_TIMER_STOP(_rs_packet_timer,AQUA_LOG,"SerialAdapter Emulation Processed packet in");
|
||||
}
|
||||
#ifdef AQ_ONETOUCH
|
||||
else if (packet_length > 0 && isONET_ENABLED && packet_buffer[PKT_DEST] == _aqconfig_.extended_device_id && getProtocolType(packet_buffer) == JANDY) {
|
||||
#ifdef AQ_RS_EXTRA_OPTS
|
||||
if (_aqconfig_.prioritize_ack) {
|
||||
set_onetouch_lastmsg(packet_buffer[PKT_CMD]);
|
||||
caculate_ack_packet(rs_fd, packet_buffer, ONETOUCH);
|
||||
_aqualink_data.updated = process_onetouch_packet(packet_buffer, packet_length, &_aqualink_data);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
_aqualink_data.updated = process_onetouch_packet(packet_buffer, packet_length, &_aqualink_data);
|
||||
caculate_ack_packet(rs_fd, packet_buffer, ONETOUCH);
|
||||
}
|
||||
_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) {
|
||||
#ifdef AQ_RS_EXTRA_OPTS
|
||||
if (_aqconfig_.prioritize_ack) {
|
||||
set_iaqtouch_lastmsg(packet_buffer[PKT_CMD]);
|
||||
caculate_ack_packet(rs_fd, packet_buffer, IAQTOUCH);
|
||||
_aqualink_data.updated = process_iaqtouch_packet(packet_buffer, packet_length, &_aqualink_data);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
_aqualink_data.updated = process_iaqtouch_packet(packet_buffer, packet_length, &_aqualink_data);
|
||||
caculate_ack_packet(rs_fd, packet_buffer, IAQTOUCH);
|
||||
}
|
||||
_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
|
||||
|
|
17
config.c
17
config.c
|
@ -138,13 +138,6 @@ void init_parameters (struct aqconfig * parms)
|
|||
|
||||
parms->sync_panel_time = true;
|
||||
|
||||
|
||||
#ifdef AQ_RS_EXTRA_OPTS
|
||||
// Default parameters for threading and USB blocking
|
||||
parms->readahead_b4_write = false;
|
||||
parms->prioritize_ack = false;
|
||||
#endif
|
||||
|
||||
#ifdef AQ_NO_THREAD_NETSERVICE
|
||||
parms->rs_poll_speed = DEFAULT_POLL_SPEED;
|
||||
parms->thread_netservices = true;
|
||||
|
@ -153,7 +146,7 @@ void init_parameters (struct aqconfig * parms)
|
|||
parms->enable_scheduler = true;
|
||||
parms->ftdi_low_latency = true;
|
||||
parms->frame_delay = 0;
|
||||
|
||||
|
||||
generate_mqtt_id(parms->mqtt_ID, MQTT_ID_LEN);
|
||||
}
|
||||
|
||||
|
@ -589,14 +582,6 @@ bool setConfigValue(struct aqualinkdata *aqdata, char *param, char *value) {
|
|||
} else if (strncasecmp (param, "display_warnings_in_web", 23) == 0) {
|
||||
_aqconfig_.display_warnings_web = text2bool(value);
|
||||
rtn=true;
|
||||
#ifdef AQ_RS_EXTRA_OPTS
|
||||
} else if (strncasecmp (param, "serial_readahead_b4_write", 25) == 0) {
|
||||
_aqconfig_.readahead_b4_write = text2bool(value);
|
||||
rtn=true;
|
||||
} else if (strncasecmp (param, "prioritize_ack", 14) == 0) {
|
||||
_aqconfig_.prioritize_ack = text2bool(value);
|
||||
rtn=true;
|
||||
#endif
|
||||
} else if (strncasecmp (param, "mqtt_timed_update", 17) == 0) {
|
||||
_aqconfig_.mqtt_timed_update = text2bool(value);
|
||||
rtn=true;
|
||||
|
|
4
config.h
4
config.h
|
@ -54,7 +54,7 @@ struct aqconfig
|
|||
char *mqtt_server;
|
||||
char *mqtt_user;
|
||||
char *mqtt_passwd;
|
||||
char mqtt_ID[MQTT_ID_LEN];
|
||||
char mqtt_ID[MQTT_ID_LEN+1];
|
||||
int dzidx_air_temp;
|
||||
int dzidx_pool_water_temp;
|
||||
int dzidx_spa_water_temp;
|
||||
|
@ -85,10 +85,12 @@ struct aqconfig
|
|||
bool log_raw_bytes; // Read as bytes
|
||||
unsigned char RSSD_LOG_filter;
|
||||
//bool log_raw_RS_bytes;
|
||||
/*
|
||||
#ifdef AQ_RS_EXTRA_OPTS
|
||||
bool readahead_b4_write;
|
||||
bool prioritize_ack;
|
||||
#endif
|
||||
*/
|
||||
bool mqtt_timed_update;
|
||||
bool sync_panel_time;
|
||||
bool enable_scheduler;
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 38 KiB |
Binary file not shown.
After Width: | Height: | Size: 26 KiB |
|
@ -32,6 +32,7 @@
|
|||
#include "version.h"
|
||||
#include "aq_timer.h"
|
||||
#include "aq_programmer.h"
|
||||
#include "rs_msg_utils.h"
|
||||
|
||||
//#define test_message "{\"type\": \"status\",\"version\": \"8157 REV MMM\",\"date\": \"09/01/16 THU\",\"time\": \"1:16 PM\",\"temp_units\": \"F\",\"air_temp\": \"96\",\"pool_temp\": \"86\",\"spa_temp\": \" \",\"battery\": \"ok\",\"pool_htr_set_pnt\": \"85\",\"spa_htr_set_pnt\": \"99\",\"freeze_protection\": \"off\",\"frz_protect_set_pnt\": \"0\",\"leds\": {\"pump\": \"on\",\"spa\": \"off\",\"aux1\": \"off\",\"aux2\": \"off\",\"aux3\": \"off\",\"aux4\": \"off\",\"aux5\": \"off\",\"aux6\": \"off\",\"aux7\": \"off\",\"pool_heater\": \"off\",\"spa_heater\": \"off\",\"solar_heater\": \"off\"}}"
|
||||
//#define test_labels "{\"type\": \"aux_labels\",\"aux1_label\": \"Cleaner\",\"aux2_label\": \"Waterfall\",\"aux3_label\": \"Spa Blower\",\"aux4_label\": \"Pool Light\",\"aux5_label\": \"Spa Light\",\"aux6_label\": \"Unassigned\",\"aux7_label\": \"Unassigned\"}"
|
||||
|
@ -91,10 +92,12 @@ int build_logmsg_JSON(char *dest, int loglevel, const char *src, int dest_len, i
|
|||
|
||||
const char* _getStatus(struct aqualinkdata *aqdata, const char *blankmsg)
|
||||
{
|
||||
/*
|
||||
if (aqdata->active_thread.thread_id != 0 && !aqdata->simulate_panel) {
|
||||
//return JSON_PROGRAMMING;
|
||||
return programtypeDisplayName(aqdata->active_thread.ptype);
|
||||
}
|
||||
*/
|
||||
|
||||
//if (aqdata->last_message != NULL && stristr(aqdata->last_message, "SERVICE") != NULL ) {
|
||||
if (aqdata->service_mode_state == ON) {
|
||||
|
@ -516,6 +519,7 @@ int build_aqualink_aqmanager_JSON(struct aqualinkdata *aqdata, char* buffer, int
|
|||
length += logmaskjsonobject(PROG_LOG, buffer+length);
|
||||
length += logmaskjsonobject(DBGT_LOG, buffer+length);
|
||||
length += logmaskjsonobject(TIMR_LOG, buffer+length);
|
||||
length += logmaskjsonobject(SIM_LOG, buffer+length);
|
||||
if (buffer[length-1] == ',')
|
||||
length--;
|
||||
length += sprintf(buffer+length, "]");
|
||||
|
@ -709,6 +713,83 @@ int build_aux_labels_JSON(struct aqualinkdata *aqdata, char* buffer, int size)
|
|||
|
||||
//return strlen(buffer);
|
||||
}
|
||||
/*
|
||||
const char* emulationtype2name(emulation_type type) {
|
||||
switch (type) {
|
||||
case ALLBUTTON:
|
||||
return "allbutton";
|
||||
break;
|
||||
case RSSADAPTER:
|
||||
return "allbutton";
|
||||
break;
|
||||
case ONETOUCH:
|
||||
return "onetouch";
|
||||
break;
|
||||
case IAQTOUCH:
|
||||
return "iaqualinktouch";
|
||||
break;
|
||||
case AQUAPDA:
|
||||
return "aquapda";
|
||||
break;
|
||||
case JANDY_DEVICE:
|
||||
return "jandydevice";
|
||||
break;
|
||||
case SIMULATOR:
|
||||
return "allbutton";
|
||||
break;
|
||||
default:
|
||||
return "none";
|
||||
break;
|
||||
}
|
||||
}
|
||||
*/
|
||||
int build_aqualink_simulator_packet_JSON(struct aqualinkdata *aqdata, char* buffer, int size)
|
||||
{
|
||||
memset(&buffer[0], 0, size);
|
||||
int length = 0;
|
||||
int i;
|
||||
|
||||
length += sprintf(buffer+length, "{\"type\": \"simpacket\"");
|
||||
|
||||
if (aqdata->simulator_packet[PKT_DEST] >= 0x40 && aqdata->simulator_packet[PKT_DEST] <= 0x43) {
|
||||
length += sprintf(buffer+length, ",\"simtype\": \"onetouch\"");
|
||||
} else if (aqdata->simulator_packet[PKT_DEST] >= 0x08 && aqdata->simulator_packet[PKT_DEST] <= 0x0a) {
|
||||
length += sprintf(buffer+length, ",\"simtype\": \"allbutton\"");
|
||||
} else if (aqdata->simulator_packet[PKT_DEST] >= 0x30 && aqdata->simulator_packet[PKT_DEST] <= 0x33) {
|
||||
length += sprintf(buffer+length, ",\"simtype\": \"iaqtouch\"");
|
||||
} else if (aqdata->simulator_packet[PKT_DEST] >= 0x60 && aqdata->simulator_packet[PKT_DEST] <= 0x63) {
|
||||
length += sprintf(buffer+length, ",\"simtype\": \"aquapda\"");
|
||||
} else {
|
||||
length += sprintf(buffer+length, ",\"simtype\": \"unknown\"");
|
||||
}
|
||||
//if (aqdata->simulator_packet[i][])
|
||||
//length += sprintf(buffer+length, ",\"simtype\": \"onetouch\"");
|
||||
|
||||
length += sprintf(buffer+length, ",\"raw\": [");
|
||||
for (i=0; i < aqdata->simulator_packet_length; i++)
|
||||
{
|
||||
length += sprintf(buffer+length, "\"0x%02hhx\",", aqdata->simulator_packet[i]);
|
||||
}
|
||||
if (buffer[length-1] == ',')
|
||||
length--;
|
||||
length += sprintf(buffer+length, "]");
|
||||
|
||||
length += sprintf(buffer+length, ",\"dec\": [");
|
||||
for (i=0; i < aqdata->simulator_packet_length; i++)
|
||||
{
|
||||
length += sprintf(buffer+length, "%d,", aqdata->simulator_packet[i]);
|
||||
}
|
||||
if (buffer[length-1] == ',')
|
||||
length--;
|
||||
|
||||
length += sprintf(buffer+length, "]");
|
||||
|
||||
length += sprintf(buffer+length, "}");
|
||||
|
||||
//printf("Buffer=%d, used=%d, OUT='%s'\n",size,length,buffer);
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
// WS Received '{"parameter":"SPA_HTR","value":99}'
|
||||
// WS Received '{"command":"KEY_HTR_POOL"}'
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#define JSON_LABEL_SIZE 600
|
||||
#define JSON_BUFFER_SIZE 5120
|
||||
#define JSON_STATUS_SIZE 2048
|
||||
#define JSON_SIMULATOR_SIZE 2048
|
||||
|
||||
#define JSON_MQTT_MSG_SIZE 100
|
||||
|
||||
|
@ -57,6 +58,7 @@ int build_aqualink_aqmanager_JSON(struct aqualinkdata *aqdata, char* buffer, int
|
|||
//int build_device_JSON(struct aqualinkdata *aqdata, int programable_switch, char* buffer, int size, bool homekit);
|
||||
//int build_device_JSON(struct aqualinkdata *aqdata, int programable_switch1, int programable_switch2, char* buffer, int size, bool homekit);
|
||||
int build_device_JSON(struct aqualinkdata *aqdata, char* buffer, int size, bool homekit);
|
||||
int build_aqualink_simulator_packet_JSON(struct aqualinkdata *aqdata, char* buffer, int size);
|
||||
|
||||
#endif /* JSON_MESSAGES_H_ */
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#include "aq_timer.h"
|
||||
#include "aq_scheduler.h"
|
||||
#include "rs_msg_utils.h"
|
||||
#include "simulator.h"
|
||||
#include "version.h"
|
||||
|
||||
#ifdef AQ_PDA
|
||||
|
@ -141,6 +142,24 @@ void _broadcast_aqualinkstate_error(struct mg_connection *nc, char *msg)
|
|||
// Maybe enhacment in future to sent error messages to MQTT
|
||||
}
|
||||
|
||||
|
||||
void _broadcast_simulator_message(struct mg_connection *nc) {
|
||||
struct mg_connection *c;
|
||||
char data[JSON_SIMULATOR_SIZE];
|
||||
|
||||
build_aqualink_simulator_packet_JSON(_aqualink_data, data, JSON_SIMULATOR_SIZE);
|
||||
|
||||
for (c = mg_next(nc->mgr, NULL); c != NULL; c = mg_next(nc->mgr, c)) {
|
||||
if (is_websocket(c) && is_websocket_simulator(c)) {
|
||||
ws_send(c, data);
|
||||
}
|
||||
}
|
||||
|
||||
//LOG(NET_LOG,LOG_DEBUG, "Sent to simulator '%s'\n",data);
|
||||
|
||||
_aqualink_data->simulator_packet_updated = false;
|
||||
}
|
||||
|
||||
#ifdef AQ_MANAGER
|
||||
|
||||
#define WS_LOG_LENGTH 200
|
||||
|
@ -159,7 +178,13 @@ sd_journal *open_journal() {
|
|||
sd_journal *journal;
|
||||
char filter[51];
|
||||
|
||||
#ifndef AQ_CONTAINER
|
||||
// Below works for local
|
||||
if (sd_journal_open(&journal, SD_JOURNAL_LOCAL_ONLY) < 0)
|
||||
#else
|
||||
// Container doesn't have local systemd_journal so use hosts through mapped filesystem
|
||||
if (sd_journal_open_directory(&journal, "/var/log/journal", SD_JOURNAL_SYSTEM) < 0)
|
||||
#endif
|
||||
{
|
||||
LOGSystemError(errno, NET_LOG, "Failed to open journal");
|
||||
return journal;
|
||||
|
@ -171,6 +196,7 @@ sd_journal *open_journal() {
|
|||
sd_journal_close(journal);
|
||||
return journal;
|
||||
}
|
||||
/* Docker wll also have problem with this
|
||||
// Daemon will change PID after printing startup message, so don't filter on current PID
|
||||
if (_aqconfig_.deamonize != true) {
|
||||
snprintf(filter, 50, "_PID=%d",getpid());
|
||||
|
@ -180,7 +206,7 @@ sd_journal *open_journal() {
|
|||
sd_journal_close(journal);
|
||||
return journal;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
if (sd_journal_set_data_threshold(journal, LOGBUFFER) < 0)
|
||||
{
|
||||
|
@ -414,7 +440,8 @@ void _broadcast_aqualinkstate(struct mg_connection *nc)
|
|||
#endif
|
||||
|
||||
for (c = mg_next(nc->mgr, NULL); c != NULL; c = mg_next(nc->mgr, c)) {
|
||||
if (is_websocket(c))
|
||||
//if (is_websocket(c) && !is_websocket_simulator(c)) // No need to broadcast status messages to simulator.
|
||||
if (is_websocket(c)) // All button simulator needs status messages
|
||||
ws_send(c, data);
|
||||
#ifndef MG_DISABLE_MQTT
|
||||
else if (is_mqtt(c))
|
||||
|
@ -959,10 +986,25 @@ uriAtype action_URI(request_source from, const char *URI, int uri_length, float
|
|||
} else if (strncmp(ri1, "schedules", 9) == 0) {
|
||||
return uSchedules;
|
||||
} else if (strncmp(ri1, "simulator", 9) == 0 && from == NET_WS) { // Only valid from websocket.
|
||||
if (ri2 != NULL && strncmp(ri2, "onetouch", 8) == 0) {
|
||||
start_simulator(_aqualink_data, ONETOUCH);
|
||||
} else if (ri2 != NULL && strncmp(ri2, "allbutton", 9) == 0) {
|
||||
start_simulator(_aqualink_data, ALLBUTTON);
|
||||
} else if (ri2 != NULL && strncmp(ri2, "aquapda", 7) == 0) {
|
||||
start_simulator(_aqualink_data, AQUAPDA);
|
||||
} else if (ri2 != NULL && strncmp(ri2, "iaqtouch", 8) == 0) {
|
||||
start_simulator(_aqualink_data, IAQTOUCH);
|
||||
} else {
|
||||
return uBad;
|
||||
}
|
||||
return uSimulator;
|
||||
} else if (strncmp(ri1, "simcmd", 10) == 0 && from == NET_WS) { // Only valid from websocket.
|
||||
simulator_send_cmd((unsigned char)value);
|
||||
return uActioned;
|
||||
/*
|
||||
} else if (strncmp(ri1, "rawcommand", 10) == 0 && from == NET_WS) { // Only valid from websocket.
|
||||
aq_send_cmd((unsigned char)value);
|
||||
return uActioned;
|
||||
return uActioned;*/
|
||||
#ifdef AQ_MANAGER
|
||||
} else if (strncmp(ri1, "aqmanager", 9) == 0 && from == NET_WS) { // Only valid from websocket.
|
||||
return uAQmanager;
|
||||
|
@ -1562,9 +1604,11 @@ void action_websocket_request(struct mg_connection *nc, struct websocket_message
|
|||
break;
|
||||
case uSimulator:
|
||||
{
|
||||
LOG(NET_LOG,LOG_DEBUG, "Started Simulator Mode\n");
|
||||
LOG(NET_LOG,LOG_DEBUG, "Request to start Simulator\n");
|
||||
set_websocket_simulator(nc);
|
||||
_aqualink_data->simulate_panel = true;
|
||||
//_aqualink_data->simulate_panel = true;
|
||||
// Clear simulator ID incase sim type changes
|
||||
//_aqualink_data->simulator_id = NUL;
|
||||
DEBUG_TIMER_START(&tid);
|
||||
char message[JSON_BUFFER_SIZE];
|
||||
build_aqualink_status_JSON(_aqualink_data, message, JSON_BUFFER_SIZE);
|
||||
|
@ -1706,9 +1750,8 @@ static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
|
|||
if (is_websocket(nc)) {
|
||||
_aqualink_data->open_websockets--;
|
||||
LOG(NET_LOG,LOG_DEBUG, "-- Websocket left\n");
|
||||
// Need something below to detect is_websocket_simulator() and turn off aq_data.simulate_panel
|
||||
if (is_websocket_simulator(nc)) {
|
||||
_aqualink_data->simulate_panel = false;
|
||||
stop_simulator(_aqualink_data);
|
||||
LOG(NET_LOG,LOG_DEBUG, "Stoped Simulator Mode\n");
|
||||
} else if (is_websocket_aqmanager(nc)) {
|
||||
_aqualink_data->aqManagerActive = false;
|
||||
|
@ -1923,9 +1966,9 @@ void *net_services_thread( void *ptr )
|
|||
while (_keepNetServicesRunning == true)
|
||||
{
|
||||
//poll_net_services(&_mgr, 10);
|
||||
// Shorten poll cycle when logging messages to WS
|
||||
//mg_mgr_poll(&_mgr, (_aqualink_data->aqManagerActive)?50:100);
|
||||
mg_mgr_poll(&_mgr, 100);
|
||||
// Shorten poll cycle when in simulator mode
|
||||
mg_mgr_poll(&_mgr, (_aqualink_data->simulator_active != SIM_NONE)?10:100);
|
||||
//mg_mgr_poll(&_mgr, 100);
|
||||
|
||||
if (aqdata->updated == true /*|| _broadcast == true*/) {
|
||||
//LOG(NET_LOG,LOG_DEBUG, "********** Broadcast ************\n");
|
||||
|
@ -1933,10 +1976,13 @@ void *net_services_thread( void *ptr )
|
|||
aqdata->updated = false;
|
||||
}
|
||||
#ifdef AQ_MANAGER
|
||||
if ( ! broadcast_systemd_logmessages(_aqualink_data->aqManagerActive)) {
|
||||
if ( ! broadcast_systemd_logmessages(aqdata->aqManagerActive)) {
|
||||
LOG(AQUA_LOG,LOG_ERR, "Couldn't open systemd journal log\n");
|
||||
}
|
||||
#endif
|
||||
if (aqdata->simulator_active != SIM_NONE && aqdata->simulator_packet_updated == true ) {
|
||||
_broadcast_simulator_message(_mgr.active_connections);
|
||||
}
|
||||
}
|
||||
|
||||
f_end:
|
||||
|
@ -1958,6 +2004,10 @@ void broadcast_aqualinkstate() {
|
|||
void broadcast_aqualinkstate_error(char *msg) {
|
||||
_broadcast_aqualinkstate_error(_mgr.active_connections, msg);
|
||||
}
|
||||
void broadcast_simulator_message() {
|
||||
_aqualink_data->simulator_packet_updated = true;
|
||||
}
|
||||
|
||||
|
||||
void stop_net_services() {
|
||||
_keepNetServicesRunning = false;
|
||||
|
@ -2009,6 +2059,11 @@ void broadcast_aqualinkstate_error(/*struct mg_connection *nc,*/ char *msg)
|
|||
}
|
||||
LOG(NET_LOG,LOG_NOTICE, "Broadcast error to network\n");
|
||||
}
|
||||
void broadcast_simulator_message() {
|
||||
if ( ! _aqconfig_.thread_netservices) {
|
||||
return _broadcast_simulator_message();
|
||||
}
|
||||
}
|
||||
time_t poll_net_services(/*struct mg_mgr *mgr,*/ int timeout_ms)
|
||||
{
|
||||
if (timeout_ms < 0)
|
||||
|
|
|
@ -29,6 +29,7 @@ void stop_net_services();
|
|||
time_t poll_net_services(int timeout_ms);
|
||||
void broadcast_aqualinkstate();
|
||||
void broadcast_aqualinkstate_error(char *msg);
|
||||
void broadcast_simulator_message();
|
||||
|
||||
// superseded with systemd/sd-journal
|
||||
//void broadcast_log(char *msg);
|
||||
|
|
|
@ -865,7 +865,7 @@ bool set_PDA_numeric_field_value(struct aqualinkdata *aq_data, int val, int cur_
|
|||
char *hghlight_chars;
|
||||
int hlight_length=0;
|
||||
int i=0;
|
||||
//hghlight_chars = pda_m_hlightchars(&hlight_length);
|
||||
hghlight_chars = pda_m_hlightchars(&hlight_length); // NSF May need to take this out and there for the LOG entry after while
|
||||
while (hlight_length >= 15 || hlight_length <= 0) {
|
||||
delay(500);
|
||||
waitForPDANextMessageType(aq_data,CMD_PDA_HIGHLIGHTCHARS,5);
|
||||
|
|
Binary file not shown.
|
@ -132,8 +132,6 @@ report_zero_pool_temp = no
|
|||
#serial_debug_filter = 0x00
|
||||
|
||||
# Not documented. These are experimental. Will change how RS485 / Serial works, Only use if asked to for problem solving purposes.
|
||||
#serial_readahead_b4_write = yes
|
||||
#prioritize_ack = yes
|
||||
rs485_frame_delay = 4
|
||||
|
||||
# Get rid of the startup warning message about no low latency. BETTER option is to buy a better adapter.
|
||||
|
|
|
@ -98,11 +98,12 @@ device_id=0x60
|
|||
#extended_device_id_programming = no
|
||||
|
||||
# Not documented
|
||||
serial_readahead_b4_write = yes
|
||||
mqtt_timed_update = no
|
||||
thread_netservices = yes
|
||||
rs_poll_speed = -1
|
||||
#serial_readahead_b4_write = yes
|
||||
#mqtt_timed_update = no
|
||||
#thread_netservices = yes
|
||||
#rs_poll_speed = -1
|
||||
#rs_poll_speed = 1
|
||||
rs485_frame_delay = 4
|
||||
|
||||
# Your RS panel size. ie 4, 6, 8, 12 or 16 relates to RS4, RS6, RS8, RS12 or RS16.
|
||||
# VERY important that you select 12 or 16, if you have either of those size panels.
|
||||
|
|
Binary file not shown.
|
@ -41,7 +41,7 @@
|
|||
#define SLOG_MAX 80
|
||||
#define PACKET_MAX 600
|
||||
|
||||
#define VERSION "serial_logger V2.0"
|
||||
#define VERSION "serial_logger V2.1"
|
||||
|
||||
/*
|
||||
typedef enum used {
|
||||
|
@ -86,7 +86,7 @@ bool _playback_file = false;
|
|||
|
||||
int sl_timespec_subtract (struct timespec *result, const struct timespec *x, const struct timespec *y);
|
||||
|
||||
int _serial_logger(int rs_fd, char *port_name, int logPackets, int logLevel, bool panleProbe, bool rsSerialSpeedTest, bool errorMonitor);
|
||||
int _serial_logger(int rs_fd, char *port_name, int logPackets, int logLevel, bool panleProbe, bool rsSerialSpeedTest, bool errorMonitor, bool printAllIDs);
|
||||
|
||||
|
||||
#ifdef SERIAL_LOGGER
|
||||
|
@ -101,7 +101,7 @@ void intHandler(int dummy) {
|
|||
}
|
||||
#else
|
||||
int serial_logger (int rs_fd, char *port_name, int logLevel) {
|
||||
return _serial_logger(rs_fd, port_name, PACKET_MAX, (logLevel>=LOG_NOTICE?logLevel:LOG_NOTICE), true, false, false);
|
||||
return _serial_logger(rs_fd, port_name, PACKET_MAX, (logLevel>=LOG_NOTICE?logLevel:LOG_NOTICE), true, false, false, false);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -362,11 +362,9 @@ int main(int argc, char *argv[]) {
|
|||
bool rsSerialSpeedTest = false;
|
||||
bool serialBlocking = true;
|
||||
bool errorMonitor = false;
|
||||
bool printAllIDs = false;
|
||||
|
||||
// aq_serial.c uses the following
|
||||
#ifdef AQ_RS_EXTRA_OPTS
|
||||
_aqconfig_.readahead_b4_write = false;
|
||||
#endif
|
||||
_aqconfig_.log_protocol_packets = false;
|
||||
_aqconfig_.log_raw_bytes = false;
|
||||
_aqconfig_.ftdi_low_latency = true;
|
||||
|
@ -391,6 +389,7 @@ int main(int argc, char *argv[]) {
|
|||
fprintf(stderr, "\t-lpack (log RS packets to %s)\n",RS485LOGFILE);
|
||||
fprintf(stderr, "\t-lrawb (log raw RS bytes to %s)\n",RS485BYTELOGFILE);
|
||||
fprintf(stderr, "\t-e (monitor errors)\n");
|
||||
fprintf(stderr, "\t-a (Print all ID's the panel queried)\n");
|
||||
fprintf(stderr, "\nie:\t%s /dev/ttyUSB0 -d -p 1000 -i 0x08 -i 0x0a\n\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
@ -424,6 +423,8 @@ int main(int argc, char *argv[]) {
|
|||
serialBlocking = false;
|
||||
} else if (strcmp(argv[i], "-e") == 0) {
|
||||
errorMonitor = true;
|
||||
} else if (strcmp(argv[i], "-a") == 0) {
|
||||
printAllIDs = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -471,7 +472,7 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
startPacketLogger();
|
||||
|
||||
_serial_logger(rs_fd, argv[1], logPackets, logLevel, panleProbe, rsSerialSpeedTest, errorMonitor);
|
||||
_serial_logger(rs_fd, argv[1], logPackets, logLevel, panleProbe, rsSerialSpeedTest, errorMonitor, printAllIDs);
|
||||
|
||||
stopPacketLogger();
|
||||
|
||||
|
@ -483,7 +484,7 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
|
||||
|
||||
int _serial_logger(int rs_fd, char *port_name, int logPackets, int logLevel, bool panleProbe, bool rsSerialSpeedTest, bool errorMonitor) {
|
||||
int _serial_logger(int rs_fd, char *port_name, int logPackets, int logLevel, bool panleProbe, bool rsSerialSpeedTest, bool errorMonitor, bool printAllIDs) {
|
||||
int packet_length;
|
||||
int last_packet_length = 0;
|
||||
unsigned char packet_buffer[AQ_MAXPKTLEN];
|
||||
|
@ -569,6 +570,7 @@ int _serial_logger(int rs_fd, char *port_name, int logPackets, int logLevel, boo
|
|||
}
|
||||
}
|
||||
if (found != true && sindex < SLOG_MAX) {
|
||||
//printf("Added id 0x%02hhx\n",packet_buffer[PKT_DEST]);
|
||||
slog[sindex].ID = packet_buffer[PKT_DEST];
|
||||
slog[sindex].inuse = false;
|
||||
sindex++;
|
||||
|
@ -654,7 +656,8 @@ int _serial_logger(int rs_fd, char *port_name, int logPackets, int logLevel, boo
|
|||
for (i = 0; i < sindex; i++) {
|
||||
//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) {
|
||||
//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 || printAllIDs == true) {
|
||||
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)?canUseExtended(slog[i].ID):getDevice(slog[i].ID));
|
||||
}
|
||||
|
|
|
@ -0,0 +1,139 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "aqualink.h"
|
||||
#include "net_services.h"
|
||||
#include "packetLogger.h"
|
||||
|
||||
#define MAX_STACK 20
|
||||
int _sim_stack_place = 0;
|
||||
unsigned char _commands[MAX_STACK];
|
||||
|
||||
bool push_simulator_cmd(unsigned char cmd);
|
||||
|
||||
int simulator_cmd_length()
|
||||
{
|
||||
return _sim_stack_place;
|
||||
}
|
||||
|
||||
// External command
|
||||
void simulator_send_cmd(unsigned char cmd)
|
||||
{
|
||||
push_simulator_cmd(cmd);
|
||||
}
|
||||
|
||||
bool push_simulator_cmd(unsigned char cmd)
|
||||
{
|
||||
if (_sim_stack_place < MAX_STACK) {
|
||||
_commands[_sim_stack_place] = cmd;
|
||||
_sim_stack_place++;
|
||||
} else {
|
||||
LOG(SIM_LOG, LOG_ERR, "Command queue overflow, too many unsent commands to RS control panel\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned char pop_simulator_cmd(unsigned char receive_type)
|
||||
{
|
||||
unsigned char cmd = NUL;
|
||||
|
||||
if (_sim_stack_place > 0 && receive_type == CMD_STATUS ) {
|
||||
cmd = _commands[0];
|
||||
_sim_stack_place--;
|
||||
memmove(&_commands[0], &_commands[1], sizeof(unsigned char) * _sim_stack_place ) ;
|
||||
}
|
||||
|
||||
LOG(SIM_LOG,LOG_DEBUG, "Sending '0x%02hhx' to controller\n", cmd);
|
||||
return cmd;
|
||||
}
|
||||
|
||||
bool processSimulatorPacket(unsigned char *packet, int packet_length, struct aqualinkdata *aqdata)
|
||||
{
|
||||
// copy packed into buffer to be sent to web
|
||||
//memset(aqdata->simulator_packet, 0, sizeof aqdata->simulator_packet);
|
||||
memcpy(aqdata->simulator_packet, packet, packet_length);
|
||||
aqdata->simulator_packet_length = packet_length;
|
||||
|
||||
if ( getLogLevel(SIM_LOG) >= LOG_DEBUG ) {
|
||||
char buff[1000];
|
||||
//sprintf("Sending control command:")
|
||||
beautifyPacket(buff, packet, packet_length, false);
|
||||
LOG(SIM_LOG,LOG_DEBUG, "Received message : %s", buff);
|
||||
}
|
||||
|
||||
broadcast_simulator_message();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool start_simulator(struct aqualinkdata *aqdata, emulation_type type) {
|
||||
|
||||
// If we are a PDA panel and PDA sim, we are connected, so just set that
|
||||
// since PDA only panel can only handle one remote ID.
|
||||
if (isPDA_PANEL && type == AQUAPDA) {
|
||||
aqdata->simulator_active = type;
|
||||
aqdata->simulator_id = _aqconfig_.device_id;
|
||||
}
|
||||
|
||||
// if type is same AND id is valid, sim is already started, their is nothing to do.
|
||||
if (aqdata->simulator_active == type) {
|
||||
if (aqdata->simulator_id >= 0x40 && aqdata->simulator_id <= 0x43) {
|
||||
LOG(SIM_LOG,LOG_NOTICE, "OneTouch Simulator already active!\n");
|
||||
return true;
|
||||
} else if (aqdata->simulator_id >= 0x08 && aqdata->simulator_id <= 0x0a) {
|
||||
LOG(SIM_LOG,LOG_NOTICE, "AllButton Simulator already active!\n");
|
||||
return true;
|
||||
} else if (aqdata->simulator_id >= 0x30 && aqdata->simulator_id <= 0x33) {
|
||||
LOG(SIM_LOG,LOG_NOTICE, "iAqualinkTouch Simulator already active!\n");
|
||||
return true;
|
||||
} else if (aqdata->simulator_id >= 0x60 && aqdata->simulator_id <= 0x63) {
|
||||
LOG(SIM_LOG,LOG_NOTICE, "PDA Simulator already active!\n");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Check it's a valid request
|
||||
if (type == ALLBUTTON) {
|
||||
LOG(SIM_LOG,LOG_NOTICE, "Starting AllButton Simulator!\n");
|
||||
} else if (type == ONETOUCH) {
|
||||
LOG(SIM_LOG,LOG_NOTICE, "Starting OneTouch Simulator!\n");
|
||||
} else if (type == AQUAPDA ) {
|
||||
LOG(SIM_LOG,LOG_NOTICE, "Starting PDA Simulator!\n");
|
||||
} else if (type == IAQTOUCH) {
|
||||
LOG(SIM_LOG,LOG_NOTICE, "Starting iAqualinkTouch Simulator!\n");
|
||||
} else {
|
||||
LOG(SIM_LOG,LOG_ERR, "Request to start simulator of unknown type : %d", type);
|
||||
return false;
|
||||
}
|
||||
|
||||
// start the simulator
|
||||
aqdata->simulator_active = type;
|
||||
aqdata->simulator_id = NUL;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool stop_simulator(struct aqualinkdata *aqdata) {
|
||||
aqdata->simulator_active = SIM_NONE;
|
||||
aqdata->simulator_id = NUL;
|
||||
|
||||
LOG(SIM_LOG,LOG_DEBUG, "Stoped Simulator Mode\n");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool is_simulator_packet(struct aqualinkdata *aqdata, unsigned char *packet, int packet_length) {
|
||||
|
||||
if ( (aqdata->simulator_active == ONETOUCH && packet[PKT_DEST] >= 0x40 && packet[PKT_DEST] <= 0x43) ||
|
||||
(aqdata->simulator_active == ALLBUTTON && packet[PKT_DEST] >= 0x08 && packet[PKT_DEST] <= 0x0a) ||
|
||||
(aqdata->simulator_active == IAQTOUCH && packet[PKT_DEST] >= 0x30 && packet[PKT_DEST] <= 0x33) ||
|
||||
(aqdata->simulator_active == AQUAPDA && packet[PKT_DEST] >= 0x60 && packet[PKT_DEST] <= 0x63) ) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
#ifndef SIMULATOR_H_
|
||||
#define SIMULATOR_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
bool processSimulatorPacket(unsigned char *packet_buffer, int packet_length, struct aqualinkdata *aqdata);
|
||||
//unsigned char pop_simulator_cmd(struct aqualinkdata *aq_data);
|
||||
unsigned char pop_simulator_cmd(unsigned char receive_type);
|
||||
int simulator_cmd_length();
|
||||
//bool push_simulator_cmd(unsigned char cmd);
|
||||
void simulator_send_cmd(unsigned char cmd);
|
||||
|
||||
bool start_simulator(struct aqualinkdata *aqdata, emulation_type type);
|
||||
bool stop_simulator(struct aqualinkdata *aqdata);
|
||||
|
||||
bool is_simulator_packet(struct aqualinkdata *aqdata, unsigned char *packet, int packet_length);
|
||||
|
||||
#endif // SIMULATOR_H_
|
3
utils.c
3
utils.c
|
@ -322,6 +322,9 @@ const char* logmask2name(int16_t from)
|
|||
case TIMR_LOG:
|
||||
return "Schd/Timer:";
|
||||
break;
|
||||
case SIM_LOG:
|
||||
return "Simulator: ";
|
||||
break;
|
||||
case AQUA_LOG:
|
||||
default:
|
||||
return "AqualinkD: ";
|
||||
|
|
1
utils.h
1
utils.h
|
@ -42,6 +42,7 @@
|
|||
#define PROG_LOG (1 << 10) // Programmer
|
||||
#define DBGT_LOG (1 << 11) // Debug Timer
|
||||
#define TIMR_LOG (1 << 12) // Timers
|
||||
#define SIM_LOG (1 << 13) // Simulator
|
||||
|
||||
// Set scheduler log to timer log
|
||||
#define SCHD_LOG TIMR_LOG
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
|
||||
|
||||
#define AQUALINKD_NAME "Aqualink Daemon"
|
||||
#define AQUALINKD_VERSION "2.3.3"
|
||||
#define AQUALINKD_VERSION "2.3.4"
|
||||
|
|
|
@ -0,0 +1,772 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang='en'>
|
||||
|
||||
<head>
|
||||
<meta http-equiv='Content-Type' content='text/html; charset=windows-1252'>
|
||||
<title>AqualinkD Simulator</title>
|
||||
<meta name='viewport' content='width=device-width'>
|
||||
<meta name='apple-mobile-web-app-capable' content='yes'>
|
||||
<meta name='apple-mobile-web-app-status-bar-style' content='black'>
|
||||
<meta name='apple-mobile-web-app-status-bar-style' content='black'>
|
||||
<link href="aqualinkd.png" rel="apple-touch-icon">
|
||||
<link href="aqualinkd.png" rel="icon">
|
||||
<style>
|
||||
html {}
|
||||
|
||||
body {
|
||||
font-family: 'HelveticaNeue-Light', 'Helvetica Neue Light', 'Helvetica Neue', Helvetica, Arial, 'Lucida Grande', sans-serif;
|
||||
font-weight: 300;
|
||||
background-color: white;
|
||||
color: #000000;
|
||||
margin: 0 !important;
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
/*position: absolute;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
height: 100%;*/
|
||||
}
|
||||
|
||||
table {
|
||||
background-color: rgb(221, 221, 221);
|
||||
padding: 10px;
|
||||
/* border-collapse: collapse;*/
|
||||
}
|
||||
|
||||
th {
|
||||
font-weight: normal;
|
||||
background-color: white;
|
||||
padding-top: 0px;
|
||||
padding-bottom: 0px;
|
||||
padding-left: 4px;
|
||||
padding-right: 4px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.td_led {
|
||||
padding-top: 3px;
|
||||
padding-bottom: 3px;
|
||||
padding-left: 4px;
|
||||
padding-right: 0px;
|
||||
}
|
||||
|
||||
.td_button {
|
||||
padding-top: 3px;
|
||||
padding-bottom: 3px;
|
||||
padding-left: 0px;
|
||||
padding-right: 8px;
|
||||
}
|
||||
|
||||
|
||||
#title {
|
||||
background-color: rgb(200, 200, 200);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
input[type=button],
|
||||
input[type=submit],
|
||||
input[type=reset] {
|
||||
/*font-family: monospace;*/
|
||||
background-color: rgb(165, 165, 165);
|
||||
border: none;
|
||||
color: rgb(0, 0, 0);
|
||||
padding: 2px 2px;
|
||||
text-decoration: none;
|
||||
margin: 0px 0px;
|
||||
min-width: 70px;
|
||||
border-radius: 70px;
|
||||
}
|
||||
|
||||
.led {
|
||||
border-radius: calc(var(--tile_icon-height) / 2);
|
||||
border-radius: 20px;
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
filter: alpha(opacity=100);
|
||||
opacity: 1.0;
|
||||
}
|
||||
|
||||
.lcd_display {
|
||||
/* font-family: monospace;*/
|
||||
background-color: #2b2b2b;
|
||||
color: white;
|
||||
white-space: pre;
|
||||
}
|
||||
.lcd_history {
|
||||
/* font-family: monospace;*/
|
||||
background-color: #aeaeae;
|
||||
color: white;
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
.on {
|
||||
background-color: rgb(255, 0, 0);
|
||||
}
|
||||
|
||||
.off {
|
||||
background-color: rgb(116, 116, 116);
|
||||
}
|
||||
|
||||
.error {
|
||||
background-color: rgb(255, 0, 0) !important;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.version {
|
||||
/*font-family: monospace;*/
|
||||
font-size: x-small;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script type='text/javascript'>
|
||||
|
||||
var _panel_size = 6;
|
||||
var _panel_set = 0;
|
||||
var _keep_socket_alive=true;
|
||||
|
||||
// See if we are in an iframe and capture focus
|
||||
function capture_iframe_focus() {
|
||||
var targetNode = parent.document.getElementById('allbutton_iframe');
|
||||
if (targetNode != null) {
|
||||
var observer = new MutationObserver(function(){
|
||||
if(targetNode.style.display != 'none'){
|
||||
console.log("AllButton sim Displaying");
|
||||
startWebsockets();
|
||||
} else {
|
||||
console.log("AllButton sim Hiding");
|
||||
stopWebsockets();
|
||||
}
|
||||
});
|
||||
observer.observe(targetNode, { attributes: true, childList: true });
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function send(source) {
|
||||
console.log("from" + source.id);
|
||||
|
||||
var cmd = {};
|
||||
cmd.uri = "simcmd"
|
||||
switch (source.id) {
|
||||
case "Filter_Pump_button":
|
||||
cmd.value = "0x02";
|
||||
break;
|
||||
case "Spa_Mode_button":
|
||||
cmd.value = "0x01";
|
||||
break;
|
||||
case "Aux_1_button":
|
||||
cmd.value = "0x05";
|
||||
break;
|
||||
case "Aux_2_button":
|
||||
cmd.value = "0x0a";
|
||||
break;
|
||||
case "Aux_3_button":
|
||||
cmd.value = "0x0f";
|
||||
break;
|
||||
case "Aux_4_button":
|
||||
if (_panel_size < 12)
|
||||
cmd.value = "0x06";
|
||||
else
|
||||
cmd.value = "0x14"; //Different on RS12+ (0x14)
|
||||
break;
|
||||
case "Aux_5_button":
|
||||
if (_panel_size < 12)
|
||||
cmd.value = "0x0b";
|
||||
else
|
||||
cmd.value = "0x03"; //Different on RS12+ (0x03)
|
||||
break;
|
||||
case "Aux_6_button":
|
||||
if (_panel_size < 12)
|
||||
cmd.value = "0x10";
|
||||
else
|
||||
cmd.value = "0x07"; //Different on RS12+ (0x07)
|
||||
break;
|
||||
case "Aux_7_button":
|
||||
if (_panel_size < 12)
|
||||
cmd.value = "0x15";
|
||||
else
|
||||
cmd.value = "0x06"; //Different on RS12+ (0x06)
|
||||
break;
|
||||
case "Aux_B1_button":
|
||||
cmd.value = "0x0b";
|
||||
break;
|
||||
case "Aux_B2_button":
|
||||
cmd.value = "0x10";
|
||||
break;
|
||||
case "Aux_B3_button":
|
||||
cmd.value = "0x15";
|
||||
break;
|
||||
case "Aux_B4_button":
|
||||
cmd.value = "0x1a";
|
||||
break;
|
||||
case "Aux_B5_button":
|
||||
cmd.value = "0x04";
|
||||
break;
|
||||
case "Aux_B6_button":
|
||||
cmd.value = "0x08";
|
||||
break;
|
||||
case "Aux_B7_button":
|
||||
cmd.value = "0x0d";
|
||||
break;
|
||||
case "Aux_B8_button":
|
||||
cmd.value = "0x0c";
|
||||
break;
|
||||
case "Pool_Heater_button":
|
||||
cmd.value = "0x12";
|
||||
break;
|
||||
case "Spa_Heater_button":
|
||||
cmd.value = "0x17";
|
||||
break;
|
||||
case "Solar_Heater_button":
|
||||
cmd.value = "0x1c";
|
||||
break;
|
||||
case "B_menu":
|
||||
cmd.value = "0x09";
|
||||
break;
|
||||
case "B_cancel":
|
||||
cmd.value = "0x0e";
|
||||
break;
|
||||
case "B_back":
|
||||
cmd.value = "0x13";
|
||||
break;
|
||||
case "B_forward":
|
||||
cmd.value = "0x18";
|
||||
break;
|
||||
case "B_enter":
|
||||
cmd.value = "0x1d";
|
||||
break;
|
||||
case "B_hold":
|
||||
cmd.value = "0x19";
|
||||
break;
|
||||
case "B_overide":
|
||||
cmd.value = "0x1c";
|
||||
break;
|
||||
default:
|
||||
alert("Unknown button");
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
cmd.value = todec(cmd.value);
|
||||
send_command(cmd);
|
||||
|
||||
// I know we are converting hex to dec and back to hex, but here for checking.
|
||||
//document.getElementById("messages").innerHTML = "Sent "+tohex(cmd.value)+" please wait for response!";
|
||||
}
|
||||
|
||||
function tohex(value) {
|
||||
var rtn = parseInt(value).toString(16);
|
||||
if (rtn.length <= 1)
|
||||
return "0x0"+rtn;
|
||||
else
|
||||
return "0x"+rtn;
|
||||
}
|
||||
function todec(value) {
|
||||
let number = parseInt(value, 16);
|
||||
return number;
|
||||
}
|
||||
|
||||
function set_panel_size(size)
|
||||
{
|
||||
if (_panel_set == size){
|
||||
return;
|
||||
}
|
||||
|
||||
_panel_set = size;
|
||||
|
||||
switch(size){
|
||||
case 6:
|
||||
document.getElementById("Aux_6_led").classList.add("hidden");
|
||||
document.getElementById("Aux_6_button").classList.add("hidden");
|
||||
document.getElementById("Aux_7_led").classList.add("hidden");
|
||||
document.getElementById("Aux_7_button").classList.add("hidden");
|
||||
case 8:
|
||||
document.getElementById("Aux_B1_led").classList.add("hidden");
|
||||
document.getElementById("Aux_B1_button").classList.add("hidden");
|
||||
document.getElementById("Aux_B2_led").classList.add("hidden");
|
||||
document.getElementById("Aux_B2_button").classList.add("hidden");
|
||||
document.getElementById("Aux_B3_led").classList.add("hidden");
|
||||
document.getElementById("Aux_B3_button").classList.add("hidden");
|
||||
document.getElementById("Aux_B4_led").classList.add("hidden");
|
||||
document.getElementById("Aux_B4_button").classList.add("hidden");
|
||||
case 12:
|
||||
document.getElementById("Aux_B5_button").classList.add("hidden");
|
||||
document.getElementById("Aux_B6_button").classList.add("hidden");
|
||||
document.getElementById("Aux_B7_button").classList.add("hidden");
|
||||
document.getElementById("Aux_B8_button").classList.add("hidden");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
function update_status(data) {
|
||||
// Some form of error if PDA only panel.
|
||||
if (data.panel_type.startsWith("PDA")) {
|
||||
document.getElementById("title").innerHTML = ' !!! PDA only panels are not Supported !!! '
|
||||
document.getElementById("title").classList.add("error");
|
||||
document.getElementById("messages").innerHTML = ' !!! PDA Not Supported !!! '
|
||||
document.getElementById("messages").classList.add("error");
|
||||
}
|
||||
|
||||
for (var obj in data.leds) {
|
||||
if ((led = document.getElementById(obj.toString() + "_led")) == null) {
|
||||
//console.log("Error " + obj.toString() + " LED not found");
|
||||
//return;
|
||||
} else {
|
||||
if (data.leds[obj] == "on" || data.leds[obj] == "enabled" || data.leds[obj] == "flash") {
|
||||
//console.log("Set " + obj.toString() + " LED on");
|
||||
led.classList.add("on");
|
||||
led.classList.remove("off");
|
||||
} else {
|
||||
//console.log("Set " + obj.toString() + " LED off");
|
||||
led.classList.add("off");
|
||||
led.classList.remove("on");
|
||||
}
|
||||
}
|
||||
if (obj.toString() == "Aux_4" && _panel_size < 6)
|
||||
_panel_size=6;
|
||||
if (obj.toString() == "Aux_6" && _panel_size < 8)
|
||||
_panel_size=8;
|
||||
if (obj.toString() == "Aux_B1" && _panel_size < 12)
|
||||
_panel_size=12;
|
||||
if (obj.toString() == "Aux_B4")
|
||||
_panel_size=16;
|
||||
}
|
||||
|
||||
set_panel_size(_panel_size);
|
||||
|
||||
const versionlabel = document.getElementById("version");
|
||||
if (versionlabel.innerHTML = " ") {
|
||||
versionlabel.innerHTML = "AqualinkD "+data.aqualinkd_version+"<br>"+data.panel_type+" "+data.version;
|
||||
}
|
||||
}
|
||||
|
||||
function update_device(data) {
|
||||
for (var obj in data['devices']) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function set_labels(data) {
|
||||
for (var obj in data) {
|
||||
if ((button = document.getElementById(obj + "_button")) != null && data[obj] != "NONE") {
|
||||
button.value = data[obj];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function update_status_message(message=null, error=false) {
|
||||
const status = document.getElementById("status");
|
||||
|
||||
if (message != null) {
|
||||
status.innerHTML = message;
|
||||
} else {
|
||||
status.innerHTML = "AqualinkD All Button Simulator";
|
||||
}
|
||||
|
||||
if (error) {
|
||||
status.classList.add("error");
|
||||
} else {
|
||||
status.classList.remove("error");
|
||||
}
|
||||
}
|
||||
|
||||
function packet_to_ascii(packet) {
|
||||
var msg="";
|
||||
|
||||
for (i=5; i <= 20; i++) {
|
||||
if (packet[i] >= 31 && packet[i] <= 127) {
|
||||
msg=msg+String.fromCharCode(packet[i]);
|
||||
//console.log("char ("+packet[i]+") = "+msg);
|
||||
} else if (packet[i] == 223) {
|
||||
msg=msg+"°";
|
||||
} else if (packet[i] == 0) {
|
||||
break; // End on a nul
|
||||
} else {
|
||||
console.log("Bad char in string '"+msg+"' next ("+packet[i]+") from ["+packet+"]" );
|
||||
}
|
||||
}
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
function lcd_display(line, message) {
|
||||
|
||||
const message_lcd = document.getElementById("lcd");
|
||||
const message_lcd1 = document.getElementById("lcd_2");
|
||||
const message_lcd2 = document.getElementById("lcd_3");
|
||||
|
||||
if (message == "" || message == " "){message = " ";}
|
||||
|
||||
message_lcd2.innerHTML = message_lcd1.innerHTML;
|
||||
message_lcd1.innerHTML = message_lcd.innerHTML;
|
||||
message_lcd.innerHTML = message;
|
||||
}
|
||||
|
||||
function lcd_display_append(line, message) {
|
||||
const message_lcd = document.getElementById("lcd");
|
||||
message_lcd.innerHTML = message_lcd.innerHTML+message;
|
||||
}
|
||||
|
||||
const PKT_CMD = 3;
|
||||
const PKT_DATA1 = 4;
|
||||
|
||||
const CMD_PROBE = 0;
|
||||
const CMD_STATUS = 2
|
||||
const CMD_MSG = 3 // message
|
||||
const CMD_MSG_LONG = 4
|
||||
const CMD_MSG_LOOP_ST = 8 // pda highlight
|
||||
|
||||
function process_packet(data) {
|
||||
if (data.simtype != "allbutton") {
|
||||
update_status_message("Wrong message - is Another simulator running?", true);
|
||||
return;
|
||||
}
|
||||
|
||||
switch(data.dec[PKT_CMD]) {
|
||||
case CMD_PROBE:
|
||||
// We are about to start
|
||||
break;
|
||||
case CMD_MSG: // Message
|
||||
//console.log("Received Line "+data.dec[PKT_DATA1]+" = "+packet_to_ascii(data.dec));
|
||||
lcd_display(data.dec[PKT_DATA1], packet_to_ascii(data.dec));
|
||||
break;
|
||||
case CMD_MSG_LONG: // Message
|
||||
//console.log("Received Line long "+data.dec[PKT_DATA1]+" = "+packet_to_ascii(data.dec));
|
||||
lcd_display_append(data.dec[PKT_DATA1], packet_to_ascii(data.dec));
|
||||
break;
|
||||
|
||||
case CMD_MSG_LOOP_ST:
|
||||
case CMD_STATUS:
|
||||
// Nothing to do for these messages
|
||||
break;
|
||||
|
||||
default:
|
||||
console.log("Received unknown command "+data.dec[PKT_CMD]+" "+tohex(data.dec[PKT_CMD]));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function get_appropriate_ws_url() {
|
||||
var pcol;
|
||||
var u = document.URL;
|
||||
/*
|
||||
* We open the websocket encrypted if this page came on an
|
||||
* https:// url itself, otherwise unencrypted
|
||||
*/
|
||||
if (u.substring(0, 5) == "https") {
|
||||
pcol = "wss://";
|
||||
u = u.substr(8);
|
||||
} else {
|
||||
pcol = "ws://";
|
||||
if (u.substring(0, 4) == "http")
|
||||
u = u.substr(7);
|
||||
}
|
||||
u = u.split('/');
|
||||
//alert (pcol + u[0] + ":6500");
|
||||
return pcol + u[0];
|
||||
}
|
||||
/* dumb increment protocol */
|
||||
var socket_di;
|
||||
|
||||
function startWebsockets() {
|
||||
socket_di = new WebSocket(get_appropriate_ws_url());
|
||||
_keep_socket_alive = true;
|
||||
try {
|
||||
socket_di.onopen = function () {
|
||||
// success!
|
||||
start_simulator();
|
||||
get_devices();
|
||||
}
|
||||
socket_di.onmessage = function got_packet(msg) {
|
||||
//document.getElementById("status").classList.remove("error");
|
||||
update_status_message();
|
||||
var data = JSON.parse(msg.data);
|
||||
if (data.type == 'simpacket') {
|
||||
process_packet(data);
|
||||
} else if (data.type == 'status') {
|
||||
update_status(data);
|
||||
} else if (data.type == 'devices') {
|
||||
//update_status(data);
|
||||
update_device(data);
|
||||
} else if (data.type == 'aux_labels') {
|
||||
set_labels(data);
|
||||
}
|
||||
}
|
||||
socket_di.onclose = function () {
|
||||
// something went wrong
|
||||
//document.getElementById("status").innerHTML = ' !!! Connection error !!! '
|
||||
//document.getElementById("status").classList.add("error");
|
||||
update_status_message(' !!! Connection error !!! ', true);
|
||||
// Try to reconnect every 5 seconds.
|
||||
setTimeout(function () {
|
||||
if (_keep_socket_alive == true) {
|
||||
startWebsockets();
|
||||
}
|
||||
}, 5000);
|
||||
}
|
||||
} catch (exception) {
|
||||
alert('<p>Error' + exception);
|
||||
}
|
||||
}
|
||||
|
||||
function stopWebsockets() {
|
||||
if (socket_di) {
|
||||
socket_di.close();
|
||||
}
|
||||
_keep_socket_alive = false;
|
||||
}
|
||||
|
||||
function start_simulator() {
|
||||
var msg = {
|
||||
//command: "simulator"
|
||||
uri: "simulator/allbutton"
|
||||
};
|
||||
document.getElementById("lcd").innerHTML = "Connecting to panel, please wait!"
|
||||
socket_di.send(JSON.stringify(msg));
|
||||
}
|
||||
|
||||
function get_devices() {
|
||||
var msg = {
|
||||
uri: "devices"
|
||||
};
|
||||
socket_di.send(JSON.stringify(msg));
|
||||
}
|
||||
|
||||
function send_command(cmd) {
|
||||
socket_di.send(JSON.stringify(cmd));
|
||||
}
|
||||
/*
|
||||
function reset() {
|
||||
socket_di.send("reset\n");
|
||||
}
|
||||
*/
|
||||
|
||||
function init() {
|
||||
if ( capture_iframe_focus() ) {
|
||||
// In iframe wait for focus event to start
|
||||
} else {
|
||||
//update_status_message();
|
||||
startWebsockets();
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
<body onload="init();">
|
||||
<div class="wrapper">
|
||||
|
||||
<table border='0' id="deviceList">
|
||||
<tr style="title">
|
||||
<td style="title" colspan="12" align="center"><label id="status"> AqualinkD All Button Simulator </label></th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th colspan="12" align="center" class="lcd_history"><label id="lcd_3"> </label></th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th colspan="12" align="center" class="lcd_history"><label id="lcd_2"> </label></th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th colspan="12" class="lcd_display"><label id="lcd"> </label></th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="td_led">
|
||||
<div id="Filter_Pump_led" class="led off"></div>
|
||||
</td>
|
||||
<td class="td_button">
|
||||
<input id="Filter_Pump_button" type="button" onclick="send(this);" value="Filter Pump">
|
||||
</td>
|
||||
<td class="td_led">
|
||||
<div id="Spa_Mode_led" class="led off"></div>
|
||||
</td>
|
||||
<td class="td_button">
|
||||
<input id="Spa_Mode_button" type="button" onclick="send(this);" value="Spa Mode">
|
||||
</td>
|
||||
<td class="td_led">
|
||||
<div id="Aux_1_led" class="led off"></div>
|
||||
</td>
|
||||
<td class="td_button">
|
||||
<input id="Aux_1_button" type="button" onclick="send(this);" value="AUX1">
|
||||
</td>
|
||||
<td class="td_led">
|
||||
<div id="Aux_2_led" class="led off"></div>
|
||||
</td>
|
||||
<td class="td_button">
|
||||
<input id="Aux_2_button" type="button" onclick="send(this);" value="AUX2">
|
||||
</td>
|
||||
<td class="td_led">
|
||||
<div id="Aux_3_led" class="led off"></div>
|
||||
</td>
|
||||
<td class="td_button">
|
||||
<input id="Aux_3_button" type="button" onclick="send(this);" value="AUX3">
|
||||
</td>
|
||||
<td class="td_led">
|
||||
<div id="Aux_4_led" class="led off"></div>
|
||||
</td>
|
||||
<td class="td_button">
|
||||
<input id="Aux_4_button" type="button" onclick="send(this);" value="AUX4">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="td_led">
|
||||
<div id="Aux_5_led" class="led off"></div>
|
||||
</td>
|
||||
<td class="td_button">
|
||||
<input id="Aux_5_button" type="button" onclick="send(this);" value="AUX5">
|
||||
</td>
|
||||
<td class="td_led">
|
||||
<div id="Aux_6_led" class="led off"></div>
|
||||
</td>
|
||||
<td class="td_button">
|
||||
<input id="Aux_6_button" type="button" onclick="send(this);" value="AUX6">
|
||||
</td>
|
||||
<td class="td_led">
|
||||
<div id="Aux_7_led" class="led off"></div>
|
||||
</td>
|
||||
<td class="td_button">
|
||||
<input id="Aux_7_button" type="button" onclick="send(this);" value="AUX7">
|
||||
</td>
|
||||
<td class="td_led">
|
||||
<div id="Aux_B1_led" class="led off"></div>
|
||||
</td>
|
||||
<td class="td_button">
|
||||
<input id="Aux_B1_button" type="button" onclick="send(this);" value="AUXB1">
|
||||
</td>
|
||||
<td class="td_led">
|
||||
<div id="Aux_B2_led" class="led off"></div>
|
||||
</td>
|
||||
<td class="td_button">
|
||||
<input id="Aux_B2_button" type="button" onclick="send(this);" value="AUXB2">
|
||||
</td>
|
||||
<td class="td_led">
|
||||
<div id="Aux_B3_led" class="led off"></div>
|
||||
</td>
|
||||
<td class="td_button">
|
||||
<input id="Aux_B3_button" type="button" onclick="send(this);" value="AUXB3">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="td_led">
|
||||
<div id="Aux_B4_led" class="led off"></div>
|
||||
</td>
|
||||
<td class="td_button">
|
||||
<input id="Aux_B4_button" type="button" onclick="send(this);" value="AUXB4">
|
||||
</td>
|
||||
<td class="td_led">
|
||||
|
||||
</td>
|
||||
<td class="td_button">
|
||||
<input id="Aux_B5_button" type="button" onclick="send(this);" value="AUXB5">
|
||||
</td>
|
||||
<td class="td_led">
|
||||
|
||||
</td>
|
||||
<td class="td_button">
|
||||
<input id="Aux_B6_button" type="button" onclick="send(this);" value="AUXB6">
|
||||
</td>
|
||||
<td class="td_led">
|
||||
|
||||
</td>
|
||||
<td class="td_button">
|
||||
<input id="Aux_B7_button" type="button" onclick="send(this);" value="AUXB7">
|
||||
</td>
|
||||
<td class="td_led">
|
||||
|
||||
</td>
|
||||
<td class="td_button">
|
||||
<input id="Aux_B8_button" type="button" onclick="send(this);" value="AUXB8">
|
||||
</td>
|
||||
<td class="td_led">
|
||||
|
||||
</td>
|
||||
<td class="td_button">
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="td_led">
|
||||
|
||||
</td>
|
||||
<td class="td_button">
|
||||
|
||||
</td>
|
||||
<td class="td_led">
|
||||
|
||||
</td>
|
||||
<td class="td_button">
|
||||
|
||||
</td>
|
||||
<td class="td_led">
|
||||
|
||||
</td>
|
||||
<td class="td_button">
|
||||
|
||||
</td>
|
||||
<td class="td_led">
|
||||
<div id="Pool_Heater_led" class="led off"></div>
|
||||
</td>
|
||||
<td class="td_button">
|
||||
<input id="Pool_Heater_button" type="button" onclick="send(this);" value="Pool Heater">
|
||||
</td>
|
||||
<td class="td_led">
|
||||
<div id="Spa_Heater_led" class="led off"></div>
|
||||
</td>
|
||||
<td class="td_button">
|
||||
<input id="Spa_Heater_button" type="button" onclick="send(this);" value="Spa Heater">
|
||||
</td>
|
||||
<td class="td_led">
|
||||
<div id="Solar_Heater_led" class="led off"></div>
|
||||
</td>
|
||||
<td class="td_button">
|
||||
<input id="Solar_Heater_button" type="button" onclick="send(this);" value="Solar Heater">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<TD> </TD>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" colspan="2">
|
||||
<input type="button" onclick="send(this);" id="B_menu" value="Menu">
|
||||
</td>
|
||||
<td align="center" colspan="2">
|
||||
<input type="button" onclick="send(this);" id="B_cancel" value="Cancel">
|
||||
</td>
|
||||
<td align="center" colspan="2">
|
||||
<input type="button" onclick="send(this);" id="B_back" value="Back <">
|
||||
</td>
|
||||
<td align="center" colspan="2">
|
||||
<input type="button" onclick="send(this);" id="B_forward" value="Forward >">
|
||||
</td>
|
||||
<td align="center" colspan="2">
|
||||
<input type="button" onclick="send(this);" id="B_enter" value="Enter *">
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td colspan="12" align="center"><label id="messages"> </label></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td colspan="12" id="version" class="version"> </td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -485,6 +485,7 @@
|
|||
*/
|
||||
if (data['deamonized'] == 'off') {
|
||||
console.log("deamonized=" + data['deamonized'] + " Need to rename Restart to Reload");
|
||||
//disablebutton("restart");
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -0,0 +1,686 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang='en'>
|
||||
|
||||
<head>
|
||||
<meta http-equiv='Content-Type' content='text/html; charset=windows-1252'>
|
||||
<title>AqualinkD Simulator</title>
|
||||
<meta name='viewport' content='width=device-width'>
|
||||
<meta name='apple-mobile-web-app-capable' content='yes'>
|
||||
<meta name='apple-mobile-web-app-status-bar-style' content='black'>
|
||||
<meta name='apple-mobile-web-app-status-bar-style' content='black'>
|
||||
<link href="aqualinkd.png" rel="apple-touch-icon">
|
||||
<link href="aqualinkd.png" rel="icon">
|
||||
<style>
|
||||
html {}
|
||||
|
||||
body {
|
||||
font-family: 'HelveticaNeue-Light', 'Helvetica Neue Light', 'Helvetica Neue', Helvetica, Arial, 'Lucida Grande', sans-serif;
|
||||
font-weight: 300;
|
||||
background-color: white;
|
||||
color: #000000;
|
||||
margin: 0 !important;
|
||||
padding: 0 !important;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.inner {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
align-items: center;
|
||||
/*position: absolute;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
height: 100%;*/
|
||||
}
|
||||
|
||||
table {
|
||||
background-color: rgb(221, 221, 221);
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
th {
|
||||
/*
|
||||
background-color: white;
|
||||
border-spacing: 10px;*/
|
||||
padding-top: 0px;
|
||||
padding-bottom: 0px;
|
||||
padding-left: 0px;
|
||||
padding-right: 0px;
|
||||
}
|
||||
|
||||
td {
|
||||
/*
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
*/
|
||||
/*padding: 10px;*/
|
||||
padding-top: 3px;
|
||||
padding-bottom: 3px;
|
||||
padding-left: 0px;
|
||||
padding-right: 0px;
|
||||
}
|
||||
|
||||
#title {
|
||||
background-color: rgb(200, 200, 200);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
input[type=button],
|
||||
input[type=submit],
|
||||
input[type=reset] {
|
||||
background-color: rgb(165, 165, 165);
|
||||
border: none;
|
||||
color: rgb(0, 0, 0);
|
||||
padding: 2px 2px;
|
||||
text-decoration: none;
|
||||
margin: 0px 0px;
|
||||
min-width: 70px;
|
||||
border-radius: 70px;
|
||||
}
|
||||
|
||||
.button_s {
|
||||
min-width: 40px !important;
|
||||
border-radius: 40px !important;
|
||||
}
|
||||
|
||||
.led {
|
||||
border-radius: calc(var(--tile_icon-height) / 2);
|
||||
border-radius: 20px;
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
filter: alpha(opacity=100);
|
||||
opacity: 1.0;
|
||||
}
|
||||
|
||||
.on {
|
||||
background-color: rgb(255, 0, 0);
|
||||
}
|
||||
|
||||
.off {
|
||||
background-color: rgb(116, 116, 116);
|
||||
}
|
||||
|
||||
.error {
|
||||
background-color: rgb(255, 0, 0) !important;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
.lcd_display {
|
||||
font-family: monospace;
|
||||
background-color: #2b2b2b;
|
||||
color: white;
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
.lcd_highlight {
|
||||
font-family: monospace;
|
||||
background-color: #8e1e1e !important;
|
||||
color: white !important;
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
.version {
|
||||
/*font-family: monospace;*/
|
||||
font-size: x-small;
|
||||
}
|
||||
|
||||
.hide {
|
||||
display: none;
|
||||
/*
|
||||
filter: alpha(opacity=0);
|
||||
opacity: 0.0;
|
||||
*/
|
||||
}
|
||||
</style>
|
||||
|
||||
<script type='text/javascript'>
|
||||
|
||||
var _socket_di;
|
||||
var _keep_socket_alive=true;
|
||||
|
||||
const PKT_CMD = 3;
|
||||
const PKT_DATA1 = 4;
|
||||
const PKT_DATA2 = 5;
|
||||
const PKT_DATA3 = 6;
|
||||
|
||||
const CMD_PROBE = 0;
|
||||
const CMD_MSG_LONG = 4;
|
||||
const CMD_PDA_CLEAR = 9;
|
||||
const CMD_PDA_HIGHLIGHT = 8;
|
||||
const CMD_PDA_HIGHLIGHTCHARS = 16;
|
||||
const CMD_PDA_SHIFTLINES = 15;
|
||||
|
||||
const PDA_LINES = 9; // 0 to 9
|
||||
|
||||
var _hlightcharlineno = -1;
|
||||
var _hlightcharline = "";
|
||||
var _hlightcharstart = -1;
|
||||
var _hlightcharend = -1;
|
||||
|
||||
var _initial_click=false;
|
||||
|
||||
// See if we are in an iframe and capture focus
|
||||
function capture_iframe_focus() {
|
||||
var targetNode = parent.document.getElementById('aquapda_iframe');
|
||||
if (targetNode != null) {
|
||||
var observer = new MutationObserver(function(){
|
||||
if(targetNode.style.display != 'none'){
|
||||
console.log("AquaPDA sim Displaying");
|
||||
startWebsockets();
|
||||
} else {
|
||||
console.log("AquaPDA sim Hiding");
|
||||
stopWebsockets();
|
||||
}
|
||||
});
|
||||
observer.observe(targetNode, { attributes: true, childList: true });
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function send(source) {
|
||||
console.log("from" + source.id);
|
||||
|
||||
var cmd = {};
|
||||
cmd.uri = "simcmd"
|
||||
switch (source.id) {
|
||||
case "Up":
|
||||
cmd.value = "0x06";
|
||||
break;
|
||||
case "Down":
|
||||
cmd.value = "0x05";
|
||||
break;
|
||||
case "Select":
|
||||
cmd.value = "0x04";
|
||||
break;
|
||||
case "Page_up":
|
||||
cmd.value = "0x03";
|
||||
break;
|
||||
case "Back":
|
||||
cmd.value = "0x02";
|
||||
break;
|
||||
case "Page_down":
|
||||
cmd.value = "0x01";
|
||||
break;
|
||||
|
||||
default:
|
||||
alert("Unknown button");
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
cmd.value = todec(cmd.value);
|
||||
send_command(cmd);
|
||||
}
|
||||
|
||||
function tohex(value) {
|
||||
var rtn = parseInt(value).toString(16);
|
||||
if (rtn.length <= 1)
|
||||
return "0x0" + rtn;
|
||||
else
|
||||
return "0x" + rtn;
|
||||
}
|
||||
function todec(value) {
|
||||
let number = parseInt(value, 16);
|
||||
return number;
|
||||
}
|
||||
|
||||
|
||||
|
||||
function lcd_clear() {
|
||||
//var container = document.getElementById("lcd_display");
|
||||
for (i = 0; i <= PDA_LINES; i++) {
|
||||
//container.lastElementChild.remove();
|
||||
//child = container.children[i];
|
||||
//console.log("Line "+i+" replacing "+child.innerHTML)
|
||||
//child.innerHTML = " ";
|
||||
var line = document.getElementById("lcd-l" + i);
|
||||
//console.log("Line "+i+" replacing "+line.innerHTML)
|
||||
line.innerHTML = " ";
|
||||
line.classList.remove("lcd_highlight");
|
||||
line.classList.add("lcd_display");
|
||||
}
|
||||
|
||||
lcd_clear_highlight_chrs(false);
|
||||
}
|
||||
|
||||
function lcd_display(lineno, message) {
|
||||
// We get lines 0,2,3,4,5,6.... no line 1. (so using 0 as 1)
|
||||
if (lineno == 0) { lineno = 1; }
|
||||
// Line 64 is time,
|
||||
if (lineno == 64) { lineno = 0; }
|
||||
// line 130 is pool air temp
|
||||
if (lineno == 130) { lineno = 2; }
|
||||
|
||||
|
||||
var line = document.getElementById("lcd-l" + lineno);
|
||||
//console.log("Line "+lineno+" replacing '"+line.innerHTML+"' with '"+message+"'");
|
||||
line.innerHTML = message;
|
||||
|
||||
// See if we need to re-highlight any chrs
|
||||
check_rehighlight_chrs(lineno);
|
||||
}
|
||||
|
||||
function lcd_display_shiftlines(first, last, direction) {
|
||||
|
||||
if (direction == 255) {
|
||||
for (i = first; i <= last; i++) {
|
||||
var line1 = document.getElementById("lcd-l" + i);
|
||||
var line2 = document.getElementById("lcd-l" + (i + 1));
|
||||
line1.innerHTML = line2.innerHTML;
|
||||
}
|
||||
} else if (direction == 1) {
|
||||
for (i = last; i >= first; i--) {
|
||||
var line1 = document.getElementById("lcd-l" + i);
|
||||
var line2 = document.getElementById("lcd-l" + (i - 1) );
|
||||
line1.innerHTML = line2.innerHTML;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function lcd_display_highlight(lineno) {
|
||||
// We get lines 0,2,3,4,5,6.... no line 1. (so using 0 as 1)
|
||||
if (lineno == 0) { lineno = 1; }
|
||||
|
||||
for (i = 0; i <= PDA_LINES; i++) {
|
||||
var line = document.getElementById("lcd-l" + i);
|
||||
if (i != lineno) {
|
||||
line.classList.remove("lcd_highlight");
|
||||
line.classList.add("lcd_display");
|
||||
//console.log("remove highlight to line #"+i+" "+line.innerHTML)
|
||||
} else {
|
||||
line.classList.add("lcd_highlight");
|
||||
line.classList.remove("lcd_display");
|
||||
//console.log("add highlight to line #"+i+" "+line.innerHTML)
|
||||
}
|
||||
}
|
||||
//line.classList.add("lcd_highlight");
|
||||
//line.classList.remove("lcd_display");
|
||||
}
|
||||
|
||||
|
||||
|
||||
function check_rehighlight_chrs(lineno) {
|
||||
if (_hlightcharlineno == lineno && _hlightcharstart >= 0 && _hlightcharend > 0) {
|
||||
// We would have received a new line text, so don't preserve old text
|
||||
lcd_display_highlight_chrs(_hlightcharlineno, _hlightcharstart, _hlightcharend, false);
|
||||
}
|
||||
}
|
||||
|
||||
function lcd_clear_highlight_chrs(preserve = true) {
|
||||
|
||||
// if preserve, then we put back the old text.
|
||||
if (preserve && _hlightcharlineno >= 0 && _hlightcharline != "") {
|
||||
var line = document.getElementById("lcd-l" + _hlightcharlineno);
|
||||
line.innerHTML = _hlightcharline;
|
||||
}
|
||||
|
||||
_hlightcharlineno = -1;
|
||||
_hlightcharline = "";
|
||||
_hlightcharstart = -1;
|
||||
_hlightcharend = -1;
|
||||
}
|
||||
|
||||
function lcd_display_highlight_chrs(lineno, start, end, preserve = true) {
|
||||
|
||||
lcd_clear_highlight_chrs(preserve);
|
||||
|
||||
var line = document.getElementById("lcd-l" + lineno);
|
||||
text = line.innerHTML;
|
||||
|
||||
var newtxt = text.slice(0, end + 1) + "</span>" + text.slice(end + 1);
|
||||
var newtxt = newtxt.slice(0, start) + "<span class=\"lcd_highlight\">" + newtxt.slice(start);
|
||||
line.innerHTML = newtxt;
|
||||
|
||||
_hlightcharlineno = lineno;
|
||||
_hlightcharline = text;
|
||||
_hlightcharstart = start;
|
||||
_hlightcharend = end;
|
||||
|
||||
console.log("Line '" + text + "' now '" + newtxt + "'");
|
||||
}
|
||||
|
||||
function packet_to_ascii(packet) {
|
||||
var msg = "";
|
||||
|
||||
for (i = 5; i <= 20; i++) {
|
||||
if (packet[i] >= 31 && packet[i] <= 127) {
|
||||
msg = msg + String.fromCharCode(packet[i]);
|
||||
} else if (packet[i] == 223) {
|
||||
msg = msg + "°";
|
||||
} else if (packet[i] == 0) {
|
||||
break; // End on a nul
|
||||
} else {
|
||||
console.log("Bad char in string '" + msg + "' next (" + packet[i] + ")");
|
||||
}
|
||||
}
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
|
||||
|
||||
function process_packet(data) {
|
||||
|
||||
if (data.simtype != "aquapda") {
|
||||
update_status_message("Another simulator running", true);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (data.dec[PKT_CMD]) {
|
||||
case CMD_PROBE:
|
||||
// We are about to start
|
||||
break;
|
||||
case CMD_PDA_CLEAR: // Clear
|
||||
//console.log("Received Clear");
|
||||
lcd_clear();
|
||||
_shift_lines = false;
|
||||
break;
|
||||
case CMD_MSG_LONG: // Message
|
||||
//console.log("Received Line " + data.dec[PKT_DATA1] + " = " + packet_to_ascii(data.dec));
|
||||
lcd_display(data.dec[PKT_DATA1], packet_to_ascii(data.dec));
|
||||
break;
|
||||
case CMD_PDA_HIGHLIGHT:
|
||||
//console.log("Received Highlight " + data.dec[PKT_DATA1]);
|
||||
// We sometimes get 255 for line number, need to find out why
|
||||
lcd_display_highlight(data.dec[PKT_DATA1]);
|
||||
break;
|
||||
case CMD_PDA_HIGHLIGHTCHARS:
|
||||
//console.log("Received Highlight chars, Line=" + data.dec[PKT_DATA1] + ", Start=" + data.dec[PKT_DATA2] + ", Stop=" + data.dec[PKT_DATA3]);
|
||||
lcd_display_highlight_chrs(data.dec[PKT_DATA1], data.dec[PKT_DATA2], data.dec[PKT_DATA3]);
|
||||
break;
|
||||
case CMD_PDA_SHIFTLINES:
|
||||
//console.log("Received shift lines, Start=" + data.dec[PKT_DATA1] + ", End=" + data.dec[PKT_DATA2] + ", Direction=" + data.dec[PKT_DATA3]);
|
||||
lcd_display_shiftlines(data.dec[PKT_DATA1], data.dec[PKT_DATA2], data.dec[PKT_DATA3]);
|
||||
break;
|
||||
default:
|
||||
// 2 is READY for commands
|
||||
console.log("Received unknown command " + data.dec[PKT_CMD] + " " + tohex(data.dec[PKT_CMD]));
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
function update_status_message(message = null, error = false) {
|
||||
const status = document.getElementById("status");
|
||||
|
||||
if (message != null) {
|
||||
status.innerHTML = message;
|
||||
} else {
|
||||
status.innerHTML = "AqualinkD PDA Simulator";
|
||||
}
|
||||
|
||||
if (error) {
|
||||
status.classList.add("error");
|
||||
} else {
|
||||
status.classList.remove("error");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function update_status(data) {
|
||||
// Some form of error if PDA only panel.
|
||||
|
||||
if (data.panel_type.startsWith("PDA")) {
|
||||
// If we are a PDA only panel, we are already connected, send the back command to get some PDA clar
|
||||
// message to reset the screen.
|
||||
if (_initial_click == false) {
|
||||
document.getElementById("pdaWarning").style.display = 'block';
|
||||
document.getElementById("Back").click();
|
||||
_initial_click = true;
|
||||
}
|
||||
}
|
||||
|
||||
const versionlabel = document.getElementById("version");
|
||||
if (versionlabel.innerHTML = " ") {
|
||||
versionlabel.innerHTML = "AqualinkD " + data.aqualinkd_version + "<br>" + data.panel_type + " " + data.version;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
function get_appropriate_ws_url() {
|
||||
var pcol;
|
||||
var u = document.URL;
|
||||
/*
|
||||
* We open the websocket encrypted if this page came on an
|
||||
* https:// url itself, otherwise unencrypted
|
||||
*/
|
||||
if (u.substring(0, 5) == "https") {
|
||||
pcol = "wss://";
|
||||
u = u.substr(8);
|
||||
} else {
|
||||
pcol = "ws://";
|
||||
if (u.substring(0, 4) == "http")
|
||||
u = u.substr(7);
|
||||
}
|
||||
u = u.split('/');
|
||||
//alert (pcol + u[0] + ":6500");
|
||||
return pcol + u[0];
|
||||
}
|
||||
/* dumb increment protocol */
|
||||
|
||||
|
||||
function startWebsockets() {
|
||||
_socket_di = new WebSocket(get_appropriate_ws_url());
|
||||
_keep_socket_alive = true;
|
||||
try {
|
||||
_socket_di.onopen = function () {
|
||||
// success!
|
||||
start_simulator();
|
||||
//get_devices();
|
||||
}
|
||||
_socket_di.onmessage = function got_packet(msg) {
|
||||
update_status_message();
|
||||
var data = JSON.parse(msg.data);
|
||||
if (data.type == 'simpacket') {
|
||||
process_packet(data);
|
||||
} else if (data.type == 'status') {
|
||||
update_status(data);
|
||||
}
|
||||
}
|
||||
_socket_di.onclose = function () {
|
||||
// something went wrong
|
||||
//document.getElementById("status").innerHTML = ' !!! Connection error !!! '
|
||||
//document.getElementById("status").classList.add("error");
|
||||
update_status_message("!!! Connection error !!!", true);
|
||||
// Try to reconnect every 5 seconds.
|
||||
setTimeout(function () {
|
||||
if (_keep_socket_alive == true) {
|
||||
startWebsockets();
|
||||
}
|
||||
}, 5000);
|
||||
}
|
||||
} catch (exception) {
|
||||
alert('<p>Error' + exception);
|
||||
}
|
||||
}
|
||||
|
||||
function stopWebsockets() {
|
||||
if (_socket_di) {
|
||||
_socket_di.close();
|
||||
}
|
||||
_keep_socket_alive = false;
|
||||
}
|
||||
|
||||
function start_simulator() {
|
||||
var msg = {
|
||||
//command: "simulator"
|
||||
uri: "simulator/aquapda"
|
||||
};
|
||||
lcd_clear();
|
||||
document.getElementById("lcd-l2").innerHTML = " Connecting ";
|
||||
document.getElementById("lcd-l3").innerHTML = " Please wait! ";
|
||||
|
||||
_socket_di.send(JSON.stringify(msg));
|
||||
}
|
||||
|
||||
function get_devices() {
|
||||
var msg = {
|
||||
uri: "devices"
|
||||
};
|
||||
_socket_di.send(JSON.stringify(msg));
|
||||
}
|
||||
|
||||
function send_command(cmd) {
|
||||
_socket_di.send(JSON.stringify(cmd));
|
||||
}
|
||||
/*
|
||||
function reset() {
|
||||
_socket_di.send("reset\n");
|
||||
}
|
||||
*/
|
||||
function init() {
|
||||
if ( capture_iframe_focus() ) {
|
||||
// In iframe wait for focus event to start
|
||||
} else {
|
||||
update_status_message();
|
||||
startWebsockets();
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
<body onload="init();">
|
||||
<div class="wrapper">
|
||||
|
||||
<div class="inner">
|
||||
<div>
|
||||
<table border='0' id="deviceList">
|
||||
<tr>
|
||||
<th id="status" align="center" colspan="5"> </th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td colspan="3" align="center">
|
||||
<table border='0'>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td colspan="3" class="lcd_display" id="lcd-l0">
|
||||
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td colspan="3" class="lcd_display" id="lcd-l1">
|
||||
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td colspan="3" class="lcd_display" id="lcd-l2"></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td colspan="3" class="lcd_display" id="lcd-l3"> </td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td colspan="3" class="lcd_display" id="lcd-l4"> </td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td colspan="3" class="lcd_display" id="lcd-l5"> </td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td colspan="3" class="lcd_display" id="lcd-l6"> </td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td colspan="3" class="lcd_display" id="lcd-l7"> </td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td colspan="3" class="lcd_display" id="lcd-l8"> </td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td colspan="3" class="lcd_display" id="lcd-l9"> </td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<!--
|
||||
<tr>
|
||||
<td></td>
|
||||
<td colspan="3" class="lcd_display" id="lcd-l10"> </td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td colspan="3" class="lcd_display" id="lcd-l11"> </td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td colspan="3" class="lcd_display" id="lcd-l12"> </td>
|
||||
<td></td>
|
||||
</tr>
|
||||
-->
|
||||
</table>
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
<td align="center"><input class="button_s" id="Back" type="button" onclick="send(this);"value="↩"></td>
|
||||
<td align="center"><input class="button_s" id="Up" type="button" onclick="send(this);"value="↑"></td>
|
||||
<!--<td align="center"><input class="button_s" id="Power" type="button" onclick="send(this);"value="↻"></td>-->
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td align="center" colspan="3"><input id="Select" type="button" onclick="send(this);"
|
||||
value="Select"></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td align="center"><input class="button_s" id="Page_up" type="button" onclick="send(this);" value="1"></td>
|
||||
<td align="center"><input class="button_s" id="Down" type="button" onclick="send(this);"value="↓"></td>
|
||||
<td align="center"><input class="button_s" id="Page_down" type="button" onclick="send(this);" value="2">
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="5" id="version" class="version"> </td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<!--<div class="inner">END</div>-->
|
||||
<div id="pdaWarning" class='hide'>
|
||||
Warning<br>AqualinkD will not respond to commands while this window is open,<br>Please close when finished.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -141,6 +141,27 @@
|
|||
/*flex-direction: column;*/
|
||||
}
|
||||
|
||||
.simulator_pane {
|
||||
background-color: var(--options_pane_background);
|
||||
border: 2px solid var(--options_pane_bordercolor);
|
||||
border-radius: 20px;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
/* Actual size of sim 305 by 385 */
|
||||
width: 325px;
|
||||
height: 405px;
|
||||
padding: 10px;
|
||||
/*overflow-y: scroll; didn't work*/
|
||||
/*height: 100%;*/
|
||||
/*flex-basis: content;*/
|
||||
/*flex-direction: column;*/
|
||||
}
|
||||
|
||||
.simiframe {
|
||||
width: 305px;
|
||||
height: 385px;
|
||||
}
|
||||
|
||||
.options {
|
||||
top: 10px;
|
||||
/*left: 10px;*/
|
||||
|
@ -609,6 +630,8 @@
|
|||
document.getElementById('vspswitch_options').classList.remove("hide");
|
||||
document.getElementById('timer_options').classList.remove("hide");
|
||||
document.getElementById('scheduler_options').classList.remove("hide");
|
||||
//document.getElementById('simulator_options').classList.remove("hide");
|
||||
document.getElementById('simulator_iframe').classList.remove("hide");
|
||||
setColors();
|
||||
load_background();
|
||||
showTileOptions(false);
|
||||
|
@ -1233,6 +1256,7 @@
|
|||
document.getElementById('vspswitch_options').style.display = 'none';
|
||||
document.getElementById('timer_options').style.display = 'none';
|
||||
document.getElementById('scheduler_options').style.display = 'none';
|
||||
document.getElementById('simulator_iframe').style.display = 'none';
|
||||
} else if (id != null && document.getElementById(id).getAttribute('type') == 'switch_program') {
|
||||
active_option = document.getElementById('pswitch_options');
|
||||
document.getElementById('thermostat_options').style.display = 'none';
|
||||
|
@ -1240,6 +1264,7 @@
|
|||
document.getElementById('vspswitch_options').style.display = 'none';
|
||||
document.getElementById('timer_options').style.display = 'none';
|
||||
document.getElementById('scheduler_options').style.display = 'none';
|
||||
document.getElementById('simulator_iframe').style.display = 'none';
|
||||
} else if (id != null && document.getElementById(id).getAttribute('type') == 'setpoint_swg') {
|
||||
active_option = document.getElementById('swg_options');
|
||||
document.getElementById('thermostat_options').style.display = 'none';
|
||||
|
@ -1247,6 +1272,7 @@
|
|||
document.getElementById('vspswitch_options').style.display = 'none';
|
||||
document.getElementById('timer_options').style.display = 'none';
|
||||
document.getElementById('scheduler_options').style.display = 'none';
|
||||
document.getElementById('simulator_iframe').style.display = 'none';
|
||||
} else if (id != null && document.getElementById(id).getAttribute('type') == 'setpoint_freeze') {
|
||||
active_option = document.getElementById('swg_options');
|
||||
document.getElementById('thermostat_options').style.display = 'none';
|
||||
|
@ -1254,6 +1280,7 @@
|
|||
document.getElementById('vspswitch_options').style.display = 'none';
|
||||
document.getElementById('timer_options').style.display = 'none';
|
||||
document.getElementById('scheduler_options').style.display = 'none';
|
||||
document.getElementById('simulator_iframe').style.display = 'none';
|
||||
} else if (id != null && document.getElementById(id).getAttribute('type') == 'switch_vsp') {
|
||||
active_option = document.getElementById('vspswitch_options');
|
||||
document.getElementById('thermostat_options').style.display = 'none';
|
||||
|
@ -1261,6 +1288,7 @@
|
|||
document.getElementById('swg_options').style.display = 'none';
|
||||
document.getElementById('timer_options').style.display = 'none';
|
||||
document.getElementById('scheduler_options').style.display = 'none';
|
||||
document.getElementById('simulator_iframe').style.display = 'none';
|
||||
} else if (id != null && document.getElementById(id).getAttribute('type') == 'switch_timer') {
|
||||
active_option = document.getElementById('timer_options');
|
||||
document.getElementById('thermostat_options').style.display = 'none';
|
||||
|
@ -1268,6 +1296,7 @@
|
|||
document.getElementById('swg_options').style.display = 'none';
|
||||
document.getElementById('vspswitch_options').style.display = 'none';
|
||||
document.getElementById('scheduler_options').style.display = 'none';
|
||||
document.getElementById('simulator_iframe').style.display = 'none';
|
||||
} else if (id != null && document.getElementById(id).getAttribute('type') == 'scheduler') {
|
||||
active_option = document.getElementById('scheduler_options');
|
||||
document.getElementById('thermostat_options').style.display = 'none';
|
||||
|
@ -1275,6 +1304,15 @@
|
|||
document.getElementById('swg_options').style.display = 'none';
|
||||
document.getElementById('vspswitch_options').style.display = 'none';
|
||||
document.getElementById('timer_options').style.display = 'none';
|
||||
document.getElementById('simulator_iframe').style.display = 'none';
|
||||
} else if (id != null && document.getElementById(id).getAttribute('type') == 'simulator') {
|
||||
active_option = document.getElementById('simulator_iframe');
|
||||
document.getElementById('thermostat_options').style.display = 'none';
|
||||
document.getElementById('pswitch_options').style.display = 'none';
|
||||
document.getElementById('swg_options').style.display = 'none';
|
||||
document.getElementById('vspswitch_options').style.display = 'none';
|
||||
document.getElementById('timer_options').style.display = 'none';
|
||||
document.getElementById('scheduler_options').style.display = 'none';
|
||||
}
|
||||
|
||||
active_option.style.display = 'flex';
|
||||
|
@ -1310,6 +1348,7 @@
|
|||
document.getElementById('vspswitch_options').style.display = 'none';
|
||||
document.getElementById('timer_options').style.display = 'none';
|
||||
document.getElementById('scheduler_options').style.display = 'none';
|
||||
document.getElementById('simulator_iframe').style.display = 'none';
|
||||
document.getElementById('wrapper').classList.remove("opaque");
|
||||
return;
|
||||
}
|
||||
|
@ -1363,6 +1402,8 @@
|
|||
} else if (type == 'scheduler') {
|
||||
title = document.getElementById("scheduler_options_title");
|
||||
close_button = document.getElementById("scheduler_options_close");
|
||||
} else if (type == 'simulator') {
|
||||
close_button = document.getElementById("simulator_iframe_close");
|
||||
} else {
|
||||
slider = document.getElementById("option_slider_range");
|
||||
slider_output = document.getElementById("option_slider_text_value");
|
||||
|
@ -1415,6 +1456,8 @@
|
|||
|
||||
if (type == 'scheduler') {
|
||||
title.innerHTML = "Scheduler";
|
||||
} else if (type == 'simulator') {
|
||||
// title.innerHTML = "Simulator";
|
||||
} else {
|
||||
title.innerHTML = document.getElementById(id + '_name').innerHTML;
|
||||
}
|
||||
|
@ -1480,6 +1523,8 @@
|
|||
cs_clearSchedules();
|
||||
//cs_loadJSON("/api/schedules", cs_schedules,'jsonp');
|
||||
get_schedules();
|
||||
} else if (type == 'simulator') {
|
||||
startSimulator();
|
||||
} else {
|
||||
slider.value = sp_value;
|
||||
oswitch = document.getElementById("option_switch");
|
||||
|
@ -1597,6 +1642,7 @@
|
|||
if ( ! cs_createJSON() ) {
|
||||
return // This stops pane from closing.
|
||||
}
|
||||
} else if (type == 'simulator') {
|
||||
} else {
|
||||
var value = slider.value;
|
||||
if (state == (tile.getAttribute('status') == 'off'))
|
||||
|
@ -1673,6 +1719,16 @@
|
|||
}
|
||||
}
|
||||
|
||||
function showSimulator(caller){
|
||||
caller.setAttribute('type', 'simulator');
|
||||
showTileOptions(true, caller.id);
|
||||
}
|
||||
|
||||
function startSimulator() {
|
||||
console.log("Starting ifram sim init");
|
||||
document.getElementById('onetouch_iframe').display = 'block';
|
||||
}
|
||||
|
||||
// NSF CHANGE TO USING WS FOR THIS REQUEST
|
||||
/*
|
||||
function cs_loadJSON(path, success, error) {
|
||||
|
@ -2418,6 +2474,7 @@
|
|||
<!-- <div id='body_wrap' class='body_wrap' onmousedown='showTileOptions(false);'> -->
|
||||
<div id='wrapper' class="wrapper">
|
||||
<div id="header" class="head" onclick="showBackground();">
|
||||
<!--<div id="header" class="head" onclick="event.stopPropagation();showSimulator(this);">-->
|
||||
<table border='0' width='100%' cellpadding='0' cellspacing='0'>
|
||||
<tr>
|
||||
<td width="70px" align='left' id='td_name'><span class='title' id='name'
|
||||
|
@ -2426,7 +2483,7 @@
|
|||
<td align='center'><span class='title' id='message'></span>
|
||||
</td>
|
||||
<td width="70px" align='right' id='td_timedate'><span class='timedate' id='datetime'
|
||||
onclick="event.stopPropagation();showScheduler(this);"></class>
|
||||
onclick="event.stopPropagation();showScheduler(this);">X</class>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
@ -2650,6 +2707,14 @@
|
|||
</div>
|
||||
|
||||
|
||||
<div id="simulator_iframe" class='options hide'>
|
||||
<div id="onetouch_iframe" class="simulator_pane" onclick='event.stopPropagation();''>
|
||||
<iframe id="simulatoriframe" src="/onetouch_sim.html" class="simiframe"></iframe>
|
||||
<input type="button" class="options_button" id="simulator_iframe_close" value="Close">
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div id='scheduler_options' class='options hide'>
|
||||
<div id='scheduler_options_pane' class='scheduler_pane' onclick='event.stopPropagation();'>
|
||||
<table id="cronschedules" border="0">
|
||||
|
@ -2684,6 +2749,8 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</body>
|
||||
|
|
|
@ -0,0 +1,651 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang='en'>
|
||||
|
||||
<head>
|
||||
<meta http-equiv='Content-Type' content='text/html; charset=windows-1252'>
|
||||
<title>AqualinkD Simulator</title>
|
||||
<meta name='viewport' content='width=device-width'>
|
||||
<meta name='apple-mobile-web-app-capable' content='yes'>
|
||||
<meta name='apple-mobile-web-app-status-bar-style' content='black'>
|
||||
<meta name='apple-mobile-web-app-status-bar-style' content='black'>
|
||||
<link href="aqualinkd.png" rel="apple-touch-icon">
|
||||
<link href="aqualinkd.png" rel="icon">
|
||||
<style>
|
||||
html {}
|
||||
|
||||
body {
|
||||
font-family: 'HelveticaNeue-Light', 'Helvetica Neue Light', 'Helvetica Neue', Helvetica, Arial, 'Lucida Grande', sans-serif;
|
||||
font-weight: 300;
|
||||
background-color: white;
|
||||
color: #000000;
|
||||
margin: 0 !important;
|
||||
padding: 0 !important;
|
||||
display:flex;
|
||||
flex-direction:column;
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
/*position: absolute;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
height: 100%;*/
|
||||
}
|
||||
|
||||
table {
|
||||
background-color: rgb(221, 221, 221);
|
||||
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
th {
|
||||
/*
|
||||
background-color: white;
|
||||
border-spacing: 10px;*/
|
||||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
td {
|
||||
/*
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
*/
|
||||
/*padding: 10px;*/
|
||||
padding-top: 2px;
|
||||
padding-bottom: 2px;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
#title {
|
||||
background-color: rgb(200, 200, 200);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
input[type=button],
|
||||
input[type=submit],
|
||||
input[type=reset] {
|
||||
background-color: rgb(165, 165, 165);
|
||||
border: none;
|
||||
color: rgb(0, 0, 0);
|
||||
padding: 2px 2px;
|
||||
text-decoration: none;
|
||||
margin: 0px 0px;
|
||||
min-width: 60px;
|
||||
border-radius: 60px;
|
||||
}
|
||||
|
||||
.led {
|
||||
border-radius: calc(var(--tile_icon-height) / 2);
|
||||
border-radius: 20px;
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
filter: alpha(opacity=100);
|
||||
opacity: 1.0;
|
||||
}
|
||||
|
||||
.on {
|
||||
background-color: rgb(255, 0, 0);
|
||||
}
|
||||
|
||||
.off {
|
||||
background-color: rgb(116, 116, 116);
|
||||
}
|
||||
|
||||
.error {
|
||||
background-color: rgb(255, 0, 0) !important;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
.lcd_display {
|
||||
font-family: monospace;
|
||||
background-color: #2b2b2b;
|
||||
color: white;
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
.lcd_highlight {
|
||||
font-family: monospace;
|
||||
background-color: #8e1e1e !important;
|
||||
/*background-color: #8b7d7d !important;*/
|
||||
/*background-color: #868383 !important;*/
|
||||
color: white !important;
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
.version {
|
||||
/*font-family: monospace;*/
|
||||
font-size: x-small;
|
||||
}
|
||||
|
||||
|
||||
|
||||
</style>
|
||||
|
||||
<script type='text/javascript'>
|
||||
console.log("SIM LOAD");
|
||||
var _socket_di;
|
||||
var _keep_socket_alive=true;
|
||||
|
||||
const PKT_CMD = 3;
|
||||
const PKT_DATA1 = 4;
|
||||
const PKT_DATA2 = 5;
|
||||
const PKT_DATA3 = 6;
|
||||
|
||||
const CMD_PROBE = 0;
|
||||
const CMD_MSG_LONG = 4;
|
||||
const CMD_PDA_CLEAR = 9;
|
||||
const CMD_PDA_HIGHLIGHT = 8;
|
||||
const CMD_PDA_HIGHLIGHTCHARS = 16;
|
||||
const CMD_PDA_SHIFTLINES = 15;
|
||||
|
||||
const ONET_LINES = 11; // 0 to 11
|
||||
|
||||
var _hlightcharlineno = -1;
|
||||
var _hlightcharline = "";
|
||||
var _hlightcharstart = -1;
|
||||
var _hlightcharend = -1;
|
||||
|
||||
// See if we are in an iframe and capture focus
|
||||
function capture_iframe_focus() {
|
||||
|
||||
var targetNode = parent.document.getElementById('onetouch_iframe');
|
||||
/*
|
||||
if (targetNode == null)
|
||||
targetNode = parent.document.getElementById('simulator_iframe');*/
|
||||
|
||||
console.log("OneTouch checking if iframe");
|
||||
if (targetNode != null) {
|
||||
var observer = new MutationObserver(function(){
|
||||
if(targetNode.style.display != 'none'){
|
||||
console.log("OneTouch sim Displaying");
|
||||
startWebsockets();
|
||||
} else {
|
||||
console.log("OneTouch sim Hiding");
|
||||
stopWebsockets();
|
||||
}
|
||||
});
|
||||
observer.observe(targetNode, { attributes: true, childList: true });
|
||||
console.log("OneTouch in iframe");
|
||||
return true;
|
||||
}
|
||||
console.log("OneTouch no iframe");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
function send(source) {
|
||||
console.log("from" + source.id);
|
||||
|
||||
var cmd = {};
|
||||
cmd.uri = "simcmd"
|
||||
switch (source.id) {
|
||||
case "Up":
|
||||
cmd.value = "0x06";
|
||||
break;
|
||||
case "Down":
|
||||
cmd.value = "0x05";
|
||||
break;
|
||||
case "Select":
|
||||
cmd.value = "0x04";
|
||||
break;
|
||||
case "Page_up":
|
||||
cmd.value = "0x03";
|
||||
break;
|
||||
case "Back":
|
||||
cmd.value = "0x02";
|
||||
break;
|
||||
case "Page_down":
|
||||
cmd.value = "0x01";
|
||||
break;
|
||||
|
||||
default:
|
||||
alert("Unknown button");
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
cmd.value = todec(cmd.value);
|
||||
send_command(cmd);
|
||||
}
|
||||
|
||||
function tohex(value) {
|
||||
var rtn = parseInt(value).toString(16);
|
||||
if (rtn.length <= 1)
|
||||
return "0x0"+rtn;
|
||||
else
|
||||
return "0x"+rtn;
|
||||
}
|
||||
function todec(value) {
|
||||
let number = parseInt(value, 16);
|
||||
return number;
|
||||
}
|
||||
|
||||
|
||||
|
||||
function lcd_clear() {
|
||||
//var container = document.getElementById("lcd_display");
|
||||
for (i=0; i <= ONET_LINES; i++) {
|
||||
//container.lastElementChild.remove();
|
||||
//child = container.children[i];
|
||||
//console.log("Line "+i+" replacing "+child.innerHTML)
|
||||
//child.innerHTML = " ";
|
||||
var line = document.getElementById("lcd-l"+i);
|
||||
//console.log("Line "+i+" replacing "+line.innerHTML)
|
||||
line.innerHTML = " ";
|
||||
line.classList.remove("lcd_highlight");
|
||||
line.classList.add("lcd_display");
|
||||
}
|
||||
|
||||
lcd_clear_highlight_chrs(false);
|
||||
}
|
||||
|
||||
function lcd_display(lineno, message) {
|
||||
// We get lines 0,2,3,4,5,6.... no line 1. (so using 0 as 1)
|
||||
//if (lineno == 0){lineno=1;}
|
||||
var line = document.getElementById("lcd-l"+lineno);
|
||||
//console.log("Line "+lineno+" replacing '"+line.innerHTML+"' with '"+message+"'");
|
||||
line.innerHTML = message;
|
||||
|
||||
// See if we need to re-highlight any chrs
|
||||
check_rehighlight_chrs(lineno);
|
||||
}
|
||||
|
||||
function lcd_display_shiftlines(first, last, direction) {
|
||||
// Add 1 to first & last we get 0 to 10 not 1 to 11
|
||||
if (direction == 255) {
|
||||
for (i = first; i <= last; i++) {
|
||||
var line1 = document.getElementById("lcd-l" + i);
|
||||
var line2 = document.getElementById("lcd-l" + (i + 1));
|
||||
line1.innerHTML = line2.innerHTML;
|
||||
}
|
||||
} else if (direction == 1) {
|
||||
for (i = last; i >= first; i--) {
|
||||
var line1 = document.getElementById("lcd-l" + i);
|
||||
var line2 = document.getElementById("lcd-l" + (i - 1) );
|
||||
line1.innerHTML = line2.innerHTML;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function lcd_display_highlight(lineno) {
|
||||
// We get lines 0,2,3,4,5,6.... no line 1. (so using 0 as 1)
|
||||
//if (lineno == 0){lineno=1;}
|
||||
|
||||
for (i=0; i <= ONET_LINES; i++) {
|
||||
var line = document.getElementById("lcd-l"+i);
|
||||
if (i != lineno) {
|
||||
line.classList.remove("lcd_highlight");
|
||||
line.classList.add("lcd_display");
|
||||
//console.log("remove highlight to line #"+i+" "+line.innerHTML)
|
||||
} else {
|
||||
line.classList.add("lcd_highlight");
|
||||
line.classList.remove("lcd_display");
|
||||
//console.log("add highlight to line #"+i+" "+line.innerHTML)
|
||||
}
|
||||
}
|
||||
//line.classList.add("lcd_highlight");
|
||||
//line.classList.remove("lcd_display");
|
||||
}
|
||||
|
||||
|
||||
|
||||
function check_rehighlight_chrs(lineno) {
|
||||
if (_hlightcharlineno == lineno && _hlightcharstart >= 0 && _hlightcharend > 0 ) {
|
||||
// We would have received a new line text, so don't preserve old text
|
||||
lcd_display_highlight_chrs(_hlightcharlineno, _hlightcharstart, _hlightcharend, false);
|
||||
}
|
||||
}
|
||||
|
||||
function lcd_clear_highlight_chrs(preserve=true){
|
||||
|
||||
// if preserve, then we put back the old text.
|
||||
if (preserve && _hlightcharlineno >= 0 && _hlightcharline != "") {
|
||||
var line = document.getElementById("lcd-l"+_hlightcharlineno);
|
||||
line.innerHTML = _hlightcharline;
|
||||
}
|
||||
|
||||
_hlightcharlineno = -1;
|
||||
_hlightcharline = "";
|
||||
_hlightcharstart = -1;
|
||||
_hlightcharend = -1;
|
||||
}
|
||||
|
||||
function lcd_display_highlight_chrs(lineno, start, end, preserve=true) {
|
||||
|
||||
lcd_clear_highlight_chrs(preserve);
|
||||
|
||||
var line = document.getElementById("lcd-l"+lineno);
|
||||
text = line.innerHTML;
|
||||
|
||||
var newtxt = text.slice(0, end+1) + "</span>" + text.slice(end+1);
|
||||
var newtxt = newtxt.slice(0, start) + "<span class=\"lcd_highlight\">" + newtxt.slice(start);
|
||||
line.innerHTML = newtxt;
|
||||
|
||||
_hlightcharlineno = lineno;
|
||||
_hlightcharline = text;
|
||||
_hlightcharstart = start;
|
||||
_hlightcharend = end;
|
||||
|
||||
console.log("Line '"+text+"' now '"+newtxt+"'");
|
||||
}
|
||||
|
||||
function packet_to_ascii(packet) {
|
||||
var msg="";
|
||||
|
||||
for (i=5; i <= 20; i++) {
|
||||
if (packet[i] >= 31 && packet[i] <= 127) {
|
||||
msg=msg+String.fromCharCode(packet[i]);
|
||||
} else if (packet[i] == 223) {
|
||||
msg=msg+"°";
|
||||
} else if (packet[i] == 0) {
|
||||
break; // End on a nul
|
||||
} else {
|
||||
console.log("Bad char in string '"+msg+"' next ("+packet[i]+")" );
|
||||
}
|
||||
}
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
|
||||
|
||||
function process_packet(data) {
|
||||
|
||||
if (data.simtype != "onetouch") {
|
||||
update_status_message("! Another simulator running !", true);
|
||||
return;
|
||||
}
|
||||
|
||||
switch(data.dec[PKT_CMD]) {
|
||||
case CMD_PROBE:
|
||||
// We are about to start
|
||||
document.getElementById("lcd-l2").innerHTML = " Connected ";
|
||||
document.getElementById("lcd-l3").innerHTML = "";
|
||||
break;
|
||||
case CMD_PDA_CLEAR: // Clear
|
||||
//console.log("Received Clear");
|
||||
lcd_clear();
|
||||
break;
|
||||
case CMD_MSG_LONG: // Message
|
||||
//console.log("Received Line "+data.dec[PKT_DATA1]+" = "+packet_to_ascii(data.dec));
|
||||
lcd_display(data.dec[PKT_DATA1], packet_to_ascii(data.dec));
|
||||
break;
|
||||
case CMD_PDA_HIGHLIGHT:
|
||||
//console.log("Received Highlight "+data.dec[PKT_DATA1]);
|
||||
// We sometimes get 255 for line number, need to find out why
|
||||
lcd_display_highlight(data.dec[PKT_DATA1]);
|
||||
break;
|
||||
case CMD_PDA_HIGHLIGHTCHARS:
|
||||
//console.log("Received Highlight chars, Line="+data.dec[PKT_DATA1]+", Start="+data.dec[PKT_DATA2]+", Stop="+data.dec[PKT_DATA3]);
|
||||
lcd_display_highlight_chrs(data.dec[PKT_DATA1], data.dec[PKT_DATA2], data.dec[PKT_DATA3]);
|
||||
break;
|
||||
case CMD_PDA_SHIFTLINES:
|
||||
//console.log("Received shift lines, Start=" + data.dec[PKT_DATA1] + ", End=" + data.dec[PKT_DATA2] + ", Direction=" + data.dec[PKT_DATA3]);
|
||||
lcd_display_shiftlines(data.dec[PKT_DATA1], data.dec[PKT_DATA2], data.dec[PKT_DATA3]);
|
||||
break;
|
||||
default:
|
||||
// 2 is READY for commands
|
||||
console.log("Received unknown command "+data.dec[PKT_CMD]+" "+tohex(data.dec[PKT_CMD]));
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
function update_status_message(message=null, error=false) {
|
||||
const status = document.getElementById("status");
|
||||
|
||||
if (message != null) {
|
||||
status.innerHTML = message;
|
||||
} else {
|
||||
status.innerHTML = "AqualinkD Onetouch Simulator";
|
||||
}
|
||||
|
||||
if (error) {
|
||||
status.classList.add("error");
|
||||
} else {
|
||||
status.classList.remove("error");
|
||||
}
|
||||
}
|
||||
|
||||
function update_status(data) {
|
||||
// Some form of error if PDA only panel.
|
||||
if (data.panel_type.startsWith("PDA")) {
|
||||
//document.getElementById("status").innerHTML = ' !!! PDA only panels are not Supported !!! '
|
||||
//document.getElementById("status").classList.add("error");
|
||||
update_status_message("PDA only panels are not Supported", true);
|
||||
}
|
||||
|
||||
const versionlabel = document.getElementById("version");
|
||||
if (versionlabel.innerHTML = " ") {
|
||||
versionlabel.innerHTML = "AqualinkD "+data.aqualinkd_version+"<br>"+data.panel_type+" "+data.version;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
function get_appropriate_ws_url() {
|
||||
var pcol;
|
||||
var u = document.URL;
|
||||
/*
|
||||
* We open the websocket encrypted if this page came on an
|
||||
* https:// url itself, otherwise unencrypted
|
||||
*/
|
||||
if (u.substring(0, 5) == "https") {
|
||||
pcol = "wss://";
|
||||
u = u.substr(8);
|
||||
} else {
|
||||
pcol = "ws://";
|
||||
if (u.substring(0, 4) == "http")
|
||||
u = u.substr(7);
|
||||
}
|
||||
u = u.split('/');
|
||||
//alert (pcol + u[0] + ":6500");
|
||||
return pcol + u[0];
|
||||
}
|
||||
/* dumb increment protocol */
|
||||
|
||||
|
||||
function startWebsockets() {
|
||||
_socket_di = new WebSocket(get_appropriate_ws_url());
|
||||
_keep_socket_alive = true;
|
||||
try {
|
||||
_socket_di.onopen = function () {
|
||||
// success!
|
||||
start_simulator();
|
||||
//get_devices();
|
||||
}
|
||||
_socket_di.onmessage = function got_packet(msg) {
|
||||
update_status_message();
|
||||
var data = JSON.parse(msg.data);
|
||||
if (data.type == 'simpacket') {
|
||||
process_packet(data);
|
||||
} else if (data.type == 'status') {
|
||||
update_status(data);
|
||||
}
|
||||
}
|
||||
_socket_di.onclose = function () {
|
||||
// something went wrong
|
||||
//document.getElementById("status").innerHTML = ' !!! Connection error !!! '
|
||||
//document.getElementById("status").classList.add("error");
|
||||
update_status_message("!!! Connection error !!!", true);
|
||||
// Try to reconnect every 5 seconds.
|
||||
setTimeout(function () {
|
||||
if (_keep_socket_alive == true) {
|
||||
startWebsockets();
|
||||
}
|
||||
}, 5000);
|
||||
}
|
||||
} catch (exception) {
|
||||
alert('<p>Error' + exception);
|
||||
}
|
||||
}
|
||||
|
||||
function stopWebsockets() {
|
||||
if (_socket_di) {
|
||||
_socket_di.close();
|
||||
}
|
||||
_keep_socket_alive = false;
|
||||
}
|
||||
|
||||
function start_simulator() {
|
||||
var msg = {
|
||||
//command: "simulator"
|
||||
uri: "simulator/onetouch"
|
||||
};
|
||||
lcd_clear();
|
||||
document.getElementById("lcd-l2").innerHTML = " Connecting ";
|
||||
document.getElementById("lcd-l3").innerHTML = " Please wait! ";
|
||||
|
||||
_socket_di.send(JSON.stringify(msg));
|
||||
}
|
||||
|
||||
function get_devices() {
|
||||
var msg = {
|
||||
uri: "devices"
|
||||
};
|
||||
_socket_di.send(JSON.stringify(msg));
|
||||
}
|
||||
|
||||
function send_command(cmd) {
|
||||
_socket_di.send(JSON.stringify(cmd));
|
||||
}
|
||||
/*
|
||||
function reset() {
|
||||
_socket_di.send("reset\n");
|
||||
}
|
||||
*/
|
||||
function init() {
|
||||
if ( capture_iframe_focus() ) {
|
||||
// In iframe wait for focus event to start
|
||||
} else {
|
||||
update_status_message();
|
||||
startWebsockets();
|
||||
}
|
||||
}
|
||||
|
||||
// Print all events
|
||||
/*
|
||||
Object.keys(window).forEach(key => {
|
||||
if (/^on/.test(key)) {
|
||||
window.addEventListener(key.slice(2), event => {
|
||||
console.log(event);
|
||||
|
||||
});
|
||||
}
|
||||
});
|
||||
*/
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
<body onload="init();">
|
||||
<div class="wrapper">
|
||||
|
||||
<div class="inner">
|
||||
|
||||
<table border='0' id="deviceList">
|
||||
<tr>
|
||||
<th id="status" align="center" colspan="3"> </th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="lcd_display" id="lcd-l0"> </td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="lcd_display" id="lcd-l1"></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><input id="Page_up" type="button" onclick="send(this);" value="↑↑"></td>
|
||||
<td class="lcd_display" id="lcd-l2"></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="lcd_display" id="lcd-l3"> </td>
|
||||
<td><input id="Up" type="button" onclick="send(this);" value="↑"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="lcd_display" id="lcd-l4"> </td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><input id="Back" type="button" onclick="send(this);" value="↩"></td>
|
||||
<td class="lcd_display" id="lcd-l5"> </td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="lcd_display" id="lcd-l6"> </td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="lcd_display" id="lcd-l7"> </td>
|
||||
<td><input id="Down" type="button" onclick="send(this);" value="↓"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><input id="Page_down" type="button" onclick="send(this);" value="↓↓"></td>
|
||||
<td class="lcd_display" id="lcd-l8"> </td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="lcd_display" id="lcd-l9"> </td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="lcd_display" id="lcd-l10"> </td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="lcd_display"id="lcd-l11"> </td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<!--
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="lcd_display" id="lcd-l12"> </td>
|
||||
<td></td>
|
||||
</tr>
|
||||
-->
|
||||
<tr>
|
||||
<td></td>
|
||||
<th align="center"><input id="Select" type="button" onclick="send(this);" value="Select"></th>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="3" id="version" class="version"> </td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<!--<div class="inner">END</div>-->
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
||||
|
|
@ -10,590 +10,111 @@
|
|||
<meta name='apple-mobile-web-app-status-bar-style' content='black'>
|
||||
<link href="aqualinkd.png" rel="apple-touch-icon">
|
||||
<link href="aqualinkd.png" rel="icon">
|
||||
|
||||
<style>
|
||||
html {}
|
||||
|
||||
body {
|
||||
font-family: 'HelveticaNeue-Light', 'Helvetica Neue Light', 'Helvetica Neue', Helvetica, Arial, 'Lucida Grande', sans-serif;
|
||||
font-weight: 300;
|
||||
background-color: white;
|
||||
color: #000000;
|
||||
margin: 0 !important;
|
||||
padding: 0 !important;
|
||||
/* Style the tab */
|
||||
.tab {
|
||||
overflow: hidden;
|
||||
border: 1px solid #ccc;
|
||||
background-color: #f1f1f1;
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
/*position: absolute;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
height: 100%;*/
|
||||
}
|
||||
|
||||
table {
|
||||
background-color: rgb(221, 221, 221);
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
th {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
#title {
|
||||
background-color: rgb(200, 200, 200);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
input[type=button],
|
||||
input[type=submit],
|
||||
input[type=reset] {
|
||||
background-color: rgb(165, 165, 165);
|
||||
/* Style the buttons that are used to open the tab content */
|
||||
.tab button {
|
||||
background-color: inherit;
|
||||
float: left;
|
||||
border: none;
|
||||
color: rgb(0, 0, 0);
|
||||
padding: 2px 2px;
|
||||
text-decoration: none;
|
||||
margin: 0px 0px;
|
||||
min-width: 70px;
|
||||
border-radius: 70px;
|
||||
outline: none;
|
||||
cursor: pointer;
|
||||
padding: 14px 16px;
|
||||
transition: 0.3s;
|
||||
}
|
||||
|
||||
.led {
|
||||
border-radius: calc(var(--tile_icon-height) / 2);
|
||||
border-radius: 20px;
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
filter: alpha(opacity=100);
|
||||
opacity: 1.0;
|
||||
/* Change background color of buttons on hover */
|
||||
.tab button:hover {
|
||||
background-color: #ddd;
|
||||
}
|
||||
|
||||
.on {
|
||||
background-color: rgb(255, 0, 0);
|
||||
/* Create an active/current tablink class */
|
||||
.tab button.active {
|
||||
background-color: #ccc;
|
||||
}
|
||||
|
||||
.off {
|
||||
background-color: rgb(116, 116, 116);
|
||||
/* Style the tab content */
|
||||
.tabcontent {
|
||||
display: none;
|
||||
/*padding: 6px 12px;*/
|
||||
border: 1px solid #ccc;
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
.error {
|
||||
background-color: rgb(255, 0, 0) !important;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
.tabiframe {
|
||||
width: 100%;
|
||||
height: 500px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script type='text/javascript'>
|
||||
function openPage(evt, pageName) {
|
||||
// Declare all variables
|
||||
var i, tabcontent, tablinks;
|
||||
|
||||
var _panel_size = 6;
|
||||
var _panel_set = 0;
|
||||
|
||||
function send(source) {
|
||||
console.log("from" + source.id);
|
||||
|
||||
var cmd = {};
|
||||
cmd.uri = "rawcommand"
|
||||
switch (source.id) {
|
||||
case "Filter_Pump_button":
|
||||
cmd.value = "0x02";
|
||||
break;
|
||||
case "Spa_Mode_button":
|
||||
cmd.value = "0x01";
|
||||
break;
|
||||
case "Aux_1_button":
|
||||
cmd.value = "0x05";
|
||||
break;
|
||||
case "Aux_2_button":
|
||||
cmd.value = "0x0a";
|
||||
break;
|
||||
case "Aux_3_button":
|
||||
cmd.value = "0x0f";
|
||||
break;
|
||||
case "Aux_4_button":
|
||||
if (_panel_size < 12)
|
||||
cmd.value = "0x06";
|
||||
else
|
||||
cmd.value = "0x14"; //Different on RS12+ (0x14)
|
||||
break;
|
||||
case "Aux_5_button":
|
||||
if (_panel_size < 12)
|
||||
cmd.value = "0x0b";
|
||||
else
|
||||
cmd.value = "0x03"; //Different on RS12+ (0x03)
|
||||
break;
|
||||
case "Aux_6_button":
|
||||
if (_panel_size < 12)
|
||||
cmd.value = "0x10";
|
||||
else
|
||||
cmd.value = "0x07"; //Different on RS12+ (0x07)
|
||||
break;
|
||||
case "Aux_7_button":
|
||||
if (_panel_size < 12)
|
||||
cmd.value = "0x15";
|
||||
else
|
||||
cmd.value = "0x06"; //Different on RS12+ (0x06)
|
||||
break;
|
||||
case "Aux_B1_button":
|
||||
cmd.value = "0x0b";
|
||||
break;
|
||||
case "Aux_B2_button":
|
||||
cmd.value = "0x10";
|
||||
break;
|
||||
case "Aux_B3_button":
|
||||
cmd.value = "0x15";
|
||||
break;
|
||||
case "Aux_B4_button":
|
||||
cmd.value = "0x1a";
|
||||
break;
|
||||
case "Aux_B5_button":
|
||||
cmd.value = "0x04";
|
||||
break;
|
||||
case "Aux_B6_button":
|
||||
cmd.value = "0x08";
|
||||
break;
|
||||
case "Aux_B7_button":
|
||||
cmd.value = "0x0d";
|
||||
break;
|
||||
case "Aux_B8_button":
|
||||
cmd.value = "0x0c";
|
||||
break;
|
||||
case "Pool_Heater_button":
|
||||
cmd.value = "0x12";
|
||||
break;
|
||||
case "Spa_Heater_button":
|
||||
cmd.value = "0x17";
|
||||
break;
|
||||
case "Solar_Heater_button":
|
||||
cmd.value = "0x1c";
|
||||
break;
|
||||
case "B_menu":
|
||||
cmd.value = "0x09";
|
||||
break;
|
||||
case "B_cancel":
|
||||
cmd.value = "0x0e";
|
||||
break;
|
||||
case "B_back":
|
||||
cmd.value = "0x13";
|
||||
break;
|
||||
case "B_forward":
|
||||
cmd.value = "0x18";
|
||||
break;
|
||||
case "B_enter":
|
||||
cmd.value = "0x1d";
|
||||
break;
|
||||
case "B_hold":
|
||||
cmd.value = "0x19";
|
||||
break;
|
||||
case "B_overide":
|
||||
cmd.value = "0x1c";
|
||||
break;
|
||||
default:
|
||||
alert("Unknown button");
|
||||
return;
|
||||
break;
|
||||
// Get all elements with class="tabcontent" and hide them
|
||||
tabcontent = document.getElementsByClassName("tabcontent");
|
||||
for (i = 0; i < tabcontent.length; i++) {
|
||||
tabcontent[i].style.display = "none";
|
||||
}
|
||||
|
||||
cmd.value = todec(cmd.value);
|
||||
send_command(cmd);
|
||||
|
||||
// I know we are converting hex to dec and back to hex, but here for checking.
|
||||
document.getElementById("messages").innerHTML = "Sent "+tohex(cmd.value)+" please wait for response!";
|
||||
}
|
||||
|
||||
function tohex(value) {
|
||||
var rtn = parseInt(value).toString(16);
|
||||
if (rtn.length <= 1)
|
||||
return "0x0"+rtn;
|
||||
else
|
||||
return "0x"+rtn;
|
||||
}
|
||||
function todec(value) {
|
||||
let number = parseInt(value, 16);
|
||||
return number;
|
||||
}
|
||||
|
||||
function set_panel_size(size)
|
||||
{
|
||||
if (_panel_set == size){
|
||||
return;
|
||||
// Get all elements with class="tablinks" and remove the class "active"
|
||||
tablinks = document.getElementsByClassName("tablinks");
|
||||
for (i = 0; i < tablinks.length; i++) {
|
||||
tablinks[i].className = tablinks[i].className.replace(" active", "");
|
||||
}
|
||||
|
||||
_panel_set = size;
|
||||
// Show the current tab, and add an "active" class to the button that opened the tab
|
||||
document.getElementById(pageName).style.display = "block";
|
||||
|
||||
switch(size){
|
||||
case 6:
|
||||
document.getElementById("Aux_6_led").classList.add("hidden");
|
||||
document.getElementById("Aux_6_button").classList.add("hidden");
|
||||
document.getElementById("Aux_7_led").classList.add("hidden");
|
||||
document.getElementById("Aux_7_button").classList.add("hidden");
|
||||
case 8:
|
||||
document.getElementById("Aux_B1_led").classList.add("hidden");
|
||||
document.getElementById("Aux_B1_button").classList.add("hidden");
|
||||
document.getElementById("Aux_B2_led").classList.add("hidden");
|
||||
document.getElementById("Aux_B2_button").classList.add("hidden");
|
||||
document.getElementById("Aux_B3_led").classList.add("hidden");
|
||||
document.getElementById("Aux_B3_button").classList.add("hidden");
|
||||
document.getElementById("Aux_B4_led").classList.add("hidden");
|
||||
document.getElementById("Aux_B4_button").classList.add("hidden");
|
||||
case 12:
|
||||
document.getElementById("Aux_B5_button").classList.add("hidden");
|
||||
document.getElementById("Aux_B6_button").classList.add("hidden");
|
||||
document.getElementById("Aux_B7_button").classList.add("hidden");
|
||||
document.getElementById("Aux_B8_button").classList.add("hidden");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
function update_status(data) {
|
||||
// Some form of error if PDA only panel.
|
||||
if (data.panel_type.startsWith("PDA")) {
|
||||
document.getElementById("title").innerHTML = ' !!! PDA only panels are not Supported !!! '
|
||||
document.getElementById("title").classList.add("error");
|
||||
document.getElementById("messages").innerHTML = ' !!! PDA Not Supported !!! '
|
||||
document.getElementById("messages").classList.add("error");
|
||||
}
|
||||
|
||||
if (document.getElementById("status").getAttribute("raw") != data.panel_message) {
|
||||
document.getElementById("status_three").innerHTML = document.getElementById("status_two").innerHTML;
|
||||
document.getElementById("status_two").innerHTML = document.getElementById("status").innerHTML;
|
||||
if (data.panel_message == "") {
|
||||
document.getElementById("status").innerHTML = " ";
|
||||
} else {
|
||||
document.getElementById("status").innerHTML = data.panel_message;
|
||||
}
|
||||
document.getElementById("status").setAttribute("raw", data.panel_message);
|
||||
document.getElementById("messages").innerHTML = " ";
|
||||
}
|
||||
|
||||
for (var obj in data.leds) {
|
||||
if ((led = document.getElementById(obj.toString() + "_led")) == null) {
|
||||
//console.log("Error " + obj.toString() + " LED not found");
|
||||
//return;
|
||||
} else {
|
||||
if (data.leds[obj] == "on" || data.leds[obj] == "enabled" || data.leds[obj] == "flash") {
|
||||
//console.log("Set " + obj.toString() + " LED on");
|
||||
led.classList.add("on");
|
||||
led.classList.remove("off");
|
||||
} else {
|
||||
//console.log("Set " + obj.toString() + " LED off");
|
||||
led.classList.add("off");
|
||||
led.classList.remove("on");
|
||||
}
|
||||
}
|
||||
if (obj.toString() == "Aux_4" && _panel_size < 6)
|
||||
_panel_size=6;
|
||||
if (obj.toString() == "Aux_6" && _panel_size < 8)
|
||||
_panel_size=8;
|
||||
if (obj.toString() == "Aux_B1" && _panel_size < 12)
|
||||
_panel_size=12;
|
||||
if (obj.toString() == "Aux_B4")
|
||||
_panel_size=16;
|
||||
}
|
||||
|
||||
set_panel_size(_panel_size);
|
||||
}
|
||||
|
||||
function update_device(data) {
|
||||
for (var obj in data['devices']) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function set_labels(data) {
|
||||
for (var obj in data) {
|
||||
if ((button = document.getElementById(obj + "_button")) != null && data[obj] != "NONE") {
|
||||
button.value = data[obj];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function get_appropriate_ws_url() {
|
||||
var pcol;
|
||||
var u = document.URL;
|
||||
/*
|
||||
* We open the websocket encrypted if this page came on an
|
||||
* https:// url itself, otherwise unencrypted
|
||||
*/
|
||||
if (u.substring(0, 5) == "https") {
|
||||
pcol = "wss://";
|
||||
u = u.substr(8);
|
||||
if (evt != null) {
|
||||
evt.currentTarget.className += " active";
|
||||
} else {
|
||||
pcol = "ws://";
|
||||
if (u.substring(0, 4) == "http")
|
||||
u = u.substr(7);
|
||||
document.getElementById('opentab').className += " active";
|
||||
}
|
||||
u = u.split('/');
|
||||
//alert (pcol + u[0] + ":6500");
|
||||
return pcol + u[0];
|
||||
}
|
||||
/* dumb increment protocol */
|
||||
var socket_di;
|
||||
|
||||
function startWebsockets() {
|
||||
socket_di = new WebSocket(get_appropriate_ws_url());
|
||||
try {
|
||||
socket_di.onopen = function () {
|
||||
// success!
|
||||
start_simulator();
|
||||
get_devices();
|
||||
}
|
||||
socket_di.onmessage = function got_packet(msg) {
|
||||
document.getElementById("status").classList.remove("error");
|
||||
var data = JSON.parse(msg.data);
|
||||
if (data.type == 'status') {
|
||||
update_status(data);
|
||||
} else if (data.type == 'devices') {
|
||||
//update_status(data);
|
||||
update_device(data);
|
||||
} else if (data.type == 'aux_labels') {
|
||||
set_labels(data);
|
||||
}
|
||||
}
|
||||
socket_di.onclose = function () {
|
||||
// something went wrong
|
||||
document.getElementById("status").innerHTML = ' !!! Connection error !!! '
|
||||
document.getElementById("status").classList.add("error");
|
||||
// Try to reconnect every 5 seconds.
|
||||
setTimeout(function () {
|
||||
startWebsockets();
|
||||
}, 5000);
|
||||
}
|
||||
} catch (exception) {
|
||||
alert('<p>Error' + exception);
|
||||
}
|
||||
}
|
||||
|
||||
function start_simulator() {
|
||||
var msg = {
|
||||
//command: "simulator"
|
||||
uri: "simulator"
|
||||
};
|
||||
socket_di.send(JSON.stringify(msg));
|
||||
}
|
||||
|
||||
function get_devices() {
|
||||
var msg = {
|
||||
uri: "devices"
|
||||
};
|
||||
socket_di.send(JSON.stringify(msg));
|
||||
}
|
||||
|
||||
function send_command(cmd) {
|
||||
socket_di.send(JSON.stringify(cmd));
|
||||
}
|
||||
/*
|
||||
function reset() {
|
||||
socket_di.send("reset\n");
|
||||
}
|
||||
*/
|
||||
function init() {
|
||||
startWebsockets();
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
<body onload="init();">
|
||||
<div class="wrapper">
|
||||
|
||||
<table border='0' id="deviceList">
|
||||
<tr style="title">
|
||||
<td style="title" colspan="12" align="center"><label id="title"> AqualinkD All Button Simulator </label></th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="12" align="center"><label id="status_three"> </label></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="12" align="center"><label id="status_two"> </label></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th colspan="12"><label id="status">AqualinkD</label></th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<div id="Filter_Pump_led" class="led off"></div>
|
||||
</td>
|
||||
<td align="left">
|
||||
<input id="Filter_Pump_button" type="button" onclick="send(this);" value="Filter Pump">
|
||||
</td>
|
||||
<td align="right">
|
||||
<div id="Spa_Mode_led" class="led off"></div>
|
||||
</td>
|
||||
<td align="left">
|
||||
<input id="Spa_Mode_button" type="button" onclick="send(this);" value="Spa Mode">
|
||||
</td>
|
||||
<td align="right">
|
||||
<div id="Aux_1_led" class="led off"></div>
|
||||
</td>
|
||||
<td align="left">
|
||||
<input id="Aux_1_button" type="button" onclick="send(this);" value="AUX1">
|
||||
</td>
|
||||
<td align="right">
|
||||
<div id="Aux_2_led" class="led off"></div>
|
||||
</td>
|
||||
<td align="left">
|
||||
<input id="Aux_2_button" type="button" onclick="send(this);" value="AUX2">
|
||||
</td>
|
||||
<td align="right">
|
||||
<div id="Aux_3_led" class="led off"></div>
|
||||
</td>
|
||||
<td align="left">
|
||||
<input id="Aux_3_button" type="button" onclick="send(this);" value="AUX3">
|
||||
</td>
|
||||
<td align="right">
|
||||
<div id="Aux_4_led" class="led off"></div>
|
||||
</td>
|
||||
<td align="left">
|
||||
<input id="Aux_4_button" type="button" onclick="send(this);" value="AUX4">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<div id="Aux_5_led" class="led off"></div>
|
||||
</td>
|
||||
<td align="left">
|
||||
<input id="Aux_5_button" type="button" onclick="send(this);" value="AUX5">
|
||||
</td>
|
||||
<td align="right">
|
||||
<div id="Aux_6_led" class="led off"></div>
|
||||
</td>
|
||||
<td align="left">
|
||||
<input id="Aux_6_button" type="button" onclick="send(this);" value="AUX6">
|
||||
</td>
|
||||
<td align="right">
|
||||
<div id="Aux_7_led" class="led off"></div>
|
||||
</td>
|
||||
<td align="left">
|
||||
<input id="Aux_7_button" type="button" onclick="send(this);" value="AUX7">
|
||||
</td>
|
||||
<td align="right">
|
||||
<div id="Aux_B1_led" class="led off"></div>
|
||||
</td>
|
||||
<td align="left">
|
||||
<input id="Aux_B1_button" type="button" onclick="send(this);" value="AUXB1">
|
||||
</td>
|
||||
<td align="right">
|
||||
<div id="Aux_B2_led" class="led off"></div>
|
||||
</td>
|
||||
<td align="left">
|
||||
<input id="Aux_B2_button" type="button" onclick="send(this);" value="AUXB2">
|
||||
</td>
|
||||
<td align="right">
|
||||
<div id="Aux_B3_led" class="led off"></div>
|
||||
</td>
|
||||
<td align="left">
|
||||
<input id="Aux_B3_button" type="button" onclick="send(this);" value="AUXB3">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<div id="Aux_B4_led" class="led off"></div>
|
||||
</td>
|
||||
<td align="left">
|
||||
<input id="Aux_B4_button" type="button" onclick="send(this);" value="AUXB4">
|
||||
</td>
|
||||
<td align="right">
|
||||
|
||||
</td>
|
||||
<td align="left">
|
||||
<input id="Aux_B5_button" type="button" onclick="send(this);" value="AUXB5">
|
||||
</td>
|
||||
<td align="right">
|
||||
|
||||
</td>
|
||||
<td align="left">
|
||||
<input id="Aux_B6_button" type="button" onclick="send(this);" value="AUXB6">
|
||||
</td>
|
||||
<td align="right">
|
||||
|
||||
</td>
|
||||
<td align="left">
|
||||
<input id="Aux_B7_button" type="button" onclick="send(this);" value="AUXB7">
|
||||
</td>
|
||||
<td align="right">
|
||||
|
||||
</td>
|
||||
<td align="left">
|
||||
<input id="Aux_B8_button" type="button" onclick="send(this);" value="AUXB8">
|
||||
</td>
|
||||
<td align="right">
|
||||
|
||||
</td>
|
||||
<td align="left">
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
|
||||
</td>
|
||||
<td align="left">
|
||||
|
||||
</td>
|
||||
<td align="right">
|
||||
|
||||
</td>
|
||||
<td align="left">
|
||||
|
||||
</td>
|
||||
<td align="right">
|
||||
|
||||
</td>
|
||||
<td align="left">
|
||||
|
||||
</td>
|
||||
<td align="right">
|
||||
<div id="Pool_Heater_led" class="led off"></div>
|
||||
</td>
|
||||
<td align="left">
|
||||
<input id="Pool_Heater_button" type="button" onclick="send(this);" value="Pool Heater">
|
||||
</td>
|
||||
<td align="right">
|
||||
<div id="Spa_Heater_led" class="led off"></div>
|
||||
</td>
|
||||
<td align="left">
|
||||
<input id="Spa_Heater_button" type="button" onclick="send(this);" value="Spa Heater">
|
||||
</td>
|
||||
<td align="right">
|
||||
<div id="Solar_Heater_led" class="led off"></div>
|
||||
</td>
|
||||
<td align="left">
|
||||
<input id="Solar_Heater_button" type="button" onclick="send(this);" value="Solar Heater">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<TD> </TD>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" colspan="2">
|
||||
<input type="button" onclick="send(this);" id="B_menu" value="Menu">
|
||||
</td>
|
||||
<td align="center" colspan="2">
|
||||
<input type="button" onclick="send(this);" id="B_cancel" value="Cancel">
|
||||
</td>
|
||||
<td align="center" colspan="2">
|
||||
<input type="button" onclick="send(this);" id="B_back" value="Back <">
|
||||
</td>
|
||||
<td align="center" colspan="2">
|
||||
<input type="button" onclick="send(this);" id="B_forward" value="Forward >">
|
||||
</td>
|
||||
<td align="center" colspan="2">
|
||||
<input type="button" onclick="send(this);" id="B_enter" value="Enter *">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="12" align="center"><label id="messages"> </label></td>
|
||||
</tr>
|
||||
</table>
|
||||
<body onload="openPage(null, 'aqualinka_iframe');">
|
||||
<div class="wrapper">
|
||||
<div class="tab">
|
||||
<button id="opentab" class="tablinks" onclick="openPage(event, 'aqualinka_iframe')">AqualinkD</button>
|
||||
<button class="tablinks" onclick="openPage(event, 'allbutton_iframe')">Allbutton Simulator</button>
|
||||
<button class="tablinks" onclick="openPage(event, 'onetouch_iframe')">One Touch Simulator</button>
|
||||
<!--<button class="tablinks" onclick="openPage(event, 'iaqtouch')">iAqualink Touch Simulator</button>-->
|
||||
<button class="tablinks" onclick="openPage(event, 'aquapda_iframe')">PDA Simulator</button>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
<!-- Tab content -->
|
||||
<div id="aqualinka_iframe" class="tabcontent">
|
||||
<iframe id="aqd" src="/" class="tabiframe"></iframe>
|
||||
</div>
|
||||
|
||||
<div id="allbutton_iframe" class="tabcontent">
|
||||
<iframe id="aqd" src="/allbutton_sim.html" class="tabiframe"></iframe>
|
||||
</div>
|
||||
|
||||
<div id="onetouch_iframe" class="tabcontent">
|
||||
<iframe id="aqd" src="/onetouch_sim.html" class="tabiframe"></iframe>
|
||||
</div>
|
||||
|
||||
<div id="aquapda_iframe" class="tabcontent">
|
||||
<iframe id="aqd" src="/aquapda_sim.html" class="tabiframe"></iframe>
|
||||
</div>
|
||||
|
||||
<div id="iaqtouch_iframe" class="tabcontent">
|
||||
<iframe id="aqd" src="/iaqtouch_sim.html" class="tabiframe"></iframe>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
Loading…
Reference in New Issue