-
Notifications
You must be signed in to change notification settings - Fork 64
/
Copy pathRefrigeratorMonitoringApp.device.nut
184 lines (145 loc) · 6.05 KB
/
RefrigeratorMonitoringApp.device.nut
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
// Refrigerator Monitor Application Device Code
// ---------------------------------------------------
// SENSOR LIBRARIES
// ---------------------------------------------------
// Libraries must be required before all other code
// Temperature Humidity sensor Library
#require "HTS221.device.lib.nut:2.0.2"
// Library to manage agent/device communication
#require "MessageManager.lib.nut:2.4.0"
// HARDWARE ABSTRACTION LAYER
// ---------------------------------------------------
// HAL's are tables that map human readable names to
// the hardware objects used in the application.
// Copy and Paste Your HAL here
// YOUR_HAL <- {...}
// REFRIGERATOR MONITOR APPLICATION CODE
// ---------------------------------------------------
// Application code, take readings from our temperature
// humidity and light sensors. Use the light level to
// determine if the door is open (true or false) and send
// the door status, temperature and humidity to the agent
class SmartFridge {
// Time in seconds to wait between readings
static READING_INTERVAL_SEC = 5;
// Time in seconds to wait between connections
static REPORTING_INTERVAL_SEC = 300;
// Time to wait after boot before first disconection
// This allows time for blinkup recovery on cold boots
static BOOT_TIMER_SEC = 60;
// The lx level at which we know the door is open
static LX_THRESHOLD = 3000;
// Hardware variables
i2c = null; // Replace with your sensori2c
tempHumidAddr = null; // Replace with your tempHumid i2c addr
// Sensor variables
tempHumid = null;
// Message Manager variable
mm = null;
// An array to store readings between connections
readings = [];
// Track current door status so we know when there is a
// there is a change
currentDoorOpenStatus = false;
// Varaible to track when to connect
nextConnectTime = null;
// Flag to track first disconnection
_boot = true;
constructor() {
// Power save mode will reduce power consumption when the radio
// is idle, a good first step for saving power for battery
// powered devices.
// NOTE: Power save mode will add latency when sending data.
// Power save mode is not supported on impC001 and is not
// recommended for imp004m, so don't set for those types of imps.
local type = imp.info().type;
if (type != "imp004m" && type != "impC001") {
imp.setpowersave(true);
}
// Use the current time and the REPORTING_INTERVAL_SEC
// to set a timestamp, so we know when we should connect
// and send the stored readings
setNextConnectTime();
// Configure message manager for device/agent communication
mm = MessageManager();
// Message Manager allows us to call a function when a message
// has been delivered. We will use this to know when it is ok
// to delete locally stored readings and disconnect
mm.onAck(readingsAckHandler.bindenv(this));
initializeSensors();
// We want to make sure we can always blinkUp a device
// when it is first powered on, so we do not want to
// immediately disconnect after boot
// Set up first disconnect
imp.wakeup(BOOT_TIMER_SEC, function() {
_boot = false;
server.disconnect();
}.bindenv(this))
}
function run() {
// Take an async temp/humid reading
tempHumid.read(function(result) {
// Set up the reading table with a timestamp
local reading = { "time" : time() };
// Add temperature and humidity readings
if ("temperature" in result) reading.temperature <- result.temperature;
if ("humidity" in result) reading.humidity <- result.humidity;
// Check door status using internal LX sensor to
// determine if the door is open
reading.doorOpen <- (hardware.lightlevel() > LX_THRESHOLD);
// Add table to the readings array for storage til next connection
readings.push(reading);
// Only send readings if we have some and are either already
// connected, there is a change in the door status or if it
// is time to connect
if (readings.len() > 0 && (server.isconnected() || currentDoorOpenStatus != reading.doorOpen || timeToConnect())) {
sendReadings();
}
// update current door status
currentDoorOpenStatus = reading.doorOpen;
// Schedule the next reading
imp.wakeup(READING_INTERVAL_SEC, run.bindenv(this));
}.bindenv(this));
}
function sendReadings() {
// Connect device
server.connect();
// Send readings to the agent
mm.send("readings", readings);
// Update the next connection time varaible
setNextConnectTime();
// When this message is acknowleged by the agent
// the readingsAckHandler will be triggered
}
function readingsAckHandler(msg) {
// The agent received the readings
// Clear readings we just sent
readings = [];
// Disconnect from server if we have not just booted up
if (!_boot) server.disconnect();
}
function timeToConnect() {
// return a boolean - if it is time to connect based on
// the current time
return (time() >= nextConnectTime);
}
function setNextConnectTime() {
// Update the local nextConnectTime variable
nextConnectTime = time() + REPORTING_INTERVAL_SEC;
}
function initializeSensors() {
// Configure i2c
i2c.configure(CLOCK_SPEED_400_KHZ);
// Initialize sensor
tempHumid = HTS221(i2c, tempHumidAddr);
// Configure sensor to take readings
tempHumid.setMode(HTS221_MODE.ONE_SHOT);
}
}
// RUNTIME
// ---------------------------------------------------
server.log("Device running...");
// Initialize application
fridge <- SmartFridge();
// Start reading loop
fridge.run();