[Debian-iot-packaging] [openzwave-controlpanel] 29/81: Support new events. Add test interface. Need more real time support then polling to make this work. Add statistics interface.
Dara Adib
daradib-guest at moszumanska.debian.org
Thu Dec 22 16:57:48 UTC 2016
This is an automated email from the git hooks/post-receive script.
daradib-guest pushed a commit to branch debian/master
in repository openzwave-controlpanel.
commit 62ab61db4ea61b18226226b84525d10b998ef502
Author: glsatz <glsatz at gmail.com>
Date: Mon Dec 10 17:01:22 2012 +0000
Support new events.
Add test interface. Need more real time support then polling to make this
work.
Add statistics interface.
---
cp.html | 115 ++++++++++++++++++++++++++++---
cp.js | 218 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
ozwcp.cpp | 33 ++++++++-
webserver.cpp | 205 ++++++++++++++++++++++++++++++++++++++++++++++++++----
webserver.h | 2 +
zwavelib.cpp | 1 +
6 files changed, 548 insertions(+), 26 deletions(-)
diff --git a/cp.html b/cp.html
index 30c25f7..ad29923 100644
--- a/cp.html
+++ b/cp.html
@@ -76,8 +76,7 @@
</div>
</div>
<div style="padding: 0pt; width: 34%; float: left;">
- <div
- style="margin-left: auto; margin-right: auto; width: 280px; height: 100px;">
+ <div style="margin-left: auto; margin-right: auto; width: 280px; height: 100px;">
<fieldset> <legend> Controller Status </legend>
<form>
<div style="float: left; width: 50%;">
@@ -139,8 +138,13 @@
<option value="choice" selected="true">Select an operation:</option>
<option value="scen">Scenes</option>
<option value="topo">Topology</option>
+ <option value="stat">Statistics</option>
+ <option value="test">Test Network</option>
</select>
</div>
+ <div class="rsb" style="margin-left: 10px;">
+ <span id="netinfo" name="netinfo" class="admmsg" style="display: none;"></span>
+ </div>
<div id="scencntl" name="scencntl" class="rsb" style="display: none; margin-right: 10px;">
<div class="rsb" style="margin-left: 10px;">
<table>
@@ -230,12 +234,7 @@
<button id="refreshtopo" name="refreshtopo" onclick="return TopoLoad('load');" type="submit">Refresh</button>
</div>
</div>
- <div class="rsb" style="margin-left: 10px;">
- <span id="netinfo" name="netinfo" class="admmsg" style="display: none;"></span>
- </div>
- <br>
- <br>
- <div id="topo" style="float: left; margin-left: 5px; width: 98%; display: none; overflow="scroll";">
+ <div id="topo" style="float: left; margin-left: 5px; width: 98%; display: none; overflow: scroll;">
<table border="0" cellpadding="1" cellspacing="0" style="text-align: center;">
<thead id="topohead">
<tr>
@@ -255,6 +254,106 @@
</tbody>
</table>
</div>
+ <div id="statcntl" name="statcntl" class="rsb" style="display: none; margin-right: 5px;">
+ <div class="rsb" style="margin-left: 5px;">
+ <button id="refreshstat" name="refreshstat" onclick="return StatLoad('load');" type="submit">Refresh</button>
+ </div>
+ </div>
+ <div id="statnet" style="float: left; margin-left: 5px; width: 98%; display: none;">
+ <table border="0" cellpadding="1" cellspacing="0" style="text-align: center;">
+ <thead id="statnethead">
+ <tr>
+ <th style="text-align: right;">Network Errors</th>
+ <th style="text-decoration: none;"> </th>
+ <th style="text-align: right;">Message Counts</th>
+ <th style="text-decoration: none;"> </th>
+ <th style="text-align: right;">Network Info</th>
+ <th style="text-decoration: none;"> </th>
+ </tr>
+ </thead>
+ <tbody id="statnetbody">
+ <tr>
+ <td> </td>
+ <td> </td>
+ </tr>
+ <tr>
+ <td> </td>
+ <td> </td>
+ </tr>
+ <tr>
+ <td> </td>
+ <td> </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ <div id="allstats" style="margin-left: auto; margin-right: auto; width: 100%;">
+ <div id="statnode" style="float: left; margin-left: 5px; width: 100%; display: none;">
+ <table border="0" cellpadding="1" cellspacing="0" style="text-align: center;">
+ <thead id="statnodehead">
+ <tr>
+ <th style="text-align: center;">Node</th>
+ <th style="text-align: center;">Sent</th>
+ <th style="text-align: center;">Failed</th>
+ <th style="text-align: center;">Retries</th>
+ <th style="text-align: center;">Received</th>
+ <th style="text-align: center;">Duplicates</th>
+ <th style="text-align: center;">Last Sent</th>
+ <th style="text-align: center;">Last Received</th>
+ <th style="text-align: center;">Last RTT</th>
+ <th style="text-align: center;">Average RTT</th>
+ <th style="text-align: center;">Quality</th>
+ </tr>
+ </thead>
+ <tbody id="statnodebody" style="cursor: help;">
+ <tr>
+ <td> </td>
+ <td> </td>
+ </tr>
+ <tr>
+ <td> </td>
+ <td> </td>
+ </tr>
+ <tr>
+ <td> </td>
+ <td> </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ <div id="statclass" style="float: left; margin-left: 5px; width: 25%; display: none;">
+ <table border="0" cellpadding="1" cellspacing="0" style="text-align: center;">
+ <thead id="statclasshead">
+ <tr>
+ <th style="text-align: center;">Class</th>
+ <th style="text-align: center;">Sent</th>
+ <th style="text-align: center;">Received</th>
+ </tr>
+ </thead>
+ <tbody id="statclassbody">
+ <tr>
+ <td> </td>
+ <td> </td>
+ <td> </td>
+ </tr>
+ <tr>
+ <td> </td>
+ <td> </td>
+ <td> </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </div>
+ <div id="testcntl" name="testcntl" class="rsb" style="display: none; margin-right: 5px;">
+ <div class="rsb" style="margin-left: 5px;">
+ <button id="testbutton" name="testbutton" onclick="return TestLoad('load');" type="submit">Run</button>
+ <label><span class="legend" style="font-size: 12px;">Message count:</span></label>
+ <input id="testmcnt" type="text" size="5" class="legend">
+ </div>
+ </div>
+ <div id="testreport" class="log" style="float: left; margin-left: 5px; width: 98%; text-align: left; display: none;">
+ </div>
</form>
</fieldset>
</div>
diff --git a/cp.js b/cp.js
index 9dcb2ca..404d7e7 100644
--- a/cp.js
+++ b/cp.js
@@ -1,6 +1,8 @@
var pollhttp;
var scenehttp;
var topohttp;
+var stathttp;
+var atsthttp;
var racphttp;
var polltmr=null;
var pollwait=null;
@@ -35,6 +37,8 @@ var curnode=null;
var curscene=null;
var scenes=new Array();
var routes=new Array();
+var curclassstat=null;
+var classstats=new Array();
if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari
pollhttp=new XMLHttpRequest();
} else {
@@ -51,6 +55,16 @@ if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari
topohttp=new ActiveXObject("Microsoft.XMLHTTP");
}
if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari
+ stathttp=new XMLHttpRequest();
+} else {
+ stathttp=new ActiveXObject("Microsoft.XMLHTTP");
+}
+if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari
+ atsthttp=new XMLHttpRequest();
+} else {
+ atsthttp=new ActiveXObject("Microsoft.XMLHTTP");
+}
+if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari
racphttp=new XMLHttpRequest();
} else {
racphttp=new ActiveXObject("Microsoft.XMLHTTP");
@@ -132,6 +146,10 @@ function PollReply()
document.getElementById('saveinfo').style.display = 'none';
}
}
+ if (elem[0].getAttribute('noop') == '1') {
+ var testreport = document.getElementById('testreport');
+ testreport.innerHTML = testreport.innerHTML + 'No Operation message completed.<br>';
+ }
elem = xml.getElementsByTagName('admin');
if (elem[0].getAttribute('active') == 'true') {
if (!astate) {
@@ -157,9 +175,7 @@ function PollReply()
if (elem.length > 0) {
var remove = elem[0].getAttribute('remove');
if (remove != undefined) {
- console.log('remove='+remove);
var remnodes = remove.split(',');
- console.log('remnodes len='+remnodes.length);
changed = true;
for (var i = 0; i < remnodes.length; i++) {
nodes[remnodes[i]] = null;
@@ -544,12 +560,24 @@ function DoNetHelp()
var scencntl = document.getElementById('scencntl');
var topocntl = document.getElementById('topocntl');
var topo = document.getElementById('topo');
+ var statcntl = document.getElementById('statcntl');
+ var statnet = document.getElementById('statnet');
+ var statnode = document.getElementById('statnode');
+ var statclass = document.getElementById('statclass');
+ var testcntl = document.getElementById('testcntl');
+ var testreport = document.getElementById('testreport');
if (document.NetPost.netops.value == 'scen') {
ninfo.innerHTML = 'Scene management and execution.';
ninfo.style.display = 'block';
scencntl.style.display = 'block';
topocntl.style.display = 'none';
topo.style.display = 'none';
+ statcntl.style.display = 'none';
+ statnet.style.display = 'none';
+ statnode.style.display = 'none';
+ statclass.style.display = 'none';
+ testcntl.style.display = 'none';
+ testreport.style.display = 'none';
SceneLoad('load');
} else if (document.NetPost.netops.value == 'topo') {
ninfo.innerHTML = 'Topology views';
@@ -557,13 +585,51 @@ function DoNetHelp()
scencntl.style.display = 'none';
topocntl.style.display = 'block';
topo.style.display = 'block';
+ statcntl.style.display = 'none';
+ statnet.style.display = 'none';
+ statnode.style.display = 'none';
+ statclass.style.display = 'none';
+ testcntl.style.display = 'none';
+ testreport.style.display = 'none';
curscene = null;
TopoLoad('load');
+ } else if (document.NetPost.netops.value == 'stat') {
+ ninfo.innerHTML = 'Statistic views';
+ ninfo.style.display = 'block';
+ scencntl.style.display = 'none';
+ topocntl.style.display = 'none';
+ topo.style.display = 'none';
+ statcntl.style.display = 'block';
+ statnet.style.display = 'block';
+ statnode.style.display = 'block';
+ testcntl.style.display = 'none';
+ testreport.style.display = 'none';
+ curscene = null;
+ StatLoad('load');
+ } else if (document.NetPost.netops.value == 'test') {
+ ninfo.innerHTML = 'Test Network';
+ ninfo.style.display = 'block';
+ scencntl.style.display = 'none';
+ topocntl.style.display = 'none';
+ topo.style.display = 'none';
+ statcntl.style.display = 'none';
+ statnet.style.display = 'none';
+ statnode.style.display = 'none';
+ statclass.style.display = 'none';
+ testcntl.style.display = 'block';
+ testreport.style.display = 'block';
+ curscene = null;
} else {
ninfo.style.display = 'none';
scencntl.style.display = 'none';
topocntl.style.display = 'none';
topo.style.display = 'none';
+ statcntl.style.display = 'none';
+ statnet.style.display = 'none';
+ statnode.style.display = 'none';
+ statclass.style.display = 'none';
+ testcntl.style.display = 'none';
+ testreport.style.display = 'none';
curscene = null;
}
return true;
@@ -729,7 +795,7 @@ function DoNodeHelp()
var node=curnode.substr(4);
var ncntl = document.getElementById('nodecntl');
if (document.NodePost.nodeops.value == 'nam') {
- ninfo.innerHTML = 'Node naming functions.';
+ ninfo.innerHTML = 'Naming functions.';
ninfo.style.display = 'block';
ncntl.innerHTML = nodename[node];
ncntl.style.display = 'block';
@@ -1189,6 +1255,152 @@ function TopoReply()
}
}
}
+function DisplayStatClass(t,n)
+{
+ var scb = document.getElementById('statclassbody');
+ var sn = document.getElementById('statnode');
+ if (curclassstat != null) {
+ var lastn = curclassstat.id.substr(8);
+ if (n != lastn) {
+ curclassstat.className = 'normal';
+ }
+ }
+ if (curclassstat == null || t != curclassstat) {
+ curclassstat = t;
+ t.className = 'highlight';
+ sn.style.width = '72%';
+ scb.innerHTML = classstats[n];
+ document.getElementById('statclass').style.display = 'block';
+ } else {
+ curclassstat = null;
+ t.className = 'normal';
+ sn.style.width = '100%';
+ scb.innerHTML = '';
+ document.getElementById('statclass').style.display = 'none';
+ }
+ return true;
+}
+function StatLoad(fun)
+{
+ var params='fun='+fun;
+ stathttp.open('POST','statpost.html', true);
+ stathttp.onreadystatechange = StatReply;
+ stathttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
+ stathttp.send(params);
+
+ return false;
+}
+function StatReply()
+{
+ var xml;
+ var elem;
+
+ if (stathttp.readyState == 4 && stathttp.status == 200) {
+ xml = stathttp.responseXML;
+ elem = xml.getElementsByTagName('stats');
+ if (elem.length > 0) {
+ var errors = xml.getElementsByTagName('errors');
+ var counts = xml.getElementsByTagName('counts');
+ var info = xml.getElementsByTagName('info');
+ var cnt = errors[0].childNodes.length;
+ if (counts[0].childNodes.length > cnt)
+ cnt = counts[0].childNodes.length;
+ if (info[0].childNodes.length > cnt)
+ cnt = info[0].childNodes.length;
+ var stuff = '';
+ var i;
+ for (i = 0; i < cnt; i++) {
+ if (i < errors[0].childNodes.length)
+ if (errors[0].childNodes[i].nodeType != 1)
+ continue;
+ if (i < counts[0].childNodes.length)
+ if (counts[0].childNodes[i].nodeType != 1)
+ continue;
+ if (i < info[0].childNodes.length)
+ if (info[0].childNodes[i].nodeType != 1)
+ continue;
+ stuff = stuff + '<tr>';
+ if (i < errors[0].childNodes.length)
+ stuff = stuff + '<td style="text-align: right;">'+errors[0].childNodes[i].getAttribute('label')+': </td><td style="text-align: left;">'+errors[0].childNodes[i].firstChild.nodeValue+'</td>';
+ else
+ stuff = stuff + '<td> </td><td> </td>';
+ if (i < counts[0].childNodes.length)
+ stuff = stuff + '<td style="text-align: right;">'+counts[0].childNodes[i].getAttribute('label')+': </td><td style="text-align: left;">'+counts[0].childNodes[i].firstChild.nodeValue+'</td>';
+ else
+ stuff = stuff + '<td> </td><td> </td>';
+ if (i < info[0].childNodes.length)
+ stuff = stuff + '<td style="text-align: right;">'+info[0].childNodes[i].getAttribute('label')+': </td><td style="text-align: left;">'+info[0].childNodes[i].firstChild.nodeValue+'</td>';
+ else
+ stuff = stuff + '<td> </td><td> </td>';
+ stuff = stuff + '</tr>';
+ }
+ var statnetbody = document.getElementById('statnetbody');
+ statnetbody.innerHTML = stuff;
+ var node = xml.getElementsByTagName('node');
+ var stuff = '';
+ var oldnode = null;
+ if (curclassstat != null)
+ oldnode = curclassstat.id;
+ for (var i = 0; i < node.length; i++) {
+ stuff = stuff+'<tr id="statnode'+i+'" onclick="return DisplayStatClass(this,'+i+');"><td>'+node[i].getAttribute('id')+'</td>';
+ var nstat = node[i].getElementsByTagName('nstat');
+ for (var j = 0; j < nstat.length; j++) {
+ stuff = stuff+'<td>'+nstat[j].firstChild.nodeValue+'</td>';
+ }
+ stuff = stuff+'</tr>';
+ var cstuff = '';
+ var cclass = node[i].getElementsByTagName('commandclass');
+ for (var j = 0; j < cclass.length; j++) {
+ cstuff = cstuff+'<tr><td>'+cclass[j].getAttribute('name')+'</td>';
+ var cstat = cclass[j].getElementsByTagName('cstat');
+ for (var k = 0; k < cstat.length; k++) {
+ cstuff = cstuff+'<td>'+cstat[k].firstChild.nodeValue+'</td>';
+ }
+ cstuff = cstuff+'</tr>';
+ }
+ classstats[i] = cstuff;
+ }
+ var statnodebody = document.getElementById('statnodebody');
+ statnodebody.innerHTML = stuff;
+ }
+ if (oldnode != null) {
+ var scb = document.getElementById('statclassbody');
+ scb.innerHTML = classstats[oldnode.substr(8)];
+ curclassstat = document.getElementById(oldnode);
+ curclassstat.className = 'highlight';
+ }
+ }
+}
+function TestLoad(fun)
+{
+ var params='fun='+fun;
+ var cnt = document.getElementById('testmcnt');
+ if (cnt.value.length == 0) {
+ alert('Missing count value');
+ return false;
+ }
+ params = params+'&cnt='+cnt.value;
+ atsthttp.open('POST','testpost.html', true);
+ atsthttp.onreadystatechange = TestReply;
+ atsthttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
+ atsthttp.send(params);
+
+ return false;
+}
+function TestReply()
+{
+ var xml;
+ var elem;
+
+ if (atsthttp.readyState == 4 && atsthttp.status == 200) {
+ xml = atsthttp.responseXML;
+ elem = xml.getElementsByTagName('test');
+ if (elem.length > 0) {
+ var testreport = document.getElementById('testreport');
+ testreport.innerHTML = '';
+ }
+ }
+}
function RequestAllConfig(n)
{
var params='fun=racp&node='+n;
diff --git a/ozwcp.cpp b/ozwcp.cpp
index 54c03e2..d9e461a 100644
--- a/ozwcp.cpp
+++ b/ozwcp.cpp
@@ -64,6 +64,7 @@ int32 MyNode::nodecount = 0;
pthread_mutex_t glock = PTHREAD_MUTEX_INITIALIZER;
bool done = false;
bool needsave = false;
+bool noop = false;
uint32 homeId = 0;
uint8 nodeId = 0;
const char *cmode = "";
@@ -564,6 +565,12 @@ void OnNotification (Notification const* _notification, void* _context)
//nodes[_notification->GetNodeId()]->setPolled(true);
//pthread_mutex_unlock(&nlock);
break;
+ case Notification::Type_SceneEvent:
+ Log::Write(LogLevel_Info, "Notification: Scene Event Home %08x Node %d Genre %s Class %s Instance %d Index %d Type %s Scene Id %d",
+ _notification->GetHomeId(), _notification->GetNodeId(),
+ valueGenreStr(id.GetGenre()), cclassStr(id.GetCommandClassId()), id.GetInstance(),
+ id.GetIndex(), valueTypeStr(id.GetType()), _notification->GetSceneId());
+ break;
case Notification::Type_CreateButton:
Log::Write(LogLevel_Info, "Notification: Create button Home %08x Node %d Button %d",
_notification->GetHomeId(), _notification->GetNodeId(), _notification->GetButtonId());
@@ -625,9 +632,6 @@ void OnNotification (Notification const* _notification, void* _context)
MyNode::remove(i);
pthread_mutex_unlock(&nlock);
break;
- case Notification::Type_MsgComplete:
- Log::Write(LogLevel_Info, "Notification: Message Complete");
- break;
case Notification::Type_EssentialNodeQueriesComplete:
Log::Write(LogLevel_Info, "Notification: Essential Node %d Queries Complete", _notification->GetNodeId());
break;
@@ -643,6 +647,29 @@ void OnNotification (Notification const* _notification, void* _context)
case Notification::Type_AllNodesQueried:
Log::Write(LogLevel_Info, "Notification: All Nodes Queried");
break;
+ case Notification::Type_Notification:
+ switch (_notification->GetNotification()) {
+ case Notification::Code_MsgComplete:
+ Log::Write(LogLevel_Info, "Notification: Notification home %08x node %d Message Complete",
+ _notification->GetHomeId(), _notification->GetNodeId());
+ break;
+ case Notification::Code_Timeout:
+ Log::Write(LogLevel_Info, "Notification: Notification home %08x node %d Timeout",
+ _notification->GetHomeId(), _notification->GetNodeId());
+ break;
+ case Notification::Code_NoOperation:
+ Log::Write(LogLevel_Info, "Notification: Notification home %08x node %d No Operation Message Complete",
+ _notification->GetHomeId(), _notification->GetNodeId());
+ pthread_mutex_lock(&glock);
+ noop = true;
+ pthread_mutex_unlock(&glock);
+ break;
+ default:
+ Log::Write(LogLevel_Info, "Notification: Notification home %08x node %d Unknown %d",
+ _notification->GetHomeId(), _notification->GetNodeId(), _notification->GetNotification());
+ break;
+ }
+ break;
default:
Log::Write(LogLevel_Info, "Notification: type %d home %08x node %d genre %d class %d instance %d index %d type %d",
_notification->GetType(), _notification->GetHomeId(),
diff --git a/webserver.cpp b/webserver.cpp
index e01f5c0..f7d4f0c 100644
--- a/webserver.cpp
+++ b/webserver.cpp
@@ -91,6 +91,7 @@ extern bool needsave;
extern uint32 homeId;
extern uint8 nodeId; // controller node id
extern char *cmode;
+extern bool noop;
extern int debug;
/*
@@ -287,7 +288,6 @@ const char *Webserver::SendTopoResponse (struct MHD_Connection *conn, const char
{
TiXmlDocument doc;
char str[16];
- string s;
static char fntemp[32];
char *fn;
uint i, j, k;
@@ -328,7 +328,164 @@ const char *Webserver::SendTopoResponse (struct MHD_Connection *conn, const char
i++;
}
}
- strncpy(fntemp, "/tmp/ozwcp.scenes.XXXXXX", sizeof(fntemp));
+ strncpy(fntemp, "/tmp/ozwcp.topo.XXXXXX", sizeof(fntemp));
+ fn = mktemp(fntemp);
+ if (fn == NULL)
+ return EMPTY;
+ strncat(fntemp, ".xml", sizeof(fntemp));
+ if (debug)
+ doc.Print(stdout, 0);
+ doc.SaveFile(fn);
+ return fn;
+}
+
+static TiXmlElement *newstat (char const *tag, char const *label, uint32 const value)
+{
+ char str[32];
+
+ TiXmlElement* statElement = new TiXmlElement(tag);
+ statElement->SetAttribute("label", label);
+ snprintf(str, sizeof(str), "%d", value);
+ TiXmlText *textElement = new TiXmlText(str);
+ statElement->LinkEndChild(textElement);
+ return statElement;
+}
+
+static TiXmlElement *newstat (char const *tag, char const *label, char const *value)
+{
+ TiXmlElement* statElement = new TiXmlElement(tag);
+ statElement->SetAttribute("label", label);
+ TiXmlText *textElement = new TiXmlText(value);
+ statElement->LinkEndChild(textElement);
+ return statElement;
+}
+
+/*
+ * SendStatResponse
+ * Process statistics request and return appropiate data
+ */
+
+const char *Webserver::SendStatResponse (struct MHD_Connection *conn, const char *fun,
+ const char *arg1, const char *arg2, const char *arg3)
+{
+ TiXmlDocument doc;
+ static char fntemp[32];
+ char *fn;
+
+ TiXmlDeclaration* decl = new TiXmlDeclaration( "1.0", "utf-8", "" );
+ doc.LinkEndChild(decl);
+ TiXmlElement* statElement = new TiXmlElement("stats");
+ doc.LinkEndChild(statElement);
+
+ if (strcmp(fun, "load") == 0) {
+ struct Driver::DriverData data;
+ int i, j;
+ int cnt;
+ char str[16];
+
+ Manager::Get()->GetDriverStatistics(homeId, &data);
+
+ TiXmlElement* errorsElement = new TiXmlElement("errors");
+ errorsElement->LinkEndChild(newstat("stat", "ACK Waiting", data.m_ACKWaiting));
+ errorsElement->LinkEndChild(newstat("stat", "Read Aborts", data.m_readAborts));
+ errorsElement->LinkEndChild(newstat("stat", "Bad Checksums", data.m_badChecksum));
+ errorsElement->LinkEndChild(newstat("stat", "CANs", data.m_CANCnt));
+ errorsElement->LinkEndChild(newstat("stat", "NAKs", data.m_NAKCnt));
+ errorsElement->LinkEndChild(newstat("stat", "Out of Frame", data.m_OOFCnt));
+ statElement->LinkEndChild(errorsElement);
+
+ TiXmlElement* countsElement = new TiXmlElement("counts");
+ countsElement->LinkEndChild(newstat("stat", "SOF", data.m_SOFCnt));
+ countsElement->LinkEndChild(newstat("stat", "Total Reads", data.m_readCnt));
+ countsElement->LinkEndChild(newstat("stat", "Total Writes", data.m_writeCnt));
+ countsElement->LinkEndChild(newstat("stat", "ACKs", data.m_ACKCnt));
+ countsElement->LinkEndChild(newstat("stat", "Total Broadcasts Received", data.m_broadcastReadCnt));
+ countsElement->LinkEndChild(newstat("stat", "Total Broadcasts Transmitted", data.m_broadcastWriteCnt));
+ statElement->LinkEndChild(countsElement);
+
+ TiXmlElement* infoElement = new TiXmlElement("info");
+ infoElement->LinkEndChild(newstat("stat", "Dropped", data.m_dropped));
+ infoElement->LinkEndChild(newstat("stat", "Retries", data.m_retries));
+ infoElement->LinkEndChild(newstat("stat", "Unexpected Callbacks", data.m_callbacks));
+ infoElement->LinkEndChild(newstat("stat", "Bad Routes", data.m_badroutes));
+ infoElement->LinkEndChild(newstat("stat", "No ACK", data.m_noack));
+ infoElement->LinkEndChild(newstat("stat", "Network Busy", data.m_netbusy));
+ infoElement->LinkEndChild(newstat("stat", "Non Delivery", data.m_nondelivery));
+ infoElement->LinkEndChild(newstat("stat", "Routes Busy", data.m_routedbusy));
+ statElement->LinkEndChild(infoElement);
+
+ cnt = MyNode::getNodeCount();
+ i = 0;
+ j = 1;
+ while (j <= cnt && i < MAX_NODES) {
+ struct Node::NodeData ndata;
+
+ if (nodes[i] != NULL) {
+ Manager::Get()->GetNodeStatistics(homeId, i, &ndata);
+ TiXmlElement* nodeElement = new TiXmlElement("node");
+ snprintf(str, sizeof(str), "%d", i);
+ nodeElement->SetAttribute("id", str);
+ nodeElement->LinkEndChild(newstat("nstat", "Sent messages", ndata.m_sentCnt));
+ nodeElement->LinkEndChild(newstat("nstat", "Failed sent messages", ndata.m_sentFailed));
+ nodeElement->LinkEndChild(newstat("nstat", "Retried sent messages", ndata.m_retries));
+ nodeElement->LinkEndChild(newstat("nstat", "Received messages", ndata.m_receivedCnt));
+ nodeElement->LinkEndChild(newstat("nstat", "Received duplicates", ndata.m_receivedDups));
+ nodeElement->LinkEndChild(newstat("nstat", "Last sent message", ndata.m_sentTS.c_str()));
+ nodeElement->LinkEndChild(newstat("nstat", "Last received message", ndata.m_receivedTS.c_str()));
+ nodeElement->LinkEndChild(newstat("nstat", "Last RTT", ndata.m_averageRTT));
+ nodeElement->LinkEndChild(newstat("nstat", "Average RTT", ndata.m_averageRTT));
+ nodeElement->LinkEndChild(newstat("nstat", "Quality", ndata.m_quality));
+ while (!ndata.m_ccData.empty()) {
+ Node::CommandClassData ccd = ndata.m_ccData.front();
+ TiXmlElement* ccElement = new TiXmlElement("commandclass");
+ snprintf(str, sizeof(str), "%d", ccd.m_commandClassId);
+ ccElement->SetAttribute("id", str);
+ ccElement->SetAttribute("name", cclassStr(ccd.m_commandClassId));
+ ccElement->LinkEndChild(newstat("cstat", "Messages sent", ccd.m_sentCnt));
+ ccElement->LinkEndChild(newstat("cstat", "Messages received", ccd.m_receivedCnt));
+ nodeElement->LinkEndChild(ccElement);
+ ndata.m_ccData.pop_front();
+ }
+ statElement->LinkEndChild(nodeElement);
+ j++;
+ }
+ i++;
+ }
+ }
+ strncpy(fntemp, "/tmp/ozwcp.stat.XXXXXX", sizeof(fntemp));
+ fn = mktemp(fntemp);
+ if (fn == NULL)
+ return EMPTY;
+ strncat(fntemp, ".xml", sizeof(fntemp));
+ if (debug)
+ doc.Print(stdout, 0);
+ doc.SaveFile(fn);
+ return fn;
+}
+
+/*
+ * SendTestResponse
+ * Process network test request
+ */
+
+const char *Webserver::SendTestResponse (struct MHD_Connection *conn, const char *fun,
+ const char *arg1, const char *arg2, const char *arg3)
+{
+ TiXmlDocument doc;
+ int cnt;
+ static char fntemp[32];
+ char *fn;
+
+ TiXmlDeclaration* decl = new TiXmlDeclaration( "1.0", "utf-8", "" );
+ doc.LinkEndChild(decl);
+ TiXmlElement* testElement = new TiXmlElement("test");
+ doc.LinkEndChild(testElement);
+
+ if (strcmp(fun, "load") == 0 && arg1 != NULL) {
+ cnt = atoi((char *)arg1);
+ Manager::Get()->TestNetwork(homeId, cnt);
+ }
+ strncpy(fntemp, "/tmp/ozwcp.test.XXXXXX", sizeof(fntemp));
fn = mktemp(fntemp);
if (fn == NULL)
return EMPTY;
@@ -490,6 +647,9 @@ int Webserver::SendPollResponse (struct MHD_Connection *conn)
pollElement->SetAttribute("nodecount", MyNode::getNodeCount());
pollElement->SetAttribute("cmode", cmode);
pollElement->SetAttribute("save", needsave);
+ pollElement->SetAttribute("noop", noop);
+ if (noop)
+ noop = false;
bcnt = logbytes;
if (stat("./OZW_Log.txt", &buf) != -1 &&
buf.st_size > bcnt &&
@@ -696,6 +856,14 @@ int web_config_post (void *cls, enum MHD_ValueKind kind, const char *key, const
} else if (strcmp(cp->conn_url, "/topopost.html") == 0) {
if (strcmp(key, "fun") == 0)
cp->conn_arg1 = (void *)strdup(data);
+ } else if (strcmp(cp->conn_url, "/statpost.html") == 0) {
+ if (strcmp(key, "fun") == 0)
+ cp->conn_arg1 = (void *)strdup(data);
+ } else if (strcmp(cp->conn_url, "/testpost.html") == 0) {
+ if (strcmp(key, "fun") == 0)
+ cp->conn_arg1 = (void *)strdup(data);
+ if (strcmp(key, "cnt") == 0)
+ cp->conn_arg2 = (void *)strdup(data);
} else if (strcmp(cp->conn_url, "/confparmpost.html") == 0) {
if (strcmp(key, "fun") == 0)
cp->conn_arg1 = (void *)strdup(data);
@@ -725,7 +893,7 @@ int Webserver::Handler (struct MHD_Connection *conn, const char *url,
conninfo_t *cp;
if (debug)
- fprintf(stderr, "%x: %s: \"%s\"\n", pthread_self(), method, url);
+ fprintf(stderr, "%x: %s: \"%s\" conn=%x size=%d *ptr=%x\n", pthread_self(), method, url, conn, *up_data_size, *ptr);
if (*ptr == NULL) { /* do never respond on first call */
cp = (conninfo_t *)malloc(sizeof(conninfo_t));
if (cp == NULL)
@@ -737,7 +905,7 @@ int Webserver::Handler (struct MHD_Connection *conn, const char *url,
cp->conn_arg4 = NULL;
cp->conn_res = NULL;
if (strcmp(method, MHD_HTTP_METHOD_POST) == 0) {
- cp->conn_pp = MHD_create_post_processor(conn, 512, web_config_post, (void *)cp);
+ cp->conn_pp = MHD_create_post_processor(conn, 1024, web_config_post, (void *)cp);
if (cp->conn_pp == NULL) {
free(cp);
return MHD_NO;
@@ -803,13 +971,6 @@ int Webserver::Handler (struct MHD_Connection *conn, const char *url,
homeId = 0;
} else if (strcmp((char *)cp->conn_arg1, "reset") == 0) { /* reset */
Manager::Get()->ResetController(homeId);
- sleep(2);
- Manager::Get()->RemoveDriver(devname ? devname : "HID Controller");
- sleep(5);
- if (devname != NULL)
- Manager::Get()->AddDriver(devname);
- else
- Manager::Get()->AddDriver("HID Controller", Driver::ControllerInterface_Hid );
} else if (strcmp((char *)cp->conn_arg1, "sreset") == 0) { /* soft reset */
Manager::Get()->SoftReset(homeId);
} else if (strcmp((char *)cp->conn_arg1, "exit") == 0) { /* exit */
@@ -835,7 +996,7 @@ int Webserver::Handler (struct MHD_Connection *conn, const char *url,
if (val != NULL) {
string arg = (char *)cp->conn_arg2;
if (!Manager::Get()->SetValue(val->getId(), arg))
- fprintf(stderr, "SetValue string failed");
+ fprintf(stderr, "SetValue string failed\n");
}
return MHD_YES;
} else
@@ -864,6 +1025,7 @@ int Webserver::Handler (struct MHD_Connection *conn, const char *url,
*up_data_size = 0;
cp->conn_res = (void *)SendSceneResponse(conn, (char *)cp->conn_arg1, (char *)cp->conn_arg2, (char *)cp->conn_arg3, (char *)cp->conn_arg4);
+ return MHD_YES;
} else
ret = web_send_file(conn, (char *)cp->conn_res, MHD_HTTP_OK, true);
} else if (strcmp(url, "/topopost.html") == 0) {
@@ -872,6 +1034,25 @@ int Webserver::Handler (struct MHD_Connection *conn, const char *url,
*up_data_size = 0;
cp->conn_res = (void *)SendTopoResponse(conn, (char *)cp->conn_arg1, (char *)cp->conn_arg2, (char *)cp->conn_arg3, (char *)cp->conn_arg4);
+ return MHD_YES;
+ } else
+ ret = web_send_file(conn, (char *)cp->conn_res, MHD_HTTP_OK, true);
+ } else if (strcmp(url, "/statpost.html") == 0) {
+ if (*up_data_size != 0) {
+ MHD_post_process(cp->conn_pp, up_data, *up_data_size);
+ *up_data_size = 0;
+
+ cp->conn_res = (void *)SendStatResponse(conn, (char *)cp->conn_arg1, (char *)cp->conn_arg2, (char *)cp->conn_arg3, (char *)cp->conn_arg4);
+ } else
+ ret = web_send_file(conn, (char *)cp->conn_res, MHD_HTTP_OK, true);
+ return MHD_YES;
+ } else if (strcmp(url, "/testpost.html") == 0) {
+ if (*up_data_size != 0) {
+ MHD_post_process(cp->conn_pp, up_data, *up_data_size);
+ *up_data_size = 0;
+
+ cp->conn_res = (void *)SendTestResponse(conn, (char *)cp->conn_arg1, (char *)cp->conn_arg2, (char *)cp->conn_arg3, (char *)cp->conn_arg4);
+ return MHD_YES;
} else
ret = web_send_file(conn, (char *)cp->conn_res, MHD_HTTP_OK, true);
} else if (strcmp(url, "/confparmpost.html") == 0) {
diff --git a/webserver.h b/webserver.h
index 9050417..ed45df9 100644
--- a/webserver.h
+++ b/webserver.h
@@ -60,6 +60,8 @@ private:
int SendPollResponse(struct MHD_Connection *conn);
const char *SendSceneResponse(struct MHD_Connection *conn, const char *fun, const char *arg1, const char *arg2, const char *arg3);
const char *SendTopoResponse(struct MHD_Connection *conn, const char *fun, const char *arg1, const char *arg2, const char *arg3);
+ const char *SendStatResponse(struct MHD_Connection *conn, const char *fun, const char *arg1, const char *arg2, const char *arg3);
+ const char *SendTestResponse(struct MHD_Connection *conn, const char *fun, const char *arg1, const char *arg2, const char *arg3);
static bool usb;
static char *devname;
diff --git a/zwavelib.cpp b/zwavelib.cpp
index b6e4ac7..3720d0d 100644
--- a/zwavelib.cpp
+++ b/zwavelib.cpp
@@ -301,6 +301,7 @@ const char *cclassStr (uint8 cc)
case 0xF0:
return "NON INTEROPERABLE";
}
+ return "UNKNOWN";
}
uint8 cclassNum (char const *str)
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-iot/openzwave-controlpanel.git
More information about the Debian-iot-packaging
mailing list