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:
12:a52996515063
Parent:
11:30182b9aa833
Child:
14:3c3aa4fd7e1a
--- a/main.cpp	Sun Feb 22 20:28:21 2015 +0000
+++ b/main.cpp	Sun Feb 22 22:08:37 2015 +0000
@@ -5,7 +5,8 @@
 #include "GasUseCounter.h"
 #include "Thermometers.h"
 #include "VoltAlerter.h"
-#include <stdarg.h>
+#include "Watchdog.h"
+#include "Logger.h"
 
 // Web and UDB ports 
 const int WEBPORT = 80; // Port for web server
@@ -33,10 +34,16 @@
 // File system for SD card
 SDFileSystem sd(p5, p6, p7, p8, "sd");
 
+// Log file names
+const char* gasPulseFileName = "/sd/curPulse.txt";
+const char* eventLogFileName = "/sd/log.txt";
+const char* dataLogFileBase = "/sd/";
+
+// Logger
+Logger logger(eventLogFileName, dataLogFileBase);
+
 // Gas use counter
 DigitalIn gasPulsePin(p21);
-const char* gasPulseFileName = "/sd/curPulse.txt";
-const char* logFilename = "/sd/log.txt";
 GasUseCounter gasUseCounter(gasPulseFileName, gasPulsePin, pc);
 
 // Thermometers - DS18B20 OneWire Thermometer connections
@@ -49,6 +56,9 @@
 VoltAlerter voltAlerter2(p24);
 VoltAlerter voltAlerter3(p25);
 
+// Watchdog
+Watchdog watchdog;
+
 // Broadcast message format
 // Data format of the broadcast message - senml - https://tools.ietf.org/html/draft-jennings-senml-08
 // {
@@ -77,28 +87,11 @@
             60;
 char broadcastMsgBuffer[broadcastMsgLen];
     
-// Utility function to log data
-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);
-    }
-}
-
 // Send broadcast message with current data
 void SendInfoBroadcast()
 {
     led3 = true;
+    
     // Init the sending socket
     sendUDPSocket.init();
     sendUDPSocket.set_broadcasting();
@@ -112,7 +105,7 @@
 //        printf("Temp: %.1f, Addr: %s, Time: %d\r\n", tempValues[tempIdx].tempInCentigrade, tempValues[tempIdx].address, tempValues[tempIdx].timeStamp);
 //    }
     
-    // Send the broadcast    
+    // Format the broadcast message
     time_t timeNow = time(NULL);
     strcpy(broadcastMsgBuffer, broadcastMsgPrefix);
     sprintf(broadcastMsgBuffer+strlen(broadcastMsgBuffer), broadcastMsgGasFormat, gasUseCounter.GetCount(), gasUseCounter.GetPulseRateMs());
@@ -145,11 +138,8 @@
         pc.printf("Broadcast Didn't send all of %s\r\n", broadcastMsgBuffer);
     }
     
-    // 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());
+    // Log the data
+    logger.LogData(broadcastMsgBuffer);
     
     led3 = false;
 }
@@ -180,6 +170,7 @@
     RdWebServer webServer;
     webServer.addCommand("", RdWebServerCmdDef::CMD_SDORUSBFILE, NULL, "index.htm", false);
     webServer.addCommand("gear-gr.png", RdWebServerCmdDef::CMD_SDORUSBFILE, NULL, NULL, true);
+    webServer.addCommand("listfiles", RdWebServerCmdDef::CMD_SDORUSBFILE, NULL, "/", false);
     webServer.addCommand("getgascount", RdWebServerCmdDef::CMD_CALLBACK, &getGasUseCallback);
     webServer.addCommand("setgascount", RdWebServerCmdDef::CMD_CALLBACK, &setGasUseCallback);
     webServer.init(WEBPORT, &led4, baseWebFolder);
@@ -220,6 +211,11 @@
     }
 }
 
+// #define TEST_WATCHDOG 1
+#ifdef TEST_WATCHDOG
+int watchdogTestLoopCount = 0;
+#endif
+
 // Main
 int main()
 {
@@ -244,6 +240,15 @@
     // Web Server
     Thread httpServer(&http_thread, NULL, osPriorityNormal, (DEFAULT_STACK_SIZE * 3));
     
+    // Record the reason for restarting in the log file
+    if (watchdog.WatchdogCausedRestart())
+        logger.LogEvent("Watchdog Restart");
+    else
+        logger.LogEvent("Normal Restart");
+        
+    // Setup the watchdog for 10s reset
+    watchdog.SetTimeoutSecs(10);
+    
     // Time of last broadcast
     time_t timeOfLastBroadcast = time(NULL);
     const int TIME_BETWEEN_BROADCASTS_IN_SECS = 60;
@@ -251,6 +256,7 @@
     {
         osDelay(LOOP_DELAY_IN_MS);
         led1 = !led1;
+        watchdog.Feed();
 
         // Service gas count
         if (gasUseCounter.Service())
@@ -276,6 +282,15 @@
         
         // Set LED2 to the state of the first volt alerter
         led2 = voltAlerter1.GetState();
+        
+#ifdef TEST_WATCHDOG
+        // After about 20 seconds of operation we'll hang to test the watchdog
+        if (watchdogTestLoopCount++ > 80)
+        {
+            // This should cause watchdog to kick in and reset
+            osDelay(20000);
+        }
+#endif
     }
 }