Skip to content

Instantly share code, notes, and snippets.

@rikonor
Created April 21, 2017 12:56
Show Gist options
  • Select an option

  • Save rikonor/659879ef0711f1e59978092b4c6c7793 to your computer and use it in GitHub Desktop.

Select an option

Save rikonor/659879ef0711f1e59978092b4c6c7793 to your computer and use it in GitHub Desktop.
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