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:
5:5bccf48799d4
Parent:
4:0d3a207680b0
Child:
6:b7064d33e402
--- a/main.cpp	Mon Feb 02 16:24:30 2015 +0000
+++ b/main.cpp	Tue Feb 17 21:33:39 2015 +0000
@@ -1,93 +1,189 @@
 #include "mbed.h"
 #include "EthernetInterface.h"
-#include "PulsePin.h"
-#include "SDFileSystem.h"
- 
+#include "NTPClient.h"
+#include "RdWebServer.h"
+#include "GasUseCounter.h"
+#include <stdarg.h>
+
+// Web and UDB ports 
+const int WEBPORT = 80; // Port for web server
+const int BROADCAST_PORT = 42853; // Arbitrarily chosen port number
+
+// Ticker collects data
+Ticker ticker;
+const int TICK_MS = 250;
+
+// Debugging and status
+RawSerial pc(USBTX, USBRX);
+DigitalOut led1(LED1); //ticking (flashes)
+DigitalOut led2(LED2); //server listning status (flashes)
+DigitalOut led3(LED3); //socket connecting status
+DigitalOut led4(LED4); //server status
+
+// Web server
+EthernetInterface eth;
+NTPClient ntp;
+UDPSocket sendUDPSocket;
+Endpoint broadcastEndpoint;
+
+// File system for SD card
 SDFileSystem sd(p5, p6, p7, p8, "sd");
-DigitalIn gpPin(p21);
-PulsePin pulsePin(gpPin, false, 200);
-DigitalOut led(LED1);
+
+// Gas use counter
+DigitalIn gasPulsePin(p21);
+const char* gasPulseFileName = "/sd/curPulse.txt";
+const char* logFilename = "/sd/log.txt";
+GasUseCounter gasUseCounter(gasPulseFileName, gasPulsePin, pc);
+
+void LogData(const char* format, ...)
+{
+    FILE* fp = fopen(logFilename, "a");
+    if (fp == NULL)
+    {
+        pc.printf ("Log ... Filename %s not found\r\n", logFilename);
+    }
+    else
+    {
+        va_list argptr;
+        va_start(argptr, format);
+        vfprintf(fp, format, argptr);
+        va_end(argptr);
+        fclose(fp);
+    }
+}
+
+void SendInfoBroadcast()
+{
+    led3 = true;
+    // Init the sending socket
+    sendUDPSocket.init();
+    sendUDPSocket.set_broadcasting();
+    broadcastEndpoint.set_address("255.255.255.255", BROADCAST_PORT);
+    
+    // Format message
+    char outBuf[200];
+    sprintf(outBuf, "{\"e\":[{\"n\":\"gasCount\",\"v\":%d},{\"n\":\"gasPulseRateMs\",\"v\":%d,\"u\":\"ms\"}]}", 
+                        gasUseCounter.GetCount(), gasUseCounter.GetPulseRateMs());
+    
+    // Send
+    int bytesToSend = strlen(outBuf);
+    int rslt = sendUDPSocket.sendTo(broadcastEndpoint, outBuf, bytesToSend);
+    if (rslt == bytesToSend)
+    {
+        pc.printf("Broadcast Sent ok %s\n", outBuf);
+    }
+    else if (rslt == -1)
+    {
+        pc.printf("Broadcast Failed to send %s\n", outBuf);
+    }
+    else
+    {
+        pc.printf("Broadcast Didn't send all of %s\n", outBuf);
+    }
+    
+    // Log
+    char timeBuf[32];
+    time_t seconds = time(NULL);
+    strftime(timeBuf, 32, "%Y-%m-%d %H:%M:%S", localtime(&seconds));
+    LogData("%s\t%d\t%d ms\n", timeBuf, gasUseCounter.GetCount(), gasUseCounter.GetPulseRateMs());
+    
+    led3 = false;
+}
 
