-
Notifications
You must be signed in to change notification settings - Fork 2
/
particleLocalSSE.js
134 lines (121 loc) · 6.28 KB
/
particleLocalSSE.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
(function () {
/*
Datasource Definition - what shows up on the dialog box
*/
freeboard.loadDatasourcePlugin({
"type_name": "particleSSE",
"display_name": "Particle Cloud SSE",
"description": "Subscribe to SSE (Server-Sent-Events) broadcast by the <strong>Particle Cloud</strong>. Supports both Particle.io and locally-setup clouds.",
"settings": [
/* TODO #1: Add DEVICEID filtering support once local cloud device firehose is fixed by Particle.io
{
name: "deviceId",
display_name: "Device ID",
description: 'Device ID to subscribe to',
type: "text"
},
*/
{
name: "cloudURL",
display_name: "Cloud URL",
description: 'example: http://particle.local:8080 or https://particle.io (port number is required for a local cloud)',
type: "text"
},
{
name: "accessToken",
display_name: "Cloud Access Token",
description: '',
type: "text"
},
{
name: "eventName",
display_name: "Event Name",
description: 'Leave blank to subscribe to Cloud firehose (warning: potentially lots of data!)',
type: "text"
},
{
name: "keepAliveInterval",
display_name: "KeepAlive Interval",
description: 'Should the SSE connection go down, a keepAlive interval runs in the background to restore it. This value should be larger that your longest SSE broadcast interval (default: 30sec)',
type: "text",
default_value: "30"
}
],
newInstance: function (settings, newInstanceCallback, updateCallback) {
newInstanceCallback(new sseDatasource(settings, updateCallback));
}
});
/*
Datasource Implementation
*/
var sseDatasource = function (settings, updateCallback) {
var self = this;
var currentSettings = settings;
var eventSource;
var keepAliveTimer = null;
function checkAlive() {
// check if EventSource connection is still alive; if it is, reset the timer, if not, let the timeout force a disconnect/reconnect
if(keepAliveTimer != null) clearTimeout(keepAliveTimer);
var ka;
(currentSettings.keepAliveInterval==undefined) ? ka = 30 : ka = currentSettings.keepAliveInterval;
keepAliveTimer = setTimeout(self.updateNow, ka * 1000);
}
function startSSE() {
// firehose only; refer to #3
eventSource = new EventSource(currentSettings.cloudURL + "/v1/events/" + currentSettings.eventName + "?access_token=" + currentSettings.accessToken);
eventSource.addEventListener('open', function(e) {
switch( e.target.readyState ) {
// if reconnecting
case EventSource.CONNECTING:
console.log("PARTICLESSE_ERR: SSE Reconnecting…");
break;
// if error was fatal
case EventSource.CLOSED:
console.log("PARTICLESSE_ERR: Connection failed. Will not retry.");
break;
}
console.log("PARTICLESSE: Opened new connection for event: " + currentSettings.eventName);
},false);
eventSource.addEventListener('error', function(e) {
switch( e.target.readyState ) {
// if reconnecting
case EventSource.CONNECTING:
console.log("PARTICLESSE_ERR: SSE Reconnecting…");
break;
// if error was fatal
case EventSource.CLOSED:
console.log("PARTICLESSE_ERR: Connection failed. Will not retry.");
break;
}
},false);
eventSource.addEventListener(currentSettings.eventName, function(e) {
// reset the keepAlive interval timer!
checkAlive();
var parsedData = JSON.parse(e.data);
updateCallback(parsedData);
}, false);
}
function disposeSSE() {
// dispose of EventSource SSE connection if it already exists
if(eventSource != undefined) {
console.log("PARTICLESSE: closing connection");
eventSource.close();
eventSource = undefined;
}
}
self.updateNow = function () {
disposeSSE(); // always get rid of previous SSE first
checkAlive();
startSSE();
}
self.onDispose = function () {
disposeSSE();
}
self.onSettingsChanged = function (newSettings) {
currentSettings = newSettings;
self.updateNow();
}
console.log("PARTICLESSE: settings changed, re-initialising");
};
}
());