mirror of https://github.com/sfeakes/AqualinkD.git
Version 2.3.2
parent
1e1e825829
commit
4a6c948a6a
26
Makefile
26
Makefile
|
@ -1,8 +1,8 @@
|
|||
#
|
||||
# Options
|
||||
#
|
||||
# make // standard everything
|
||||
# make debug // Give standard binary just with debugging
|
||||
# make // standard build aqualinkd and serial_logger
|
||||
# make debug // Compule standard aqualinkd binary just with debugging
|
||||
# make aqdebug // Compile with extra aqualink debug information like timings
|
||||
# make slog // Serial logger
|
||||
# make <other> // not documenting
|
||||
|
@ -13,6 +13,7 @@ AQ_RS16 = true
|
|||
AQ_PDA = true
|
||||
AQ_ONETOUCH = true
|
||||
AQ_IAQTOUCH = true
|
||||
AQ_MANAGER = false
|
||||
#AQ_MEMCMP = true // Not implimented correctly yet.
|
||||
|
||||
# Turn off threadded net services
|
||||
|
@ -22,8 +23,9 @@ AQ_NO_THREAD_NETSERVICE = false
|
|||
CC = gcc
|
||||
|
||||
#LIBS := -lpthread -lm
|
||||
LIBS := -l pthread -l m
|
||||
#LIBS := -l pthread -l m
|
||||
#LIBS := -l pthread -l m -static # Take out -static, just for dev
|
||||
LIBS := -lpthread -lm
|
||||
|
||||
# Standard compile flags
|
||||
GCCFLAGS = -Wall -O3
|
||||
|
@ -100,8 +102,22 @@ ifeq ($(AQ_MEMCMP), true)
|
|||
AQ_FLAGS := $(AQ_FLAGS) -D AQ_MEMCMP
|
||||
endif
|
||||
|
||||
ifeq ($(AQ_NO_THREAD_NETSERVICE), true)
|
||||
AQ_FLAGS := $(AQ_FLAGS) -D AQ_NO_THREAD_NETSERVICE
|
||||
|
||||
ifeq ($(AQ_MANAGER), true)
|
||||
AQ_FLAGS := $(AQ_FLAGS) -D AQ_MANAGER
|
||||
LIBS := $(LIBS) -lsystemd
|
||||
# aq_manager requires threads, so make sure that's turned on.
|
||||
ifeq ($(AQ_NO_THREAD_NETSERVICE), true)
|
||||
# Show error
|
||||
$(warning AQ_MANAGER requires threads, ignoring AQ_NO_THREAD_NETSERVICE)
|
||||
endif
|
||||
else
|
||||
# No need for serial_logger without aq_manager
|
||||
SRCS := $(filter-out serial_logger.c, $(SRCS))
|
||||
# no threadded net service only valid without aq manager.
|
||||
ifeq ($(AQ_NO_THREAD_NETSERVICE), true)
|
||||
AQ_FLAGS := $(AQ_FLAGS) -D AQ_NO_THREAD_NETSERVICE
|
||||
endif
|
||||
endif
|
||||
|
||||
|
||||
|
|
|
@ -79,6 +79,9 @@ Designed to mimic AqualinkRS6 All Button keypad and (like the keypad) is used to
|
|||
* Add set time to OneTouch protocol.
|
||||
* Publish AqualinkD Management console. (Configure, Restart, run serial_logger) within AqualinkD.
|
||||
|
||||
# Update in Release 2.3.2 (Current Development)
|
||||
* Added support for VSP on panel versions REV 0.1 & 0.2
|
||||
|
||||
# Update in Release 2.3.1
|
||||
* Changed a lot of logic around different protocols.
|
||||
* Added low latency support for FTDI usb driver.
|
||||
|
|
|
@ -165,8 +165,8 @@ int save_schedules_js(char* inBuf, int inSize, char* outBuf, int outSize)
|
|||
} else if ( inarray && inBuf[i] == '{') {
|
||||
passJson_scObj( &inBuf[i], (inSize-i), &cline);
|
||||
LOG(SCHD_LOG,LOG_DEBUG, "Write to cron Min:%s Hour:%s DayM:%s Month:%s DayW:%s URL:%s Value:%s\n",cline.minute,cline.hour,cline.daym,cline.month,cline.dayw,cline.url,cline.value);
|
||||
LOG(SCHD_LOG,LOG_INFO, "%s%s %s %s %s %s curl localhost:%s%s -d value=%s -X PUT\n",(cline.enabled?"":"#"),cline.minute, cline.hour, cline.daym, cline.month, cline.dayw, _aqconfig_.socket_port, cline.url, cline.value);
|
||||
fprintf(fp, "%s%s %s %s %s %s root curl localhost:%s%s -d value=%s -X PUT\n",(cline.enabled?"":"#"),cline.minute, cline.hour, cline.daym, cline.month, cline.dayw, _aqconfig_.socket_port, cline.url, cline.value);
|
||||
LOG(SCHD_LOG,LOG_INFO, "%s%s %s %s %s %s curl -s -S --show-error -o /dev/null localhost:%s%s -d value=%s -X PUT\n",(cline.enabled?"":"#"),cline.minute, cline.hour, cline.daym, cline.month, cline.dayw, _aqconfig_.socket_port, cline.url, cline.value);
|
||||
fprintf(fp, "%s%s %s %s %s %s root curl -s -S --show-error -o /dev/null localhost:%s%s -d value=%s -X PUT\n",(cline.enabled?"":"#"),cline.minute, cline.hour, cline.daym, cline.month, cline.dayw, _aqconfig_.socket_port, cline.url, cline.value);
|
||||
} else if ( inarray && inBuf[i] == '}') {
|
||||
//inobj=false;
|
||||
//objed=i;
|
||||
|
|
|
@ -6,8 +6,9 @@
|
|||
#include <stdbool.h>
|
||||
|
||||
#define CONNECTION_ERROR "ERROR No connection to RS control panel"
|
||||
#ifdef AQ_MANAGER
|
||||
#define CONNECTION_RUNNING_SLOG "Running serial_logger, this will take some time"
|
||||
|
||||
#endif
|
||||
|
||||
#define SERIAL_BLOCKING_TIME 50 // (1 to 255) in 1/10th second so 1 = 0.1 sec, 255 = 25.5 sec
|
||||
|
||||
|
@ -230,6 +231,10 @@
|
|||
//#define LNG_MSG_FREEZE_PROTECTION_ACTIVATED "FREEZE PROTECTION ACTIVATED"
|
||||
#define LNG_MSG_FREEZE_PROTECTION_ACTIVATED "FREEZE PROTECTION IS ACTIVATED"
|
||||
|
||||
// These are
|
||||
#define LNG_MSG_CHEM_FEED_ON "CHEM FEED ON"
|
||||
#define LNG_MSG_CHEM_FEED_OFF "CHEM FEED OFF"
|
||||
|
||||
|
||||
#define MSG_AIR_TEMP "AIR TEMP"
|
||||
#define MSG_POOL_TEMP "POOL TEMP"
|
||||
|
|
|
@ -42,7 +42,8 @@ void intHandler(int dummy);
|
|||
#ifdef AQ_PDA
|
||||
bool checkAqualinkTime(); // Only need to externalise this for PDA
|
||||
#endif
|
||||
// There are cases where SWG will read 80% in allbutton and 0% in onetouch/aqualinktouch, this will compile that in or our
|
||||
|
||||
// There are cases where SWG will read 80% in allbutton and 0% in onetouch/aqualinktouch, this will compile that in or out
|
||||
//#define READ_SWG_FROM_EXTENDED_ID
|
||||
|
||||
//#define TOTAL_BUTTONS 12
|
||||
|
@ -189,6 +190,7 @@ typedef struct clightd
|
|||
struct aqualinkdata
|
||||
{
|
||||
char version[AQ_MSGLEN*2];
|
||||
char revision[AQ_MSGLEN];
|
||||
char date[AQ_MSGLEN];
|
||||
char time[AQ_MSGLEN];
|
||||
char last_message[AQ_MSGLONGLEN+1]; // Last ascii message from panel - allbutton (or PDA) protocol
|
||||
|
@ -233,7 +235,10 @@ struct aqualinkdata
|
|||
unsigned char raw_status[AQ_PSTLEN];
|
||||
// Multiple threads update this value.
|
||||
volatile bool updated;
|
||||
|
||||
#ifdef AQ_MANAGER
|
||||
volatile bool run_slogger;
|
||||
#endif
|
||||
|
||||
#ifdef AQ_RS16
|
||||
int rs16_vbutton_start;
|
||||
|
|
19
aqualinkd.c
19
aqualinkd.c
|
@ -51,7 +51,10 @@
|
|||
#include "rs_msg_utils.h"
|
||||
#include "serialadapter.h"
|
||||
#include "debug_timer.h"
|
||||
|
||||
#ifdef AQ_MANAGER
|
||||
#include "serial_logger.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
#if defined AQ_DEBUG || defined AQ_TM_DEBUG
|
||||
|
@ -590,6 +593,12 @@ void _processMessage(char *message, bool reset)
|
|||
//freeze_msg_count = 0;
|
||||
strcpy(_aqualink_data.last_display_message, msg); // Also display the message on web UI
|
||||
}
|
||||
/* // Not sure when to do with these for the moment, so no need to compile in the test.
|
||||
else if (stristr(msg, LNG_MSG_CHEM_FEED_ON) != NULL) {
|
||||
}
|
||||
else if (stristr(msg, LNG_MSG_CHEM_FEED_OFF) != NULL) {
|
||||
}
|
||||
*/
|
||||
else if (msg[2] == '/' && msg[5] == '/' && msg[8] == ' ')
|
||||
{ // date in format '08/29/16 MON'
|
||||
strcpy(_aqualink_data.date, msg);
|
||||
|
@ -653,8 +662,10 @@ void _processMessage(char *message, bool reset)
|
|||
{ // '8157 REV MMM'
|
||||
// A master firmware revision message.
|
||||
strcpy(_aqualink_data.version, msg);
|
||||
rsm_get_revision(_aqualink_data.revision, msg, strlen(msg));
|
||||
//_gotREV = true;
|
||||
LOG(AQRS_LOG,LOG_NOTICE, "Control Panel %s\n", msg);
|
||||
LOG(AQRS_LOG,LOG_NOTICE, "Control Panel version %s\n", _aqualink_data.version);
|
||||
LOG(AQRS_LOG,LOG_NOTICE, "Control Panel revision %s\n", _aqualink_data.revision);
|
||||
if (_initWithRS == false)
|
||||
{
|
||||
//LOG(ALLBUTTON,LOG_NOTICE, "Standard protocol initialization complete\n");
|
||||
|
@ -1080,7 +1091,9 @@ int main(int argc, char *argv[])
|
|||
// struct lws_context_creation_info info;
|
||||
// Log only NOTICE messages and above. Debug and info messages
|
||||
// will not be logged to syslog.
|
||||
#ifndef AQ_MANAGER
|
||||
setlogmask(LOG_UPTO(LOG_NOTICE));
|
||||
#endif
|
||||
|
||||
if (getuid() != 0)
|
||||
{
|
||||
|
@ -1766,12 +1779,14 @@ void main_loop()
|
|||
blank_read = 0;
|
||||
}
|
||||
|
||||
#ifdef AQ_MANAGER
|
||||
if (_aqualink_data.run_slogger) {
|
||||
LOG(AQUA_LOG,LOG_WARNING, "Starting serial_logger, this will take some time!\n");
|
||||
broadcast_aqualinkstate_error(CONNECTION_RUNNING_SLOG);
|
||||
serial_logger(rs_fd, _aqconfig_.serial_port, getSystemLogLevel());
|
||||
_aqualink_data.run_slogger = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
packet_length = get_packet(rs_fd, packet_buffer);
|
||||
|
||||
|
@ -1816,7 +1831,7 @@ void main_loop()
|
|||
} else {
|
||||
// If we did not process the packet, above we need to record it for the caculate_ack_packet call.
|
||||
// Should find a better place to put this, but since prioritize_ack is expermental it's ok for now.
|
||||
// NSF The exact same needs to be done for onetouch / iaqtouch and probably rssaadapter.
|
||||
// NSF We shouldn;t need to do the same for rssa / onetouch / iaqtouch and probably rssaadapter since they don;t queue commands & programming commands.
|
||||
_aqualink_data.last_packet_type = packet_buffer[PKT_CMD];
|
||||
}
|
||||
#ifdef AQ_PDA
|
||||
|
|
|
@ -75,9 +75,9 @@ int json_chars(char *dest, const char *src, int dest_len, int src_len)
|
|||
return i;
|
||||
}
|
||||
|
||||
int build_logmsg_JSON(char *dest, const char *src, int dest_len, int src_len)
|
||||
int build_logmsg_JSON(char *dest, int loglevel, const char *src, int dest_len, int src_len)
|
||||
{
|
||||
int length = sprintf(dest, "{\"logmsg\":\"");
|
||||
int length = sprintf(dest, "{\"logmsg\":\"%-7s",elevel2text(loglevel));
|
||||
length += json_chars(dest+length, src, (dest_len-20), src_len);
|
||||
length += sprintf(dest+length, "\"}");
|
||||
dest[length] = '\0';
|
||||
|
|
|
@ -48,7 +48,7 @@ int build_aqualink_status_JSON(struct aqualinkdata *aqdata, char* buffer, int si
|
|||
int build_aux_labels_JSON(struct aqualinkdata *aqdata, char* buffer, int size);
|
||||
bool parseJSONwebrequest(char *buffer, struct JSONwebrequest *request);
|
||||
bool parseJSONrequest(char *buffer, struct JSONkvptr *request);
|
||||
int build_logmsg_JSON(char *dest, const char *src, int dest_len, int src_len);
|
||||
int build_logmsg_JSON(char *dest, int loglevel, const char *src, int dest_len, int src_len);
|
||||
int build_mqtt_status_JSON(char* buffer, int size, int idx, int nvalue, float setpoint/*char *svalue*/);
|
||||
bool parseJSONmqttrequest(const char *str, size_t len, int *idx, int *nvalue, char *svalue);
|
||||
int build_aqualink_error_status_JSON(char* buffer, int size, char *msg);
|
||||
|
|
197
net_services.c
197
net_services.c
|
@ -22,6 +22,9 @@
|
|||
#include <sys/time.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#ifdef AQ_MANAGER
|
||||
#include <systemd/sd-journal.h>
|
||||
#endif
|
||||
|
||||
#include "mongoose.h"
|
||||
|
||||
|
@ -39,14 +42,13 @@
|
|||
#include "serialadapter.h"
|
||||
#include "aq_timer.h"
|
||||
#include "aq_scheduler.h"
|
||||
#include "rs_msg_utils.h"
|
||||
#include "version.h"
|
||||
|
||||
#ifdef AQ_PDA
|
||||
#include "pda.h"
|
||||
#endif
|
||||
|
||||
// NSF remove once aqmanager is released.
|
||||
#define INCLUDE_OLD_DEBUG_HTML
|
||||
|
||||
/*
|
||||
#if defined AQ_DEBUG || defined AQ_TM_DEBUG
|
||||
#include "timespec_subtract.h"
|
||||
|
@ -139,15 +141,11 @@ void _broadcast_aqualinkstate_error(struct mg_connection *nc, char *msg)
|
|||
// Maybe enhacment in future to sent error messages to MQTT
|
||||
}
|
||||
|
||||
#define MAX_LOGSTACK 30
|
||||
#ifdef AQ_MANAGER
|
||||
|
||||
#define WS_LOG_LENGTH 200
|
||||
char _logstack[MAX_LOGSTACK][WS_LOG_LENGTH];
|
||||
int _logstack_place=0;
|
||||
pthread_mutex_t logmsg_mutex;
|
||||
|
||||
|
||||
// Send log message to any aqManager websocket.
|
||||
void _ws_send_logmsg(struct mg_connection *nc, char *msg) {
|
||||
void ws_send_logmsg(struct mg_connection *nc, char *msg) {
|
||||
struct mg_connection *c;
|
||||
|
||||
for (c = mg_next(nc->mgr, NULL); c != NULL; c = mg_next(nc->mgr, c)) {
|
||||
|
@ -157,26 +155,148 @@ void _ws_send_logmsg(struct mg_connection *nc, char *msg) {
|
|||
}
|
||||
}
|
||||
|
||||
void find_aqualinkd_startupmsg(sd_journal *journal)
|
||||
{
|
||||
static bool once=false;
|
||||
const void *log;
|
||||
size_t len;
|
||||
|
||||
// Only going to do this one time, incase re reset while reading.
|
||||
if (once) {
|
||||
return;
|
||||
}
|
||||
once=true;
|
||||
|
||||
sd_journal_previous_skip(journal, 200);
|
||||
|
||||
while ( sd_journal_next(journal) > 0) // need to capture return of this
|
||||
{
|
||||
if (sd_journal_get_data(journal, "MESSAGE", &log, &len) >= 0) {
|
||||
if (rsm_strnstr((const char *)log+8, AQUALINKD_NAME, len-8) != NULL) {
|
||||
// Go back one and return
|
||||
sd_journal_previous_skip(journal, 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Blindly go back 100 messages since above didn;t find start
|
||||
sd_journal_previous_skip(journal, 100);
|
||||
}
|
||||
|
||||
bool broadcast_systemd_logmessages(bool aqMgrActive) {
|
||||
static sd_journal *journal;
|
||||
static bool active = false;
|
||||
char msg[WS_LOG_LENGTH];
|
||||
static int cnt=0;
|
||||
static char *cursor = NULL;
|
||||
|
||||
if (!aqMgrActive) {
|
||||
if (!active) {
|
||||
return true;
|
||||
} else {
|
||||
sd_journal_close(journal);
|
||||
active = false;
|
||||
return true;
|
||||
cursor = NULL;
|
||||
}
|
||||
}
|
||||
// aqManager is active
|
||||
if (!active) {
|
||||
if ( sd_journal_open(&journal, SD_JOURNAL_LOCAL_ONLY) < 0) {
|
||||
build_logmsg_JSON(msg, LOG_ERR, "Failed to open journal", WS_LOG_LENGTH,22);
|
||||
ws_send_logmsg(_mgr.active_connections, msg);
|
||||
return false;
|
||||
}
|
||||
if (sd_journal_add_match(journal, "SYSLOG_IDENTIFIER=aqualinkd", 0) < 0) {
|
||||
build_logmsg_JSON(msg, LOG_ERR, "Failed to set journal filter", WS_LOG_LENGTH,27);
|
||||
ws_send_logmsg(_mgr.active_connections, msg);
|
||||
sd_journal_close(journal);
|
||||
return false;
|
||||
}
|
||||
if (sd_journal_seek_tail(journal) < 0) {
|
||||
build_logmsg_JSON(msg, LOG_ERR, "Failed to seek to journal end", WS_LOG_LENGTH,29);
|
||||
ws_send_logmsg(_mgr.active_connections, msg);
|
||||
sd_journal_close(journal);
|
||||
return false;
|
||||
}
|
||||
//if we have cusror go to it, otherwise jump back and try to find startup message
|
||||
if (cursor != NULL) {
|
||||
sd_journal_seek_cursor(journal, cursor);
|
||||
sd_journal_next(journal);
|
||||
} else
|
||||
find_aqualinkd_startupmsg(journal);
|
||||
|
||||
active = true;
|
||||
}
|
||||
|
||||
const void *log;
|
||||
size_t len;
|
||||
const void *pri;
|
||||
size_t plen;
|
||||
int rtn;
|
||||
|
||||
while ( (rtn = sd_journal_next(journal)) > 0) // need to capture return of this
|
||||
{
|
||||
if (sd_journal_get_data(journal, "MESSAGE", &log, &len) < 0) {
|
||||
build_logmsg_JSON(msg, LOG_ERR, "Failed to get journal message", WS_LOG_LENGTH,29);
|
||||
ws_send_logmsg(_mgr.active_connections, msg);
|
||||
} else if (sd_journal_get_data(journal, "PRIORITY", &pri, &plen) < 0) {
|
||||
build_logmsg_JSON(msg, LOG_ERR, "Failed to seek to journal message priority", WS_LOG_LENGTH,42);
|
||||
ws_send_logmsg(_mgr.active_connections, msg);
|
||||
} else {
|
||||
build_logmsg_JSON(msg, atoi((const char *)pri+9), (const char *)log+8, WS_LOG_LENGTH,(int)len-8);
|
||||
ws_send_logmsg(_mgr.active_connections, msg);
|
||||
cnt=0;
|
||||
sd_journal_get_cursor(journal, &cursor);
|
||||
}
|
||||
}
|
||||
if (rtn < 0) {
|
||||
build_logmsg_JSON(msg, LOG_ERR, "Failed to get seen to next journal message", WS_LOG_LENGTH,42);
|
||||
ws_send_logmsg(_mgr.active_connections, msg);
|
||||
sd_journal_close(journal);
|
||||
active = false;
|
||||
} else if (rtn == 0) {
|
||||
// Sometimes we get no errors, and nothing to read, even when their is.
|
||||
// So if we get too many, restart but don;t reset the cursor.
|
||||
// Could tesd moving sd_journal_get_cursor(journal, &cursor); line to here from above.
|
||||
if (cnt++ == 100) {
|
||||
//printf("**** %d Too many blank reads, resetting!! ****\n",cnt);
|
||||
sd_journal_close(journal);
|
||||
active = false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* superseded with systemd/sd-journal
|
||||
#define MAX_LOGSTACK 30
|
||||
#define WS_LOG_LENGTH 200
|
||||
char _logstack[MAX_LOGSTACK][WS_LOG_LENGTH];
|
||||
int _logstack_place=0;
|
||||
pthread_mutex_t logmsg_mutex;
|
||||
|
||||
void send_ws_logmessages()
|
||||
{
|
||||
pthread_mutex_lock(&logmsg_mutex);
|
||||
// This pulls them off in the wrong order.
|
||||
while (_logstack_place > 0) {
|
||||
_ws_send_logmsg(_mgr.active_connections, _logstack[0]);
|
||||
ws_send_logmsg(_mgr.active_connections, _logstack[0]);
|
||||
memmove(&_logstack[0], &_logstack[1], WS_LOG_LENGTH * _logstack_place ) ;
|
||||
_logstack_place--;
|
||||
}
|
||||
pthread_mutex_unlock(&logmsg_mutex);
|
||||
}
|
||||
|
||||
// This needs to be thread safe.
|
||||
void broadcast_log(char *msg) {
|
||||
// NSF This causes mongoose to core dump after a period of time due to number of messages
|
||||
// so remove until get time to update to new mongoose version.
|
||||
//return;
|
||||
|
||||
#ifdef AQ_NO_THREAD_NETSERVICE
|
||||
if (_keepNetServicesRunning && !_aqconfig_.thread_netservices && _aqualink_data->aqManagerActive)
|
||||
if (_keepNetServicesRunning && !_aqconfig_.thread_netservices && _aqualink_data != NULL && _aqualink_data->aqManagerActive)
|
||||
{
|
||||
char message[WS_LOG_LENGTH];
|
||||
build_logmsg_JSON(message, msg, WS_LOG_LENGTH, strlen(msg));
|
||||
|
@ -186,7 +306,7 @@ void broadcast_log(char *msg) {
|
|||
#endif
|
||||
// See if we have and manager runnig first so we return ASAP.
|
||||
// Since this get's called long before net_Services is started, also check we are running.
|
||||
if (_keepNetServicesRunning && _net_thread_id != 0 && _aqualink_data->aqManagerActive)
|
||||
if (_keepNetServicesRunning && _net_thread_id != 0 && _aqualink_data != NULL && _aqualink_data->aqManagerActive)
|
||||
{
|
||||
pthread_mutex_lock(&logmsg_mutex);
|
||||
if (_logstack_place < MAX_LOGSTACK)
|
||||
|
@ -204,6 +324,7 @@ void broadcast_log(char *msg) {
|
|||
}
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
void _broadcast_aqualinkstate(struct mg_connection *nc)
|
||||
{
|
||||
|
@ -692,7 +813,7 @@ void mqtt_broadcast_aqualinkstate(struct mg_connection *nc)
|
|||
}
|
||||
|
||||
|
||||
typedef enum {uActioned, uBad, uDevices, uStatus, uHomebridge, uDynamicconf, uDebugStatus, uDebugDownload, uSimulator, uSchedules, uSetSchedules, uAQmanager} uriAtype;
|
||||
typedef enum {uActioned, uBad, uDevices, uStatus, uHomebridge, uDynamicconf, uDebugStatus, uDebugDownload, uSimulator, uSchedules, uSetSchedules, uAQmanager, uNotAvailable} uriAtype;
|
||||
//typedef enum {NET_MQTT=0, NET_API, NET_WS, DZ_MQTT} netRequest;
|
||||
const char actionName[][5] = {"MQTT", "API", "WS", "DZ"};
|
||||
|
||||
|
@ -785,6 +906,7 @@ uriAtype action_URI(request_source from, const char *URI, int uri_length, float
|
|||
} else if (strncmp(ri1, "rawcommand", 10) == 0 && from == NET_WS) { // Only valid from websocket.
|
||||
aq_send_cmd((unsigned char)value);
|
||||
return uActioned;
|
||||
#ifdef AQ_MANAGER
|
||||
} else if (strncmp(ri1, "aqmanager", 9) == 0 && from == NET_WS) { // Only valid from websocket.
|
||||
return uAQmanager;
|
||||
} else if (strncmp(ri1, "setloglevel", 11) == 0 && from == NET_WS) { // Only valid from websocket.
|
||||
|
@ -802,14 +924,23 @@ uriAtype action_URI(request_source from, const char *URI, int uri_length, float
|
|||
} else if (ri2 != NULL && strncmp(ri2, "stop", 4) == 0) {
|
||||
stopInlineLog2File();
|
||||
} else if (ri2 != NULL && strncmp(ri2, "clean", 5) == 0) {
|
||||
cleanInlineLogFile();
|
||||
cleanInlineLog2File();
|
||||
} else if (ri2 != NULL && strncmp(ri2, "download", 8) == 0) {
|
||||
return uDebugDownload;
|
||||
}
|
||||
return uAQmanager; // Want to resent updated status
|
||||
|
||||
// BELOW IS FOR OLD DEBUG.HTML, Need to remove in future release
|
||||
#ifdef INCLUDE_OLD_DEBUG_HTML
|
||||
} else if (strncmp(ri1, "restart", 7) == 0 && from == NET_WS) { // Only valid from websocket.
|
||||
LOG(NET_LOG,LOG_NOTICE, "Received restart request!\n");
|
||||
raise(SIGRESTART);
|
||||
return uActioned;
|
||||
} else if (strncmp(ri1, "seriallogger", 12) == 0 && from == NET_WS) { // Only valid from websocket.
|
||||
LOG(NET_LOG,LOG_NOTICE, "Received request to run serial_logger!\n");
|
||||
_aqualink_data->run_slogger = true;
|
||||
return uActioned;
|
||||
#else // AQ_MANAGER
|
||||
} else if (strncmp(ri1, "aqmanager", 9) == 0 && from == NET_WS) { // Only valid from websocket.
|
||||
return uNotAvailable;
|
||||
// BELOW IS FOR OLD DEBUG.HTML, Need to remove in future release with aqmanager goes live
|
||||
} else if (strncmp(ri1, "debug", 5) == 0) {
|
||||
if (ri2 != NULL && strncmp(ri2, "start", 5) == 0) {
|
||||
startInlineDebug();
|
||||
|
@ -825,16 +956,8 @@ uriAtype action_URI(request_source from, const char *URI, int uri_length, float
|
|||
return uDebugDownload;
|
||||
}
|
||||
return uDebugStatus;
|
||||
#endif
|
||||
#endif //AQ_MANAGER
|
||||
// couple of debug items for testing
|
||||
} else if (strncmp(ri1, "restart", 13) == 0 && from == NET_WS) { // Only valid from websocket.
|
||||
/*
|
||||
LOG(NET_LOG,LOG_NOTICE, "Received restart request!\n");
|
||||
raise(SIGRESTART);
|
||||
return uActioned;
|
||||
*/
|
||||
LOG(NET_LOG,LOG_WARNING, "Received restart request, not implimented in this release!\n");
|
||||
return uBad;
|
||||
} else if (strncmp(ri1, "set_date_time", 13) == 0) {
|
||||
//aq_programmer(AQ_SET_TIME, NULL, _aqualink_data);
|
||||
panel_device_request(_aqualink_data, DATE_TIME, 0, 0, from);
|
||||
|
@ -1271,7 +1394,7 @@ void action_web_request(struct mg_connection *nc, struct http_message *http_msg)
|
|||
mg_send(nc, message, size);
|
||||
}
|
||||
break;
|
||||
#ifdef INCLUDE_OLD_DEBUG_HTML
|
||||
#ifndef AQ_MANAGER
|
||||
case uDebugStatus:
|
||||
{
|
||||
char message[JSON_BUFFER_SIZE];
|
||||
|
@ -1391,6 +1514,11 @@ void action_websocket_request(struct mg_connection *nc, struct websocket_message
|
|||
ws_send(nc, message);
|
||||
}
|
||||
break;
|
||||
case uNotAvailable:
|
||||
{
|
||||
sprintf(buffer, "{\"na_message\":\"not available in this version!\"}");
|
||||
ws_send(nc, buffer);
|
||||
}
|
||||
case uSchedules:
|
||||
{
|
||||
DEBUG_TIMER_START(&tid);
|
||||
|
@ -1712,7 +1840,6 @@ void *net_services_thread( void *ptr )
|
|||
{
|
||||
struct aqualinkdata *aqdata = (struct aqualinkdata *) ptr;
|
||||
//struct mg_mgr mgr;
|
||||
|
||||
if (!_start_net_services(&_mgr, aqdata)) {
|
||||
//LOG(NET_LOG,LOG_ERR, "Failed to start network services\n");
|
||||
// Not the best way to do this (have thread exit process), but forks for the moment.
|
||||
|
@ -1726,17 +1853,19 @@ void *net_services_thread( void *ptr )
|
|||
{
|
||||
//poll_net_services(&_mgr, 10);
|
||||
// Shorten poll cycle when logging messages to WS
|
||||
mg_mgr_poll(&_mgr, (_aqualink_data->aqManagerActive)?5:100);
|
||||
//mg_mgr_poll(&_mgr, 100);
|
||||
//mg_mgr_poll(&_mgr, (_aqualink_data->aqManagerActive)?50:100);
|
||||
mg_mgr_poll(&_mgr, 100);
|
||||
|
||||
if (aqdata->updated == true /*|| _broadcast == true*/) {
|
||||
//LOG(NET_LOG,LOG_DEBUG, "********** Broadcast ************\n");
|
||||
_broadcast_aqualinkstate(_mgr.active_connections);
|
||||
aqdata->updated = false;
|
||||
}
|
||||
if (_aqualink_data->aqManagerActive) {
|
||||
send_ws_logmessages();
|
||||
#ifdef AQ_MANAGER
|
||||
if ( ! broadcast_systemd_logmessages(_aqualink_data->aqManagerActive)) {
|
||||
LOG(AQUA_LOG,LOG_ERR, "Couldn't open systemd journal log\n");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
f_end:
|
||||
|
|
|
@ -29,7 +29,9 @@ void stop_net_services();
|
|||
time_t poll_net_services(int timeout_ms);
|
||||
void broadcast_aqualinkstate();
|
||||
void broadcast_aqualinkstate_error(char *msg);
|
||||
void broadcast_log(char *msg);
|
||||
|
||||
// superseded with systemd/sd-journal
|
||||
//void broadcast_log(char *msg);
|
||||
//#endif
|
||||
|
||||
|
||||
|
|
304
onetouch.c
304
onetouch.c
|
@ -40,6 +40,8 @@ static int _ot_hlightcharindexstart = -1;
|
|||
static int _ot_hlightcharindexstop = -1;
|
||||
static char _menu[ONETOUCH_LINES][AQ_MSGLEN+1];
|
||||
static struct ot_macro _macros[3];
|
||||
bool _panel_version_P2 = false; // Older panels REV 0.1 and 0.2
|
||||
|
||||
|
||||
void set_macro_status();
|
||||
void pump_update(struct aqualinkdata *aq_data, int updated);
|
||||
|
@ -290,6 +292,17 @@ bool log_panelversion(struct aqualinkdata *aq_data)
|
|||
end = aq_data->version + strlen(aq_data->version) - 1;
|
||||
while(end > aq_data->version && isspace(*end)) end--;
|
||||
|
||||
rsm_get_revision(aq_data->revision, _menu[7], AQ_MSGLEN);
|
||||
LOG(ONET_LOG,LOG_NOTICE, "Control Panel version %s\n", aq_data->version);
|
||||
LOG(ONET_LOG,LOG_NOTICE, "Control Panel revision %s\n", aq_data->revision);
|
||||
|
||||
if ( strcmp(aq_data->revision, "0.1") == 0 || strcmp(aq_data->revision, "0.2") == 0 ) {
|
||||
LOG(ONET_LOG,LOG_NOTICE, "Setting early version for OneTouch\n");
|
||||
_panel_version_P2 = true;
|
||||
}
|
||||
|
||||
// Probably should check the panel size here as well.
|
||||
// One Touch: OneTouch Menu Line 5 = RS-16 Combo
|
||||
// Write new null terminator
|
||||
*(end+1) = 0;
|
||||
|
||||
|
@ -314,115 +327,214 @@ bool log_freeze_setpoints(struct aqualinkdata *aq_data)
|
|||
}
|
||||
|
||||
|
||||
|
||||
bool get_pumpinfo_from_menu(struct aqualinkdata *aq_data, int menuLineIdx)
|
||||
{
|
||||
int rpm = 0;
|
||||
int watts = 0;
|
||||
int gpm = 0;
|
||||
int pump_index = rsm_atoi(&_menu[menuLineIdx][14]);
|
||||
if (pump_index <= 0)
|
||||
pump_index = rsm_atoi(&_menu[menuLineIdx][12]); // Pump inxed is in different position on line ` ePump AC 4`
|
||||
|
||||
// RPM displays differently depending on 3 or 4 digit rpm.
|
||||
if (rsm_strcmp(_menu[menuLineIdx + 1], "RPM:") == 0)
|
||||
{
|
||||
rpm = rsm_atoi(&_menu[menuLineIdx + 1][10]);
|
||||
if (rsm_strcmp(_menu[menuLineIdx + 2], "Watts:") == 0){
|
||||
watts = rsm_atoi(&_menu[menuLineIdx + 2][10]);
|
||||
}
|
||||
if (rsm_strcmp(_menu[menuLineIdx + 3], "GPM:") == 0){
|
||||
gpm = rsm_atoi(&_menu[menuLineIdx + 3][10]);
|
||||
}
|
||||
}
|
||||
else if (rsm_strcmp(_menu[menuLineIdx+1], "*** Priming ***") == 0){
|
||||
rpm = PUMP_PRIMING;
|
||||
}
|
||||
else if (rsm_strcmp(_menu[menuLineIdx+1], "(Offline)") == 0){
|
||||
rpm = PUMP_OFFLINE;
|
||||
}
|
||||
else if (rsm_strcmp(_menu[menuLineIdx+1], "(Priming Error)") == 0){
|
||||
rpm = PUMP_ERROR;
|
||||
}
|
||||
|
||||
LOG(ONET_LOG, LOG_DEBUG, "Found OneTouch Pump '%s', Index %d, RPM %d, Watts %d, GPM %d\n", _menu[menuLineIdx], pump_index, rpm, watts, gpm);
|
||||
|
||||
for (int i = 0; i < aq_data->num_pumps; i++)
|
||||
{
|
||||
if (aq_data->pumps[i].pumpIndex == pump_index)
|
||||
{
|
||||
// printf("**** FOUND PUMP %d at index %d *****\n",pump_index,i);
|
||||
// aq_data->pumps[i].updated = true;
|
||||
pump_update(aq_data, i);
|
||||
aq_data->pumps[i].rpm = rpm;
|
||||
aq_data->pumps[i].watts = watts;
|
||||
aq_data->pumps[i].gpm = gpm;
|
||||
// LOG(ONET_LOG,LOG_INFO, "Matched OneTouch Pump to Index %d, RPM %d, Watts %d, GPM %d\n",i,rpm,watts,gpm);
|
||||
LOG(ONET_LOG, LOG_INFO, "Matched OneTouch Pump to '%s', Index %d, RPM %d, Watts %d, GPM %d\n", aq_data->pumps[i].button->name, i, rpm, watts, gpm);
|
||||
if (aq_data->pumps[i].pumpType == PT_UNKNOWN)
|
||||
{
|
||||
if (rsm_strcmp(_menu[2], "Intelliflo VS") == 0)
|
||||
aq_data->pumps[i].pumpType = VSPUMP;
|
||||
else if (rsm_strcmp(_menu[2], "Intelliflo VF") == 0)
|
||||
aq_data->pumps[i].pumpType = VFPUMP;
|
||||
else if (rsm_strcmp(_menu[2], "Jandy ePUMP") == 0 ||
|
||||
rsm_strcmp(_menu[2], "ePump AC") == 0)
|
||||
aq_data->pumps[i].pumpType = EPUMP;
|
||||
|
||||
LOG(ONET_LOG, LOG_INFO, "OneTouch Pump index %d set PumpType to %d\n", i, aq_data->pumps[i].pumpType);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
LOG(ONET_LOG, LOG_WARNING, "Did not find AqualinkD config for Pump '%s'\n",_menu[menuLineIdx]);
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
Info: OneTouch Menu Line 1 =
|
||||
Info: OneTouch Menu Line 2 = Chemlink 1
|
||||
Info: OneTouch Menu Line 3 = ORP 750/PH 7.0
|
||||
*/
|
||||
bool get_chemlinkinfo_from_menu(struct aqualinkdata *aq_data, int menuLineIdx)
|
||||
{
|
||||
if (rsm_strcmp(_menu[menuLineIdx + 1], "ORP") == 0)
|
||||
{
|
||||
int orp = atoi(&_menu[menuLineIdx + 1][4]);
|
||||
char *indx = strchr(_menu[menuLineIdx + 1], '/');
|
||||
float ph = atof(indx + 3);
|
||||
LOG(ONET_LOG, LOG_INFO, "OneTouch Cemlink ORP = %d PH = %f\n", orp, ph);
|
||||
if (aq_data->ph != ph || aq_data->orp != orp)
|
||||
{
|
||||
aq_data->ph = ph;
|
||||
aq_data->orp = orp;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
LOG(ONET_LOG, LOG_WARNING, "Did not understand Chemlink message '%s'\n",_menu[menuLineIdx + 1]);
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
Info: OneTouch Menu Line 2 = AQUAPURE 60%
|
||||
Info: OneTouch Menu Line 3 = Salt 7600 PPM */
|
||||
bool get_aquapureinfo_from_menu(struct aqualinkdata *aq_data, int menuLineIdx)
|
||||
{
|
||||
bool rtn = false;
|
||||
|
||||
#ifdef READ_SWG_FROM_EXTENDED_ID
|
||||
|
||||
int swgp = atoi(&_menu[menuLineIdx][10]);
|
||||
if (aq_data->swg_percent != swgp)
|
||||
{
|
||||
changeSWGpercent(aq_data, swgp);
|
||||
rtn = true;
|
||||
}
|
||||
|
||||
if (rsm_strcmp(_menu[menuLineIdx+1], "Salt") == 0)
|
||||
{
|
||||
int ppm = atoi(&_menu[menuLineIdx+1][6]);
|
||||
if (aq_data->swg_ppm != ppm)
|
||||
{
|
||||
aq_data->swg_ppm = ppm;
|
||||
rtn = true;
|
||||
}
|
||||
LOG(ONET_LOG, LOG_INFO, "OneTouch Aquapure SWG %d%, %d PPM\n", swgp, ppm);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return rtn;
|
||||
}
|
||||
|
||||
#ifdef AQ_RS16
|
||||
bool get_RS16buttoninfo_from_menu(struct aqualinkdata *aq_data, int menuLineIdx)
|
||||
{
|
||||
for (int i = aq_data->rs16_vbutton_start; i <= aq_data->rs16_vbutton_end; i++)
|
||||
{
|
||||
if (rsm_strcmp(_menu[menuLineIdx], aq_data->aqbuttons[i].label) == 0)
|
||||
{
|
||||
// Matched must be on.
|
||||
LOG(ONET_LOG, LOG_INFO, "OneTouch RS16 equiptment status '%s' matched '%s'\n", _menu[menuLineIdx], aq_data->aqbuttons[i].label);
|
||||
rs16led_update(aq_data, i);
|
||||
aq_data->aqbuttons[i].led->state = ON;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
For older Panel versions 0.1 and 0.2
|
||||
These display information all on one page, kind'a limped together like PDA
|
||||
OneTouch Menu Line 0 = EQUIPMENT STATUS
|
||||
OneTouch Menu Line 1 =
|
||||
OneTouch Menu Line 2 = AquaPure 35%
|
||||
OneTouch Menu Line 3 = SALT 3200 PPM
|
||||
OneTouch Menu Line 4 = FILTER PUMP
|
||||
OneTouch Menu Line 5 = Intelliflo VS 1
|
||||
OneTouch Menu Line 6 = RPM: 1750
|
||||
OneTouch Menu Line 7 = WATTS: 330
|
||||
OneTouch Menu Line 8 =
|
||||
OneTouch Menu Line 9 =
|
||||
OneTouch Menu Line 10 =
|
||||
OneTouch Menu Line 11 =
|
||||
*/
|
||||
bool log_qeuiptment_status_VP2(struct aqualinkdata *aq_data)
|
||||
{
|
||||
bool rtn = false;
|
||||
|
||||
int i;
|
||||
for (i = 0; i < ONETOUCH_LINES; i++)
|
||||
{
|
||||
if (rsm_strcmp(_menu[i], "Intelliflo VS") == 0 ||
|
||||
rsm_strcmp(_menu[i], "Intelliflo VF") == 0 ||
|
||||
rsm_strcmp(_menu[i], "Jandy ePUMP") == 0 ||
|
||||
rsm_strcmp(_menu[i], "ePump AC") == 0)
|
||||
{
|
||||
rtn = get_pumpinfo_from_menu(aq_data, i);
|
||||
} else if (rsm_strcmp(_menu[2],"AQUAPURE") == 0) {
|
||||
rtn = get_aquapureinfo_from_menu(aq_data, i);
|
||||
} else if (rsm_strcmp(_menu[i],"Chemlink") == 0) {
|
||||
rtn = get_chemlinkinfo_from_menu(aq_data, i);
|
||||
#ifdef AQ_RS16
|
||||
} else if (PANEL_SIZE() >= 16 ) {
|
||||
// Loop over RS 16 buttons.
|
||||
get_RS16buttoninfo_from_menu(aq_data, i);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return rtn;
|
||||
}
|
||||
/*
|
||||
Newer panels have a page per device and specific lines with information
|
||||
*/
|
||||
bool log_qeuiptment_status(struct aqualinkdata *aq_data)
|
||||
{
|
||||
int i;
|
||||
if (_panel_version_P2)
|
||||
return log_qeuiptment_status_VP2(aq_data);
|
||||
|
||||
bool rtn = false;
|
||||
|
||||
if (rsm_strcmp(_menu[2],"Intelliflo VS") == 0 ||
|
||||
rsm_strcmp(_menu[2],"Intelliflo VF") == 0 ||
|
||||
rsm_strcmp(_menu[2],"Jandy ePUMP") == 0 ||
|
||||
rsm_strcmp(_menu[2],"ePump AC") == 0) {
|
||||
rtn = true;
|
||||
int rpm = 0;
|
||||
int watts = 0;
|
||||
int gpm = 0;
|
||||
int pump_index = rsm_atoi(&_menu[2][14]);
|
||||
if (pump_index <= 0)
|
||||
pump_index = rsm_atoi(&_menu[2][12]); // Pump inxed is in different position on line ` ePump AC 4`
|
||||
// RPM displays differently depending on 3 or 4 digit rpm.
|
||||
if (rsm_strcmp(_menu[3],"RPM:") == 0){
|
||||
rpm = rsm_atoi(&_menu[3][10]);
|
||||
if (rsm_strcmp(_menu[4],"Watts:") == 0) {
|
||||
watts = rsm_atoi(&_menu[4][10]);
|
||||
}
|
||||
if (rsm_strcmp(_menu[5],"GPM:") == 0) {
|
||||
gpm = rsm_atoi(&_menu[5][10]);
|
||||
}
|
||||
} else if (rsm_strcmp(_menu[3],"*** Priming ***") == 0){
|
||||
rpm = PUMP_PRIMING;
|
||||
} else if (rsm_strcmp(_menu[3],"(Offline)") == 0){
|
||||
rpm = PUMP_OFFLINE;
|
||||
} else if (rsm_strcmp(_menu[3],"(Priming Error)") == 0){
|
||||
rpm = PUMP_ERROR;
|
||||
}
|
||||
|
||||
LOG(ONET_LOG,LOG_INFO, "OneTouch Pump %s, Index %d, RPM %d, Watts %d, GPM %d\n",_menu[2],pump_index,rpm,watts,gpm);
|
||||
|
||||
for (i=0; i < aq_data->num_pumps; i++) {
|
||||
if (aq_data->pumps[i].pumpIndex == pump_index) {
|
||||
//printf("**** FOUND PUMP %d at index %d *****\n",pump_index,i);
|
||||
//aq_data->pumps[i].updated = true;
|
||||
pump_update(aq_data, i);
|
||||
aq_data->pumps[i].rpm = rpm;
|
||||
aq_data->pumps[i].watts = watts;
|
||||
aq_data->pumps[i].gpm = gpm;
|
||||
if (aq_data->pumps[i].pumpType == PT_UNKNOWN){
|
||||
if (rsm_strcmp(_menu[2],"Intelliflo VS") == 0)
|
||||
aq_data->pumps[i].pumpType = VSPUMP;
|
||||
else if (rsm_strcmp(_menu[2],"Intelliflo VF") == 0)
|
||||
aq_data->pumps[i].pumpType = VFPUMP;
|
||||
else if (rsm_strcmp(_menu[2],"Jandy ePUMP") == 0 ||
|
||||
rsm_strcmp(_menu[2],"ePump AC") == 0)
|
||||
aq_data->pumps[i].pumpType = EPUMP;
|
||||
}
|
||||
//printf ("Set Pump Type to %d\n",aq_data->pumps[i].pumpType);
|
||||
}
|
||||
}
|
||||
#ifdef READ_SWG_FROM_EXTENDED_ID
|
||||
rtn = get_pumpinfo_from_menu(aq_data, 2);
|
||||
} else if (rsm_strcmp(_menu[2],"AQUAPURE") == 0) {
|
||||
/* Info: OneTouch Menu Line 0 = Equipment Status
|
||||
Info: OneTouch Menu Line 1 =
|
||||
Info: OneTouch Menu Line 2 = AQUAPURE 60%
|
||||
Info: OneTouch Menu Line 3 = Salt 7600 PPM */
|
||||
int swgp = atoi(&_menu[2][10]);
|
||||
if ( aq_data->swg_percent != swgp ) {
|
||||
//aq_data->swg_percent = swgp;
|
||||
if (changeSWGpercent(aq_data, swgp))
|
||||
LOG(ONET_LOG,LOG_INFO, "OneTouch SWG = %d\n",swgp);
|
||||
rtn = true;
|
||||
}
|
||||
|
||||
if (rsm_strcmp(_menu[3],"Salt") == 0) {
|
||||
int ppm = atoi(&_menu[3][6]);
|
||||
if ( aq_data->swg_ppm != ppm ) {
|
||||
aq_data->swg_ppm = ppm;
|
||||
rtn = true;
|
||||
}
|
||||
LOG(ONET_LOG,LOG_INFO, "OneTouch PPM = %d\n",ppm);
|
||||
}
|
||||
#endif
|
||||
rtn = get_aquapureinfo_from_menu(aq_data, 2);
|
||||
} else if (rsm_strcmp(_menu[2],"Chemlink") == 0) {
|
||||
/* Info: OneTouch Menu Line 0 = Equipment Status
|
||||
Info: OneTouch Menu Line 1 =
|
||||
Info: OneTouch Menu Line 2 = Chemlink 1
|
||||
Info: OneTouch Menu Line 3 = ORP 750/PH 7.0 */
|
||||
if (rsm_strcmp(_menu[3],"ORP") == 0) {
|
||||
int orp = atoi(&_menu[3][4]);
|
||||
char *indx = strchr(_menu[3], '/');
|
||||
float ph = atof(indx+3);
|
||||
if (aq_data->ph != ph || aq_data->orp != orp) {
|
||||
aq_data->ph = ph;
|
||||
aq_data->orp = orp;
|
||||
return true;
|
||||
}
|
||||
LOG(ONET_LOG,LOG_INFO, "OneTouch Cemlink ORP = %d PH = %f\n",orp,ph);
|
||||
}
|
||||
rtn = get_chemlinkinfo_from_menu(aq_data, 2);
|
||||
}
|
||||
|
||||
#ifdef AQ_RS16
|
||||
#ifdef AQ_RS16
|
||||
else if (PANEL_SIZE() >= 16 ) { // This fails on RS4, comeback and find out why. // Run over devices that have no status LED's on RS12&16 panels.
|
||||
//else if ( 16 <= (int)PANEL_SIZE ) {
|
||||
int j;
|
||||
int i;
|
||||
for (i=2; i <= ONETOUCH_LINES; i++) {
|
||||
for (j = aq_data->rs16_vbutton_start; j <= aq_data->rs16_vbutton_end; j++) {
|
||||
if ( rsm_strcmp(_menu[i], aq_data->aqbuttons[j].label) == 0 ) {
|
||||
//Matched must be on.
|
||||
LOG(ONET_LOG,LOG_DEBUG, "OneTouch equiptment status '%s' matched '%s'\n",_menu[i],aq_data->aqbuttons[j].label);
|
||||
rs16led_update(aq_data, j);
|
||||
aq_data->aqbuttons[j].led->state = ON;
|
||||
}
|
||||
}
|
||||
get_RS16buttoninfo_from_menu(aq_data, i);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -456,7 +568,7 @@ ot_menu_type get_onetouch_menu_type()
|
|||
return OTM_BOOST;
|
||||
else if (rsm_strcmp(_menu[0],"Set AQUAPURE") == 0)
|
||||
return OTM_SET_AQUAPURE;
|
||||
else if (rsm_strcmp(_menu[7],"REV ") == 0) // NSF Need a better check.
|
||||
else if (rsm_strcmp(_menu[7],"REV") == 0) // NSF Need a better check.
|
||||
return OTM_VERSION;
|
||||
|
||||
return OTM_UNKNOWN;
|
||||
|
|
8
pda.c
8
pda.c
|
@ -658,23 +658,23 @@ void process_pda_packet_msg_long_equiptment_status(const char *msg_line, int lin
|
|||
// Check message for status of device
|
||||
// Loop through all buttons and match the PDA text.
|
||||
// Should probably use strncasestr
|
||||
if ((index = rsm_strnstr(msg, "CHECK AquaPure", AQ_MSGLEN)) != NULL)
|
||||
if ((index = rsm_strncasestr(msg, "CHECK AquaPure", AQ_MSGLEN)) != NULL)
|
||||
{
|
||||
LOG(PDA_LOG,LOG_DEBUG, "CHECK AquaPure\n");
|
||||
}
|
||||
else if ((index = rsm_strnstr(msg, "FREEZE PROTECT", AQ_MSGLEN)) != NULL)
|
||||
else if ((index = rsm_strncasestr(msg, "FREEZE PROTECT", AQ_MSGLEN)) != NULL)
|
||||
{
|
||||
_aqualink_data->frz_protect_state = ON;
|
||||
LOG(PDA_LOG,LOG_DEBUG, "Freeze Protect is on\n");
|
||||
}
|
||||
else if ((index = rsm_strnstr(msg, MSG_SWG_PCT, AQ_MSGLEN)) != NULL)
|
||||
else if ((index = rsm_strncasestr(msg, MSG_SWG_PCT, AQ_MSGLEN)) != NULL)
|
||||
{
|
||||
changeSWGpercent(_aqualink_data, atoi(index + strlen(MSG_SWG_PCT)));
|
||||
//_aqualink_data->swg_percent = atoi(index + strlen(MSG_SWG_PCT));
|
||||
//if (_aqualink_data->ar_swg_status == SWG_STATUS_OFF) {_aqualink_data->ar_swg_status = SWG_STATUS_ON;}
|
||||
LOG(PDA_LOG,LOG_DEBUG, "AquaPure = %d\n", _aqualink_data->swg_percent);
|
||||
}
|
||||
else if ((index = rsm_strnstr(msg, MSG_SWG_PPM, AQ_MSGLEN)) != NULL)
|
||||
else if ((index = rsm_strncasestr(msg, MSG_SWG_PPM, AQ_MSGLEN)) != NULL)
|
||||
{
|
||||
_aqualink_data->swg_ppm = atoi(index + strlen(MSG_SWG_PPM));
|
||||
//if (_aqualink_data->ar_swg_status == SWG_STATUS_OFF) {_aqualink_data->ar_swg_status = SWG_STATUS_ON;}
|
||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -22,6 +22,7 @@
|
|||
#include <ctype.h>
|
||||
|
||||
#include "utils.h"
|
||||
#include "rs_msg_utils.h"
|
||||
|
||||
/*
|
||||
int check_panel_conf(char *panel)
|
||||
|
@ -44,6 +45,45 @@ int check_panel_conf(char *panel)
|
|||
"RS-8 Combo"
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
Pull revision from string examples
|
||||
'E0260801 REV. O.2'
|
||||
' REV. O.2 '
|
||||
'B0029221 REV T.0.1'
|
||||
' REV T.0.1'
|
||||
*/
|
||||
bool rsm_get_revision(char *dest, const char *src, int src_len)
|
||||
{
|
||||
char *sp = NULL;
|
||||
char *ep = NULL;
|
||||
|
||||
sp = rsm_strnstr(src, "REV", src_len);
|
||||
if (sp == NULL) {
|
||||
return false;
|
||||
}
|
||||
sp = sp+3;
|
||||
while ( *sp == ' ' || *sp == '.') {
|
||||
sp = sp+1;
|
||||
}
|
||||
// sp is now the start of string revision #
|
||||
ep = sp;
|
||||
while ( *ep != ' ' && *ep != '\0') {
|
||||
ep = ep+1;
|
||||
}
|
||||
|
||||
int len=ep-sp;
|
||||
// Check we got something usefull
|
||||
if (len > 5) {
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(dest, sp, len);
|
||||
dest[len] = '\0';
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
char *rsm_strstr(const char *haystack, const char *needle)
|
||||
{
|
||||
char *sp1 = (char *)haystack;
|
||||
|
@ -60,12 +100,38 @@ char *rsm_strstr(const char *haystack, const char *needle)
|
|||
//LOG(AQUA_LOG,LOG_DEBUG, "Compare (reset)%d chars of '%s' to '%s'\n",strlen(sp2),sp1,sp2);
|
||||
return strcasestr(sp1, sp2);
|
||||
}
|
||||
char *rsm_strnstr(const char *haystack, const char *needle, int length)
|
||||
|
||||
|
||||
char *rsm_strncasestr(const char *haystack, const char *needle, int length)
|
||||
{
|
||||
// NEED TO WRITE THIS MYSELF. Same as below but limit length
|
||||
return strcasestr(haystack, needle);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the first occurrence of find in s, where the search is limited to the
|
||||
* first slen characters of s.
|
||||
*/
|
||||
char *rsm_strnstr(const char *s, const char *find, size_t slen)
|
||||
{
|
||||
char c, sc;
|
||||
size_t len;
|
||||
|
||||
if ((c = *find++) != '\0') {
|
||||
len = strlen(find);
|
||||
do {
|
||||
do {
|
||||
if (slen-- < 1 || (sc = *s++) == '\0')
|
||||
return (NULL);
|
||||
} while (sc != c);
|
||||
if (len > slen)
|
||||
return (NULL);
|
||||
} while (strncmp(s, find, len) != 0);
|
||||
s--;
|
||||
}
|
||||
return ((char *)s);
|
||||
}
|
||||
|
||||
// Check s2 exists in s1
|
||||
int rsm_strcmp(const char *haystack, const char *needle)
|
||||
{
|
||||
|
|
|
@ -2,7 +2,9 @@
|
|||
#define RS_MSG_UTILS_H_
|
||||
|
||||
char *rsm_strstr(const char *haystack, const char *needle);
|
||||
char *rsm_strnstr(const char *haystack, const char *needle, int length);
|
||||
//char *rsm_strnstr(const char *haystack, const char *needle, int length);
|
||||
char *rsm_strnstr(const char *s, const char *find, size_t slen);
|
||||
char *rsm_strncasestr(const char *haystack, const char *needle, int length);
|
||||
int rsm_strncpy(char *dest, const unsigned char *src, int dest_len, int src_len);
|
||||
int rsm_strcmp(const char *s1, const char *s2);
|
||||
int rsm_strncmp(const char *haystack, const char *needle, int length);
|
||||
|
@ -10,5 +12,6 @@ int rsm_strncpy_nul2sp(char *dest, const unsigned char *src, int dest_len, int s
|
|||
int rsm_atoi(const char* str);
|
||||
float rsm_atof(const char* str);
|
||||
char *rsm_strncpycut(char *dest, const char *src, int dest_len, int src_len);
|
||||
bool rsm_get_revision(char *dest, const char *src, int src_len);
|
||||
|
||||
#endif //RS_MSG_UTILS_H_
|
||||
|
|
216
serial_logger.c
216
serial_logger.c
|
@ -41,7 +41,7 @@
|
|||
#define SLOG_MAX 80
|
||||
#define PACKET_MAX 600
|
||||
|
||||
#define VERSION "serial_logger V1.8"
|
||||
#define VERSION "serial_logger V2.0"
|
||||
|
||||
/*
|
||||
typedef enum used {
|
||||
|
@ -243,32 +243,6 @@ bool canUse(unsigned char ID) {
|
|||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
bool canUse(unsigned char ID) {
|
||||
int i;
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (ID == _goodID[i])
|
||||
return true;
|
||||
}
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (ID == _goodPDAID[i])
|
||||
return true;
|
||||
}
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (ID == _goodONETID[i])
|
||||
return true;
|
||||
}
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (ID == _goodIAQTID[i])
|
||||
return true;
|
||||
}
|
||||
for (i = 0; i < 2; i++) {
|
||||
if (ID == _goodRSSAID[i])
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
char* canUseExtended(unsigned char ID) {
|
||||
int i;
|
||||
for (i = 0; i < 4; i++) {
|
||||
|
@ -294,85 +268,11 @@ char* canUseExtended(unsigned char ID) {
|
|||
return "";
|
||||
}
|
||||
|
||||
|
||||
void printHex(char *pk, int length)
|
||||
{
|
||||
int i=0;
|
||||
for (i=0;i<length;i++)
|
||||
{
|
||||
printf("0x%02hhx|",pk[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void printPacket(unsigned char ID, unsigned char *packet_buffer, int packet_length)
|
||||
{
|
||||
int i;
|
||||
//if (_filter != 0x00 && ID != _filter && packet_buffer[PKT_DEST] != _filter )
|
||||
// return;
|
||||
if (_rawlog) {
|
||||
printHex((char *)packet_buffer, packet_length);
|
||||
printf("\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (_filters != 0)
|
||||
{
|
||||
//int i;
|
||||
bool dest_match = false;
|
||||
bool src_match = false;
|
||||
|
||||
for (i=0; i < _filters; i++) {
|
||||
if ( packet_buffer[PKT_DEST] == _filter[i])
|
||||
dest_match = true;
|
||||
if ( ID == _filter[i] && packet_buffer[PKT_DEST] == 0x00 )
|
||||
src_match = true;
|
||||
}
|
||||
|
||||
if(dest_match == false && src_match == false)
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
if (_filter != 0x00) {
|
||||
if ( packet_buffer[PKT_DEST]==0x00 && ID != _filter )
|
||||
return;
|
||||
if ( packet_buffer[PKT_DEST]!=0x00 && packet_buffer[PKT_DEST] != _filter )
|
||||
return;
|
||||
}
|
||||
*/
|
||||
if (getProtocolType(packet_buffer)==JANDY) {
|
||||
if (packet_buffer[PKT_DEST] != 0x00)
|
||||
printf("\n");
|
||||
printf("Jandy %4.4s 0x%02hhx of type %16.16s", (packet_buffer[PKT_DEST]==0x00?"From":"To"), (packet_buffer[PKT_DEST]==0x00?ID:packet_buffer[PKT_DEST]), get_packet_type(packet_buffer, packet_length));
|
||||
} else {
|
||||
printf("Pentair From 0x%02hhx To 0x%02hhx ",packet_buffer[PEN_PKT_FROM],packet_buffer[PEN_PKT_DEST] );
|
||||
}
|
||||
printf(" | HEX: ");
|
||||
printHex((char *)packet_buffer, packet_length);
|
||||
|
||||
if (packet_buffer[PKT_CMD] == CMD_MSG || packet_buffer[PKT_CMD] == CMD_MSG_LONG) {
|
||||
printf(" Message : ");
|
||||
//fwrite(packet_buffer + 4, 1, AQ_MSGLEN+1, stdout);
|
||||
//fwrite(packet_buffer + 4, 1, packet_length-7, stdout);
|
||||
for(i=4; i < packet_length-3; i++) {
|
||||
if (packet_buffer[i] >= 32 && packet_buffer[i] <= 126)
|
||||
printf("%c",packet_buffer[i]);
|
||||
}
|
||||
}
|
||||
|
||||
//if (packet_buffer[PKT_DEST]==0x00)
|
||||
// printf("\n\n");
|
||||
//else
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void getPanelInfo(int rs_fd, unsigned char *packet_buffer, int packet_length)
|
||||
{
|
||||
static unsigned char getPanelRev[] = {0x00,0x14,0x01};
|
||||
static unsigned char getPanelType[] = {0x00,0x14,0x02};
|
||||
static int msgcnt=0;
|
||||
//int i;
|
||||
|
||||
if (packet_buffer[PKT_CMD] == CMD_PROBE) {
|
||||
if (msgcnt == 0)
|
||||
|
@ -388,55 +288,77 @@ void getPanelInfo(int rs_fd, unsigned char *packet_buffer, int packet_length)
|
|||
rsm_strncpy(_panelRev, packet_buffer+4, AQ_MSGLEN, packet_length-5);
|
||||
else if (msgcnt == 3)
|
||||
rsm_strncpy(_panelType, packet_buffer+4, AQ_MSGLEN, packet_length-5);
|
||||
/*
|
||||
for(i=4; i < packet_length-3; i++) {
|
||||
if (packet_buffer[i] == 0x00)
|
||||
break;
|
||||
else if (packet_buffer[i] >= 32 && packet_buffer[i] <= 126)
|
||||
printf("%c",packet_buffer[i]);
|
||||
}
|
||||
printf("\n");
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SERIAL_LOGGER
|
||||
|
||||
void printHex(char *pk, int length)
|
||||
{
|
||||
int i=0;
|
||||
for (i=0;i<length;i++)
|
||||
{
|
||||
printf("0x%02hhx|",pk[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void printPacket(unsigned char ID, unsigned char *packet_buffer, int packet_length)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (_rawlog) {
|
||||
printHex((char *)packet_buffer, packet_length);
|
||||
printf("\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (_filters != 0)
|
||||
{
|
||||
bool dest_match = false;
|
||||
bool src_match = false;
|
||||
|
||||
for (i=0; i < _filters; i++) {
|
||||
if ( packet_buffer[PKT_DEST] == _filter[i])
|
||||
dest_match = true;
|
||||
if ( ID == _filter[i] && packet_buffer[PKT_DEST] == 0x00 )
|
||||
src_match = true;
|
||||
}
|
||||
|
||||
if(dest_match == false && src_match == false)
|
||||
return;
|
||||
}
|
||||
|
||||
if (getProtocolType(packet_buffer)==JANDY) {
|
||||
if (packet_buffer[PKT_DEST] != 0x00)
|
||||
printf("\n");
|
||||
printf("Jandy %4.4s 0x%02hhx of type %16.16s", (packet_buffer[PKT_DEST]==0x00?"From":"To"), (packet_buffer[PKT_DEST]==0x00?ID:packet_buffer[PKT_DEST]), get_packet_type(packet_buffer, packet_length));
|
||||
} else {
|
||||
printf("Pentair From 0x%02hhx To 0x%02hhx ",packet_buffer[PEN_PKT_FROM],packet_buffer[PEN_PKT_DEST] );
|
||||
}
|
||||
printf(" | HEX: ");
|
||||
printHex((char *)packet_buffer, packet_length);
|
||||
|
||||
if (packet_buffer[PKT_CMD] == CMD_MSG || packet_buffer[PKT_CMD] == CMD_MSG_LONG) {
|
||||
printf(" Message : ");
|
||||
for(i=4; i < packet_length-3; i++) {
|
||||
if (packet_buffer[i] >= 32 && packet_buffer[i] <= 126)
|
||||
printf("%c",packet_buffer[i]);
|
||||
}
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int rs_fd;
|
||||
//int packet_length;
|
||||
//int last_packet_length = 0;
|
||||
//unsigned char packet_buffer[AQ_MAXPKTLEN];
|
||||
//unsigned char last_packet_buffer[AQ_MAXPKTLEN];
|
||||
//unsigned char lastID = 0x00;
|
||||
int i = 0;
|
||||
//bool found;
|
||||
//serial_id_log slog[SLOG_MAX];
|
||||
//serial_id_log pent_slog[SLOG_MAX];
|
||||
//int sindex = 0;
|
||||
//int pent_sindex = 0;
|
||||
//int received_packets = 0;
|
||||
int logPackets = PACKET_MAX;
|
||||
int logLevel = LOG_NOTICE;
|
||||
bool panleProbe = true;
|
||||
bool rsSerialSpeedTest = false;
|
||||
bool serialBlocking = true;
|
||||
bool errorMonitor = false;
|
||||
//struct timespec start_time;
|
||||
//struct timespec end_time;
|
||||
//struct timespec elapsed;
|
||||
//int blankReads = 0;
|
||||
//bool returnError = false;
|
||||
|
||||
|
||||
|
||||
|
||||
//bool monitorOnly = false;
|
||||
|
||||
//bool playback_file = false;
|
||||
|
||||
//int logLevel;
|
||||
//char buffer[256];
|
||||
//bool idMode = true;
|
||||
|
||||
// aq_serial.c uses the following
|
||||
_aqconfig_.readahead_b4_write = false;
|
||||
|
@ -611,9 +533,10 @@ int _serial_logger(int rs_fd, char *port_name, int logPackets, int logLevel, boo
|
|||
} else if (packet_length > 0) {
|
||||
blankReads = 0;
|
||||
//LOG(RSSD_LOG, LOG_DEBUG_SERIAL, "Received Packet for ID 0x%02hhx of type %s\n", packet_buffer[PKT_DEST], get_packet_type(packet_buffer, packet_length));
|
||||
#ifdef SERIAL_LOGGER
|
||||
if (logLevel > LOG_NOTICE)
|
||||
printPacket(lastID, packet_buffer, packet_length);
|
||||
|
||||
#endif
|
||||
if (getProtocolType(packet_buffer) == PENTAIR) {
|
||||
found = false;
|
||||
for (i = 0; i <= pent_sindex; i++) {
|
||||
|
@ -661,18 +584,6 @@ int _serial_logger(int rs_fd, char *port_name, int logPackets, int logLevel, boo
|
|||
}
|
||||
received_packets++;
|
||||
|
||||
// NSF TESTING
|
||||
/*
|
||||
if (packet_buffer[PKT_DEST] == 0x40) {
|
||||
static int hex = 0;
|
||||
//printf("Sent ack\n");
|
||||
//printf("Sent ack hex 0x%02hhx\n",(unsigned char)hex);
|
||||
//send_extended_ack (rs_fd, 0x8b, (unsigned char)hex);
|
||||
send_extended_ack (rs_fd, 0x8b, 0x00);
|
||||
hex++;
|
||||
|
||||
}*/
|
||||
// NSF
|
||||
// Test Serial speed & caching
|
||||
if (rsSerialSpeedTest) {
|
||||
packet_length = get_packet(rs_fd, packet_buffer);
|
||||
|
@ -706,11 +617,6 @@ int _serial_logger(int rs_fd, char *port_name, int logPackets, int logLevel, boo
|
|||
|
||||
clock_gettime(CLOCK_REALTIME, &end_time);
|
||||
|
||||
//stopPacketLogger();
|
||||
|
||||
// Reset and close the port.
|
||||
//close_serial_port(rs_fd);
|
||||
|
||||
// If we were monitoring errors, or filtering messages, or no panel probe, don;t print details
|
||||
if (errorMonitor || panleProbe==false || _filters > 0) {
|
||||
return 0;
|
||||
|
|
|
@ -14,5 +14,6 @@ int logPackets = PACKET_MAX;
|
|||
//int serial_logger(int rs_fd, char *port_name, int logPackets, int logLevel, bool panleProbe, bool rsSerialSpeedTest, bool errorMonitor);
|
||||
|
||||
int serial_logger (int rs_fd, char *port_name, int logLevel);
|
||||
void getPanelInfo(int rs_fd, unsigned char *packet_buffer, int packet_length);
|
||||
|
||||
#endif // SERIAL_LOGGER_H_
|
61
utils.c
61
utils.c
|
@ -34,6 +34,10 @@
|
|||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#ifdef AQ_MANAGER
|
||||
#include <systemd/sd-journal.h>
|
||||
#endif
|
||||
|
||||
#ifndef _UTILS_C_
|
||||
#define _UTILS_C_
|
||||
#endif
|
||||
|
@ -101,6 +105,8 @@ int getLogLevel(int16_t from)
|
|||
return _log_level;
|
||||
}
|
||||
|
||||
#ifdef AQ_MANAGER
|
||||
|
||||
void startInlineLog2File()
|
||||
{
|
||||
_log2file = true;
|
||||
|
@ -111,28 +117,12 @@ void stopInlineLog2File()
|
|||
{
|
||||
_log2file = _cfg_log2file;
|
||||
}
|
||||
char *getInlineLogFName()
|
||||
{
|
||||
return _log_filename;
|
||||
}
|
||||
void cleanInlineLogFile() {
|
||||
void cleanInlineLog2File() {
|
||||
if (_log_filename != NULL) {
|
||||
fclose(fopen(_log_filename, "w"));
|
||||
}
|
||||
}
|
||||
bool islogFileReady()
|
||||
{
|
||||
if (_log_filename != NULL) {
|
||||
struct stat st;
|
||||
stat(_log_filename, &st);
|
||||
if ( st.st_size > 0)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
#ifdef INCLUDE_OLD_DEBUG_HTML
|
||||
#else // AQ_MANAGER
|
||||
void startInlineDebug()
|
||||
{
|
||||
_log_level = LOG_DEBUG;
|
||||
|
@ -159,7 +149,23 @@ void cleanInlineDebug() {
|
|||
fclose(fopen(_log_filename, "w"));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif // AQ_MANAGER
|
||||
|
||||
char *getInlineLogFName()
|
||||
{
|
||||
return _log_filename;
|
||||
}
|
||||
|
||||
bool islogFileReady()
|
||||
{
|
||||
if (_log_filename != NULL) {
|
||||
struct stat st;
|
||||
stat(_log_filename, &st);
|
||||
if ( st.st_size > 0)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
@ -529,6 +535,17 @@ void _LOG(int16_t from, int msg_level, char *message)
|
|||
closelog ();
|
||||
}
|
||||
|
||||
#ifdef AQ_MANAGER // Always use syslog with aqmanager
|
||||
//sd_journal_print()
|
||||
//openlog("aqualinkd", 0, LOG_DAEMON);
|
||||
if (msg_level > LOG_DEBUG) // Let's not confuse syslog with custom levels
|
||||
sd_journal_print (LOG_DEBUG, "%s", &message[9]);
|
||||
//sd_journal_print_with_location(LOG_DEBUG, "aqualinkd", "%s", &message[9]);
|
||||
else
|
||||
sd_journal_print (msg_level, "%s", &message[9]);
|
||||
//sd_journal_print_with_location(msg_level, "aqualinkd", "%s", &message[9]);
|
||||
//closelog ();
|
||||
#else
|
||||
if (_daemonise == TRUE)
|
||||
{
|
||||
if (msg_level > LOG_DEBUG) // Let's not confuse syslog with custom levels
|
||||
|
@ -538,6 +555,7 @@ void _LOG(int16_t from, int msg_level, char *message)
|
|||
closelog ();
|
||||
//return;
|
||||
}
|
||||
#endif
|
||||
|
||||
//int len;
|
||||
message[8] = ' ';
|
||||
|
@ -551,8 +569,9 @@ void _LOG(int16_t from, int msg_level, char *message)
|
|||
}
|
||||
*/
|
||||
|
||||
// Send logs to any websocket that's interested.
|
||||
broadcast_log(message);
|
||||
// Superceded systemd/sd-journal
|
||||
//with Send logs to any websocket that's interested.
|
||||
//broadcast_log(message);
|
||||
|
||||
// Sent the log to the UI if configured.
|
||||
if (msg_level <= LOG_ERR && _loq_display_message != NULL) {
|
||||
|
|
13
utils.h
13
utils.h
|
@ -5,10 +5,7 @@
|
|||
#ifndef UTILS_H_
|
||||
#define UTILS_H_
|
||||
|
||||
// In future release, delete this and all code, it's been replaced with aqmanager
|
||||
#define INCLUDE_OLD_DEBUG_HTML
|
||||
|
||||
#define LOG_DEBUG_SERIAL 8
|
||||
#define LOG_DEBUG_SERIAL LOG_DEBUG+1
|
||||
|
||||
#ifndef EXIT_SUCCESS
|
||||
#define EXIT_FAILURE 1
|
||||
|
@ -103,18 +100,18 @@ char *prittyString(char *str);
|
|||
//void writePacketLog(char *buff);
|
||||
//void closePacketLog();
|
||||
|
||||
|
||||
#ifdef AQ_MANAGER
|
||||
void startInlineLog2File();
|
||||
void stopInlineLog2File();
|
||||
void cleanInlineLogFile();
|
||||
|
||||
#ifdef INCLUDE_OLD_DEBUG_HTML
|
||||
void cleanInlineLog2File();
|
||||
#else
|
||||
void startInlineDebug();
|
||||
void stopInlineDebug();
|
||||
void startInlineSerialDebug();
|
||||
void cleanInlineDebug();
|
||||
#endif
|
||||
|
||||
|
||||
char *getInlineLogFName();
|
||||
bool islogFileReady();
|
||||
//const char *logmask2name(int16_t from);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
|
||||
|
||||
#define AQUALINKD_NAME "Aqualink Daemon"
|
||||
#define AQUALINKD_VERSION "2.3.1"
|
||||
#define AQUALINKD_VERSION "2.3.2"
|
||||
|
|
|
@ -0,0 +1,737 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang='en'>
|
||||
|
||||
<head>
|
||||
<meta http-equiv='Content-Type' content='text/html; charset=windows-1252'>
|
||||
<title>AqualinkD Managment Console</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: grid;
|
||||
grid-template-columns: 300px 1fr;
|
||||
grid-gap: 1rem;
|
||||
}
|
||||
|
||||
.inner {
|
||||
/*padding: 1rem;*/
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
/*border: 1px solid red;*/
|
||||
align-items: flex-start;
|
||||
|
||||
}
|
||||
|
||||
.aqualinkd {
|
||||
grid-column: 1 / -1;
|
||||
}
|
||||
|
||||
.commands {
|
||||
/*padding: 1rem;*/
|
||||
|
||||
/*display: grid;*/
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
/*border: 1px solid red;*/
|
||||
row-gap: 20px;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
.loglevelstitle {
|
||||
background-color: rgb(221, 221, 221);
|
||||
}
|
||||
|
||||
.debugmaskstitle {
|
||||
background-color: rgb(221, 221, 221);
|
||||
}
|
||||
*/
|
||||
|
||||
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);*/
|
||||
background-color: #4CAAD9;
|
||||
border: none;
|
||||
color: rgb(0, 0, 0);
|
||||
padding: 2px 2px;
|
||||
text-decoration: none;
|
||||
margin: 2px 2px 2px 2px;
|
||||
min-width: 70px;
|
||||
border-radius: 70px;
|
||||
height: 20px;
|
||||
/*max-width: 120px;*/
|
||||
}
|
||||
|
||||
.disablebutton {
|
||||
background-color: #ccc !important;
|
||||
color: #777 !important;
|
||||
}
|
||||
|
||||
.disabletoggle {
|
||||
color: #777 !important;
|
||||
}
|
||||
|
||||
.statusmsg {
|
||||
|
||||
}
|
||||
|
||||
.error {
|
||||
background-color: rgb(255, 0, 0) !important;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.logmsgerror {
|
||||
color: rgb(255, 0, 0) !important;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.commands {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.loglevels {}
|
||||
|
||||
.logcontainer {
|
||||
font-family: monospace;
|
||||
height: 510px;
|
||||
|
||||
width: 100%;
|
||||
overflow: auto;
|
||||
display: flex;
|
||||
flex-direction: column-reverse;
|
||||
background-color: #2b2b2b;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.toggle {
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
margin: 1px 1px 1px 1px;
|
||||
|
||||
}
|
||||
|
||||
.logtoggle {
|
||||
width: 130px;
|
||||
}
|
||||
|
||||
.toggle-switch {
|
||||
display: inline-block;
|
||||
background: #ccc;
|
||||
border-radius: 16px;
|
||||
width: 35px;
|
||||
height: 18px;
|
||||
position: relative;
|
||||
vertical-align: middle;
|
||||
transition: background 0.25s;
|
||||
}
|
||||
|
||||
.toggle-switch:before,
|
||||
.toggle-switch:after {
|
||||
content: "";
|
||||
}
|
||||
|
||||
.toggle-switch:before {
|
||||
display: block;
|
||||
background: linear-gradient(to bottom, #fff 0%, #eee 100%);
|
||||
border-radius: 50%;
|
||||
box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.25);
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
left: 2px;
|
||||
transition: left 0.25s;
|
||||
}
|
||||
|
||||
.toggle:hover .toggle-switch:before {
|
||||
background: linear-gradient(to bottom, #fff 0%, #fff 100%);
|
||||
box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
.toggle-checkbox:checked+.toggle-switch {
|
||||
/*background: #56c080;*/
|
||||
background: #4CAAD9;
|
||||
}
|
||||
|
||||
.toggle-checkbox:checked+.toggle-switch:before {
|
||||
left: 19px;
|
||||
}
|
||||
|
||||
.toggle-checkbox {
|
||||
position: absolute;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.toggle-label {
|
||||
margin-left: 5px;
|
||||
position: relative;
|
||||
top: 2px;
|
||||
}
|
||||
|
||||
|
||||
.collapsible {
|
||||
background-color: #777;
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
/*padding: 18px;*/
|
||||
width: 100%;
|
||||
border: none;
|
||||
text-align: left;
|
||||
outline: none;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.collapsible:after {
|
||||
content: '\002B';
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
float: right;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.active:after {
|
||||
content: "\2212";
|
||||
}
|
||||
|
||||
.content {
|
||||
display: grid;
|
||||
/*padding: 0 18px;*/
|
||||
max-height: 0;
|
||||
overflow: hidden;
|
||||
transition: max-height 0.2s ease-out;
|
||||
background-color: #f1f1f1;
|
||||
font-size: 14px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script type='text/javascript'>
|
||||
|
||||
var _panel_size = 6;
|
||||
var _panel_set = 0;
|
||||
|
||||
function init_collapsible() {
|
||||
var coll = document.getElementsByClassName("collapsible");
|
||||
var i;
|
||||
|
||||
for (i = 0; i < coll.length; i++) {
|
||||
coll[i].addEventListener("click", function () {
|
||||
this.classList.toggle("active");
|
||||
var content = this.nextElementSibling;
|
||||
if (content.style.maxHeight) {
|
||||
content.style.maxHeight = null;
|
||||
} else {
|
||||
content.style.maxHeight = content.scrollHeight + "px";
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// open up the system information collapsable content
|
||||
document.getElementById("systembutton").dispatchEvent(new Event('click'));
|
||||
|
||||
// disable the download log button on startup
|
||||
disablebutton("downloadlog");
|
||||
disabletoggle("log2file");
|
||||
//disabletoggle("seriallog");
|
||||
}
|
||||
|
||||
function disablebutton(id) {
|
||||
console.log("disable " + id);
|
||||
var button = document.getElementById(id);
|
||||
if (button) {
|
||||
button.disabled = true;
|
||||
button.classList.add("disablebutton");
|
||||
}
|
||||
}
|
||||
function enablebutton(id) {
|
||||
console.log("enable " + id);
|
||||
var button = document.getElementById(id);
|
||||
if (button) {
|
||||
button.disabled = false;
|
||||
button.classList.remove("disablebutton");
|
||||
}
|
||||
}
|
||||
function disabletoggle(id) {
|
||||
disablebutton(id);
|
||||
try {
|
||||
document.getElementById(id).parentNode.classList.add("disabletoggle");
|
||||
} catch (e) { console.log("error " + e) }
|
||||
}
|
||||
function enabletoggle(id) {
|
||||
enablebutton(id);
|
||||
try {
|
||||
document.getElementById(id).parentNode.classList.remove("disabletoggle");
|
||||
} catch (e) { console.log("error " + e) }
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
var last_message_element = null;
|
||||
|
||||
function update_log_message(message) {
|
||||
var element = document.createElement("div");
|
||||
if (message.startsWith("Error:")) {
|
||||
element.classList.add("logmsgerror");
|
||||
}
|
||||
|
||||
element.appendChild(document.createTextNode(message));
|
||||
document.getElementById("logs").insertBefore(element, last_message_element);
|
||||
last_message_element = element;
|
||||
}
|
||||
|
||||
function update_status(data) {
|
||||
}
|
||||
|
||||
function setloglevel(caller) {
|
||||
//console.log(caller.id);
|
||||
var id = parseInt(caller.id.split('_')[1]);
|
||||
var msg = {
|
||||
uri: "setloglevel",
|
||||
value: id
|
||||
};
|
||||
send_command(msg);
|
||||
}
|
||||
function setlogmask(caller) {
|
||||
console.log(caller.id);
|
||||
var id = parseInt(caller.id.split('_')[1]);
|
||||
var addremove = "";
|
||||
if (caller.checked) {
|
||||
addremove = "addlogmask";
|
||||
} else {
|
||||
addremove = "removelogmask";
|
||||
}
|
||||
|
||||
var msg = {
|
||||
uri: addremove,
|
||||
value: id
|
||||
};
|
||||
send_command(msg);
|
||||
}
|
||||
function setlogfile(caller) {
|
||||
var msg = {};
|
||||
if (caller.id == "log2file") {
|
||||
var startstop = "";
|
||||
if (caller.checked) {
|
||||
startstop = "start";
|
||||
} else {
|
||||
startstop = "stop";
|
||||
}
|
||||
msg = {
|
||||
uri: "log2file/" + startstop,
|
||||
value: 0
|
||||
};
|
||||
} else if (caller.id == "cleanlog") {
|
||||
msg = {
|
||||
uri: "log2file/clean",
|
||||
value: 0
|
||||
};
|
||||
} else if (caller.id == "downloadlog") {
|
||||
//window.location = '/api/debug/download';
|
||||
downloadFile('/api/debug/download/aqualinkd.log');
|
||||
return;
|
||||
}
|
||||
|
||||
send_command(msg);
|
||||
}
|
||||
|
||||
function downloadFile(filePath) {
|
||||
var link = document.createElement('a');
|
||||
link.href = filePath;
|
||||
link.download = filePath.substr(filePath.lastIndexOf('/') + 1);
|
||||
link.click();
|
||||
}
|
||||
|
||||
function settoggle(id, onoff) {
|
||||
var element = document.getElementById(id);
|
||||
if (onoff == "on") {
|
||||
element.checked = true;
|
||||
//console.log("set " + element.id + " on");
|
||||
} else {
|
||||
element.checked = false;
|
||||
//console.log("set " + element.id + " off");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
function update_status(data) {
|
||||
/*
|
||||
read panel_message, panel_type, version, aqualinkd_version
|
||||
|
||||
*/
|
||||
if (data['aqualinkd_version']) {
|
||||
var eCommands = document.getElementById("aqualinkdversion").innerHTML = data['aqualinkd_version'];
|
||||
}
|
||||
if (data['version']) {
|
||||
var eCommands = document.getElementById("panelversion").innerHTML = data['version'];
|
||||
}
|
||||
if (data['panel_type']) {
|
||||
var eCommands = document.getElementById("paneltype").innerHTML = data['panel_type'];
|
||||
}
|
||||
if (data['status']) {
|
||||
update_status_message(data['status']);
|
||||
}
|
||||
/*
|
||||
if (data['status'] == " ") {
|
||||
document.getElementById("statusmsg").innerHTML = "Connected";
|
||||
} else if (data['status'] != " ") {
|
||||
document.getElementById("statusmsg").innerHTML = data['status'];
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
function update_status_message(message, error=false) {
|
||||
try{
|
||||
if (error || message.substring(0, 5).toLowerCase() == "error" )
|
||||
document.getElementById("statusmsg").classList.add("error");
|
||||
else
|
||||
document.getElementById("statusmsg").classList.remove("error");
|
||||
|
||||
if (message == " ") {
|
||||
document.getElementById("statusmsg").innerHTML = "Connected";
|
||||
} else if (message != " ") {
|
||||
document.getElementById("statusmsg").innerHTML = message;
|
||||
}
|
||||
} catch (Error) {}
|
||||
}
|
||||
|
||||
function setAqManagerOptions(data) {
|
||||
|
||||
/*
|
||||
read deamonized logging2file logfilename debugmasks[] loglevels[]
|
||||
if logfilename=NULL we can turn on/off logging to file.
|
||||
logging2file will tell us if it's currently on or off
|
||||
*/
|
||||
console.log("deamonized=" + data['deamonized']);
|
||||
console.log("logfilename=" + data['logfilename']);
|
||||
console.log("logfileready=" + data['logfileready']);
|
||||
|
||||
if (data['logfilename'] == "(null)")
|
||||
enabletoggle("log2file");
|
||||
else
|
||||
disabletoggle("log2file");
|
||||
|
||||
if (data['logfileready'] == "on") {
|
||||
enablebutton("downloadlog");
|
||||
enablebutton("cleanlog");
|
||||
} else {
|
||||
disablebutton("downloadlog");
|
||||
disablebutton("cleanlog");
|
||||
}
|
||||
|
||||
var eCommands = document.getElementById("loglevels");
|
||||
for (var obj in data['loglevels']) {
|
||||
//console.log(data['loglevels'][obj].name);
|
||||
var element_id = "loglevel_" + data['loglevels'][obj].id;
|
||||
var element = document.getElementById(element_id);
|
||||
if (!element) {
|
||||
element = document.createElement('label');
|
||||
element.classList.add('toggle');
|
||||
element.classList.add('logtoggle');
|
||||
element.innerHTML = '<input class="toggle-checkbox" type="checkbox" id="' + element_id + '" onclick="setloglevel(this);">' +
|
||||
'<div class="toggle-switch"></div>' +
|
||||
'<span class="toggle-label">' + data['loglevels'][obj].name + '</span>';
|
||||
eCommands.appendChild(element);
|
||||
}
|
||||
settoggle(element_id, data['loglevels'][obj].set);
|
||||
}
|
||||
|
||||
var eCommands = document.getElementById("debugmasks");
|
||||
for (var obj in data['debugmasks']) {
|
||||
var element_id = "debugmask_" + data['debugmasks'][obj].id;
|
||||
var element = document.getElementById(element_id);
|
||||
if (!element) {
|
||||
element = document.createElement('label');
|
||||
element.classList.add('toggle');
|
||||
element.classList.add('logtoggle');
|
||||
element.innerHTML = '<input class="toggle-checkbox" type="checkbox" id="' + element_id + '" onclick="setlogmask(this);">' +
|
||||
'<div class="toggle-switch"></div>' +
|
||||
'<span class="toggle-label">' + data['debugmasks'][obj].name + '</span>';
|
||||
eCommands.appendChild(element);
|
||||
}
|
||||
settoggle(element_id, data['debugmasks'][obj].set);
|
||||
}
|
||||
}
|
||||
|
||||
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());
|
||||
try {
|
||||
socket_di.onopen = function () {
|
||||
// success!
|
||||
start_manager();
|
||||
//get_devices();
|
||||
}
|
||||
socket_di.onmessage = function got_packet(msg) {
|
||||
//document.getElementById("status").classList.remove("error");
|
||||
//console.log(msg.data);
|
||||
var data
|
||||
try {
|
||||
data = JSON.parse(msg.data);
|
||||
|
||||
}
|
||||
catch (error) {
|
||||
console.error(error);
|
||||
console.log(msg.data);
|
||||
}
|
||||
|
||||
if (data.logmsg) {
|
||||
update_log_message(data.logmsg);
|
||||
} else if (data.na_message) {
|
||||
set_unavailable(data.na_message);
|
||||
} else if (data.message) {
|
||||
update_status_message(data.message);
|
||||
} else if (data.type == 'aqmanager') {
|
||||
setAqManagerOptions(data);
|
||||
//update_status(data);
|
||||
} else if (data.type == 'devices') {
|
||||
//update_device(data);
|
||||
} else if (data.type == 'status') {
|
||||
update_status(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.
|
||||
update_status_message(' !!! Connection error !!! ', true);
|
||||
setTimeout(function () {
|
||||
startWebsockets();
|
||||
}, 5000);
|
||||
}
|
||||
} catch (exception) {
|
||||
alert('<p>Error' + exception);
|
||||
}
|
||||
}
|
||||
|
||||
function send_command(cmd) {
|
||||
console.log("Send " + JSON.stringify(cmd));
|
||||
socket_di.send(JSON.stringify(cmd));
|
||||
|
||||
}
|
||||
|
||||
function start_manager() {
|
||||
var msg = {
|
||||
//command: "simulator"
|
||||
uri: "aqmanager"
|
||||
};
|
||||
socket_di.send(JSON.stringify(msg));
|
||||
}
|
||||
|
||||
function get_devices() {
|
||||
var msg = {
|
||||
uri: "devices"
|
||||
};
|
||||
socket_di.send(JSON.stringify(msg));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
function reset() {
|
||||
socket_di.send("reset\n");
|
||||
}
|
||||
*/
|
||||
function init() {
|
||||
startWebsockets();
|
||||
}
|
||||
|
||||
function set_unavailable(message) {
|
||||
|
||||
console.log("!!! NOT Available !!!");
|
||||
|
||||
update_log_message("!!! AqualinkD Manager "+message+" !!!");
|
||||
|
||||
const demoClasses = document.querySelectorAll('.inner');
|
||||
demoClasses.forEach(element => {
|
||||
element.style.opacity = 0.2;
|
||||
console.log('Element '+element);
|
||||
});
|
||||
|
||||
disablebutton("restart");
|
||||
disablebutton("seriallog");
|
||||
disablebutton("downloadlog");
|
||||
disabletoggle("log2file");
|
||||
|
||||
var coll = document.getElementsByClassName("collapsible");
|
||||
var i;
|
||||
for (i = 0; i < coll.length; i++) {
|
||||
// Remove event listeners from Element by cloning it.
|
||||
coll[i].replaceWith(coll[i].cloneNode(true));
|
||||
}
|
||||
//disabletoggle("seriallog");
|
||||
}
|
||||
|
||||
|
||||
function send(source) {
|
||||
//console.log("from" + source.id);
|
||||
|
||||
var cmd = {};
|
||||
//cmd.uri = "rawcommand"
|
||||
switch (source.id) {
|
||||
case "restart":
|
||||
cmd.uri = "restart"
|
||||
// NEED TO REGET aqmanager after restart.
|
||||
break;
|
||||
case "debugstart":
|
||||
cmd.uri = "debug/start"
|
||||
break;
|
||||
case "debugstop":
|
||||
cmd.uri = "debug/stop"
|
||||
break;
|
||||
case "seriallog":
|
||||
cmd.uri = "seriallogger"
|
||||
break;
|
||||
default:
|
||||
alert("Unknown button");
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
send_command(cmd);
|
||||
}
|
||||
</script>
|
||||
|
||||
<body onload="init();init_collapsible();">
|
||||
<div class="wrapper">
|
||||
<div class="aqualinkd">
|
||||
<iframe id="aqd" src="/" width="100%" height="350px"></iframe>
|
||||
</div>
|
||||
<div class="inner">
|
||||
<div class="commands">
|
||||
<table border='0' id="deviceList">
|
||||
<tr style="title">
|
||||
<td colspan="2" style="title" align="center"><label id="title"> AqualinkD Managment
|
||||
Console </label></th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" align="center"><label id="statusmsg" class="statusmsg" >status</label></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<input id="restart" type="button" onclick="send(this);" value="Restart AqualinkD">
|
||||
</td>
|
||||
<td>
|
||||
<input id="seriallog" type="button" onclick="send(this);" value="Run Serial Logger">
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<button class="collapsible" id="systembutton">System Information</button>
|
||||
<div class="content" id="system">
|
||||
<table border='0'>
|
||||
<tr>
|
||||
<td>AqualinkD version:</td>
|
||||
<td id="aqualinkdversion"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Panel version:</td>
|
||||
<td id="panelversion"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Panel type:</td>
|
||||
<td id="paneltype"></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<!-- -->
|
||||
<button class="collapsible">Log Levels</button>
|
||||
<div class="content" id="loglevels">
|
||||
<!-- Will be populated on load -->
|
||||
</div>
|
||||
<button class="collapsible">Log File</button>
|
||||
<div class="content" id="loglevels">
|
||||
<label class="toggle logtoggle"><input class="toggle-checkbox" type="checkbox" id="log2file"
|
||||
onclick="setlogfile(this);">
|
||||
<div class="toggle-switch"></div><span class="toggle-label">Log to file</span>
|
||||
</label>
|
||||
<input id="downloadlog" type="button" onclick="setlogfile(this);" value="Download logfile"></input>
|
||||
<input id="cleanlog" type="button" onclick="setlogfile(this);" value="Delete logfile"></input>
|
||||
</div>
|
||||
<!-- -->
|
||||
<button class="collapsible">Debug Masks</button>
|
||||
<div class="debugmasks content" id="debugmasks">
|
||||
<!-- Will be populated on load -->
|
||||
</div>
|
||||
<button class="collapsible">Config</button>
|
||||
<div class="content" id="config">
|
||||
<!-- Will be populated on load -->
|
||||
<label>Not Implimented</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="inner">
|
||||
<div class="logcontainer" id="logs">
|
||||
<!--<div class="inner">END</div>-->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
Loading…
Reference in New Issue