X10 Server - IOT device to leverage a collection of old X10 devices for home automation and lighting control.

Dependencies:   IniManager mbed HTTPClient SWUpdate mbed-rtos Watchdog X10 SW_HTTPServer SW_String EthernetInterface TimeInterface SSDP

X10 Server

See the X10 Server Nodebook page

Committer:
WiredHome
Date:
Sun Mar 03 23:41:27 2019 +0000
Revision:
10:ca0c1db6d933
Parent:
9:2c96e69b6035
Updated WattEye that has SSDP Discovery.;

Who changed what in which revision?

UserRevisionLine numberNew contents of line
WiredHome 0:de1dfa2ab813 1 //
WiredHome 10:ca0c1db6d933 2 // WattEye - Version 2
WiredHome 0:de1dfa2ab813 3 //
WiredHome 10:ca0c1db6d933 4 /// WattEye monitors a simple input pin, measures the time between pulses, and translates
WiredHome 10:ca0c1db6d933 5 /// that into a unit of power. The pulses are generated by the whole-house electric meter
WiredHome 10:ca0c1db6d933 6 /// and may be generated by an IR Emitter.
WiredHome 7:16129d213e6a 7 ///
WiredHome 7:16129d213e6a 8
WiredHome 0:de1dfa2ab813 9 #include "mbed.h" // ver 120; mbed-rtos ver 111
WiredHome 7:16129d213e6a 10 #include "EthernetInterface.h" // ver 56 - https://os.mbed.com/users/WiredHome/code/EthernetInterface/
WiredHome 7:16129d213e6a 11 #include "SW_HTTPServer.h" // ver 58
WiredHome 7:16129d213e6a 12 #include "TimeInterface.h" // ver 25
WiredHome 7:16129d213e6a 13 #include "SWUpdate.h" // ver 26
WiredHome 7:16129d213e6a 14 #include "SW_String.h" // ver 2
WiredHome 7:16129d213e6a 15 #include "SSDP.h" // ver 7
WiredHome 0:de1dfa2ab813 16 #include "Watchdog.h" // ver 6
WiredHome 7:16129d213e6a 17 #include "IniManager.h" // v20
WiredHome 10:ca0c1db6d933 18
WiredHome 10:ca0c1db6d933 19 #include "StatisticQueue.h"
WiredHome 10:ca0c1db6d933 20 #include "PowerData.h"
WiredHome 7:16129d213e6a 21
WiredHome 0:de1dfa2ab813 22 #include "WebPages.h" // Private handler for web queries
WiredHome 7:16129d213e6a 23 #include "SignOfLife.h" // LED effects
WiredHome 0:de1dfa2ab813 24
WiredHome 7:16129d213e6a 25 extern "C" void mbed_reset();
WiredHome 7:16129d213e6a 26
WiredHome 10:ca0c1db6d933 27 //#define DEBUG "MAIN"
WiredHome 10:ca0c1db6d933 28 #include <cstdio>
WiredHome 10:ca0c1db6d933 29 #if (defined(DEBUG) && !defined(TARGET_LPC11U24))
WiredHome 10:ca0c1db6d933 30 #define DBG(x, ...) std::printf("[DBG %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
WiredHome 10:ca0c1db6d933 31 #define WARN(x, ...) std::printf("[WRN %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
WiredHome 10:ca0c1db6d933 32 #define ERR(x, ...) std::printf("[ERR %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
WiredHome 10:ca0c1db6d933 33 #define INFO(x, ...) std::printf("[INF %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
WiredHome 10:ca0c1db6d933 34 #else
WiredHome 10:ca0c1db6d933 35 #define DBG(x, ...)
WiredHome 10:ca0c1db6d933 36 #define WARN(x, ...)
WiredHome 10:ca0c1db6d933 37 #define ERR(x, ...)
WiredHome 10:ca0c1db6d933 38 #define INFO(x, ...)
WiredHome 10:ca0c1db6d933 39 #endif
WiredHome 10:ca0c1db6d933 40
WiredHome 5:6244e237def1 41
WiredHome 0:de1dfa2ab813 42 RawSerial pc(USBTX, USBRX);
WiredHome 0:de1dfa2ab813 43 EthernetInterface eth;
WiredHome 7:16129d213e6a 44 DigitalOut linkup(p26);
WiredHome 7:16129d213e6a 45 DigitalOut linkdata(p25);
WiredHome 7:16129d213e6a 46
WiredHome 0:de1dfa2ab813 47 Watchdog wd;
WiredHome 7:16129d213e6a 48 bool WDEventOccurred = false;
WiredHome 0:de1dfa2ab813 49
WiredHome 7:16129d213e6a 50 TimeInterface ntp(&eth);
WiredHome 7:16129d213e6a 51 time_t ntpSyncd; // time of the last sync
WiredHome 7:16129d213e6a 52 bool ntpUpdateCheck = true; // scheduled check on startup
WiredHome 4:5da66fab599c 53
WiredHome 7:16129d213e6a 54 time_t lastboottime;
WiredHome 7:16129d213e6a 55 bool swUpdateCheck = true; // scheduled check on startup
WiredHome 7:16129d213e6a 56
WiredHome 7:16129d213e6a 57 INI ini;
WiredHome 0:de1dfa2ab813 58 LocalFileSystem local("local"); // some place to hold settings and maybe the static web pages
WiredHome 0:de1dfa2ab813 59 const char * Server_Root = "/local";
WiredHome 0:de1dfa2ab813 60
WiredHome 0:de1dfa2ab813 61 // public for the WebPages handler to see
WiredHome 0:de1dfa2ab813 62 //
WiredHome 0:de1dfa2ab813 63 const char * BUILD_DATE = __DATE__ " " __TIME__;
WiredHome 10:ca0c1db6d933 64 const char * PROG_NAME = "WattEye-2";
WiredHome 10:ca0c1db6d933 65 char * My_Name = "WattEye-2";
WiredHome 10:ca0c1db6d933 66 const char * PROG_INFO = "WattEye-2 Build " __DATE__ " " __TIME__;
WiredHome 0:de1dfa2ab813 67 const char * My_SerialNum = "0000001";
WiredHome 4:5da66fab599c 68 int Server_Port = 80;
WiredHome 0:de1dfa2ab813 69 // end public information
WiredHome 0:de1dfa2ab813 70
WiredHome 10:ca0c1db6d933 71 const char * iniFile = "/local/WattEye.ini";
WiredHome 7:16129d213e6a 72
WiredHome 10:ca0c1db6d933 73 HTTPClient http;
WiredHome 10:ca0c1db6d933 74 DigitalOut PulseIndicator(LED1);
WiredHome 10:ca0c1db6d933 75 DigitalOut UDPSendIndicator(LED2);
WiredHome 10:ca0c1db6d933 76 DigitalOut URLSendIndicator(LED3);
WiredHome 7:16129d213e6a 77
WiredHome 7:16129d213e6a 78
WiredHome 10:ca0c1db6d933 79 // Keep a sample every 5 s for 5 minutes
WiredHome 10:ca0c1db6d933 80 // 12 samples / min * 5 min => 60 samples
WiredHome 10:ca0c1db6d933 81 #define SampleInterval_Sec 5
WiredHome 10:ca0c1db6d933 82 #define SampleHistory_5m (60)
WiredHome 10:ca0c1db6d933 83 StatisticQueue stats5s(SampleHistory_5m);
WiredHome 10:ca0c1db6d933 84
WiredHome 10:ca0c1db6d933 85 // Keep 5 minute data for 1 day
WiredHome 10:ca0c1db6d933 86 // 12 samples / hour * 24 hours => 288
WiredHome 10:ca0c1db6d933 87 #define SampleInterval_Min 5
WiredHome 10:ca0c1db6d933 88 #define SampleHistory_1d 288
WiredHome 10:ca0c1db6d933 89 StatisticQueue stats5m(SampleHistory_1d);
WiredHome 10:ca0c1db6d933 90
WiredHome 10:ca0c1db6d933 91 char url[100], dest[20], port[8];
WiredHome 10:ca0c1db6d933 92 char myID[50];
WiredHome 10:ca0c1db6d933 93
WiredHome 10:ca0c1db6d933 94 InterruptIn event(p15);
WiredHome 10:ca0c1db6d933 95 Timer timer;
WiredHome 10:ca0c1db6d933 96 Timeout flash;
WiredHome 10:ca0c1db6d933 97
WiredHome 10:ca0c1db6d933 98 typedef struct {
WiredHome 10:ca0c1db6d933 99 time_t todClock;
WiredHome 10:ca0c1db6d933 100 uint32_t tLastStart;
WiredHome 10:ca0c1db6d933 101 uint32_t tLastRise;
WiredHome 10:ca0c1db6d933 102 uint16_t Samples10s[30]; // Every 10s for 5 min
WiredHome 10:ca0c1db6d933 103 uint16_t Samples10sIndex;
WiredHome 10:ca0c1db6d933 104 uint16_t Samples5m[12*24]; // Every 5m for 1 day
WiredHome 10:ca0c1db6d933 105 uint16_t Samples5mIndex;
WiredHome 10:ca0c1db6d933 106 uint16_t Samples1d[365]; // Every
WiredHome 10:ca0c1db6d933 107 uint16_t Samples1dIndex;
WiredHome 10:ca0c1db6d933 108 } WattData;
WiredHome 10:ca0c1db6d933 109
WiredHome 10:ca0c1db6d933 110 Atomic_t PowerSnapshot;
WiredHome 10:ca0c1db6d933 111
WiredHome 10:ca0c1db6d933 112 typedef struct {
WiredHome 10:ca0c1db6d933 113 bool init;
WiredHome 10:ca0c1db6d933 114 time_t startTimestamp;
WiredHome 10:ca0c1db6d933 115 uint64_t tStart;
WiredHome 10:ca0c1db6d933 116 uint64_t tLastRise;
WiredHome 10:ca0c1db6d933 117 uint64_t tStartSample;
WiredHome 10:ca0c1db6d933 118 uint32_t cycles;
WiredHome 10:ca0c1db6d933 119 } RawSample_t;
WiredHome 10:ca0c1db6d933 120
WiredHome 10:ca0c1db6d933 121 RawSample_t RawPowerSample;
WiredHome 10:ca0c1db6d933 122
WiredHome 10:ca0c1db6d933 123 void PulseRisingISR(void);
WiredHome 10:ca0c1db6d933 124 void RunPulseTask(void);
WiredHome 10:ca0c1db6d933 125 void TransmitEnergy(bool sendNow, float iKW, float min5s, float avg5s, float max5s, float min5m, float avg5m, float max5m);
WiredHome 10:ca0c1db6d933 126 void ShowRawSample();
WiredHome 10:ca0c1db6d933 127
WiredHome 10:ca0c1db6d933 128 void ShowRawSample() {
WiredHome 10:ca0c1db6d933 129 printf("Sample:\r\n");
WiredHome 10:ca0c1db6d933 130 printf(" Sample Start: %s\r\n", ntp.ctime(&RawPowerSample.startTimestamp));
WiredHome 10:ca0c1db6d933 131 printf(" tStart: %llu\r\n", RawPowerSample.tStart);
WiredHome 10:ca0c1db6d933 132 printf(" tLastRise: %llu\r\n", RawPowerSample.tLastRise);
WiredHome 10:ca0c1db6d933 133 printf(" tStartSample: %llu\r\n", RawPowerSample.tStartSample);
WiredHome 10:ca0c1db6d933 134 printf(" cycles: %ul\r\n", RawPowerSample.cycles);
WiredHome 10:ca0c1db6d933 135 }
WiredHome 10:ca0c1db6d933 136
WiredHome 10:ca0c1db6d933 137
WiredHome 10:ca0c1db6d933 138 void SoftwareUpdateCheck(bool force = false)
WiredHome 7:16129d213e6a 139 {
WiredHome 7:16129d213e6a 140 char url[100], name[10];
WiredHome 10:ca0c1db6d933 141 static time_t tstart = ntp.timelocal();
WiredHome 10:ca0c1db6d933 142 time_t tNow = ntp.timelocal();
WiredHome 10:ca0c1db6d933 143
WiredHome 7:16129d213e6a 144 //eth_mutex.lock();
WiredHome 10:ca0c1db6d933 145 #define ONE_DAY (24 * 60 * 60)
WiredHome 7:16129d213e6a 146 if (force || (tNow - tstart) > ONE_DAY) {
WiredHome 10:ca0c1db6d933 147 pc.printf(" SoftwareUpdateCheck: %s\r\n", ntp.ctime(&tNow));
WiredHome 7:16129d213e6a 148 tstart = tNow;
WiredHome 7:16129d213e6a 149 swUpdateCheck = true;
WiredHome 7:16129d213e6a 150 if (INI::INI_SUCCESS == ini.ReadString("SWUpdate", "url", url, sizeof(url))
WiredHome 7:16129d213e6a 151 && INI::INI_SUCCESS == ini.ReadString("SWUpdate", "name", name, sizeof(name))) {
WiredHome 7:16129d213e6a 152 linkdata = true;
WiredHome 7:16129d213e6a 153 pc.printf(" url: %s\r\n", url);
WiredHome 7:16129d213e6a 154 pc.printf(" name: %s\r\n", name);
WiredHome 7:16129d213e6a 155 SWUpdate_T su = SoftwareUpdate(url, name, DEFER_REBOOT);
WiredHome 7:16129d213e6a 156 if (SWUP_OK == su) {
WiredHome 7:16129d213e6a 157 pc.printf(" update installed, rebooting...\r\n");
WiredHome 7:16129d213e6a 158 Thread::wait(3000);
WiredHome 7:16129d213e6a 159 mbed_reset();
WiredHome 7:16129d213e6a 160 } else if (SWUP_SAME_VER == su) {
WiredHome 7:16129d213e6a 161 pc.printf(" no update available.\r\n");
WiredHome 7:16129d213e6a 162 swUpdateCheck = false;
WiredHome 7:16129d213e6a 163 } else {
WiredHome 10:ca0c1db6d933 164 pc.printf(" update failed %04X - %s\r\n", su,
WiredHome 10:ca0c1db6d933 165 SoftwareUpdateGetHTTPErrorMsg(SoftwareUpdateGetHTTPErrorCode()));
WiredHome 7:16129d213e6a 166 Thread::wait(1000);
WiredHome 10:ca0c1db6d933 167 swUpdateCheck = false;
WiredHome 7:16129d213e6a 168 }
WiredHome 7:16129d213e6a 169 linkdata = false;
WiredHome 7:16129d213e6a 170 } else {
WiredHome 7:16129d213e6a 171 pc.printf(" can't get info from ini file.\r\n");
WiredHome 7:16129d213e6a 172 swUpdateCheck = false;
WiredHome 7:16129d213e6a 173 }
WiredHome 10:ca0c1db6d933 174 //eth_mutex.unlock();
WiredHome 7:16129d213e6a 175 }
WiredHome 7:16129d213e6a 176 }
WiredHome 7:16129d213e6a 177
WiredHome 10:ca0c1db6d933 178 void ShowIPAddress(bool show = true)
WiredHome 10:ca0c1db6d933 179 {
WiredHome 10:ca0c1db6d933 180 char buf[16];
WiredHome 10:ca0c1db6d933 181
WiredHome 10:ca0c1db6d933 182 if (show)
WiredHome 10:ca0c1db6d933 183 sprintf(buf, "%15s", eth.getIPAddress());
WiredHome 10:ca0c1db6d933 184 else
WiredHome 10:ca0c1db6d933 185 sprintf(buf, "%15s", "---.---.---.---");
WiredHome 10:ca0c1db6d933 186 pc.printf("Ethernet connected as %s\r\n", buf);
WiredHome 10:ca0c1db6d933 187 }
WiredHome 10:ca0c1db6d933 188
WiredHome 10:ca0c1db6d933 189
WiredHome 7:16129d213e6a 190
WiredHome 7:16129d213e6a 191 /// This function syncs the node to a timeserver, if one
WiredHome 7:16129d213e6a 192 /// is configured in the .ini file.
WiredHome 7:16129d213e6a 193 ///
WiredHome 7:16129d213e6a 194 void SyncToNTPServer(bool force)
WiredHome 7:16129d213e6a 195 {
WiredHome 7:16129d213e6a 196 char url[100];
WiredHome 7:16129d213e6a 197 char tzone[10];
WiredHome 7:16129d213e6a 198 char dstFlag[5]; // off,on,auto
WiredHome 7:16129d213e6a 199 char dstStart[12]; // mm/dd,hh:mm
WiredHome 7:16129d213e6a 200 char dstStop[12]; // mm/dd,hh:mm
WiredHome 7:16129d213e6a 201 static time_t tlast = 0;
WiredHome 10:ca0c1db6d933 202 time_t tnow = ntp.timelocal();
WiredHome 7:16129d213e6a 203
WiredHome 7:16129d213e6a 204 if (((tnow - tlast) > (60*60*24)) || force) {
WiredHome 7:16129d213e6a 205 printf("SyncToNTPServer\r\n");
WiredHome 7:16129d213e6a 206 if (INI::INI_SUCCESS == ini.ReadString("Clock", "timeserver", url, sizeof(url))) {
WiredHome 7:16129d213e6a 207 ini.ReadString("Clock", "tzoffsetmin", tzone, sizeof(tzone), "0");
WiredHome 7:16129d213e6a 208 ini.ReadString("Clock", "dst", dstFlag, sizeof(dstFlag), "0");
WiredHome 7:16129d213e6a 209 ini.ReadString("Clock", "dststart", dstStart, sizeof(dstStart), "");
WiredHome 7:16129d213e6a 210 ini.ReadString("Clock", "dststop", dstStop, sizeof(dstStop), "");
WiredHome 10:ca0c1db6d933 211
WiredHome 7:16129d213e6a 212 printf("NTP update time from (%s)\r\n", url);
WiredHome 7:16129d213e6a 213 int32_t tzo_min = atoi(tzone);
WiredHome 10:ca0c1db6d933 214
WiredHome 7:16129d213e6a 215 if (strcmp(dstFlag,"on") == 0) {
WiredHome 7:16129d213e6a 216 ntp.set_dst(1);
WiredHome 7:16129d213e6a 217 } else if (strcmp(dstFlag, "off") == 0) {
WiredHome 7:16129d213e6a 218 ntp.set_dst(0);
WiredHome 10:ca0c1db6d933 219 } else { /* if (strcmp(dstFlag, "auto") == 0) */
WiredHome 7:16129d213e6a 220 ntp.set_dst(dstStart,dstStop);
WiredHome 7:16129d213e6a 221 }
WiredHome 7:16129d213e6a 222 ntp.set_tzo_min(tzo_min);
WiredHome 8:a45fe77efcc5 223 linkdata = true;
WiredHome 7:16129d213e6a 224 int res = ntp.setTime(url);
WiredHome 7:16129d213e6a 225 //printf(" NTP (release ethernet)\r\n");
WiredHome 7:16129d213e6a 226 if (res == 0) {
WiredHome 7:16129d213e6a 227 time_t ctTime;
WiredHome 10:ca0c1db6d933 228 ctTime = ntp.timelocal();
WiredHome 7:16129d213e6a 229 ntpSyncd = ntp.get_timelastset();;
WiredHome 7:16129d213e6a 230 tlast = ctTime;
WiredHome 7:16129d213e6a 231 printf(" Time set to (UTC): %s\r\n", ntp.ctime(&ctTime));
WiredHome 10:ca0c1db6d933 232 printf(" ntpSyncd: %s (UTC)\r\n", ntp.ctime(&ntpSyncd));
WiredHome 8:a45fe77efcc5 233 ntpUpdateCheck = false;
WiredHome 7:16129d213e6a 234 } else {
WiredHome 7:16129d213e6a 235 ntpSyncd = 0;
WiredHome 7:16129d213e6a 236 printf("Error return from setTime(%s) %d\r\n", url, res);
WiredHome 7:16129d213e6a 237 }
WiredHome 8:a45fe77efcc5 238 linkdata = false;
WiredHome 7:16129d213e6a 239 } else {
WiredHome 7:16129d213e6a 240 ntpSyncd = 0;
WiredHome 7:16129d213e6a 241 printf("no time server was set\r\n");
WiredHome 7:16129d213e6a 242 }
WiredHome 7:16129d213e6a 243 }
WiredHome 7:16129d213e6a 244 }
WiredHome 7:16129d213e6a 245
WiredHome 7:16129d213e6a 246
WiredHome 7:16129d213e6a 247 /// This function monitors the USB serial interface for activity
WiredHome 7:16129d213e6a 248 /// from a connected user.
WiredHome 7:16129d213e6a 249 ///
WiredHome 7:16129d213e6a 250 /// It offers a tiny bit of help if an unrecognized command is entered.
WiredHome 7:16129d213e6a 251 ///
WiredHome 7:16129d213e6a 252 void CheckConsoleInput(void)
WiredHome 7:16129d213e6a 253 {
WiredHome 7:16129d213e6a 254 static Timer timer;
WiredHome 7:16129d213e6a 255
WiredHome 7:16129d213e6a 256 if (pc.readable()) {
WiredHome 7:16129d213e6a 257 int c = pc.getc();
WiredHome 7:16129d213e6a 258 switch (c) {
WiredHome 7:16129d213e6a 259 case 'r':
WiredHome 7:16129d213e6a 260 mbed_reset();
WiredHome 7:16129d213e6a 261 break;
WiredHome 7:16129d213e6a 262 case 's':
WiredHome 7:16129d213e6a 263 swUpdateCheck = true;
WiredHome 7:16129d213e6a 264 break;
WiredHome 7:16129d213e6a 265 case 't':
WiredHome 7:16129d213e6a 266 ntpUpdateCheck = true;
WiredHome 7:16129d213e6a 267 break;
WiredHome 7:16129d213e6a 268 case '@':
WiredHome 7:16129d213e6a 269 pc.printf("Sample '%s' file.\r\n", iniFile);
WiredHome 7:16129d213e6a 270 pc.printf("[SWUpdate]\r\n");
WiredHome 7:16129d213e6a 271 pc.printf("url=http://192.168.1.201/mbed/\r\n");
WiredHome 10:ca0c1db6d933 272 pc.printf("name=WattEye\r\n");
WiredHome 7:16129d213e6a 273 pc.printf("[Clock]\r\n");
WiredHome 7:16129d213e6a 274 pc.printf("timeserver=time.nist.gov\r\n");
WiredHome 7:16129d213e6a 275 pc.printf("tzoffsetmin=-300\r\n");
WiredHome 7:16129d213e6a 276 pc.printf("[IP]\r\n");
WiredHome 10:ca0c1db6d933 277 pc.printf("ip=192.168.1.204\r\n");
WiredHome 7:16129d213e6a 278 pc.printf("nm=255.255.254.0\r\n");
WiredHome 7:16129d213e6a 279 pc.printf("gw=192.168.1.1\r\n");
WiredHome 7:16129d213e6a 280 pc.printf("[Node]\r\n");
WiredHome 10:ca0c1db6d933 281 pc.printf("id=WattEye-01\r\n");
WiredHome 7:16129d213e6a 282 pc.printf(";hint: Use either the fixed IP or the Node\r\n");
WiredHome 7:16129d213e6a 283 break;
WiredHome 7:16129d213e6a 284 case '?':
WiredHome 10:ca0c1db6d933 285 ShowRawSample();
WiredHome 10:ca0c1db6d933 286 // break;
WiredHome 7:16129d213e6a 287 default:
WiredHome 7:16129d213e6a 288 pc.printf("\r\n\r\n");
WiredHome 7:16129d213e6a 289 if (c > ' ' && c != '?')
WiredHome 7:16129d213e6a 290 pc.printf("unknown command '%c'\r\n", c);
WiredHome 10:ca0c1db6d933 291 pc.printf("Commands:\r\n"
WiredHome 10:ca0c1db6d933 292 " r = reset\r\n"
WiredHome 10:ca0c1db6d933 293 " s = software update check\r\n"
WiredHome 10:ca0c1db6d933 294 " t = time sync to NTP server\r\n"
WiredHome 10:ca0c1db6d933 295 );
WiredHome 10:ca0c1db6d933 296 ShowIPAddress();
WiredHome 10:ca0c1db6d933 297
WiredHome 7:16129d213e6a 298 break;
WiredHome 7:16129d213e6a 299 }
WiredHome 7:16129d213e6a 300 }
WiredHome 7:16129d213e6a 301 }
WiredHome 7:16129d213e6a 302
WiredHome 7:16129d213e6a 303
WiredHome 7:16129d213e6a 304
WiredHome 5:6244e237def1 305 int main()
WiredHome 4:5da66fab599c 306 {
WiredHome 7:16129d213e6a 307 char ip[20],nm[20],gw[20];
WiredHome 10:ca0c1db6d933 308 bool SensorStarted = false;
WiredHome 10:ca0c1db6d933 309
WiredHome 0:de1dfa2ab813 310 pc.baud(460800);
WiredHome 0:de1dfa2ab813 311 pc.printf("\r\n%s Build %s\r\n", PROG_NAME, BUILD_DATE);
WiredHome 4:5da66fab599c 312 lastboottime = ntp.timelocal();
WiredHome 0:de1dfa2ab813 313 if (wd.WatchdogCausedReset()) {
WiredHome 0:de1dfa2ab813 314 pc.printf("**** Watchdog Event caused reset at %s ****\r\n", ntp.ctime(&lastboottime));
WiredHome 7:16129d213e6a 315 WDEventOccurred = true;
WiredHome 0:de1dfa2ab813 316 }
WiredHome 7:16129d213e6a 317 wd.Configure(25); // very generous, but this is a network appliance, so a bit less deterministic.
WiredHome 7:16129d213e6a 318
WiredHome 7:16129d213e6a 319 ini.SetFile(iniFile, 2);
WiredHome 0:de1dfa2ab813 320
WiredHome 5:6244e237def1 321 pc.printf("Initializing network interface...\r\n");
WiredHome 7:16129d213e6a 322 int initResult;
WiredHome 10:ca0c1db6d933 323
WiredHome 7:16129d213e6a 324 if (INI::INI_SUCCESS == ini.ReadString("IP", "ip", ip, sizeof(ip))
WiredHome 10:ca0c1db6d933 325 && INI::INI_SUCCESS == ini.ReadString("IP", "nm", nm, sizeof(nm))
WiredHome 10:ca0c1db6d933 326 && INI::INI_SUCCESS == ini.ReadString("IP", "gw", gw, sizeof(gw))) {
WiredHome 7:16129d213e6a 327 initResult = eth.init(ip,nm,gw); // use Fixed
WiredHome 7:16129d213e6a 328 } else {
WiredHome 7:16129d213e6a 329 initResult = eth.init(); // use DHCP
WiredHome 7:16129d213e6a 330 }
WiredHome 7:16129d213e6a 331 if (initResult) {
WiredHome 7:16129d213e6a 332 // Failed to init ...
WiredHome 7:16129d213e6a 333 pc.printf(" ... failed to initialize, rebooting...\r\n");
WiredHome 7:16129d213e6a 334 wait_ms(5000);
WiredHome 7:16129d213e6a 335 mbed_reset();
WiredHome 7:16129d213e6a 336 } else {
WiredHome 10:ca0c1db6d933 337 bool bEU = ini.ReadString("Energy", "url", url, sizeof(url));
WiredHome 10:ca0c1db6d933 338 bool bDS = ini.ReadString("Energy", "dest", dest, sizeof(dest));
WiredHome 10:ca0c1db6d933 339 bool bPO = ini.ReadString("Energy", "port", port, sizeof(port));
WiredHome 10:ca0c1db6d933 340 bool bID = ini.ReadString("Node", "id", myID, sizeof(myID));
WiredHome 10:ca0c1db6d933 341 if (INI::INI_SUCCESS == bEU && INI::INI_SUCCESS == bDS && INI::INI_SUCCESS == bPO && INI::INI_SUCCESS == bID) {
WiredHome 10:ca0c1db6d933 342 pc.printf("Node %s\r\n", myID);
WiredHome 10:ca0c1db6d933 343 pc.printf("URL %s\r\n", url);
WiredHome 10:ca0c1db6d933 344 pc.printf("port %s\r\n", port);
WiredHome 10:ca0c1db6d933 345 pc.printf("dest %s\r\n", dest);
WiredHome 10:ca0c1db6d933 346 Server_Port = atoi(port);
WiredHome 10:ca0c1db6d933 347 }
WiredHome 10:ca0c1db6d933 348 eth.setName(myID);
WiredHome 4:5da66fab599c 349
WiredHome 5:6244e237def1 350 do {
WiredHome 5:6244e237def1 351 pc.printf("Connecting to network...\r\n");
WiredHome 5:6244e237def1 352 if (0 == eth.connect()) {
WiredHome 7:16129d213e6a 353 wd.Service();
WiredHome 7:16129d213e6a 354 linkup = true;
WiredHome 10:ca0c1db6d933 355 time_t tstart = ntp.timelocal();
WiredHome 5:6244e237def1 356 int speed = eth.get_connection_speed();
WiredHome 5:6244e237def1 357
WiredHome 7:16129d213e6a 358 pc.printf("Ethernet Connected at: %d Mb/s\r\n", speed);
WiredHome 7:16129d213e6a 359 pc.printf(" IP: %15s\r\n", eth.getIPAddress());
WiredHome 5:6244e237def1 360
WiredHome 10:ca0c1db6d933 361 HTTPServer svr(Server_Port, Server_Root);
WiredHome 5:6244e237def1 362 svr.RegisterHandler("/", RootPage);
WiredHome 7:16129d213e6a 363 svr.RegisterHandler("/info", InfoPage);
WiredHome 7:16129d213e6a 364 svr.RegisterHandler("/software", SoftwarePage);
WiredHome 8:a45fe77efcc5 365 svr.RegisterHandler("/reboot", RebootPage);
WiredHome 5:6244e237def1 366 svr.RegisterHandler("/setup.xml", Setup_xml);
WiredHome 10:ca0c1db6d933 367 SSDP ssdp(myID, eth.getMACAddress(), eth.getIPAddress(), Server_Port);
WiredHome 4:5da66fab599c 368
WiredHome 10:ca0c1db6d933 369 wait(5);
WiredHome 10:ca0c1db6d933 370 if (!SensorStarted) {
WiredHome 10:ca0c1db6d933 371 timer.start();
WiredHome 10:ca0c1db6d933 372 timer.reset();
WiredHome 10:ca0c1db6d933 373 event.rise(&PulseRisingISR);
WiredHome 10:ca0c1db6d933 374 SensorStarted = true;
WiredHome 10:ca0c1db6d933 375 printf("Sensor started\r\n");
WiredHome 10:ca0c1db6d933 376 }
WiredHome 5:6244e237def1 377 while (eth.is_connected()) {
WiredHome 5:6244e237def1 378 wd.Service();
WiredHome 5:6244e237def1 379 time_t tNow = ntp.timelocal();
WiredHome 7:16129d213e6a 380 CheckConsoleInput();
WiredHome 10:ca0c1db6d933 381 RunPulseTask();
WiredHome 7:16129d213e6a 382 svr.Poll(); // Web Server: non-blocking, but also not deterministic
WiredHome 10:ca0c1db6d933 383 ShowSignOfLife();
WiredHome 7:16129d213e6a 384 SyncToNTPServer(ntpUpdateCheck);
WiredHome 7:16129d213e6a 385 SoftwareUpdateCheck(swUpdateCheck);
WiredHome 5:6244e237def1 386 // Any other work can happen here
WiredHome 7:16129d213e6a 387 // ...
WiredHome 5:6244e237def1 388 Thread::yield();
WiredHome 5:6244e237def1 389 }
WiredHome 7:16129d213e6a 390 linkup = false;
WiredHome 7:16129d213e6a 391 linkdata = false;
WiredHome 5:6244e237def1 392 pc.printf("lost connection.\r\n");
WiredHome 10:ca0c1db6d933 393 ShowIPAddress(false);
WiredHome 5:6244e237def1 394 eth.disconnect();
WiredHome 5:6244e237def1 395 } else {
WiredHome 5:6244e237def1 396 pc.printf(" ... failed to connect.\r\n");
WiredHome 5:6244e237def1 397 }
WiredHome 5:6244e237def1 398 } while (1);
WiredHome 0:de1dfa2ab813 399 }
WiredHome 0:de1dfa2ab813 400 }
WiredHome 10:ca0c1db6d933 401
WiredHome 10:ca0c1db6d933 402
WiredHome 10:ca0c1db6d933 403 void LedOff(void)
WiredHome 10:ca0c1db6d933 404 {
WiredHome 10:ca0c1db6d933 405 PulseIndicator = 0;
WiredHome 10:ca0c1db6d933 406 }
WiredHome 10:ca0c1db6d933 407
WiredHome 10:ca0c1db6d933 408
WiredHome 10:ca0c1db6d933 409 void PulseRisingISR(void)
WiredHome 10:ca0c1db6d933 410 {
WiredHome 10:ca0c1db6d933 411 uint64_t tNow = timer.read_us();
WiredHome 10:ca0c1db6d933 412
WiredHome 10:ca0c1db6d933 413 __disable_irq();
WiredHome 10:ca0c1db6d933 414 if (!RawPowerSample.init) {
WiredHome 10:ca0c1db6d933 415 RawPowerSample.init = true;
WiredHome 10:ca0c1db6d933 416 RawPowerSample.cycles = (uint32_t)-1;
WiredHome 10:ca0c1db6d933 417 RawPowerSample.tStart = tNow;
WiredHome 10:ca0c1db6d933 418 RawPowerSample.tLastRise = tNow;
WiredHome 10:ca0c1db6d933 419 RawPowerSample.startTimestamp = ntp.timelocal();
WiredHome 10:ca0c1db6d933 420 }
WiredHome 10:ca0c1db6d933 421 RawPowerSample.cycles++;
WiredHome 10:ca0c1db6d933 422 RawPowerSample.tStartSample = RawPowerSample.tLastRise;
WiredHome 10:ca0c1db6d933 423 RawPowerSample.tLastRise = tNow;
WiredHome 10:ca0c1db6d933 424 __enable_irq();
WiredHome 10:ca0c1db6d933 425 PulseIndicator = 1;
WiredHome 10:ca0c1db6d933 426 flash.attach_us(&LedOff, 25000);
WiredHome 10:ca0c1db6d933 427 }
WiredHome 10:ca0c1db6d933 428
WiredHome 10:ca0c1db6d933 429
WiredHome 10:ca0c1db6d933 430 void RunPulseTask(void)
WiredHome 10:ca0c1db6d933 431 {
WiredHome 10:ca0c1db6d933 432 static time_t timeFor5s = 0;
WiredHome 10:ca0c1db6d933 433 static time_t timeFor5m = 0;
WiredHome 10:ca0c1db6d933 434 //static uint32_t lastCount = 0;
WiredHome 10:ca0c1db6d933 435 time_t timenow = ntp.timelocal();
WiredHome 10:ca0c1db6d933 436 float iKW = 0.0f;
WiredHome 10:ca0c1db6d933 437 bool sendToWeb = false;
WiredHome 10:ca0c1db6d933 438
WiredHome 10:ca0c1db6d933 439 __disable_irq();
WiredHome 10:ca0c1db6d933 440 uint32_t elapsed = RawPowerSample.tLastRise - RawPowerSample.tStartSample;
WiredHome 10:ca0c1db6d933 441 //uint32_t count = RawPowerSample.cycles;
WiredHome 10:ca0c1db6d933 442 __enable_irq();
WiredHome 10:ca0c1db6d933 443
WiredHome 10:ca0c1db6d933 444 if (elapsed) {
WiredHome 10:ca0c1db6d933 445 // instantaneous, from this exact sample
WiredHome 10:ca0c1db6d933 446 iKW = (float)3600 * 1000 / elapsed;
WiredHome 10:ca0c1db6d933 447 }
WiredHome 10:ca0c1db6d933 448 if (timeFor5s == 0 || timenow < timeFor5s) // startup or if something goes really bad
WiredHome 10:ca0c1db6d933 449 timeFor5s = timenow;
WiredHome 10:ca0c1db6d933 450 if (timeFor5m == 0 || timenow < timeFor5m) // startup or if something goes really bad
WiredHome 10:ca0c1db6d933 451 timeFor5m = timenow;
WiredHome 10:ca0c1db6d933 452
WiredHome 10:ca0c1db6d933 453 if ((timenow - timeFor5m) >= 60) { // 300) {
WiredHome 10:ca0c1db6d933 454 //pc.printf(" tnow: %d, t5m: %d\r\n", timenow, timeFor5m);
WiredHome 10:ca0c1db6d933 455 sendToWeb = true;
WiredHome 10:ca0c1db6d933 456 timeFor5s = timeFor5m = timenow;
WiredHome 10:ca0c1db6d933 457 stats5s.EnterItem(iKW);
WiredHome 10:ca0c1db6d933 458 stats5m.EnterItem(stats5s.Average());
WiredHome 10:ca0c1db6d933 459 TransmitEnergy(true, iKW, stats5s.Min(), stats5s.Average(), stats5s.Max(),
WiredHome 10:ca0c1db6d933 460 stats5m.Min(), stats5m.Average(), stats5m.Max());
WiredHome 10:ca0c1db6d933 461 } else if ((timenow - timeFor5s) >= 5) {
WiredHome 10:ca0c1db6d933 462 sendToWeb = true;
WiredHome 10:ca0c1db6d933 463 timeFor5s = timenow;
WiredHome 10:ca0c1db6d933 464 stats5s.EnterItem(iKW);
WiredHome 10:ca0c1db6d933 465 TransmitEnergy(false, iKW, stats5s.Min(), stats5s.Average(), stats5s.Max(),
WiredHome 10:ca0c1db6d933 466 stats5m.Min(), stats5m.Average(), stats5m.Max());
WiredHome 10:ca0c1db6d933 467 }
WiredHome 10:ca0c1db6d933 468 if (sendToWeb) { // count != lastCount) {
WiredHome 10:ca0c1db6d933 469 //lastCount = count;
WiredHome 10:ca0c1db6d933 470 pc.printf("%8.3fs => %4.3f (%4.3f,%4.3f,%4.3f) iKW, (%4.3f,%4.3f,%4.3f) KW 5m\r\n",
WiredHome 10:ca0c1db6d933 471 (float)elapsed/1000000,
WiredHome 10:ca0c1db6d933 472 iKW,
WiredHome 10:ca0c1db6d933 473 stats5s.Min(), stats5s.Average(), stats5s.Max(),
WiredHome 10:ca0c1db6d933 474 stats5m.Min(), stats5m.Average(), stats5m.Max());
WiredHome 10:ca0c1db6d933 475 }
WiredHome 10:ca0c1db6d933 476 }
WiredHome 10:ca0c1db6d933 477
WiredHome 10:ca0c1db6d933 478 void TransmitEnergy(bool sendNow, float iKW, float min5s, float avg5s, float max5s, float min5m, float avg5m, float max5m)
WiredHome 10:ca0c1db6d933 479 {
WiredHome 10:ca0c1db6d933 480 char data[150];
WiredHome 10:ca0c1db6d933 481 char fullurl[250];
WiredHome 10:ca0c1db6d933 482
WiredHome 10:ca0c1db6d933 483 if (*url) {
WiredHome 10:ca0c1db6d933 484 snprintf(data, 150, "ID=%s&iKW=%5.3f&min5s=%5.3f&avg5s=%5.3f&max5s=%5.3f&min5m=%5.3f&avg5m=%5.3f&max5m=%5.3f",
WiredHome 10:ca0c1db6d933 485 myID, iKW, min5s, avg5s, max5s, min5m, avg5m, max5m);
WiredHome 10:ca0c1db6d933 486 //eth_mutex.lock();
WiredHome 10:ca0c1db6d933 487 linkdata = true;
WiredHome 10:ca0c1db6d933 488 // Send the UDP Broadcast, picked up by a listener
WiredHome 10:ca0c1db6d933 489 UDPSendIndicator = true;
WiredHome 10:ca0c1db6d933 490 UDPSocket bcast;
WiredHome 10:ca0c1db6d933 491 Endpoint ep;
WiredHome 10:ca0c1db6d933 492 int h = ep.set_address(dest, Server_Port);
WiredHome 10:ca0c1db6d933 493 int i = bcast.bind(Server_Port);
WiredHome 10:ca0c1db6d933 494 int j = bcast.set_broadcasting(true);
WiredHome 10:ca0c1db6d933 495 int k = bcast.sendTo(ep, data, strlen(data));
WiredHome 10:ca0c1db6d933 496 bcast.close();
WiredHome 10:ca0c1db6d933 497 UDPSendIndicator = false;
WiredHome 10:ca0c1db6d933 498 // On the 5-minute interval, post the data to a specified web server
WiredHome 10:ca0c1db6d933 499 if (sendNow && *url) {
WiredHome 10:ca0c1db6d933 500 //HTTPClient http;
WiredHome 10:ca0c1db6d933 501 char buf[50];
WiredHome 10:ca0c1db6d933 502 URLSendIndicator = true;
WiredHome 10:ca0c1db6d933 503 snprintf(fullurl, 250, "%s?%s", url, data);
WiredHome 10:ca0c1db6d933 504 pc.printf("Contacting %s\r\n", fullurl);
WiredHome 10:ca0c1db6d933 505 http.setMaxRedirections(3);
WiredHome 10:ca0c1db6d933 506 int x = http.get(fullurl, buf, sizeof(buf));
WiredHome 10:ca0c1db6d933 507 URLSendIndicator = false;
WiredHome 10:ca0c1db6d933 508 pc.printf(" return: %d\r\n", x);
WiredHome 10:ca0c1db6d933 509 }
WiredHome 10:ca0c1db6d933 510 linkdata = false;
WiredHome 10:ca0c1db6d933 511 //eth_mutex.unlock();
WiredHome 10:ca0c1db6d933 512 }
WiredHome 10:ca0c1db6d933 513 }