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

Committer:
Bobty
Date:
Sun Feb 22 11:57:12 2015 +0000
Revision:
9:0e103c2f869a
Parent:
8:5980547ae71c
Child:
10:72eb217def1f
Moved thermometer code to separate class

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Bobty 0:f6611c8f453c 1 #include "mbed.h"
Bobty 0:f6611c8f453c 2 #include "EthernetInterface.h"
Bobty 5:5bccf48799d4 3 #include "NTPClient.h"
Bobty 5:5bccf48799d4 4 #include "RdWebServer.h"
Bobty 5:5bccf48799d4 5 #include "GasUseCounter.h"
Bobty 9:0e103c2f869a 6 #include "Thermometers.h"
Bobty 5:5bccf48799d4 7 #include <stdarg.h>
Bobty 5:5bccf48799d4 8
Bobty 5:5bccf48799d4 9 // Web and UDB ports
Bobty 5:5bccf48799d4 10 const int WEBPORT = 80; // Port for web server
Bobty 5:5bccf48799d4 11 const int BROADCAST_PORT = 42853; // Arbitrarily chosen port number
Bobty 5:5bccf48799d4 12
Bobty 5:5bccf48799d4 13 // Ticker collects data
Bobty 6:b7064d33e402 14 //Ticker ticker;
Bobty 6:b7064d33e402 15 //const int TICK_MS = 250;
Bobty 9:0e103c2f869a 16 const int LOOP_DELAY_IN_MS = 250;
Bobty 5:5bccf48799d4 17
Bobty 5:5bccf48799d4 18 // Debugging and status
Bobty 5:5bccf48799d4 19 RawSerial pc(USBTX, USBRX);
Bobty 5:5bccf48799d4 20 DigitalOut led1(LED1); //ticking (flashes)
Bobty 5:5bccf48799d4 21 DigitalOut led2(LED2); //server listning status (flashes)
Bobty 5:5bccf48799d4 22 DigitalOut led3(LED3); //socket connecting status
Bobty 5:5bccf48799d4 23 DigitalOut led4(LED4); //server status
Bobty 5:5bccf48799d4 24
Bobty 5:5bccf48799d4 25 // Web server
Bobty 5:5bccf48799d4 26 EthernetInterface eth;
Bobty 5:5bccf48799d4 27 NTPClient ntp;
Bobty 5:5bccf48799d4 28 UDPSocket sendUDPSocket;
Bobty 5:5bccf48799d4 29 Endpoint broadcastEndpoint;
Bobty 5:5bccf48799d4 30
Bobty 5:5bccf48799d4 31 // File system for SD card
Bobty 4:0d3a207680b0 32 SDFileSystem sd(p5, p6, p7, p8, "sd");
Bobty 5:5bccf48799d4 33
Bobty 5:5bccf48799d4 34 // Gas use counter
Bobty 5:5bccf48799d4 35 DigitalIn gasPulsePin(p21);
Bobty 5:5bccf48799d4 36 const char* gasPulseFileName = "/sd/curPulse.txt";
Bobty 5:5bccf48799d4 37 const char* logFilename = "/sd/log.txt";
Bobty 5:5bccf48799d4 38 GasUseCounter gasUseCounter(gasPulseFileName, gasPulsePin, pc);
Bobty 5:5bccf48799d4 39
Bobty 8:5980547ae71c 40 // Thermometers - DS18B20 OneWire Thermometer connections
Bobty 8:5980547ae71c 41 const PinName tempSensorPins[] = { p22 };
Bobty 9:0e103c2f869a 42 Thermometers thermometers(sizeof(tempSensorPins)/sizeof(PinName), tempSensorPins, LOOP_DELAY_IN_MS);
Bobty 8:5980547ae71c 43
Bobty 9:0e103c2f869a 44 // Utility function to log data
Bobty 5:5bccf48799d4 45 void LogData(const char* format, ...)
Bobty 5:5bccf48799d4 46 {
Bobty 5:5bccf48799d4 47 FILE* fp = fopen(logFilename, "a");
Bobty 5:5bccf48799d4 48 if (fp == NULL)
Bobty 5:5bccf48799d4 49 {
Bobty 5:5bccf48799d4 50 pc.printf ("Log ... Filename %s not found\r\n", logFilename);
Bobty 5:5bccf48799d4 51 }
Bobty 5:5bccf48799d4 52 else
Bobty 5:5bccf48799d4 53 {
Bobty 5:5bccf48799d4 54 va_list argptr;
Bobty 5:5bccf48799d4 55 va_start(argptr, format);
Bobty 5:5bccf48799d4 56 vfprintf(fp, format, argptr);
Bobty 5:5bccf48799d4 57 va_end(argptr);
Bobty 5:5bccf48799d4 58 fclose(fp);
Bobty 5:5bccf48799d4 59 }
Bobty 5:5bccf48799d4 60 }
Bobty 5:5bccf48799d4 61
Bobty 9:0e103c2f869a 62 // Send broadcast message with current data
Bobty 5:5bccf48799d4 63 void SendInfoBroadcast()
Bobty 5:5bccf48799d4 64 {
Bobty 5:5bccf48799d4 65 led3 = true;
Bobty 5:5bccf48799d4 66 // Init the sending socket
Bobty 5:5bccf48799d4 67 sendUDPSocket.init();
Bobty 5:5bccf48799d4 68 sendUDPSocket.set_broadcasting();
Bobty 5:5bccf48799d4 69 broadcastEndpoint.set_address("255.255.255.255", BROADCAST_PORT);
Bobty 5:5bccf48799d4 70
Bobty 9:0e103c2f869a 71 // Get temperature values
Bobty 9:0e103c2f869a 72 TemperatureValue tempValues[Thermometers::MAX_THERMOMETERS];
Bobty 9:0e103c2f869a 73 int numTempValues = thermometers.GetTemperatureValues(Thermometers::MAX_THERMOMETERS, tempValues, 100);
Bobty 9:0e103c2f869a 74 char tempStr[200];
Bobty 9:0e103c2f869a 75 for (int tempIdx = 0; tempIdx < numTempValues; tempIdx++)
Bobty 9:0e103c2f869a 76 {
Bobty 9:0e103c2f869a 77 printf("Temp: %.1f, Addr: %s, Time: %d\r\n", tempValues[tempIdx].tempInCentigrade, tempValues[tempIdx].address, tempValues[tempIdx].timeStamp);
Bobty 9:0e103c2f869a 78 }
Bobty 9:0e103c2f869a 79
Bobty 5:5bccf48799d4 80 // Format message
Bobty 5:5bccf48799d4 81 char outBuf[200];
Bobty 5:5bccf48799d4 82 sprintf(outBuf, "{\"e\":[{\"n\":\"gasCount\",\"v\":%d},{\"n\":\"gasPulseRateMs\",\"v\":%d,\"u\":\"ms\"}]}",
Bobty 5:5bccf48799d4 83 gasUseCounter.GetCount(), gasUseCounter.GetPulseRateMs());
Bobty 5:5bccf48799d4 84
Bobty 5:5bccf48799d4 85 // Send
Bobty 5:5bccf48799d4 86 int bytesToSend = strlen(outBuf);
Bobty 5:5bccf48799d4 87 int rslt = sendUDPSocket.sendTo(broadcastEndpoint, outBuf, bytesToSend);
Bobty 5:5bccf48799d4 88 if (rslt == bytesToSend)
Bobty 5:5bccf48799d4 89 {
Bobty 5:5bccf48799d4 90 pc.printf("Broadcast Sent ok %s\n", outBuf);
Bobty 5:5bccf48799d4 91 }
Bobty 5:5bccf48799d4 92 else if (rslt == -1)
Bobty 5:5bccf48799d4 93 {
Bobty 5:5bccf48799d4 94 pc.printf("Broadcast Failed to send %s\n", outBuf);
Bobty 5:5bccf48799d4 95 }
Bobty 5:5bccf48799d4 96 else
Bobty 5:5bccf48799d4 97 {
Bobty 5:5bccf48799d4 98 pc.printf("Broadcast Didn't send all of %s\n", outBuf);
Bobty 5:5bccf48799d4 99 }
Bobty 5:5bccf48799d4 100
Bobty 5:5bccf48799d4 101 // Log
Bobty 5:5bccf48799d4 102 char timeBuf[32];
Bobty 5:5bccf48799d4 103 time_t seconds = time(NULL);
Bobty 5:5bccf48799d4 104 strftime(timeBuf, 32, "%Y-%m-%d %H:%M:%S", localtime(&seconds));
Bobty 5:5bccf48799d4 105 LogData("%s\t%d\t%d ms\n", timeBuf, gasUseCounter.GetCount(), gasUseCounter.GetPulseRateMs());
Bobty 5:5bccf48799d4 106
Bobty 5:5bccf48799d4 107 led3 = false;
Bobty 5:5bccf48799d4 108 }
Bobty 0:f6611c8f453c 109
Bobty 5:5bccf48799d4 110 // Ticker's tick function
Bobty 6:b7064d33e402 111 //void TickFunction()
Bobty 6:b7064d33e402 112 //{
Bobty 6:b7064d33e402 113 //}
Bobty 5:5bccf48799d4 114
Bobty 5:5bccf48799d4 115 char* getGasUseCallback(int method, char* cmdStr, char* argStr)
Bobty 5:5bccf48799d4 116 {
Bobty 5:5bccf48799d4 117 char* pResp = gasUseCounter.getGasUseCallback(cmdStr, argStr);
Bobty 5:5bccf48799d4 118 pc.printf("Returning gas use %s\r\n", pResp);
Bobty 5:5bccf48799d4 119 return pResp;
Bobty 5:5bccf48799d4 120 }
Bobty 5:5bccf48799d4 121
Bobty 5:5bccf48799d4 122 char* setGasUseCallback(int method, char* cmdStr, char* argStr)
Bobty 5:5bccf48799d4 123 {
Bobty 9:0e103c2f869a 124 pc.printf("Setting gas use count %s\r\n", argStr);
Bobty 5:5bccf48799d4 125 int newGasUse = 0;
Bobty 5:5bccf48799d4 126 char* eqStr = strchr(argStr, '=');
Bobty 5:5bccf48799d4 127 if (eqStr == NULL)
Bobty 5:5bccf48799d4 128 return "SetGasValue FAILED";
Bobty 5:5bccf48799d4 129 sscanf(eqStr+1, "%d", &newGasUse);
Bobty 5:5bccf48799d4 130 gasUseCounter.SetCount(newGasUse);
Bobty 5:5bccf48799d4 131 return "SetGasValue OK";
Bobty 5:5bccf48799d4 132 }
Bobty 5:5bccf48799d4 133
Bobty 5:5bccf48799d4 134 void http_thread(void const* arg)
Bobty 5:5bccf48799d4 135 {
Bobty 5:5bccf48799d4 136 char* baseWebFolder = "/sd/";
Bobty 5:5bccf48799d4 137
Bobty 5:5bccf48799d4 138 RdWebServer webServer;
Bobty 5:5bccf48799d4 139 webServer.addCommand("", RdWebServerCmdDef::CMD_SDORUSBFILE, NULL, "index.htm", false);
Bobty 5:5bccf48799d4 140 webServer.addCommand("gear-gr.png", RdWebServerCmdDef::CMD_SDORUSBFILE, NULL, NULL, true);
Bobty 5:5bccf48799d4 141 webServer.addCommand("getgascount", RdWebServerCmdDef::CMD_CALLBACK, &getGasUseCallback);
Bobty 5:5bccf48799d4 142 webServer.addCommand("setgascount", RdWebServerCmdDef::CMD_CALLBACK, &setGasUseCallback);
Bobty 0:f6611c8f453c 143
Bobty 5:5bccf48799d4 144 webServer.init(WEBPORT, &led4, baseWebFolder);
Bobty 5:5bccf48799d4 145
Bobty 5:5bccf48799d4 146 webServer.run();
Bobty 5:5bccf48799d4 147 }
Bobty 5:5bccf48799d4 148
Bobty 5:5bccf48799d4 149 void ntp_thread(void const* arg)
Bobty 5:5bccf48799d4 150 {
Bobty 5:5bccf48799d4 151 while (1)
Bobty 5:5bccf48799d4 152 {
Bobty 5:5bccf48799d4 153 pc.printf("Trying to update time...\r\n");
Bobty 5:5bccf48799d4 154 if (ntp.setTime("0.pool.ntp.org") == 0)
Bobty 5:5bccf48799d4 155 {
Bobty 5:5bccf48799d4 156 printf("Set time successfully\r\n");
Bobty 5:5bccf48799d4 157 time_t ctTime;
Bobty 5:5bccf48799d4 158 ctTime = time(NULL);
Bobty 5:5bccf48799d4 159 printf("Time is set to (UTC): %s\r\n", ctime(&ctTime));
Bobty 5:5bccf48799d4 160 }
Bobty 5:5bccf48799d4 161 else
Bobty 5:5bccf48799d4 162 {
Bobty 5:5bccf48799d4 163 printf("Cannot set from NTP\r\n");
Bobty 5:5bccf48799d4 164 }
Bobty 5:5bccf48799d4 165 // 1 hour
Bobty 5:5bccf48799d4 166 for (int i = 0; i < 60; i++)
Bobty 5:5bccf48799d4 167 {
Bobty 5:5bccf48799d4 168 for (int j = 0; j < 60; j++)
Bobty 5:5bccf48799d4 169 {
Bobty 5:5bccf48799d4 170 osDelay(1000);
Bobty 5:5bccf48799d4 171 }
Bobty 9:0e103c2f869a 172 pc.printf("%d mins since NTP\r\n", i);
Bobty 5:5bccf48799d4 173 }
Bobty 6:b7064d33e402 174 break;
Bobty 5:5bccf48799d4 175 }
Bobty 5:5bccf48799d4 176 }
Bobty 9:0e103c2f869a 177
Bobty 0:f6611c8f453c 178 int main()
Bobty 0:f6611c8f453c 179 {
Bobty 0:f6611c8f453c 180 pc.baud(115200);
Bobty 5:5bccf48799d4 181 pc.printf("Gas Monitor V2 - Rob Dobson 2014\r\n");
Bobty 0:f6611c8f453c 182
Bobty 6:b7064d33e402 183 // ticker.attach(&TickFunction,TICK_MS / 1000.0);
Bobty 5:5bccf48799d4 184
Bobty 9:0e103c2f869a 185 // Initialise thermometers
Bobty 9:0e103c2f869a 186 thermometers.Init();
Bobty 9:0e103c2f869a 187
Bobty 5:5bccf48799d4 188 // Get the current count from the SD Card
Bobty 5:5bccf48799d4 189 gasUseCounter.Init();
Bobty 0:f6611c8f453c 190
Bobty 5:5bccf48799d4 191 // setup ethernet interface
Bobty 5:5bccf48799d4 192 eth.init(); //Use DHCP
Bobty 5:5bccf48799d4 193 eth.connect();
Bobty 2:6bfef0839102 194
Bobty 9:0e103c2f869a 195 pc.printf("IP Address is %s\r\n", eth.getIPAddress());
Bobty 8:5980547ae71c 196
Bobty 8:5980547ae71c 197 // NTP Time setter
Bobty 5:5bccf48799d4 198 Thread ntpTimeSetter(&ntp_thread);
Bobty 0:f6611c8f453c 199
Bobty 8:5980547ae71c 200 // Web Server
Bobty 6:b7064d33e402 201 Thread httpServer(&http_thread, NULL, osPriorityNormal, (DEFAULT_STACK_SIZE * 3));
Bobty 5:5bccf48799d4 202
Bobty 9:0e103c2f869a 203 // Time of last broadcast
Bobty 9:0e103c2f869a 204 time_t timeOfLastBroadcast = time(NULL);
Bobty 9:0e103c2f869a 205 const int TIME_BETWEEN_BROADCASTS_IN_SECS = 60;
Bobty 5:5bccf48799d4 206 while(true)
Bobty 0:f6611c8f453c 207 {
Bobty 9:0e103c2f869a 208 osDelay(LOOP_DELAY_IN_MS);
Bobty 5:5bccf48799d4 209 led1 = !led1;
Bobty 5:5bccf48799d4 210
Bobty 5:5bccf48799d4 211 // Service gas count
Bobty 5:5bccf48799d4 212 if (gasUseCounter.Service())
Bobty 8:5980547ae71c 213 {
Bobty 9:0e103c2f869a 214 SendInfoBroadcast();
Bobty 9:0e103c2f869a 215 timeOfLastBroadcast = time(NULL);
Bobty 9:0e103c2f869a 216 }
Bobty 8:5980547ae71c 217
Bobty 9:0e103c2f869a 218 // Service thermometers
Bobty 9:0e103c2f869a 219 thermometers.Service();
Bobty 9:0e103c2f869a 220
Bobty 9:0e103c2f869a 221 // Check if ready for a broadcast
Bobty 9:0e103c2f869a 222 if ((time(NULL) - timeOfLastBroadcast) >= TIME_BETWEEN_BROADCASTS_IN_SECS)
Bobty 9:0e103c2f869a 223 {
Bobty 9:0e103c2f869a 224 SendInfoBroadcast();
Bobty 9:0e103c2f869a 225 timeOfLastBroadcast = time(NULL);
Bobty 8:5980547ae71c 226 }
Bobty 0:f6611c8f453c 227 }
Bobty 5:5bccf48799d4 228 }
Bobty 9:0e103c2f869a 229