[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