Created
April 21, 2017 12:56
-
-
Save rikonor/659879ef0711f1e59978092b4c6c7793 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| SYSTEM_MODE(SEMI_AUTOMATIC); | |
| #include "scheduler.h"; | |
| #include "lgger.h"; | |
| #include "tmp36.h"; | |
| #include "udp_client.h"; | |
| #include "aggregator.h"; | |
| // Duration | |
| typedef unsigned int Duration; | |
| const Duration Millisecond = 1; | |
| const Duration Second = 1000 * Millisecond; | |
| const Duration Minute = 60 * Second; | |
| const Duration Hour = 60 * Minute; | |
| // Setup scheduler | |
| Scheduler sch = Scheduler(); | |
| // Setup Logger | |
| Lgger logger = Lgger(LgLevelInfo); | |
| void setup() { | |
| UpdateSystemTime(); | |
| // Motion Activity | |
| sch.add(250 * Millisecond, &CheckMotionSensor); | |
| sch.add(10 * Minute, &FlushMotionAgg); | |
| // Temperature | |
| sch.add(1 * Second, &CheckTemperatureSensor); | |
| sch.add(30 * Minute, &FlushTemperatureAgg); | |
| // Battery Level | |
| sch.add(1 * Hour, &CheckBatteryLevel); | |
| // Flush network | |
| sch.add(24 * Hour, &FlushToNetwork); | |
| } | |
| void loop() { | |
| sch.run(); | |
| } | |
| /* | |
| Network Flush | |
| */ | |
| // UDP Client Configuration | |
| int localPort = 8888; | |
| IPAddress remoteIP(69, 116, 204, 194); | |
| int remotePort = 8085; | |
| UDPClient udpClient(localPort, remoteIP, remotePort); | |
| // Setup network messages | |
| // These will be updated continuously and reset on every flush. | |
| String tempNetworkMessage = ""; | |
| String pirNetworkMessage = ""; | |
| String battNetworkMessage = ""; | |
| void networkOn() { | |
| // Turn on Cellular | |
| Cellular.connect(); | |
| waitUntil(Cellular.ready); | |
| udpClient.begin(); | |
| } | |
| void networkOff() { | |
| // Turn off WiFI | |
| udpClient.stop(); | |
| Cellular.off(); | |
| } | |
| void FlushBatteryToNetwork() { | |
| if (battNetworkMessage.length() == 0) { | |
| logger.info("Aborting battery network flush since msg is empty.."); | |
| return; | |
| } | |
| UDPResponse res = udpClient.request("report_batt_bulk", battNetworkMessage); | |
| if (res.error != 0) { | |
| logger.error("Failed to report battery level"); | |
| } | |
| battNetworkMessage = ""; | |
| } | |
| void FlushTempNetworkMsg() { | |
| if (tempNetworkMessage.length() == 0) { | |
| logger.info("Aborting temperature network flush since msg is empty.."); | |
| return; | |
| } | |
| UDPResponse res = udpClient.request("report_temp_bulk", tempNetworkMessage); | |
| if (res.error != 0) { | |
| logger.error("Failed to report temperature"); | |
| } | |
| tempNetworkMessage = ""; | |
| } | |
| void FlushMotionNetworkMsg() { | |
| if (pirNetworkMessage.length() == 0) { | |
| logger.info("Aborting motion network flush since msg is empty.."); | |
| return; | |
| } | |
| UDPResponse res = udpClient.request("report_motion_bulk", pirNetworkMessage); | |
| if (res.error != 0) { | |
| logger.error("Failed to report motion"); | |
| } | |
| pirNetworkMessage = ""; | |
| } | |
| void FlushToNetwork() { | |
| networkOn(); | |
| FlushBatteryToNetwork(); | |
| FlushTempNetworkMsg(); | |
| FlushMotionNetworkMsg(); | |
| // Wait for UDP data to flush | |
| delay(1000); | |
| networkOff(); | |
| } | |
| /* | |
| System Time | |
| */ | |
| void UpdateSystemTime() { | |
| networkOn(); | |
| // Request current time from server | |
| UDPResponse res = udpClient.requestWait("time_sync", ""); | |
| if (res.error == 0) { | |
| long serverTime = res.body.toInt(); // TODO - validate serverTime? | |
| Time.setTime(serverTime); | |
| } | |
| networkOff(); | |
| } | |
| /* | |
| Battery Level | |
| */ | |
| // Setup Battery Level Sensor | |
| FuelGauge battSensor; | |
| void CheckBatteryLevel() { | |
| float vCell = battSensor.getVCell(); | |
| float vPerc = battSensor.getSoC(); | |
| logger.info("Battery Level: " + String(vCell) + "v" + "\n" + "Battery SoC: " + String(vPerc)); | |
| // Battery doesn't need aggregator - just flush directly to message | |
| if (battNetworkMessage.length() > 0) { | |
| battNetworkMessage += "\n"; | |
| } | |
| battNetworkMessage += String(Time.now()) + "," + String(vCell) + "," + String(vPerc); | |
| } | |
| /* | |
| Temperature | |
| */ | |
| // Setup Temperature Sensor | |
| TMP36TemperatureSensor tempSensor(A0); | |
| // tempAvg aggregates temperature readings into a running average. | |
| Avger tempAvg = Avger(); | |
| void CheckTemperatureSensor() { | |
| float tempSensorTemperature = tempSensor.temperatureCelcius(); | |
| logger.info("Temperature: " + String(tempSensorTemperature) + " Celcius"); | |
| // Aggregate temperature reading | |
| tempAvg.add(tempSensorTemperature); | |
| } | |
| void FlushTemperatureAgg() { | |
| logger.info("Average temperature: " + String(tempAvg.value()) + " Celcius"); | |
| if (tempNetworkMessage.length() > 0) { | |
| tempNetworkMessage += "\n"; | |
| } | |
| tempNetworkMessage += String(Time.now()) + "," + String(tempAvg.value()); | |
| // reset the aggregator | |
| tempAvg.reset(); | |
| } | |
| /* | |
| Motion Activity | |
| */ | |
| // PIRActive and PIRInactive act as constants for comparison | |
| byte PIRActive = HIGH; | |
| byte PIRInactive = LOW; | |
| // Setup Motion Sensor | |
| int pirSensorPin = D0; | |
| // lastPIRStatus tracks last status seen from the PIR sensor. | |
| byte lastPIRStatus = 0; | |
| // pirCount aggregates motion detection events into a running count. | |
| Counter pirCount = Counter(); | |
| void CheckMotionSensor() { | |
| byte pirStatus = digitalRead(pirSensorPin); | |
| if (pirStatus == PIRActive && lastPIRStatus == PIRInactive) { | |
| // Motion Detected! | |
| logger.info("Motion Detected"); | |
| // Aggregate motion detection events | |
| pirCount.add(1); | |
| } | |
| lastPIRStatus = pirStatus; | |
| } | |
| void FlushMotionAgg() { | |
| logger.info("Motion events: " + String(pirCount.value())); | |
| if (pirCount.value() == 0) { | |
| logger.debug("aborting motion agg flush since no motion events were detected"); | |
| return; | |
| } | |
| if (pirNetworkMessage.length() > 0) { | |
| pirNetworkMessage += "\n"; | |
| } | |
| pirNetworkMessage += String(Time.now()) + "," + String(pirCount.value()); | |
| // reset the aggregator | |
| pirCount.reset(); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment