-
Notifications
You must be signed in to change notification settings - Fork 0
/
BluesApollo.ino
171 lines (143 loc) · 4.79 KB
/
BluesApollo.ino
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
#define NDEBUG
#include <Notecard.h>
#include <Notecarrier.h>
#ifdef ARDUINO_ARCH_ESP32
#include <WiFi.h>
#endif
#ifndef NDEBUG
#define serialDebug Serial
#endif
#define productUID "com.blues.zfields:showcase"
static const size_t BUTTON_PIN = D6;
static const size_t SWITCH_PIN = D5;
Notecard notecard;
int awaitDoorClose(size_t timeout_ms_ = 35000) {
int result;
// Wait for mail carrier to deposit mail
const size_t begin_door_close_wait_ms = ::millis();
bool door_ajar = ::digitalRead(SWITCH_PIN);
for ( ; door_ajar && (timeout_ms_ > (::millis() - begin_door_close_wait_ms)) ; door_ajar = ::digitalRead(SWITCH_PIN)) {
; // Wait for door to close for up to 35s.
}
const size_t door_ajar_duration_ms = (::millis() - begin_door_close_wait_ms);
if (door_ajar) {
result = -1;
// Send Motion Detection Alert
{
J * req = notecard.newRequest("note.add");
JAddBoolToObject(req, "sync", true);
JAddStringToObject(req, "file", "mailbox.qo");
J * body = JAddObjectToObject(req, "body");
JAddBoolToObject(body, "alert", true);
JAddStringToObject(body, "msg", "DOOR AJAR");
notecard.sendRequest(req);
}
#ifndef NDEBUG
notecard.logDebug("WARNING: Door close timeout occurred!\r\n");
#endif
} else {
result = door_ajar_duration_ms;
#ifndef NDEBUG
notecard.logDebugf("Door closed after %lu milliseconds.\r\n", door_ajar_duration_ms);
#endif
}
return result;
}
void configureNotecard (void) {
// Configure Notecard to synchronize with Notehub periodically,
// as well as adjust the frequency based on the battery level.
{
J * req = notecard.newRequest("hub.set");
JAddStringToObject(req, "product", productUID);
JAddStringToObject(req, "sn", "Apollo");
JAddStringToObject(req, "mode", "periodic");
JAddStringToObject(req, "vinbound", "usb:10;high:360;normal:720;low:1440;dead:0");
JAddStringToObject(req, "voutbound", "usb:10;high:180;normal:180;low:360;dead:0");
notecard.sendRequest(req);
}
// Optimize voltage variable behaviors for LiPo battery
{
J * req = notecard.newRequest("card.voltage");
JAddStringToObject(req, "mode", "lipo");
notecard.sendRequest(req);
}
// Configure IMU sensitivity
{
J * req = notecard.newRequest("card.motion.mode");
JAddBoolToObject(req, "start", true);
JAddNumberToObject(req, "sensitivity", 3); // 1.952G
notecard.sendRequest(req);
}
}
void setup() {
// Provide visual signal when the Host MCU is powered
::pinMode(LED_BUILTIN, OUTPUT);
::digitalWrite(LED_BUILTIN, HIGH);
// Configure buttons and switches
::pinMode(BUTTON_PIN, INPUT_PULLUP);
::pinMode(SWITCH_PIN, INPUT_PULLUP);
// Debounce mailbox door
::delay(250);
// Check override button
const bool override = !(::digitalRead(BUTTON_PIN)); // pull-up grounded via button press
// Check alert latch
const bool door_ajar = ::digitalRead(SWITCH_PIN); // pull-up grounded via door switch
#ifdef ARDUINO_ARCH_ESP32
// Disable radios to improve power profile
WiFi.mode(WIFI_OFF);
::btStop();
#endif
#ifndef NDEBUG
// Initialize Debug Output
serialDebug.begin(115200);
static const size_t MAX_SERIAL_WAIT_MS = 5000;
size_t begin_serial_wait_ms = ::millis();
while (!serialDebug && (MAX_SERIAL_WAIT_MS > (::millis() - begin_serial_wait_ms))) {
; // wait for serial port to connect. Needed for native USB
}
notecard.setDebugOutputStream(serialDebug);
#endif
// Initialize Notecard
notecard.begin();
// Send mailbox alert only when door is ajar
if (override && door_ajar) {
#ifndef NDEBUG
notecard.logDebug("Mail collection in progress...\r\n");
#endif
configureNotecard();
awaitDoorClose();
} else if (door_ajar) {
#ifndef NDEBUG
notecard.logDebug("Reporting mail deposit...\r\n");
#endif
const int door_open_ms = awaitDoorClose();
if (0 <= door_open_ms) {
// Send Motion Detection Alert
{
J * req = notecard.newRequest("note.add");
JAddBoolToObject(req, "sync", true);
JAddStringToObject(req, "file", "mailbox.qo");
J * body = JAddObjectToObject(req, "body");
JAddNumberToObject(body, "door_open_ms", door_open_ms);
notecard.sendRequest(req);
}
}
#ifndef NDEBUG
} else {
notecard.logDebug("Spurious motion event occurred.\r\n");
#endif
}
}
void loop() {
// Request sleep from loop to safeguard against tranmission failure, and
// ensure sleep request is honored so power usage is minimized.
{
// Create a "command" instead of a "request", because the host
// MCU is going to power down and cannot receive a response.
J * cmd = NoteNewCommand("card.attn");
JAddStringToObject(cmd, "mode", "arm,motion");
notecard.sendRequest(cmd);
// Pause for power down between retries
::delay(1000);
}
}