Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
chuank committed Oct 8, 2018
2 parents 6969ac6 + 10e2ddd commit f1ac65c
Show file tree
Hide file tree
Showing 3 changed files with 169 additions and 157 deletions.
60 changes: 43 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,43 +15,69 @@ Four separate nodes are provided to interact with Particle Devices – call a Fu

Where appropriate, the OUTPUT provides returned data from the Particle Cloud after a query has been made.

You can also set up multiple cloud connections if you are running a standalone cloud server (`spark-server`). As development on `spark-server` seems to have stalled, you'll need to work out the
You can also set up multiple cloud connections if you are running a standalone cloud server (`spark-server`). As development on `spark-server` seems to have stalled, you'll need to explore forks done by other members of the community.

Please refer to the help sidebar in node-RED for full details on each node.

Basic Example
-------------

Write something similar to this in your Particle Build code:
Example: Publish & SSE
----------------------

Import the following into Node-RED using __Menu > Import > Clipboard__. Complete cloud configuration and access token before testing. If everything is correctly configured, the Particle SSE node should print out the timestamp of the server in the debug sidebar when you click on the Inject button, which publishes a private event to the Particle Cloud.

```
[{"id":"4e1ed5ee.a82c0c","type":"ParticleSSE in","z":"1bba2c1b.324be4","pcloud":"70ab2f2a.25f9b","evtname":"myEvent","devid":"","consolelog":false,"x":560,"y":160,"wires":[["d0201000.a0de7"]]},{"id":"5141baba.30e574","type":"inject","z":"1bba2c1b.324be4","name":"","topic":"myEvent","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":200,"y":80,"wires":[["80bfead3.defba8"]]},{"id":"d0201000.a0de7","type":"debug","z":"1bba2c1b.324be4","name":"result","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":720,"y":160,"wires":[]},{"id":"80bfead3.defba8","type":"ParticlePublish out","z":"1bba2c1b.324be4","pcloud":"70ab2f2a.25f9b","evtname":"myEvent","evtnametopic":true,"param":"","private":true,"ttl":60,"once":false,"repeat":"0","consolelog":true,"x":460,"y":80,"wires":[[]]},{"id":"70ab2f2a.25f9b","type":"particle-cloud","z":"","host":"https://api.particle.io","port":"443","accesstoken":"__PWRD__","name":"Particle.io"}]
```


Example: Function & Variables
-----------------------------

Upload this to your Photon:

