-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathclairchen.ino
More file actions
189 lines (166 loc) · 4.62 KB
/
Copy pathclairchen.ino
File metadata and controls
189 lines (166 loc) · 4.62 KB
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
185
186
187
188
189
#include "scd30_sensor.h"
#include "clair.h"
#include "blinking_display.h"
#include "things_network.h"
#include "error_code.h"
#include "debug.h"
#include <arduino_lmic.h>
#include <arduino_lmic_hal_boards.h>
static ErrorCode errorCode;
static osjob_t clairjob;
static Scd30Sensor sensor;
static Clair clair(&sensor);
static BlinkingDisplay display;
static bool joined;
#define ERROR(ERROR_CODE) do { \
errorCode = ERROR_CODE; \
display.displayError(ERROR_CODE); \
} while (0)
void setup() {
os_init_ex(Arduino_LMIC::GetPinmap_ThisBoard());
PRINT_INIT();
Wire.begin();
display.setup();
if (!clair.setup()) {
ERROR(ErrorCode::CLAIR_SETUP_FAILED);
}
LMIC_reset();
#if 1
resumeConnection();
LMIC_setDrTxpow(DR_SF8, 14);
joined = true;
// LMIC_setAdrMode(1);
#else
LMIC_startJoining();
joined = false;
#endif
clair.setCurrentDatarate(LMIC.datarate);
os_setCallback(&clairjob, measureAndSendIfDue);
}
void loop() {
os_runloop_once();
}
static void measureAndSendIfDue(osjob_t* job) {
(void) (job); // unused
if (errorCode != ErrorCode::NO_ERROR) return;
int16_t currentCO2Concentration = clair.getCO2Concentration();
if (currentCO2Concentration < 0) {
ERROR(ErrorCode::CLAIR_MEASUREMENT_FAILED);
return;
}
display.displayCurrentCO2Concentration(currentCO2Concentration);
if (joined && clair.isMessageDue()) {
uint8_t messageBuffer[CLAIR_MAX_MESSAGE_SIZE];
uint8_t messageLength;
lmic_tx_error_t error;
PRINTLN("encoding message");
messageLength = clair.encodeMessage(messageBuffer, CLAIR_MAX_MESSAGE_SIZE);
error = LMIC_setTxData2(1, messageBuffer, messageLength, 0);
if (error != 0) {
ERROR(ErrorCode::TX_FAILED);
}
}
os_setTimedCallback(&clairjob, os_getTime() + ms2osticks(1000L * CLAIR_MEASURING_PERIOD_SECS), measureAndSendIfDue);
}
void onEvent (ev_t ev) {
PRINT(os_getTime());
PRINT(": ");
switch (ev) {
case EV_SCAN_TIMEOUT:
PRINTLN(F("EV_SCAN_TIMEOUT"));
break;
case EV_BEACON_FOUND:
PRINTLN(F("EV_BEACON_FOUND"));
break;
case EV_BEACON_MISSED:
PRINTLN(F("EV_BEACON_MISSED"));
break;
case EV_BEACON_TRACKED:
PRINTLN(F("EV_BEACON_TRACKED"));
break;
case EV_JOINING:
PRINTLN(F("EV_JOINING"));
break;
case EV_JOINED:
PRINTLN(F("EV_JOINED"));
PRINT_ADDRESSES_AND_KEYS();
// Enable automatic data rate adjustment
LMIC_setAdrMode(1);
clair.setCurrentDatarate(LMIC.datarate);
joined = true;
break;
/*
|| This event is defined but not used in the code. No
|| point in wasting codespace on it.
||
|| case EV_RFU1:
|| PRINTLN(F("EV_RFU1"));
|| break;
*/
case EV_JOIN_FAILED:
PRINTLN(F("EV_JOIN_FAILED"));
break;
case EV_REJOIN_FAILED:
PRINTLN(F("EV_REJOIN_FAILED"));
break;
case EV_TXCOMPLETE:
PRINTLN(F("EV_TXCOMPLETE (includes waiting for RX windows)"));
// Any data to be received?
if (LMIC.dataLen != 0 || LMIC.dataBeg != 0) {
PRINT_RECEIVED_MSG();
// Call user-supplied function with port #, pMessage, nMessage; // nMessage might be zero.
// receiveMessage(bPort, LMIC.frame + LMIC.dataBeg, LMIC.dataLen);
} else {
PRINTLN(F(" Did not receive any downlink message."));
}
PRINT(" Uplink Sequence Counter: ");
PRINTLN(LMIC.seqnoUp);
PRINT(" Downlink Sequence Counter: ");
PRINTLN(LMIC.seqnoDn);
clair.setCurrentDatarate(LMIC.datarate);
break;
case EV_LOST_TSYNC:
PRINTLN(F("EV_LOST_TSYNC"));
break;
case EV_RESET:
PRINTLN(F("EV_RESET"));
break;
case EV_RXCOMPLETE:
// data received in ping slot
PRINTLN(F("EV_RXCOMPLETE"));
break;
case EV_LINK_DEAD:
PRINTLN(F("EV_LINK_DEAD"));
break;
case EV_LINK_ALIVE:
PRINTLN(F("EV_LINK_ALIVE"));
break;
/*
|| This event is defined but not used in the code. No
|| point in wasting codespace on it.
||
|| case EV_SCAN_FOUND:
|| PRINTLN(F("EV_SCAN_FOUND"));
|| break;
*/
case EV_TXSTART:
PRINTLN(F("EV_TXSTART"));
PRINT(F("channel: ")); PRINT(LMIC.txChnl);
PRINT(F(", datarate: ")); PRINTLN(LMIC.datarate);
break;
case EV_TXCANCELED:
PRINTLN(F("EV_TXCANCELED"));
break;
case EV_RXSTART:
/* do not print anything -- it wrecks timing */
break;
case EV_JOIN_TXCOMPLETE:
PRINTLN(F("EV_JOIN_TXCOMPLETE: no JoinAccept"));
break;
default:
PRINT(F("Unknown event: "));
PRINTLN((unsigned) ev);
break;
}
PRINT_FLUSH();
}