-const int BROADCAST_PORT = 42853; // Arbitrarily chosen port number
-Serial pc(USBTX, USBRX);
+// Ticker's tick function
+void TickFunction()
+{
+}
+
+char* getGasUseCallback(int method, char* cmdStr, char* argStr)
+{
+    char* pResp = gasUseCounter.getGasUseCallback(cmdStr, argStr);
+    pc.printf("Returning gas use %s\r\n", pResp);
+    return pResp;
+}
+
+char* setGasUseCallback(int method, char* cmdStr, char* argStr)
+{
+    pc.printf("Setting gas use count %s\n\r", argStr);
+    int newGasUse = 0;
+    char* eqStr = strchr(argStr, '=');
+    if (eqStr == NULL)
+        return "SetGasValue FAILED";
+    sscanf(eqStr+1, "%d", &newGasUse);
+    gasUseCounter.SetCount(newGasUse);
+    return "SetGasValue OK";
+}
+
+void http_thread(void const* arg)
+{
+    char* baseWebFolder = "/sd/";
+
+    RdWebServer webServer;
+    webServer.addCommand("", RdWebServerCmdDef::CMD_SDORUSBFILE, NULL, "index.htm", false);
+    webServer.addCommand("gear-gr.png", RdWebServerCmdDef::CMD_SDORUSBFILE, NULL, NULL, true);
+    webServer.addCommand("getgascount", RdWebServerCmdDef::CMD_CALLBACK, &getGasUseCallback);
+    webServer.addCommand("setgascount", RdWebServerCmdDef::CMD_CALLBACK, &setGasUseCallback);
 
+    webServer.init(WEBPORT, &led4, baseWebFolder);
+
+    webServer.run();
+}
+
+void ntp_thread(void const* arg)
+{
+    while (1)
+    {
+        pc.printf("Trying to update time...\r\n");
+        if (ntp.setTime("0.pool.ntp.org") == 0)
+        {
+          printf("Set time successfully\r\n");
+          time_t ctTime;
+          ctTime = time(NULL);
+          printf("Time is set to (UTC): %s\r\n", ctime(&ctTime));
+        }
+        else
+        {
+          printf("Cannot set from NTP\r\n");
+        } 
+        // 1 hour
+        for (int i = 0; i < 60; i++)
+        {
+            for (int j = 0; j < 60; j++)
+            {
+                osDelay(1000);
+            }
+            pc.printf("Waited %d mins\r\n", i);
+        }
+    }
+}
+    
 int main()
 {
     pc.baud(115200);
-    printf("Gas Monitor - Rob Dobson 2014\n");
+    pc.printf("Gas Monitor V2 - Rob Dobson 2014\r\n");
 
-    EthernetInterface eth;
-    eth.init(); //Use DHCP
-    UDPSocket sendSocket;
-    Endpoint broadcast;
+    ticker.attach(&TickFunction,TICK_MS / 1000.0);
+
+    // Get the current count from the SD Card
+    gasUseCounter.Init();
     
-    // Connection establishment/re-establishment
-    Timer connectRetryTimer;
-    connectRetryTimer.start();
-    bool isConnected = false;
+    // setup ethernet interface
+    eth.init(); //Use DHCP
+    eth.connect();
     
-    // Count of gas pulses
-    int gasCount = 0;
+    pc.printf("IP Address is %s\n\r", eth.getIPAddress());
+
+    Thread ntpTimeSetter(&ntp_thread);
     
-    // Forever    
-    while (true)
+    Thread httpServer(&http_thread, NULL, osPriorityNormal, (DEFAULT_STACK_SIZE * 2.25));
+    
+    while(true)
     {
-        // Check if already connected to ethernet
-        if (!isConnected)
-        {
-            if (connectRetryTimer.read_ms() > 1000)
-            {
-                isConnected = eth.connect() == 0;
-                connectRetryTimer.reset();
-                if (isConnected)
-                {
-                    printf("Eth Connected - IP Address is %s - MAC is %s\n", eth.getIPAddress(), eth.getMACAddress());
-                    sendSocket.init();
-                    sendSocket.set_broadcasting();
-                    broadcast.set_address("255.255.255.255", BROADCAST_PORT);
-                    }
-                else
-                {
-                    printf("Eth Connect Attempt Failed\n");
-                }
-            }
-        }
-        else
-        {
-            led = gpPin;
-            // Check for an edge
-            bool edgeDetected = pulsePin.Service();
-            if (edgeDetected)
-            {
-                gasCount++;
-                char outBuf[200];
-                sprintf(outBuf, "{\"e\":[{\"n\":\"gasCount\",\"v\":%d},{\"n\":\"gasInterPulse\",\"v\":%d,\"u\":\"ms\"}]}", 
-                                    gasCount, pulsePin.GetLastCycleTimeMs());
-                int bytesToSend = strlen(outBuf);
-                int rslt = sendSocket.sendTo(broadcast, outBuf, bytesToSend);
-                if (rslt == bytesToSend)
-                {
-                    printf("Sent ok %s\n", outBuf);
-                }
-                else if (rslt == -1)
-                {
-                    printf("Failed to send %s\n", outBuf);
-                    isConnected = false;
-                }
-                else
-                {
-                    printf("Didn't send all of %s\n", outBuf);
-                    isConnected = false;
-                }
-            }
-            
-            // See if anything has failed
-            if (!isConnected)
-            {
-                sendSocket.close();
-                eth.disconnect();
-                Thread::wait(1000);
-            }
-        }
+        osDelay(250);
+        led1 = !led1;
+
+        // Service gas count
+        if (gasUseCounter.Service())
+            SendInfoBroadcast();
     }
-}
\ No newline at end of file
+}