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
Diff: main.cpp
- 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 +}