The ParticleBot integrates with Particle.io to import your Core, Photon, Electron and Bluz devices.
Each of your Particle.io devices are automatically mapped to a new device in Tinamous, this allows you to record sensor measurements, receive status posts and call functions on the device. You can also monitor the device status and receive notifications when it is down.
The Tinamous ParticleBot does not store your Particle.io password, instead an authentication token is generated from Particle.io that the bot stores and uses that to connect. The token is set to never expire, you should revoke it at Particle.io if you need to.
Particle Bot reads variables from your device and imports those as sensor measurement with the fields set from the variable names.
Expose variables in your Particle code in the setup() method. e.g. This exposes a cpm variable:
void setup() { Particle.variable("cpm", cpm); }
Use published events from your Particle device to create status messages on your Tinamous timeline or add sensor measurements.
Use Particle.publish(eventName, data) or preferable Particle.publish(eventName, data, ttl, PRIVATE) method to publish events to Tinamous.
Using event publishing has the advantage that your device controls when data is pushed to Tinamous so you can publish data only when it has changed, or on a different frequency and as many fields as you like.
Both Particle variables and publishing can be used on the same device. You may for example wish to set a variable for battery level and publish temperature. You can set Tinamous to read the battery level hourly and publish a temperature only when it has changed, this would provide a responsive feedback for temperature without needing frequent lookups on the device and only occasional read from the device to monitor the battery level which is unlikely to change often.
Note that by default the Particle.publish() method publishes data to the public stream, use the private option to ensure it is kept private.
Particle.publish("status", "Hello World!", 60, PRIVATE);
Supported event names:
Read more about Particle.publish() at the Particle.io reference page.
Status messages appear on the Timeline and can be useful to check on the device, if it is alive, if it needs to tell you something etc. You can also send notifications based on a status message.
To publish a status message use simple string data with as status event name:
Particle.publish("Status","Geiger setup complete. V1.0.2");The ParticleBot will watch for status events and put these events on the Timeline. You can also use non-"status" publishing by setting "Treat published events with non-numeric data as status posts." in the device Particle Settings configuration.
Published sensor measurements are stored and graphed on the device page. Sensor measurements can be published in a variety of formats.
Supported Event Names:
To publish measurements in the SenML (Sensor Markup) format:
Particle.publish("senml", "{e:[{'n':'LightLevel','v':'" + String(ambientLight) + "'},{'n':'Red','v':'" + String(redLevel) + "'},{'n':'Green','v':'" + String(greenLevel) + "'},{'n':'Blue','v':'" + String(blueLevel) + "'}]}");which results in a document looking like:
{e:[{'n':'LightLevel','v':'22'},{'n':'Red','v':'33'},{'n':'Green','v':'44'},{'n':'Blue','v':'55'}]}The time property of senml is not currently supported, all measurements are assumed to be real-time and the time is set to the current (utc) time on receipt of the event. If your devices measurements are not appearing on the device chart, check the event stream on the device page for Invalid SenML messages.
To publish measurements as simple json:
Particle.publish("json", "{'LightLevel': '" + String(ambientLight) + "','Humidity': '"+ String(redLevel) + "'}");This creates a measurement with fields LightLevel and Humidity, the formated document should look like:
{'LightLevel':'25', 'Humidity':'59'}
Simple measurement publishing: By default simple measurements are ignored, to enable them edit the Particle Bot, under "Particle Settings" enable "Treat published events with numeric data as measurements."
Particle.publish("Humidity", 53);
Tinamous tracks sensor fields automatically and will add new ones on the device when published. You don't need to do any configuration in Tinamous for your measurements to appear on the device charts. If you publish in the senml format you can also add units to the published message, these will be assigned to the field in Tinamous. For other formats you can manually set the units as you desire.
Published geo-coordinates can be used to set the devices location. This can be useful if you wish to track a device or assign sensor measurements to a location (e.g. mobile pollution monitoring).
When a devices location is set, this is stored and sensor measurements published have this location assigned to them.
Please note: Due to licensing restrictions it is not possible to use the location map as an asset tracker. You can however use the Tinamous API to retreive device location history and create your own asset tracker using other mapping solutions.
Supported Event Names:
Example:
AssetTracker t = AssetTracker(); void setup() { t.begin(); t.gpsOn(); } void loop() { t.updateGPS(); if (t.gpsFix()) { Particle.publish("G", t.readLatLon(), 60, PRIVATE); } // Wait 5 seconds before the next measurement/publish. // You would probably want a much larger time between points. delay(5000); }You will need to refresh the device page for the location map to appear for the first time, but you should then be able to see the devices location on the map.
You can also use a location within a sensor measurement. To publish measurements as json with a gps location:
Particle.publish("json", "{'LightLevel': '" + String(ambientLight) + "','Humidity': '"+ String(redLevel) + "','GPS': '"+ t.readLatLon() + "'}");This creates a measurement with fields LightLevel, Humidity and GPS, the formated document should look like:
{'LightLevel':'25', 'Humidity':'59','GPS':'0.123454,52.98765'}
Special fields in published measurements and device variables may be used to add meta-data to measurements. These inc:
Currently ParticleBot does not currently support raising alerts directly. If you need an alert you can trigger one from a status message using Notifications.
Using particle.function() you can create a function that is callable via the Internet. This can then be invoked through Tinamous.
You can see the functions exposed by your Particle device on the devices page. Select the Particle section, the Functions are listed in here. You can then click the "Invoke" button to call that function with the parameters specified.
Functions can also be invoked automatically via Notifications. For example if a Status Post with the message "It's hot in here" is raised this can be used to trigger a Photon controlled fan to switch the fan on.
To configure a function on your device, call Particle.function(name, method) in the setup method with the function name and a reference to the function implementation. The below code exposes 2 functions "fanOn" and "fanOff". The return value of these will be shown in the Tinamous UI and can be useful to determine that the function has done what you are expecting.
// Define the function headers. int fanOn(String command); int fanOff(String command); void setup() { Particle.function("fanOn", fanOn); Particle.function("fanOff", fanOff); } // Particle Function int fanOn(String command) { Particle.publish("Status", "Switching fan on for 10 minutes."); // On for 10 mins (6 iterations per min) setFan(10 * 6); return 10*6; } // Particle Method int fanOff(String command) { Particle.publish("Status", "Switching fan off."); // On for 0 iterations setFan(0); return 0; }
Read more about Particle.function() at the Particle.io reference page.
Add Alexa SmartHome functionality to your devices with only a few lines of code on your Particle Device using the Tinamous SmartHome Alexa Skill.
e.g. "Alexa, Turn On Photon One"
To support Alexa SmartHome directives you need to add a little code to your device and apply some tags to the device in Tinamous.
The skill is currently only available in the UK Skill Store, but coming to more stores soon. If you want to adapt or improve the skill the full sorce is available in the Tinamous GitHub Repository.
// Currently only °C is supported. float temperature = 12.3f; void setup() { Particle.variable("temperature", temperature); // Or use publish to push the temperature value out // Particle.publish("json", "{'temperature': " + String(temperature) + "}"); }Temperature is readonly, no functions are needed. Alexa.PercentageController
NB: If Alexa.BrightnessController is also implmented Alexa will send a brightness command not percentage.
int percentage; // 0..100 void setup() { Particle.variable("percentage", percentage); // or publish the value as and when needed. // Particle.publish("json", "{'percentage': " + String(percentage) + "}"); Particle.function("SetPercent", setPercentage); Particle.function("AdjPercent", adjustPercentage); } int setPercentage(String args) { // args will be "90" or "90 port-1", "90 port-2", etc. percentage = args.toInt(); return percentage; } int adjustPercentage(String args) { // args will be "10" or "10 port-1", "10 port-2", etc. percentage += args.toInt(); return percentage; }Example Status Posts Alexa will post:
int brightnessPercentage = 0; // 0..100 void setup() { Particle.variable("brightness", brightnessPercentage); // or publish the value as and when needed. // Particle.publish("json", "{'brightness': " + String(brightnessPercentage) + "}"); Particle.function("SetBright", setBrightness); Particle.function("AdjBright ", adjustBrightness ); } int setBrightness(String args) { // args will be "90" or "90 port-1", "90 port-2", etc. brightnessPercentage = args.toInt(); return brightnessPercentage; } int adjustBrightness(String args) { // args will be "10" or "10 port-1", "10 port-2", etc. brightnessPercentage += args.toInt(); return brightnessPercentage; }Example Status Posts the Alexa skill will post:
String color; // HSV/HSB Format: "240,0.5,0.1" void setup() { Particle.variable("color", color); // or publish the value as and when needed. // Particle.publish("json", "{'color': '" +color + "'}"); Particle.function("SetColor", setColor); } int setColor(String args) { // args will be "240,0.7, 0.9" or "240,0.7, 0.9 port-1", "240,0.7, 0.9 port-2", etc. // Maps to HSV (Hue: 0-255, Saturation: 0-1, Value/Brightness: 0-1) color = args; return 1; }Example Status Posts the Alexa skill will post:
bool powerState = false; void setup() { Particle.variable("powerState", powerState); // or publish the value as and when needed. // Particle.publish("json", "{'brightness': '" + String(powerState) + "'}"); Particle.function("TurnOn", turnOn); Particle.function("TurnOff ", turnOff ); } int turnOn(String args) { // args will either be empty, or contain "port-1", "port-2" or... powerState = true; return 1; } int turnOff(String args) { // args will either be empty, or contain "port-1", "port-2" or... powerState = false; return 0; }Example Status Posts the Alexa skill will post:
NB: If Alexa.BrightnessController is also implmented Alexa will send a brightness command not powerlevel.
int powerLevelPercentage; // 0-100 void setup() { Particle.variable("powerLevel", powerLevelPercentage); // or publish the value as and when needed. // Particle.publish("json", "{'powerLevel': '" + String(powerLevel) + "'}"); Particle.function("SetPower", setPowerLevel); Particle.function("AdjPower", adjustPowerLevel); int setPowerLevel(String args) { // args will be "90" or "90 port-1", "90 port-2", etc. powerLevelPercentage = args.toInt(); return powerLevelPercentage; } int adjustPowerLevel(String args) { // args will be "10" or "10 port-1", "10 port-2", etc. powerLevelPercentage += args.toInt(); return powerLevelPercentage; }Example Status Posts the Alexa skill will post:
Not Implemented
Alexa.SceneControllerNot Implemented
Alexa.ThermostatControllerNot Implemented