@skylord123/node-red-pebble-timeline 1.0.1 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"id": "sync-flow-tab",
|
|
4
|
+
"type": "tab",
|
|
5
|
+
"label": "Rebble Timeline Sync",
|
|
6
|
+
"disabled": false,
|
|
7
|
+
"info": "Flow to fetch timeline pins from Rebble sync endpoint"
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
"id": "inject-token",
|
|
11
|
+
"type": "inject",
|
|
12
|
+
"z": "sync-flow-tab",
|
|
13
|
+
"name": "Set Access Token",
|
|
14
|
+
"props": [
|
|
15
|
+
{
|
|
16
|
+
"p": "access_token",
|
|
17
|
+
"v": "YOUR_ACCESS_TOKEN_HERE",
|
|
18
|
+
"vt": "str"
|
|
19
|
+
}
|
|
20
|
+
],
|
|
21
|
+
"repeat": "",
|
|
22
|
+
"crontab": "",
|
|
23
|
+
"once": false,
|
|
24
|
+
"onceDelay": 0.1,
|
|
25
|
+
"topic": "",
|
|
26
|
+
"x": 140,
|
|
27
|
+
"y": 100,
|
|
28
|
+
"wires": [
|
|
29
|
+
["setup-request"]
|
|
30
|
+
]
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"id": "setup-request",
|
|
34
|
+
"type": "function",
|
|
35
|
+
"z": "sync-flow-tab",
|
|
36
|
+
"name": "Setup Request",
|
|
37
|
+
"func": "msg.url = 'https://timeline-sync.rebble.io/v1/sync';\nmsg.headers = {\n 'Authorization': 'Bearer ' + msg.access_token\n};\n\n// Optional: pass timeline/glance cursor for incremental sync\nif (msg.timeline) {\n msg.url += '?timeline=' + msg.timeline;\n if (msg.glance) {\n msg.url += '&glance=' + msg.glance;\n }\n} else if (msg.glance) {\n msg.url += '?glance=' + msg.glance;\n}\n\nreturn msg;",
|
|
38
|
+
"outputs": 1,
|
|
39
|
+
"timeout": "",
|
|
40
|
+
"noerr": 0,
|
|
41
|
+
"initialize": "",
|
|
42
|
+
"finalize": "",
|
|
43
|
+
"libs": [],
|
|
44
|
+
"x": 340,
|
|
45
|
+
"y": 100,
|
|
46
|
+
"wires": [
|
|
47
|
+
["http-request"]
|
|
48
|
+
]
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
"id": "http-request",
|
|
52
|
+
"type": "http request",
|
|
53
|
+
"z": "sync-flow-tab",
|
|
54
|
+
"name": "GET /v1/sync",
|
|
55
|
+
"method": "GET",
|
|
56
|
+
"ret": "obj",
|
|
57
|
+
"paytoqs": "ignore",
|
|
58
|
+
"url": "",
|
|
59
|
+
"tls": "",
|
|
60
|
+
"persist": false,
|
|
61
|
+
"proxy": "",
|
|
62
|
+
"insecureHTTPParser": false,
|
|
63
|
+
"authType": "",
|
|
64
|
+
"senderr": false,
|
|
65
|
+
"headers": [],
|
|
66
|
+
"x": 530,
|
|
67
|
+
"y": 100,
|
|
68
|
+
"wires": [
|
|
69
|
+
["debug-output", "parse-response"]
|
|
70
|
+
]
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
"id": "debug-output",
|
|
74
|
+
"type": "debug",
|
|
75
|
+
"z": "sync-flow-tab",
|
|
76
|
+
"name": "Sync Response",
|
|
77
|
+
"active": true,
|
|
78
|
+
"tosidebar": true,
|
|
79
|
+
"console": false,
|
|
80
|
+
"tostatus": false,
|
|
81
|
+
"complete": "payload",
|
|
82
|
+
"targetType": "msg",
|
|
83
|
+
"statusVal": "",
|
|
84
|
+
"statusType": "auto",
|
|
85
|
+
"x": 740,
|
|
86
|
+
"y": 60,
|
|
87
|
+
"wires": []
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
"id": "parse-response",
|
|
91
|
+
"type": "function",
|
|
92
|
+
"z": "sync-flow-tab",
|
|
93
|
+
"name": "Parse Updates",
|
|
94
|
+
"func": "// Extract updates array and syncURL for next request\nlet response = msg.payload;\n\nif (response.updates && response.updates.length > 0) {\n node.status({fill: 'green', shape: 'dot', text: response.updates.length + ' updates'});\n} else {\n node.status({fill: 'yellow', shape: 'ring', text: 'No updates'});\n}\n\n// Store syncURL for subsequent requests\nmsg.syncURL = response.syncURL;\nmsg.updates = response.updates || [];\n\nreturn msg;",
|
|
95
|
+
"outputs": 1,
|
|
96
|
+
"timeout": "",
|
|
97
|
+
"noerr": 0,
|
|
98
|
+
"initialize": "",
|
|
99
|
+
"finalize": "",
|
|
100
|
+
"libs": [],
|
|
101
|
+
"x": 740,
|
|
102
|
+
"y": 140,
|
|
103
|
+
"wires": [
|
|
104
|
+
["debug-updates"]
|
|
105
|
+
]
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
"id": "debug-updates",
|
|
109
|
+
"type": "debug",
|
|
110
|
+
"z": "sync-flow-tab",
|
|
111
|
+
"name": "Parsed Updates",
|
|
112
|
+
"active": true,
|
|
113
|
+
"tosidebar": true,
|
|
114
|
+
"console": false,
|
|
115
|
+
"tostatus": false,
|
|
116
|
+
"complete": "true",
|
|
117
|
+
"targetType": "full",
|
|
118
|
+
"statusVal": "",
|
|
119
|
+
"statusType": "auto",
|
|
120
|
+
"x": 940,
|
|
121
|
+
"y": 140,
|
|
122
|
+
"wires": []
|
|
123
|
+
}
|
|
124
|
+
]
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@skylord123/node-red-pebble-timeline",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Node-RED nodes for interacting with the Pebble Timeline API",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"node-red",
|
|
@@ -19,7 +19,9 @@
|
|
|
19
19
|
}
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"axios": "
|
|
22
|
+
"axios": "1.12.0",
|
|
23
23
|
"fs-extra": "^11.1.0"
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
|
+
|
|
27
|
+
|
package/pebble-timeline-add.html
CHANGED
|
@@ -115,17 +115,37 @@ module.exports = function(RED) {
|
|
|
115
115
|
if (done) done();
|
|
116
116
|
})
|
|
117
117
|
.catch(error => {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
118
|
+
// Handle 404 - pin already deleted
|
|
119
|
+
if (error.response && error.response.status === 404) {
|
|
120
|
+
node.warn(`Pin ${pinId} not found on server (404) - assuming already deleted`);
|
|
121
|
+
node.status({fill: "yellow", shape: "dot", text: "Pin already deleted"});
|
|
122
|
+
|
|
123
|
+
// Remove from local storage anyway
|
|
124
|
+
removePin(pinId, timelineToken);
|
|
125
|
+
|
|
126
|
+
msg.payload = {
|
|
127
|
+
success: true,
|
|
128
|
+
pinId: pinId,
|
|
129
|
+
alreadyDeleted: true,
|
|
130
|
+
message: "Pin not found on server, removed from local storage"
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
send(msg);
|
|
134
|
+
if (done) done();
|
|
135
|
+
} else {
|
|
136
|
+
// Other errors
|
|
137
|
+
node.status({fill: "red", shape: "dot", text: "Error: " + (error.response ? error.response.status : error.message)});
|
|
138
|
+
|
|
139
|
+
msg.payload = {
|
|
140
|
+
success: false,
|
|
141
|
+
pinId: pinId,
|
|
142
|
+
error: error.message,
|
|
143
|
+
response: error.response ? error.response.data : null
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
send(msg);
|
|
147
|
+
if (done) done(error);
|
|
148
|
+
}
|
|
129
149
|
});
|
|
130
150
|
}).catch(err => {
|
|
131
151
|
if (done) done(err);
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
label: function () {
|
|
27
27
|
return this.name || "List Timeline Pins";
|
|
28
28
|
},
|
|
29
|
+
paletteLabel: "List Timeline Pins",
|
|
29
30
|
oneditprepare: function () {
|
|
30
31
|
// Setup TypedInput for server override options
|
|
31
32
|
$("#node-input-apiUrl").typedInput({
|
|
@@ -107,7 +108,7 @@
|
|
|
107
108
|
</script>
|
|
108
109
|
|
|
109
110
|
<script type="text/html" data-help-name="pebble-timeline-list">
|
|
110
|
-
<p>Lists pins that
|
|
111
|
+
<p>Lists pins from the local storage file that tracks pins added via Node-RED.</p>
|
|
111
112
|
|
|
112
113
|
<h3>Inputs</h3>
|
|
113
114
|
<dl class="message-properties">
|
|
@@ -128,9 +129,13 @@
|
|
|
128
129
|
</dl>
|
|
129
130
|
|
|
130
131
|
<h3>Details</h3>
|
|
131
|
-
<p>This node
|
|
132
|
-
|
|
133
|
-
<p>
|
|
132
|
+
<p><strong>Important:</strong> This node does <strong>not</strong> fetch pins from the remote Pebble Timeline server.
|
|
133
|
+
Instead, it reads from a local file (<code>timeline-pins.json</code>) stored in the Node-RED user directory.</p>
|
|
134
|
+
<p>The local file is automatically updated whenever you use the <strong>pebble-timeline-add</strong> or
|
|
135
|
+
<strong>pebble-timeline-delete</strong> nodes. This provides a local record of pins that have been
|
|
136
|
+
added or removed via Node-RED.</p>
|
|
137
|
+
<p>Pins are organized by timeline token in the storage file. Only pins associated with the current timeline
|
|
138
|
+
token will be listed. Each token maintains its own separate list of pins.</p>
|
|
134
139
|
<p>You can filter the pins by start and end times. The times should be in ISO date-time format (e.g.,
|
|
135
140
|
2023-01-01T12:00:00Z).</p>
|
|
136
141
|
<p>By default, if no filters are specified, all pins for the current token will be returned.</p>
|
|
@@ -138,9 +143,10 @@
|
|
|
138
143
|
|
|
139
144
|
<h4>Example Use Cases</h4>
|
|
140
145
|
<ul>
|
|
141
|
-
<li>List all upcoming events for the day</li>
|
|
146
|
+
<li>List all upcoming events for the day that were added via Node-RED</li>
|
|
142
147
|
<li>Filter pins for a specific date range for reporting</li>
|
|
143
148
|
<li>Show pins for a specific event type based on time criteria</li>
|
|
149
|
+
<li>Track what pins have been sent to the Pebble Timeline</li>
|
|
144
150
|
</ul>
|
|
145
151
|
|
|
146
152
|
<h3>References</h3>
|