mirror of https://github.com/sfeakes/AqualinkD.git
Update
parent
4a6c948a6a
commit
642bfc3383
|
@ -235,6 +235,7 @@ struct aqualinkdata
|
|||
unsigned char raw_status[AQ_PSTLEN];
|
||||
// Multiple threads update this value.
|
||||
volatile bool updated;
|
||||
char self[AQ_MSGLEN*2];
|
||||
|
||||
#ifdef AQ_MANAGER
|
||||
volatile bool run_slogger;
|
||||
|
|
|
@ -69,6 +69,7 @@ static volatile bool _restart = false;
|
|||
//static struct aqconfig _aqconfig_;
|
||||
static struct aqualinkdata _aqualink_data;
|
||||
|
||||
// NSF Need to remove self
|
||||
char *_self;
|
||||
char *_cfgFile;
|
||||
int _cmdln_loglevel = -1;
|
||||
|
@ -1153,6 +1154,7 @@ int startup(char *self, char *cfgFile)
|
|||
_cfgFile = cfgFile;
|
||||
//initButtons(&_aqualink_data);
|
||||
|
||||
sprintf(_aqualink_data.self, basename(self));
|
||||
clearDebugLogMask();
|
||||
read_config(&_aqualink_data, cfgFile);
|
||||
|
||||
|
@ -1372,7 +1374,8 @@ int startup(char *self, char *cfgFile)
|
|||
char pidfile[256];
|
||||
// sprintf(pidfile, "%s/%s.pid",PIDLOCATION, basename(argv[0]));
|
||||
//sprintf(pidfile, "%s/%s.pid", "/run", basename(argv[0]));
|
||||
sprintf(pidfile, "%s/%s.pid", "/run", basename(self));
|
||||
//sprintf(pidfile, "%s/%s.pid", "/run", basename(self));
|
||||
sprintf(pidfile, "%s/%s.pid", "/run", _aqualink_data.self);
|
||||
daemonise(pidfile, main_loop);
|
||||
}
|
||||
else
|
||||
|
|
|
@ -497,8 +497,8 @@ int build_aqualink_aqmanager_JSON(struct aqualinkdata *aqdata, char* buffer, int
|
|||
length += sprintf(buffer+length, ",\"aqualinkd_version\":\"%s\"", AQUALINKD_VERSION ); //1.0b,
|
||||
*/
|
||||
//length += sprintf(buffer+length, ",\"logging2file\": \"%s\"",islogFileReady()?JSON_ON:JSON_OFF);
|
||||
length += sprintf(buffer+length, ",\"logfileready\": \"%s\"",islogFileReady()?JSON_ON:JSON_OFF);
|
||||
length += sprintf(buffer+length, ",\"logfilename\": \"%s\"",_aqconfig_.log_file);
|
||||
//length += sprintf(buffer+length, ",\"logfileready\": \"%s\"",islogFileReady()?JSON_ON:JSON_OFF);
|
||||
//length += sprintf(buffer+length, ",\"logfilename\": \"%s\"",_aqconfig_.log_file);
|
||||
length += sprintf(buffer+length, ",\"debugmasks\":[");
|
||||
length += logmaskjsonobject(AQUA_LOG, buffer+length);
|
||||
length += logmaskjsonobject(NET_LOG, buffer+length);
|
||||
|
|
|
@ -190,6 +190,7 @@ bool broadcast_systemd_logmessages(bool aqMgrActive) {
|
|||
char msg[WS_LOG_LENGTH];
|
||||
static int cnt=0;
|
||||
static char *cursor = NULL;
|
||||
char filter[51];
|
||||
|
||||
if (!aqMgrActive) {
|
||||
if (!active) {
|
||||
|
@ -208,8 +209,16 @@ bool broadcast_systemd_logmessages(bool aqMgrActive) {
|
|||
ws_send_logmsg(_mgr.active_connections, msg);
|
||||
return false;
|
||||
}
|
||||
snprintf(filter, 50, "SYSLOG_IDENTIFIER=%s",_aqualink_data->self );
|
||||
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);
|
||||
build_logmsg_JSON(msg, LOG_ERR, "Failed to set journal syslog filter", WS_LOG_LENGTH,35);
|
||||
ws_send_logmsg(_mgr.active_connections, msg);
|
||||
sd_journal_close(journal);
|
||||
return false;
|
||||
}
|
||||
snprintf(filter, 50, "_PID=%d",getpid());
|
||||
if (sd_journal_add_match(journal, filter, 0) < 0) {
|
||||
build_logmsg_JSON(msg, LOG_ERR, "Failed to set journal PID filter", WS_LOG_LENGTH,32);
|
||||
ws_send_logmsg(_mgr.active_connections, msg);
|
||||
sd_journal_close(journal);
|
||||
return false;
|
||||
|
@ -269,6 +278,76 @@ bool broadcast_systemd_logmessages(bool aqMgrActive) {
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool write_systemd_logmessages_2file(char *fname, int lines)
|
||||
{
|
||||
FILE *fp = NULL;
|
||||
sd_journal *journal;
|
||||
const void *log;
|
||||
size_t len;
|
||||
const void *pri;
|
||||
size_t plen;
|
||||
char filter[51];
|
||||
|
||||
fp = fopen (fname, "w");
|
||||
if (fp == NULL) {
|
||||
LOG(NET_LOG, LOG_WARNING, "Failed to open tmp log file '%s'\n",fname);
|
||||
return false;
|
||||
}
|
||||
if (sd_journal_open(&journal, SD_JOURNAL_LOCAL_ONLY) < 0)
|
||||
{
|
||||
LOG(NET_LOG, LOG_WARNING, "Failed to open journal");
|
||||
fclose (fp);
|
||||
return false;
|
||||
}
|
||||
snprintf(filter, 50, "SYSLOG_IDENTIFIER=%s",_aqualink_data->self );
|
||||
if (sd_journal_add_match(journal, "SYSLOG_IDENTIFIER=aqualinkd", 0) < 0)
|
||||
{
|
||||
LOG(NET_LOG, LOG_WARNING, "Failed to set journal syslog filter");
|
||||
fclose (fp);
|
||||
sd_journal_close(journal);
|
||||
return false;
|
||||
}
|
||||
snprintf(filter, 50, "_PID=%d",getpid());
|
||||
if (sd_journal_add_match(journal, filter, 0) < 0)
|
||||
{
|
||||
LOG(NET_LOG, LOG_WARNING, "Failed to set journal pid filter");
|
||||
fclose (fp);
|
||||
sd_journal_close(journal);
|
||||
return false;
|
||||
}
|
||||
if (sd_journal_seek_tail(journal) < 0)
|
||||
{
|
||||
LOG(NET_LOG, LOG_WARNING, "Failed to seek to journal end");
|
||||
fclose (fp);
|
||||
sd_journal_close(journal);
|
||||
return false;
|
||||
}
|
||||
if (sd_journal_previous_skip(journal, lines) < 0)
|
||||
{
|
||||
LOG(NET_LOG, LOG_WARNING, "Failed to seek to journal start");
|
||||
fclose (fp);
|
||||
sd_journal_close(journal);
|
||||
return false;
|
||||
}
|
||||
|
||||
while ( sd_journal_next(journal) > 0) // need to capture return of this
|
||||
{
|
||||
if (sd_journal_get_data(journal, "MESSAGE", &log, &len) < 0) {
|
||||
LOG(NET_LOG, LOG_WARNING, "Failed to get journal message");
|
||||
} else if (sd_journal_get_data(journal, "PRIORITY", &pri, &plen) < 0) {
|
||||
LOG(NET_LOG, LOG_WARNING, "Failed to seek to journal message priority");
|
||||
} else {
|
||||
fprintf(fp, "%-7s %.*s\n",elevel2text(atoi((const char *)pri+9)), (int)len-8,(const char *)log+8);
|
||||
}
|
||||
}
|
||||
|
||||
sd_journal_close(journal);
|
||||
fclose (fp);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* superseded with systemd/sd-journal
|
||||
|
@ -813,7 +892,7 @@ void mqtt_broadcast_aqualinkstate(struct mg_connection *nc)
|
|||
}
|
||||
|
||||
|
||||
typedef enum {uActioned, uBad, uDevices, uStatus, uHomebridge, uDynamicconf, uDebugStatus, uDebugDownload, uSimulator, uSchedules, uSetSchedules, uAQmanager, uNotAvailable} uriAtype;
|
||||
typedef enum {uActioned, uBad, uDevices, uStatus, uHomebridge, uDynamicconf, uDebugStatus, uDebugDownload, uSimulator, uSchedules, uSetSchedules, uAQmanager, uLogDownload, uNotAvailable} uriAtype;
|
||||
//typedef enum {NET_MQTT=0, NET_API, NET_WS, DZ_MQTT} netRequest;
|
||||
const char actionName[][5] = {"MQTT", "API", "WS", "DZ"};
|
||||
|
||||
|
@ -919,14 +998,15 @@ uriAtype action_URI(request_source from, const char *URI, int uri_length, float
|
|||
removeDebugLogMask(round(value));
|
||||
return uAQmanager; // Want to resent updated status
|
||||
} else if (strncmp(ri1, "log2file", 5) == 0) {
|
||||
/*
|
||||
if (ri2 != NULL && strncmp(ri2, "start", 5) == 0) {
|
||||
startInlineLog2File();
|
||||
} else if (ri2 != NULL && strncmp(ri2, "stop", 4) == 0) {
|
||||
stopInlineLog2File();
|
||||
} else if (ri2 != NULL && strncmp(ri2, "clean", 5) == 0) {
|
||||
cleanInlineLog2File();
|
||||
} else if (ri2 != NULL && strncmp(ri2, "download", 8) == 0) {
|
||||
return uDebugDownload;
|
||||
} else*/ if (ri2 != NULL && strncmp(ri2, "download", 8) == 0) {
|
||||
return uLogDownload;
|
||||
}
|
||||
return uAQmanager; // Want to resent updated status
|
||||
} else if (strncmp(ri1, "restart", 7) == 0 && from == NET_WS) { // Only valid from websocket.
|
||||
|
@ -1403,10 +1483,15 @@ void action_web_request(struct mg_connection *nc, struct http_message *http_msg)
|
|||
mg_send(nc, message, size);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case uDebugDownload:
|
||||
mg_http_serve_file(nc, http_msg, getInlineLogFName(), mg_mk_str("text/plain"), mg_mk_str(""));
|
||||
#else
|
||||
case uLogDownload:
|
||||
LOG(NET_LOG, LOG_DEBUG, "Downloading log of max %d lines\n",value>0?(int)value:1000);
|
||||
if (write_systemd_logmessages_2file("/dev/shm/aqualinkd.log", value>0?(int)value:1000) ) {
|
||||
mg_http_serve_file(nc, http_msg, "/dev/shm/aqualinkd.log", mg_mk_str("text/plain"), mg_mk_str("Content-Disposition: attachment; filename=\"aqualinkd.log\""));
|
||||
remove("/dev/shm/aqualinkd.log");
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case uBad:
|
||||
default:
|
||||
if (msg == NULL) {
|
||||
|
|
|
@ -279,6 +279,11 @@ bool log_panelversion(struct aqualinkdata *aq_data)
|
|||
|
||||
// It's already been set
|
||||
if (strlen(aq_data->version) > 0) {
|
||||
// If another protocol set it, we need to check if it's version.
|
||||
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;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
Binary file not shown.
Binary file not shown.
15
utils.c
15
utils.c
|
@ -53,12 +53,15 @@
|
|||
void broadcast_log(char *msg);
|
||||
|
||||
static bool _daemonise = false;
|
||||
|
||||
#ifndef AD_MANAGER
|
||||
static bool _log2file = false;
|
||||
//static int _log_level = LOG_ERR;
|
||||
static int _log_level = LOG_WARNING;
|
||||
static char *_log_filename = NULL;
|
||||
static bool _cfg_log2file;
|
||||
static int _cfg_log_level;
|
||||
#endif
|
||||
|
||||
static char *_loq_display_message = NULL;
|
||||
int16_t _logforcemask = 0;
|
||||
|
@ -106,7 +109,7 @@ int getLogLevel(int16_t from)
|
|||
}
|
||||
|
||||
#ifdef AQ_MANAGER
|
||||
|
||||
/*
|
||||
void startInlineLog2File()
|
||||
{
|
||||
_log2file = true;
|
||||
|
@ -122,6 +125,7 @@ void cleanInlineLog2File() {
|
|||
fclose(fopen(_log_filename, "w"));
|
||||
}
|
||||
}
|
||||
*/
|
||||
#else // AQ_MANAGER
|
||||
void startInlineDebug()
|
||||
{
|
||||
|
@ -149,8 +153,6 @@ void cleanInlineDebug() {
|
|||
fclose(fopen(_log_filename, "w"));
|
||||
}
|
||||
}
|
||||
#endif // AQ_MANAGER
|
||||
|
||||
char *getInlineLogFName()
|
||||
{
|
||||
return _log_filename;
|
||||
|
@ -166,6 +168,9 @@ bool islogFileReady()
|
|||
}
|
||||
return false;
|
||||
}
|
||||
#endif // AQ_MANAGER
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
@ -658,9 +663,9 @@ void daemonise (char *pidFile, void (*main_function) (void))
|
|||
fp = fopen (pidFile, "w");
|
||||
|
||||
if (fp == NULL)
|
||||
LOG(AQUA_LOG, LOG_ERR,"can't write to PID file %s",pidFile);
|
||||
LOG(AQUA_LOG, LOG_ERR,"can't write to PID file %s",pidFile);
|
||||
else
|
||||
fprintf(fp, "%d", process_id);
|
||||
fprintf(fp, "%d", process_id);
|
||||
|
||||
fclose (fp);
|
||||
LOG(AQUA_LOG, LOG_DEBUG, "process_id of child process %d \n", process_id);
|
||||
|
|
11
utils.h
11
utils.h
|
@ -102,18 +102,19 @@ char *prittyString(char *str);
|
|||
|
||||
|
||||
#ifdef AQ_MANAGER
|
||||
void startInlineLog2File();
|
||||
void stopInlineLog2File();
|
||||
void cleanInlineLog2File();
|
||||
//void startInlineLog2File();
|
||||
//void stopInlineLog2File();
|
||||
//void cleanInlineLog2File();
|
||||
#else
|
||||
void startInlineDebug();
|
||||
void stopInlineDebug();
|
||||
void startInlineSerialDebug();
|
||||
void cleanInlineDebug();
|
||||
#endif
|
||||
|
||||
char *getInlineLogFName();
|
||||
bool islogFileReady();
|
||||
#endif
|
||||
|
||||
|
||||
//const char *logmask2name(int16_t from);
|
||||
|
||||
//#ifndef _UTILS_C_
|
||||
|
|
|
@ -263,8 +263,8 @@
|
|||
document.getElementById("systembutton").dispatchEvent(new Event('click'));
|
||||
|
||||
// disable the download log button on startup
|
||||
disablebutton("downloadlog");
|
||||
disabletoggle("log2file");
|
||||
//disablebutton("downloadlog");
|
||||
//disabletoggle("log2file");
|
||||
//disabletoggle("seriallog");
|
||||
}
|
||||
|
||||
|
@ -369,19 +369,35 @@
|
|||
value: 0
|
||||
};
|
||||
} else if (caller.id == "downloadlog") {
|
||||
|
||||
//window.location = '/api/debug/download';
|
||||
downloadFile('/api/debug/download/aqualinkd.log');
|
||||
downloadFile('/api/log2file/download/aqualinkd.log', document.getElementById("logsize").value);
|
||||
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 downloadFile(filePath, lines) {
|
||||
console.log("Lines=" + lines);
|
||||
/*
|
||||
var link = document.createElement('a');
|
||||
link.href = filePath;
|
||||
link.download = filePath.substr(filePath.lastIndexOf('/') + 1);
|
||||
link.click();
|
||||
*/
|
||||
|
||||
var form = document.createElement('form');
|
||||
form.setAttribute("style", "display: none;");
|
||||
form.method='POST';
|
||||
form.action=filePath;
|
||||
element=document.createElement('INPUT');
|
||||
element.name='value';
|
||||
element.value=lines;
|
||||
form.appendChild(element);
|
||||
document.body.appendChild(form);
|
||||
form.submit();
|
||||
|
||||
}
|
||||
|
||||
function settoggle(id, onoff) {
|
||||
|
@ -453,7 +469,7 @@
|
|||
enabletoggle("log2file");
|
||||
else
|
||||
disabletoggle("log2file");
|
||||
|
||||
/*
|
||||
if (data['logfileready'] == "on") {
|
||||
enablebutton("downloadlog");
|
||||
enablebutton("cleanlog");
|
||||
|
@ -461,7 +477,7 @@
|
|||
disablebutton("downloadlog");
|
||||
disablebutton("cleanlog");
|
||||
}
|
||||
|
||||
*/
|
||||
var eCommands = document.getElementById("loglevels");
|
||||
for (var obj in data['loglevels']) {
|
||||
//console.log(data['loglevels'][obj].name);
|
||||
|
@ -617,7 +633,7 @@
|
|||
disablebutton("restart");
|
||||
disablebutton("seriallog");
|
||||
disablebutton("downloadlog");
|
||||
disabletoggle("log2file");
|
||||
//disabletoggle("log2file");
|
||||
|
||||
var coll = document.getElementsByClassName("collapsible");
|
||||
var i;
|
||||
|
@ -706,12 +722,17 @@
|
|||
</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>
|
||||
-->
|
||||
<table border='0'><tr><td>
|
||||
<input id="downloadlog" type="button" onclick="setlogfile(this);" value="Download logfile"></input>
|
||||
</td><td>
|
||||
<input id="logsize" type="text" value="1000" size="5">#lines</input>
|
||||
</td></tr></table>
|
||||
</div>
|
||||
<!-- -->
|
||||
<button class="collapsible">Debug Masks</button>
|
||||
|
|
Loading…
Reference in New Issue