Version 1.3.6

pull/89/head
sfeakes 2019-08-25 15:57:51 -05:00
parent ed66368ad7
commit 107fff314a
11 changed files with 262 additions and 18 deletions

View File

@ -6,7 +6,8 @@
# define the C compiler to use
CC = gcc
LIBS := -lpthread -lm
#LIBS := -lpthread -lm
LIBS := -l pthread -l m
#LIBS := -lpthread -lwebsockets
# debug of not

View File

@ -1,5 +1,6 @@
# Aqualinkd
Linux daemon to control Aqualink RS pool controllers. Provides web UI, MQTT client & HTTP API endpoints. Control your pool equiptment from any phone/tablet or computer. Is also compatible with most Home control systems including Apple HomeKit, Samsung, Alexa, Google, etc.
Binaries are supplied for Raspberry Pi, Has bean, and can be compiled for many different SBC's.
### It does not, and will never provide any layer of security. NEVER directly expose the device running this software to the outside world; only indirectly through the use of Home Automation hub's or other security measures. e.g. VPNs.
@ -64,7 +65,8 @@ Designed to mimic AqualinkRS6 All Button keypad and (like the keypad) is used to
* 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)
#<a name="release"></a>
# Update in Release 1.3.5a,b,c,d
# Update in Release 1.3.5a,b,c,d,e
* Can now debug inline from a web ui. (http://aqualinkd.ip.address/debug.html)
* Note to Homekit users. Upgrading to 1.3.5c (and above) will add an aditional SWG PPM tile, (look in default room). You'll need to update homebridge-aqualinkd to 0.0.8 (or later) to remove the old PPM tile (or delete you homebridge cache). This is due to a bug in homebridge-aqualinkd < 0.0.7 that didn't delete unused tiles.
* Logic for SWG RS486 checksum_errors.
* Fixed pentair packet logging, missing last byte.
@ -72,6 +74,8 @@ Designed to mimic AqualinkRS6 All Button keypad and (like the keypad) is used to
* Can now display warnings and errors in the web UI (as well as log).
* Memory issue with PDA.
* Better support for "single device mode" on PDA.
* Memory leak in web UI with some browsers.
* Changes for better portability when compiling on other systems.
# Update in Release 1.3.5
* Fixed SWG bug showing off/0% every ~15 seconds (introduced in 1.3.3).
* PDA updates for freeze protect/SWG and general speed increase.

View File

@ -93,7 +93,6 @@ void init_parameters (struct aqconfig * parms)
generate_mqtt_id(parms->mqtt_ID, MQTT_ID_LEN);
}
char *cleanalloc(char*str)
{
char *result;

View File

@ -740,6 +740,39 @@ void action_web_request(struct mg_connection *nc, struct http_message *http_msg)
mg_send_head(nc, 200, strlen(GET_RTN_ERROR), "Content-Type: text/plain");
mg_send(nc, GET_RTN_ERROR, strlen(GET_RTN_ERROR));
}
} else if (strcmp(command, "debug") == 0) {
char value[80];
char *rtn;
mg_get_http_var(&http_msg->query_string, "value", value, sizeof(value));
if (strcmp(value, "start") == 0) {
startInlineDebug();
rtn = GET_RTN_OK;
logMessage(LOG_DEBUG, "WEB: Started inline debug mode\n");
} else if (strcmp(value, "stop") == 0) {
logMessage(LOG_DEBUG, "WEB: Stoped inline debug mode\n");
stopInlineDebug();
rtn = GET_RTN_OK;
} else if (strcmp(value, "serialstart") == 0) {
rtn = GET_RTN_OK;
} else if (strcmp(value, "serialstop") == 0) {
rtn = GET_RTN_OK;
} else if (strcmp(value, "status") == 0) {
snprintf(value,80,"{\"sLevel\":\"%s\", \"iLevel\":%d, \"logReady\":\"%s\"}\n",elevel2text(getLogLevel()),getLogLevel(),islogFileReady()?"true":"false" );
mg_send_head(nc, 200, strlen(value), "Content-Type: text/json");
mg_send(nc, value, strlen(value));
return;
//rtn = value;
} else if (strcmp(value, "clean") == 0) {
cleanInlineDebug();
rtn = GET_RTN_OK;
} else if (strcmp(value, "download") == 0) {
mg_http_serve_file(nc, http_msg, getInlineLogFName(), mg_mk_str("text/plain"), mg_mk_str(""));
return;
} else {
rtn = GET_RTN_UNKNOWN;
}
mg_send_head(nc, 200, strlen(rtn), "Content-Type: text/plain");
mg_send(nc, rtn, strlen(rtn));
} else {
int i;
for (i = 0; i < TOTAL_BUTTONS; i++) {
@ -798,8 +831,8 @@ void action_web_request(struct mg_connection *nc, struct http_message *http_msg)
}
}
// If we get here, got a bad query
mg_send_head(nc, 200, sizeof(GET_RTN_UNKNOWN), "Content-Type: text/plain");
mg_send(nc, GET_RTN_UNKNOWN, sizeof(GET_RTN_UNKNOWN));
mg_send_head(nc, 200, strlen(GET_RTN_UNKNOWN), "Content-Type: text/plain");
mg_send(nc, GET_RTN_UNKNOWN, strlen(GET_RTN_UNKNOWN));
} else {
struct mg_serve_http_opts opts;

Binary file not shown.

Binary file not shown.

45
utils.c
View File

@ -39,6 +39,8 @@
#include "utils.h"
#define DEFAULT_LOG_FILE "/tmp/aqualinkd-inline.log"
//#define MAXCFGLINE 265
#define TIMESTAMP_LENGTH 30
@ -47,6 +49,8 @@ static bool _daemonise = false;
static bool _log2file = false;
static int _log_level = LOG_ERR;
static char *_log_filename = NULL;
static bool _cfg_log2file;
static int _cfg_log_level;
static char *_loq_display_message = NULL;
//static char _log_filename[256];
@ -56,6 +60,9 @@ void setLoggingPrms(int level , bool deamonized, char* log_file, char *error_mes
_log_level = level;
_daemonise = deamonized;
_loq_display_message = error_messages;
_cfg_log_level = _log_level;
_cfg_log2file = _log2file;
if (log_file == NULL || strlen(log_file) <= 0) {
_log2file = false;
@ -72,6 +79,44 @@ int getLogLevel()
}
void startInlineDebug()
{
_log_level = LOG_DEBUG;
_log2file = true;
if (_log_filename == NULL)
_log_filename = DEFAULT_LOG_FILE;
}
void stopInlineDebug()
{
_log_level = _cfg_log_level;
_log2file = _cfg_log2file;
}
char *getInlineLogFName()
{
return _log_filename;
}
bool islogFileReady()
{
if (_log_filename != NULL) {
struct stat st;
stat(_log_filename, &st);
if ( st.st_size > 0)
return true;
}
return false;
}
void cleanInlineDebug() {
if (_log_filename != NULL) {
fclose(fopen(_log_filename, "w"));
}
}
/*
* This function reports the error and
* exits back to the shell:

View File

@ -54,6 +54,11 @@ int ascii(char *destination, char *source);
char *prittyString(char *str);
//void writePacketLog(char *buff);
//void closePacketLog();
void startInlineDebug();
void stopInlineDebug();
void cleanInlineDebug();
char *getInlineLogFName();
bool islogFileReady();
//#ifndef _UTILS_C_
extern bool _daemon_;

View File

@ -1,4 +1,4 @@
#define AQUALINKD_NAME "Aqualink Daemon"
#define AQUALINKD_VERSION "1.3.5d"
#define AQUALINKD_VERSION "1.3.6"

View File

@ -461,6 +461,7 @@
</style>
<script type='text/javascript'>
//'use strict';
var _lightProgramDropdown = false;
var _pressEvent;
var _ignoreMouseEvent = false;
@ -498,13 +499,15 @@
var tbody = document.getElementById('pswitch_table').getElementsByTagName('tbody')[0];
var html1 = '';
var html2 = '';
fLen = light_program.length;
var fLen = light_program.length;
var i;
for (i = 0; i < fLen; i++) {
if (light_program[i].endsWith(" - Show"))
html2 = html2 + "<div class='option_radiocontainer'><label><span class='radio'><input type='radio' name='light_program' value='" + (i+1) + "' onchange='updatePwsitchOptions(this);'><span class='option_radio-value' aria-hidden='true'></span></span>" + light_program[i].substr(0, (light_program[i].length - 7)) + "</label></div>";
else
html1 = html1 + "<div class='option_radiocontainer'><label><span class='radio'><input type='radio' name='light_program' value='" + (i+1) + "' onchange='updatePwsitchOptions(this);'><span class='option_radio-value' aria-hidden='true'></span></span>" + light_program[i] + "</label></div>";
}
var row;
row = tbody.deleteRow(2);
row = tbody.insertRow(2);
row.innerHTML = "<td align='center'>Solid Color</td><td align='center'>Light Show</td>";
@ -658,17 +661,17 @@
}
function add_tile(id, name, status, type, subtype, off_imgurl, on_imgurl) {
height = getComputedStyle(document.documentElement).getPropertyValue('--tile_icon-height');
div = document.createElement('div');
var height = getComputedStyle(document.documentElement).getPropertyValue('--tile_icon-height');
var div = document.createElement('div');
div.setAttribute('class', 'tile');
div.setAttribute('id', id);
div.setAttribute('type', subtype);
//div.setAttribute('onclick', "switchTileState('" + id + "')");
subdiv = document.createElement('div');
var subdiv = document.createElement('div');
subdiv.setAttribute('class', 'tile_icon');
subdiv.setAttribute('id', id + '_icon');
if (off_imgurl != null) {
imgdiv = document.createElement('img');
var imgdiv = document.createElement('img');
imgdiv.setAttribute('height', height + 'px');
imgdiv.setAttribute('src', off_imgurl);
subdiv.appendChild(imgdiv);
@ -685,7 +688,7 @@
div.appendChild(subdiv);
}
} else if (type == "value" || type == "thermostat") {
valdiv = document.createElement('div');
var valdiv = document.createElement('div');
valdiv.setAttribute('class', 'tile_icon_value disabled');
valdiv.setAttribute('id', id + '_tile_icon_value');
valdiv.textContent = '--';
@ -741,6 +744,7 @@
}
function setThermostatSetpoint(id, sp_value) {
var tile;
if ((tile = document.getElementById(id)) == null) {
return;
}
@ -765,6 +769,7 @@
}
}
//document.getElementById(id + '_tile_icon_value').textContent = value;
var tile;
if ((tile = document.getElementById(id + '_tile_icon_value')) != null)
tile.innerHTML = value + ext;
}
@ -781,12 +786,14 @@
function setThermostatTile(id, value, sp_value) {
setTileValue(id, value);
var tile;
if ((tile = document.getElementById(id)) != null) {
tile.setAttribute('setpoint', sp_value);
}
}
function formatSatus(status) {
var index;
if ((index = status.indexOf("AUX")) >= 0) {
aux = status.substr(index, 4);
status = status.charAt(0).toUpperCase() + status.substr(1).toLowerCase();
@ -824,11 +831,14 @@
tile.classList.remove("flash");
text = "On";
}
var offimg;
var onimg;
if ((offimg = document.getElementById(id + '_icon')) != null &&
(onimg = document.getElementById(id + '_icon_on')) != null) {
offimg.style.display = 'none';
onimg.style.display = 'table';
}
var type;
if ((type = tile.getAttribute('type')) != null) {
if (type == 'setpoint_swg')
text = 'Generating';
@ -851,7 +861,7 @@
text = "Off";
}
document.getElementById(id + '_status').innerHTML = text;
tile_icon = document.getElementById(id + '_tile_icon_value');
var tile_icon = document.getElementById(id + '_tile_icon_value');
type = tile.getAttribute('type');
if (status != null && tile_icon != null) {
if (status == 'enabled' || status == 'flash') {
@ -922,7 +932,7 @@
document.getElementById('pswitch_options').style.display = 'none';
}
active_option.style.display = 'flex';
optionH = window.getComputedStyle(active_option, null).getPropertyValue("height");
var optionH = window.getComputedStyle(active_option, null).getPropertyValue("height");
if (optionH <= wrapH)
active_option.style.height = wrapH;
@ -946,9 +956,9 @@
}
if (show == true) {
var tile = document.getElementById(id);
sp_value = tile.getAttribute('setpoint');
var sp_value = tile.getAttribute('setpoint');
//tile_state = tile.classList.contains("on");
tile_state = !(tile.getAttribute('status') == 'off');
var tile_state = !(tile.getAttribute('status') == 'off');
var type = tile.getAttribute('type');
var slider;
var slider_output;
@ -1046,7 +1056,7 @@
document.getElementById("body_wrap").addEventListener("click", clickHandler);
close_button.onclick = function() {
document.getElementById("body_wrap").removeEventListener("click", clickHandler);
state = oswitch.checked;
var state = oswitch.checked;
if (type == 'switch_program') {
var mode=false;
if (_lightProgramDropdown) {
@ -1056,6 +1066,7 @@
}
} else {
var radio = document.getElementsByName("light_program");
var x;
for (x = 0; x < radio.length; x++) {
if (radio[x].checked == true) {
send_light_mode(radio[x].value, id);
@ -1069,7 +1080,7 @@
setTileState(id, state);
}
} else {
value = slider.value;
var value = slider.value;
if (state == (tile.getAttribute('status') == 'off'))
setTileState(id, state);
if (sp_value != slider.value)
@ -1248,6 +1259,7 @@
function send_setpoint(id) {
var temperature = {};
var tile;
if ((tile = document.getElementById(id)) == null) {
return;
}

145
web/debug.html Normal file
View File

@ -0,0 +1,145 @@
<!DOCTYPE html>
<html lang='en'>
<head>
<meta http-equiv='Content-Type' content='text/html; charset=windows-1252'>
<title>AqualinkD</title>
<meta name='viewport' content='width=device-width'>
<meta name='mobile-web-app-capable' content='yes'>
<meta name='apple-mobile-web-app-capable' content='yes'>
<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'>
</head>
<style>
/*
******************************************************************************
Taken from https://github.com/ubuwaits/css3-buttons */
button::-moz-focus-inner {
border: 0;
}
button.blue-pill {
background-color: #a5b8da;
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #a5b8da), color-stop(100%, #7089b3));
background-image: -webkit-linear-gradient(top, #a5b8da, #7089b3);
background-image: -moz-linear-gradient(top, #a5b8da, #7089b3);
background-image: -ms-linear-gradient(top, #a5b8da, #7089b3);
background-image: -o-linear-gradient(top, #a5b8da, #7089b3);
background-image: linear-gradient(top, #a5b8da, #7089b3);
border-top: 1px solid #758fba;
border-right: 1px solid #6c84ab;
border-bottom: 1px solid #5c6f91;
border-left: 1px solid #6c84ab;
border-radius: 18px;
-webkit-box-shadow: inset 0 1px 0 0 #aec3e5;
box-shadow: inset 0 1px 0 0 #aec3e5;
color: #fff;
font: bold 11px/1 "Lucida Grande", "Lucida Sans Unicode", "Lucida Sans", Geneva, Verdana, sans-serif;
padding: 8px 0;
text-align: center;
text-shadow: 0 -1px 1px #64799e;
text-transform: uppercase;
width: 150px;
}
button.blue-pill:disabled {
opacity: 0.5;
}
</style>
<script type='text/javascript'>
var _poller;
function action(element) {
var query;
if (element.id == "start") {
document.getElementById('messages').innerHTML = "Debug Starting!"
} else if (element.id == "stop") {
document.getElementById('messages').innerHTML = "Debug Stopping!"
} else if (element.id == "clean") {
document.getElementById('messages').innerHTML = "Cleaning Debug File!"
} else if (element.id == "download") {
window.location = location.href + '?command=debug&value=download';
} else {
return;
}
var http = new XMLHttpRequest();
http.open('GET', location.href + '?command=debug&value='+element.id);
http.send(null);
setTimeout(function () {
forceupdate();
}, 1000);
}
function forceupdate() {
clearTimeout(_poller);
update();
}
function update() {
var http = new XMLHttpRequest();
if (http) {
http.onreadystatechange = function () {
if (http.readyState === 4) {
if (http.status == 200 && http.status < 300) {
var data = JSON.parse(http.responseText);
//console.log(data.iLevel + " : " + data.sLevel);
if ( data.iLevel >= 7 ) {
document.getElementById('start').disabled = true;
document.getElementById('stop').disabled = false;
document.getElementById('messages').innerHTML = "Debug Running!"
} else if ( data.iLevel < 7 ) {
document.getElementById('start').disabled = false;
document.getElementById('stop').disabled = true;
document.getElementById('messages').innerHTML = "&nbsp"
}
if (data.logReady == "true") {
document.getElementById('download').disabled = false;
if (document.getElementById('stop').disabled == true) {
document.getElementById('clean').disabled = false;
} else {
document.getElementById('clean').disabled = true;
}
} else {
document.getElementById('download').disabled = true;
document.getElementById('clean').disabled = true;
}
}
else if (http.status >= 400 || http.status == 0) {
document.getElementById('messages').innerHTML = 'Error connecting to AqualinkD';
}
}
}
};
http.open('GET', location.href + '?command=debug&value=status');
http.send(null);
_poller = setTimeout(update, 5000);
}
</script>
<body onload="update();">
<table cellpadding="10" border="0" align="center">
<tr><td colspan="2" align="center">
<div id="messages">&nbsp</div>
</td></tr>
<tr><td align="center">
<button class="blue-pill" id="start" type="button" onclick='action(this);'>Start Debug</button>
</td><td align="center">
<button class="blue-pill" id="stop" type="button" onclick='action(this);'>Stop Debug</button>
</td></tr>
<tr><td colspan="2" align="center">
<button class="blue-pill" id="download" type="button" onclick='action(this);'>Download Debug File</button>
</td></tr>
<tr><td colspan="2" align="center">
<button class="blue-pill" id="clean" type="button" onclick='action(this);'>Clean Debug File</button>
</td></tr>
</table>
</body>
</html>