-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathforward_geolocate.js
83 lines (75 loc) · 3.98 KB
/
forward_geolocate.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
// This Cloud Code Trigger is executed whenever a CoAP message is received.
// If the message contains "ssid0" and "rssi0" values, we forward the message to
// Cloud Code Function "geolocate" to perform the geolocation.
// If the message has not been transformed, we forward to Cloud Code Function "transform"
// to transform the values, like converting raw temperature to actual temperature.
// Cloud Code Triggers must complete within 2 seconds. So we forward the processing to
// another cloud function, which can execute up to 20 seconds.
/* Cloud Code Trigger convention:
params: is an object with the keys:
- action: one of 'write' | 'read'
- thingToken: the thing that triggered the trigger
- values: only if action == 'write'. Is an array of values where each value is an object with:
- key: the key
- value: the data sent
- datetime: (can be null)
callback: is a function to be called when the trigger ends can contain a
parameter string *error* if the trigger needs to report an error. */
function trigger(params, callback) {
if (params.action !== 'write') { return callback(); } // Interested only in update actions, not read.
const values = params.values;
if (!values) { return callback(); }
const thingToken = params.thingToken;
console.log('forward_geolocate', values);
// values contains geolocation parameters:
// [{"key":"device","value":"my_device_id"},
// {"key":"ssid0","value":"88:41:fc:bb:00:00"},{"key":"rssi0","value":-82},
// {"key":"ssid1","value":"88:41:fc:d6:00:00"},{"key":"rssi1","value":-91},
// {"key":"ssid2","value":"18:d6:c7:3c:00:00"},{"key":"rssi2","value":-92}]
// or sensor data:
// [{"key":"device","value":"my_device_id"},
// {"key":"tmp","value":28.1}]
// or raw sensor data:
// [{"key":"device","value":"my_device_id"},
// {"key":"t","value":1744}]
// Look for timestamp, device, ssid0 and rssi0 keys.
const timestamp = values.reduce((found, x) => (x.key == 'timestamp' ? x.value : found), null);
const device = values.reduce((found, x) => (x.key == 'device' ? x.value : found), null);
const ssid0 = values.reduce((found, x) => (x.key == 'ssid0' ? x.value : found), null);
const rssi0 = values.reduce((found, x) => (x.key == 'rssi0' ? x.value : found), null);
// Timestamp every update to reject expired updates and throttle requests.
const now = Date.now().valueOf();
if (!timestamp) {
// If timestamp is not found, add it.
values.push({ key: 'timestamp', value: now });
} else {
// Reject if update has expired (2 seconds). This discards older updates and
// throttles the throughput.
if (now - timestamp > 2 * 1000) {
console.log('forward_geolocate expired', Math.floor((now - timestamp) / 1000),
new Date(timestamp).toISOString(), values);
return callback();
}
}
// If this is a valid geolocation request with ssid0 and rssi0 keys, forward to
// "geolocate" Cloud Code Function without waiting for it to complete.
if (ssid0 && rssi0) {
console.log('forward to geolocate', values);
thethingsAPI.cloudFunction('geolocate', params, function(err, res) {
if (err) { console.log('geolocate error', err); }
});
return callback(); // Exit without waiting for Cloud Code Function to complete.
}
// Look for the "transformed" key. If not found, then this message has not been
// transformed yet. Forward to "transform" Cloud Code Function to transform and
// update the values. Don't wait for the Cloud Code Function to complete.
const transformed = values.reduce((found, x) => (x.key == 'transformed' ? x.value : found), null);
if (!transformed) {
console.log('forward to transform', values);
thethingsAPI.cloudFunction('transform', params, function(err, res) {
if (err) { console.log('transform error', err); }
});
return callback(); // Exit without waiting for Cloud Code Function to complete.
}
return callback(); // If already transformed, do nothing.
}