```
int aValue = 0;
void setup() {
pinMode(D7, OUTPUT);
Particle.function("doLED", doLED);
Particle.variable("aValue", aValue);
}
void loop() {
Particle.publish("randomnumber", String(random(100)), PRIVATE);
delay(10000);
// assume you have an analog sensor attached to A0:
aValue = analogRead(A0);
}
```
In node-RED, drop a Particle SSE node into the workspace, and connect a debug node to view the output:
int doLED(String cmd) {
bool ledState = atoi(cmd);
digitalWrite(D7, ledState)
}
```

_[todo: image]_
In Node-RED, import the following from __Menu > Import > Clipboard__ (don't forget to set your device name and access tokens):

```
[{"id":"2244ae44.fdc752","type":"ParticleFunc out","z":"1bba2c1b.324be4","pcloud":"70ab2f2a.25f9b","devid":"myDevice","fname":"doLED","param":"","once":false,"repeat":"0","consolelog":false,"x":390,"y":420,"wires":[["139a92b1.04c17d"]]},{"id":"eadbd74f.855928","type":"inject","z":"1bba2c1b.324be4","name":"LED on","topic":"param","payload":"1","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":190,"y":400,"wires":[["2244ae44.fdc752"]]},{"id":"39b5dce1.62e274","type":"inject","z":"1bba2c1b.324be4","name":"LED off","topic":"param","payload":"0","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":190,"y":440,"wires":[["2244ae44.fdc752"]]},{"id":"139a92b1.04c17d","type":"debug","z":"1bba2c1b.324be4","name":"result","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"payload","x":590,"y":420,"wires":[]},{"id":"e04e2652.0b7388","type":"ParticleVar","z":"1bba2c1b.324be4","pcloud":"70ab2f2a.25f9b","devid":"myDevice","getvar":"aValue","once":false,"repeat":0,"consolelog":false,"x":380,"y":540,"wires":[["7a3f926a.5d0b3c"]]},{"id":"283e0e5c.9a54c2","type":"inject","z":"1bba2c1b.324be4","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":180,"y":540,"wires":[["e04e2652.0b7388"]]},{"id":"7a3f926a.5d0b3c","type":"debug","z":"1bba2c1b.324be4","name":"result","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"payload","x":590,"y":540,"wires":[]},{"id":"70ab2f2a.25f9b","type":"particle-cloud","z":"","host":"https://api.particle.io","port":"443","accesstoken":"__PWRD__","name":"Particle.io"}]
```

Remember to configure the Particle node by adding your own Particle configuration credentials and access token.
You should be able to turn the built-in D7 LED on your Photon on/off. The second flow allows you to print out aValue, which is reading off the A0 pin.

View the results via the debug node.


FAQ
---

**Are these nodes the same thing as the Particle IoT Rules Engine?**
Conceptually, they are identical. `node-red-contrib-particle` has been around as an open-source project and maintained since 2015, when Node-RED was still in its early stages. From the documentation, it appears that the Particle nodes offered in the IoT Rules Engine node possess very similar node configuration options for each Particle node. The Particle IoT Rules Engine is a separate product delivered by Particle.io that runs atop a customised Node-RED framework. `node-red-contrib-particle` here can be installed on any Node-RED setup, is free, open-source and welcomes PRs, but requires knowledge on setting up your own (read: make it secure!) Node-RED environment.
Conceptually, they are identical. `node-red-contrib-particle` has been around as an open-source project and maintained since 2015, when Node-RED was still in its early stages. From the IoT Rules Engine documentation, it appears that the Particle nodes offered in the IoT Rules Engine node possess very similar features and configuration options for each Particle node. The Particle IoT Rules Engine is a separate product delivered by Particle.io that runs atop a customised Node-RED framework.

`node-red-contrib-particle` is intended to be installed on any Node-RED setup, is free, open-source and welcomes PRs, but requires knowledge on setting up your own (read: make it secure!) Node-RED environment.

**I keep getting an Error in the ParticleSSE node!**
It's likely your Particle.io access token is incorrect. Regenerate a new token in build.particle.io, and try again with the new token in the configuration node.

**ParticleFunc/ParticleVar/ParticlePublish seems slow and laggy**
Bear in mind the throttling limits for Particle event publishing. While the limit of ["1 event/sec with bursts of up to 4 allowed in 1 second"](https://docs.particle.io/reference/firmware/raspberry-pi/#particle-publish-) is embedded within the device firmware itself, the Particle Cloud server also applies its own throttling limits on the server side. Unless you have a very fast connection to the Particle Cloud server (or your own local spark-server), you have to expect the inherent latency for round trips between your Particle device, the Particle Cloud and your Node-RED server. This can also be completely circumvented by hosting your own `spark-server` with rate limits disabled, as with the same throttling limits removed from your Particle system firmware. The scope of this is beyond what this FAQ can offer; look around to find out how it can be done.
Bear in mind the throttling limits for Particle event publishing. While the limit of ["1 event/sec with bursts of up to 4 allowed in 1 second"](https://docs.particle.io/reference/firmware/raspberry-pi/#particle-publish-) is embedded within the device firmware itself, the Particle Cloud server also applies its own throttling limits on the server side. Unless you have a very fast connection to the Particle Cloud server (or you are running your own local `spark-server`), expect the inherent latency for round trips between your Particle device, the Particle Cloud and your Node-RED server. This can also be circumvented by hosting your own `spark-server` with rate limits disabled, as with the same throttling limits removed from your Particle system firmware. The scope of this is beyond what this FAQ can offer; look around to find out how it can be done.


Local Cloud and SSE Limitations
Expand All @@ -71,13 +97,13 @@ Refer to the [official Particle documentation on the Cloud API](https://docs.par
Credits
-------

This is a forked project that built off @krvarma's `node-red-contrib-sparkcore` initial work (0.0.12).
This is a forked project that built off @krvarma's `node-red-contrib-sparkcore` initial work (v0.0.12).

Additional features implemented since `node-red-contrib-particle 0.0.2+` by @chuank:
Additional features implemented since `node-red-contrib-particle v0.0.2+` by @chuank:
* local cloud SSE (limited) support
* configuration node implementation
* configuration node & credentials
* dynamic property setting
* implementation of separate nodes for clarity
* renaming to Particle and other cosmetic fixes.

0.0.9 introduced the ParticleFunc node for calling Particle functions from Node-RED (@techlemur)
v0.0.9: introduced the ParticleFunc node for calling Particle functions from Node-RED (@techlemur)
42 changes: 21 additions & 21 deletions particle/particle.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
<!-- Particle CONFIGURATION node -->
<script type="text/x-red" data-template-name="particle-cloud">
<div class="form-row">
<label for="node-config-input-host"><i class="fa fa-server"></i> Cloud URL</label>
<label for="node-config-input-host"><i class="fa fa-cloud"></i> Cloud URL</label>
<input class="input-append-left" type="text" id="node-config-input-host" placeholder="IP or hostname" style="width:40%;">
<label for="node-config-input-port" style="margin-left: 10px; width: 35px; "> Port</label>
<input type="text" id="node-config-input-port" placeholder="8080" style="width:45px">
<input type="text" id="node-config-input-port" placeholder="443" style="width:45px">
</div>
<div class="form-row">
<label for="node-config-input-accesstoken"><i class="fa fa-key"></i> Access Token</label>
Expand All @@ -32,7 +32,7 @@
accesstoken: {type: "password"}
},
label: function() {
return this.name || this.baseurl + ":" + this.port;
return this.name || this.host + ":" + this.port;
},
oneditprepare: function() {
$.getJSON("particlecloud/"+this.id,function(data) {
Expand Down Expand Up @@ -74,8 +74,8 @@
<!-- Edit Dialog -->
<script type="text/x-red" data-template-name="ParticleSSE in">
<div class="form-row">
<label for="node-input-baseurl"><i class="fa fa-server"></i> Cloud URL</label>
<input type="text" id="node-input-baseurl">
<label for="node-input-pcloud"><i class="fa fa-cloud"></i> Cloud URL</label>
<input type="text" id="node-input-pcloud">
</div>
<div class="form-row">
<label for="node-input-devid"><i class="fa fa-bullseye"></i> Device ID/Name</label>
Expand Down Expand Up @@ -120,7 +120,7 @@ <h4>Node Properties</h4>
<code>Cloud URL</code></br>
<p>Add or choose an existing Particle cloud configuration.</p>
<code>Device ID/Name</code></br>
<p>Enter a Device ID or Name of the target Particle Device to subscribe to. For local clouds, device-specific and device-and-event specific events are <a href="https://github.com/spark/spark-server/issues/53" target="_blank">currently not supported</a>. For local cloud setups, you can a) leave the <em>Device ID/Name</em> empty, with the <em>Event Name</em> entered, or b) leave both fields empty to get the public event firehose. Filter this result in Node-RED by writing your own function.</p>
<p>Enter a Device ID or Name of the target Particle Device to subscribe to. For local clouds, device-specific and device-and-event specific events are <a href="https://github.com/spark/spark-server/issues/53" target="_blank">currently not supported</a>. For local cloud setups, you can a) leave the <em>Device ID/Name</em> empty, with the <em>Event Name</em> entered, or b) leave both fields empty to get the public event firehose. Filter this result in Node-RED by writing your own Function.</p>
<code>Event</code></br>
<p>Enter the SSE name broadcast by your Particle device (via <a href="https://docs.particle.io/reference/firmware/photon/#particle-publish-" target="_blank">Particle.publish()</a>).</p>
<code>Verbose logging?</code></br>
Expand All @@ -140,7 +140,7 @@ <h3>References</h3>
RED.nodes.registerType("ParticleSSE in", {
category: "Particle",
defaults: {
baseurl: {value:"", type:"particle-cloud"},
pcloud: {value:"", type:"particle-cloud"},
evtname: {value:"", required:true},
devid: {value:""},
consolelog: {value:false}
Expand Down Expand Up @@ -177,8 +177,8 @@ <h3>References</h3>
<!-- Edit Dialog -->
<script type="text/x-red" data-template-name="ParticlePublish out">
<div class="form-row">
<label for="node-input-baseurl"><i class="fa fa-server"></i> Cloud URL</label>
<input type="text" id="node-input-baseurl">
<label for="node-input-pcloud"><i class="fa fa-cloud"></i> Cloud URL</label>
<input type="text" id="node-input-pcloud">
</div>
<div class="form-row">
<label for="node-input-evtname"><i class="icon-tag"></i> Event</label>
Expand Down Expand Up @@ -273,7 +273,7 @@ <h3>References</h3>
RED.nodes.registerType("ParticlePublish out", {
category: "Particle",
defaults: {
baseurl: {value:"", type:"particle-cloud"},
pcloud: {value:"", type:"particle-cloud"},
evtname: {value:""},
evtnametopic: {value:false},
param: {value:"", validate:function(v) { return v.length < 64; } },
Expand Down Expand Up @@ -312,8 +312,8 @@ <h3>References</h3>
<!-- Edit Dialog -->
<script type="text/x-red" data-template-name="ParticleFunc out">
<div class="form-row">
<label for="node-input-baseurl"><i class="fa fa-server"></i> Cloud URL</label>
<input type="text" id="node-input-baseurl">
<label for="node-input-pcloud"><i class="fa fa-cloud"></i> Cloud URL</label>
<input type="text" id="node-input-pcloud">
</div>
<div class="form-row">
<label for="node-input-devid"><i class="fa fa-bullseye"></i> Device ID/Name</label>
Expand Down Expand Up @@ -398,12 +398,12 @@ <h3>References</h3>
RED.nodes.registerType("ParticleFunc out",{
category: "Particle",
defaults: {
baseurl: {value:"", type:"particle-cloud"},
devid: {value:"", required:true},
fname: {value:"", required:true, validate:function(v) { return v.length < 13; } },
param: {value:""},
once: {value:false},
repeat: {value:0, validate:function(v) { return v >= 0; } },
pcloud: {value:"", type:"particle-cloud"},
devid: {value:"", required:true},
fname: {value:"", required:true, validate:function(v) { return v.length < 13; } },
param: {value:""},
once: {value:false},
repeat: {value:0, validate:function(v) { return v >= 0; } },
consolelog: {value:false}
},
color:"#00ACED",
Expand Down Expand Up @@ -436,8 +436,8 @@ <h3>References</h3>
<!-- Edit Dialog -->
<script type="text/x-red" data-template-name="ParticleVar">
<div class="form-row">
<label for="node-input-baseurl"><i class="fa fa-server"></i> Cloud URL</label>
<input type="text" id="node-input-baseurl">
<label for="node-input-pcloud"><i class="fa fa-cloud"></i> Cloud URL</label>
<input type="text" id="node-input-pcloud">
</div>
<div class="form-row">
<label for="node-input-devid"><i class="fa fa-bullseye"></i> Device ID/Name</label>
Expand Down Expand Up @@ -515,7 +515,7 @@ <h3>References</h3>
RED.nodes.registerType("ParticleVar",{
category: "Particle",
defaults: {
baseurl: {value:"", type:"particle-cloud"},
pcloud: {value:"", type:"particle-cloud"},
devid: {value:"", required:true},
getvar: {value:"", required:true, validate:function(v) { return v.length < 13; } },
once: {value:false},
Expand Down
Loading

0 comments on commit f1ac65c

Please sign in to comment.