Monitor for central heating system (e.g. 2zones+hw) Supports up to 15 temp probes (DS18B20/DS18S20) 3 valve monitors Gas pulse meter recording Use stand-alone or with nodeEnergyServer See http://robdobson.com/2015/09/central-heating-monitor

Dependencies:   EthernetInterfacePlusHostname NTPClient Onewire RdWebServer SDFileSystem-RTOS mbed-rtos mbed-src

Revision:
23:fd5a5a9f30bc
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/index.html	Fri Oct 16 09:07:04 2015 +0000
@@ -0,0 +1,342 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+    <title>Gas Use Monitor</title>
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
+    <script type="text/javascript">
+
+    var pathToServer = "./";
+
+    function callAjax(url, callback, contentType, usePost) {
+        var xmlhttp;
+        // code for IE7+, Firefox, Chrome, Opera, Safari
+        xmlhttp = new XMLHttpRequest();
+        xmlhttp.onreadystatechange = function() {
+            if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
+                callback(xmlhttp.responseText);
+            }
+        }
+
+        if (typeof usePost !== "undefined") {
+            xmlhttp.open("POST", url, true);
+        } else {
+            xmlhttp.open("GET", url, true);
+        }
+        if (typeof contentType !== "undefined") {
+            if (contentType === "json") {
+                xmlhttp.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
+            }
+        }
+        xmlhttp.send();
+    }
+
+    function ajaxCallback() {}
+
+    function dataRefresh() {
+        updateCurData();
+        setTimeout(function() {
+            dataRefresh();
+        }, 10000);
+    }
+
+    function updateCurData() {
+        callAjax(pathToServer+"getcurdata", curDataCallback, "json");
+    }
+
+    function curDataCallback(resp) {
+        console.log("Response " + resp);
+        var respObj = JSON.parse(resp);
+        // Handle elements
+        if ("e" in respObj) {
+            // Remove temperature and pump elements
+            var elem = document.getElementById("tempValues");
+            while (elem.firstChild) {
+                elem.removeChild(elem.firstChild);
+            }
+            var elem = document.getElementById("pumpValues");
+            while (elem.firstChild) {
+                elem.removeChild(elem.firstChild);
+            }
+
+            // Extract data from ajax json block and show
+            var i;
+            for (i = 0; i < respObj.e.length; i++) {
+                dataRec = respObj.e[i];
+                if ("n" in dataRec) {
+                    if (dataRec.n === "gasCount") {
+                        var elem = document.getElementById("gasCountValue");
+                        elem.innerHTML = "" + dataRec.v;
+                    } else if (dataRec.n.indexOf("temp_") > -1) {
+                        var tempStr = dataRec.n.slice(dataRec.n.lastIndexOf("_") + 1);
+                        var elem = document.getElementById("tempValues");
+                        var para = document.createElement("p");
+                        para.className = "label";
+                        var node = document.createTextNode(tempStr);
+                        para.appendChild(node);
+                        elem.appendChild(para);
+                        para = document.createElement("p");
+                        para.className = "value";
+                        node = document.createTextNode("" + dataRec.v);
+                        para.appendChild(node);
+                        elem.appendChild(para);
+                    } else if (dataRec.n.indexOf("pump_") > -1) {
+                        var pumpStr = dataRec.n.slice(dataRec.n.lastIndexOf("_") + 1);
+                        var elem = document.getElementById("pumpValues");
+                        var para = document.createElement("p");
+                        para.className = "label";
+                        var node = document.createTextNode(pumpStr);
+                        para.appendChild(node);
+                        elem.appendChild(para);
+                        para = document.createElement("p");
+                        para.className = "value";
+                        node = document.createTextNode(dataRec.bv ? "On" : "Off");
+                        para.appendChild(node);
+                        elem.appendChild(para);
+                    }
+                }
+            }
+        }
+        if ("bt" in respObj) {
+            var elem = document.getElementById("lastUpdateTime");
+            ud = new Date(respObj.bt * 1000);
+            elem.innerHTML = "" + ud.getFullYear() + "/" + padZero(ud.getMonth() + 1, 2) + "/" + padZero(ud.getDate(), 2) + " " + padZero(ud.getHours(), 2) + ":" + padZero(ud.getMinutes(), 2) + ":" + padZero(ud.getSeconds(), 2);
+        }
+
+    }
+
+    function padZero(val, zeroes) {
+        return ("00000000" + val).slice(-zeroes);
+    }
+
+    function dispGasNewVal() {
+        document.getElementById("gasadjust").style.display = "none";
+        document.getElementById("gasnewval").style.display = "block";
+        document.getElementById("setgasnewval").style.display = "block";
+    }
+
+    function setGasNewVal() {
+        document.getElementById("gasadjust").style.display = "block";
+        document.getElementById("gasnewval").style.display = "none";
+        document.getElementById("setgasnewval").style.display = "none";
+        var elem = document.getElementById("gasnewval");
+        var newVal = elem.value;
+        callAjax(pathToServer + "setgascount?newVal=" + newVal, setValCallback, "json", "POST")
+    }
+
+    function setValCallback(resp) {
+        console.log("setGasValue returned " + resp)
+        updateCurData();
+    }
+
+    function showLog() {
+        document.getElementById("logtext").style.display = "block";
+        callAjax(pathToServer+"log.txt", getLogTextCallback);
+    }
+
+    function showUpload() {
+        document.getElementById("fileuploadform").style.display = "block";
+    }
+
+    function getLogTextCallback(resp) {
+        var elem = document.getElementById("logtext");
+        elem.innerHTML = resp;
+    }
+
+    $(document).ready(function() {
+        $('#UploadNow').click(function() {
+            var formData = new FormData($('form')[0]);
+            $.ajax({
+                url: pathToServer + 'upload', //Server script to process data
+                type: 'POST',
+                xhr: function() { // Custom XMLHttpRequest
+                    var myXhr = $.ajaxSettings.xhr();
+                    if (myXhr.upload) { // Check if upload property exists
+                        myXhr.upload.addEventListener('progress', progressHandlingFunction, false); // For handling the progress of the upload
+                    }
+                    return myXhr;
+                },
+                //Ajax events
+                // beforeSend: beforeSendHandler,
+                success: completeHandler,
+                error: errorHandler,
+                // Form data
+                data: formData,
+                //Options to tell jQuery not to process data or worry about content-type.
+                cache: false,
+                contentType: false,
+                processData: false
+            });
+        });
+
+        function progressHandlingFunction(e) {
+            if (e.lengthComputable) {
+                $('progress').attr({
+                    value: e.loaded,
+                    max: e.total
+                });
+            }
+        }
+
+        function completeHandler(e) {
+            alert("Completed file upload");
+        }
+
+        function errorHandler(jqXHR, textStatus, errorThrown) {
+            alert("Error uploading file " + textStatus + " " + errorThrown);
+        }
+    });
+    </script>
+    <style>
+    body {
+        font-family: Helvetica;
+        line-height: 1rem;
+        font-size: 12pt;
+    }
+    
+    .layout {
+        display: table;
+        width: 360px;
+        margin: 0 auto 0 auto;
+    }
+    
+    .pageheading {
+        background-color: #00344c;
+        display: block;
+        min-height: 60px;
+        text-align: center;
+    }
+    
+    .headingtxt {
+        height: 100%;
+        padding: 10px;
+        padding-top: 20px;
+        color: White;
+        vertical-align: middle;
+        text-align: center;
+    }
+
+    .label,
+    .value,
+    #gasnewval {
+        width: 100%;
+        text-align: center;
+    }
+    
+    #gasadjust,
+    #setgasnewval {
+        text-align: center;
+        padding: 10px;
+        border: 10px;
+        margin: 5%;
+        width: 90%;
+        background-color: grey;
+        color: White;
+    }
+    
+    .label {
+        color: grey;
+        margin: 0.6em 0 0.6em 0;
+    }
+    
+    .value {
+        font-size: 110%;
+        font-weight: bold;
+        color: green;
+        margin: 0.6em 0 0.6em 0;
+    }
+    
+    .datacell {
+        display: block;
+        width: 116px;
+        min-height: 180px;
+        margin: 0;
+        border: solid lightgrey 2px;
+        float: left;
+    }
+    
+    #gasnewval {
+        display: none;
+        font-size: 120%;
+    }
+    
+    #setgasnewval {
+        display: none;
+    }
+    
+    #logtext {
+        display: none;
+        margin: 0;
+        border: solid lightgrey 2px;
+        padding: 5px;
+        width: 346px;
+        height: 100%;
+        min-height: 200px;
+    }
+    #fileuploadform {
+        display: none;
+        border: solid lightgrey 2px;
+        padding: 5px;
+        width: 346px;
+    }
+    #setupbtns {
+        display: block;
+        position: relative;
+        top:-40px;
+        left:270px;
+        height: 0px;
+        text-align: left;
+    }
+    .setupbtn {
+        display: block;
+        position: relative;
+        padding-top: 3px;
+    }
+    .setupbtn button {
+        width: 80px;
+    }
+    </style>
+</head>
+
+<body onload="dataRefresh();">
+    <div class="layout">
+        <div class="pageheading">
+            <div class="headingtxt">
+                Gas Use Monitor
+            </div>
+            <div id="setupbtns">
+                <div id="showlog" class="setupbtn"><button href="#" onclick="showLog();">Log</button></div>
+                <div id="showupload" class="setupbtn"><button href="#" onclick="showUpload();">Upload</button></div>
+            </div>
+        </div>
+    </div>
+    <div class="layout">
+        <div class="datacell">
+            <p class="label">Update time</p>
+            <p class="value" id="lastUpdateTime"></p>
+            <p class="label">Gas Count</p>
+            <p class="value" id="gasCountValue"></p>
+            <button id="gasadjust" href="#" onclick="dispGasNewVal();">Change</button>
+            <input id="gasnewval" type="text" name="newGasCountValue" />
+            <button id="setgasnewval" type="button" href="#" onclick="setGasNewVal();">Set New Value</button>
+        </div>
+        <div class="datacell" id="tempValues">
+        </div>
+        <div class="datacell" id="pumpValues">
+        </div>
+    </div>
+    <div class="layout">
+        <textarea id="logtext">
+        </textarea>
+    </div>
+    <div class="layout" id="fileuploadform">
+        <form enctype="multipart/form-data">
+            <input name="file" type="file" />
+            <input type="button" value="Upload" id="UploadNow" />
+        </form>
+        <progress></progress>
+    </div>
+</body>
+
+</html>