-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy patheddystone-tlm-timeout.js
177 lines (149 loc) · 4.57 KB
/
eddystone-tlm-timeout.js
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
/**
* Copyright reelyActive 2019
* We believe in an open Internet of Things
*/
// User-configurable constants
const ACTIVITY_DURATION_SECONDS = 55; // Number of seconds of activity before blink
const ACTIVITY_TIMEOUT_BLINK_SECONDS = 5; // Number of seconds to blink before reset
const ADVERTISING_INTERVAL_MILLISECONDS = 1000;
const LED_BLINK_MILLISECONDS = 200;
const SENSOR_UPDATE_INTERVAL = 60; // Every 60 advertisements (once per minute)
// Other constants
const MAIN_INTERVAL_MILLISECONDS = Math.round(ADVERTISING_INTERVAL_MILLISECONDS / 2);
// Global variables
var gIsSleeping = false;
var gIsPacketUpdated = false;
var gMainIntervalId;
var gAdvertisingCount = 0;
var gUptimeMilliseconds = 0;
var gBatteryVoltage = 0;
var gTemperature = 0;
/**
* Initialise the advertising options.
*/
const advertisingOptions = {
interval: ADVERTISING_INTERVAL_MILLISECONDS,
showName: false
};
/**
* Initialise the packet that will be advertised.
*/
var packet = [
0x02, // Length of Flags
0x01, // Param: Flags
0x06, // Flags
0x03, // Length of Service List
0x03, // Param: Service List
0xaa, // Eddystone
0xfe, // 16-bit UUID
0x11, // Length of Service Data
0x16, // Service Data
0xaa, // Eddystone
0xfe, // 16-bit UUID
0x20, // Eddystone-TLM Frame
0x00, // Version
0x00, // Battery voltage
0x00, // (zero if unknown)
0x80, // Temperature
0x00, // (-128C if unknown)
0x00, // Advertising count
0x00, // (number of
0x00, // advertisement frames
0x00, // since last reboot)
0x00, // Uptime
0x00, // (time since
0x00, // last reboot with
0x00 // 0.1s resolution)
];
/**
* Update the battery and temperature sensor readings
*/
function updateSensorReadings() {
var isUpdateDue = ((gAdvertisingCount % SENSOR_UPDATE_INTERVAL) === 0);
if(isUpdateDue) {
gBatteryVoltage = NRF.getBattery();
gTemperature = E.getTemperature();
}
}
/**
* Update the contents of the advertising packet
*/
function updateAdvertisingPacket() {
var batteryMillivolts = Math.round(gBatteryVoltage * 1000);
var temperature = Math.round(gTemperature);
gAdvertisingCount++;
gUptimeMilliseconds += ADVERTISING_INTERVAL_MILLISECONDS;
var uptimeTenths = Math.round(gUptimeMilliseconds / 100);
packet[13] = (batteryMillivolts >> 8) & 0xff;
packet[14] = batteryMillivolts & 0xff;
packet[15] = temperature; // Not handling sub-zero temperature values
packet[16] = 0x00; // and ignoring fractions of degrees
packet[17] = (gAdvertisingCount >> 24) & 0xff;
packet[18] = (gAdvertisingCount >> 16) & 0xff;
packet[19] = (gAdvertisingCount >> 8) & 0xff;
packet[20] = gAdvertisingCount & 0xff;
packet[21] = (uptimeTenths >> 24) & 0xff;
packet[22] = (uptimeTenths >> 16) & 0xff;
packet[23] = (uptimeTenths >> 8) & 0xff;
packet[24] = uptimeTenths & 0xff;
}
/**
* This is the equivalent of the 'main' function
*/
function main() {
gIsPacketUpdated = false;
gAdvertisingCount = 0; // Reset the telemetry counts
gUptimeMilliseconds = 0; // on each restart
// This is the equivalent of the 'main' loop
gMainIntervalId = setInterval(function () {
var isActivityTimeout = (gUptimeMilliseconds / 1000) >
(ACTIVITY_DURATION_SECONDS +
ACTIVITY_TIMEOUT_BLINK_SECONDS);
var isActivityTimeoutBlink = (gUptimeMilliseconds / 1000) >
ACTIVITY_DURATION_SECONDS;
// The activity has timed out, stop the main loop and sleep
if(isActivityTimeout) {
clearInterval(gMainIntervalId);
LED1.write(false);
LED2.write(false);
gIsSleeping = true;
NRF.sleep();
}
// Advertise the latest TLM packet
else if(gIsPacketUpdated) {
NRF.setAdvertising(packet, advertisingOptions);
gIsPacketUpdated = false;
}
// Prepare the next TLM packet
else {
updateSensorReadings();
updateAdvertisingPacket();
gIsPacketUpdated = true;
// Blink red when approaching timeout
if(isActivityTimeoutBlink) {
LED1.write(true); // Red = timeout
setTimeout(function () {
LED1.write(false);
}, LED_BLINK_MILLISECONDS);
}
}
}, MAIN_INTERVAL_MILLISECONDS);
}
/**
* Watch the button to toggle from sleep to wake
*/
setWatch(function(e) {
if(gIsSleeping) {
LED2.write(true); // Green = wake
setTimeout(function () {
LED2.write(false);
gIsSleeping = false;
NRF.wake();
main();
}, LED_BLINK_MILLISECONDS);
}
}, BTN, { edge: "rising", repeat: true, debounce: 50 });
/**
* Begin puckyActive execution
*/
main();