In many cases, you need to develop a mock-up of a web app interacting with your smart object. A convenient way is to use PROTOSHARE



This tool allows you to design pretty complex UI and to link components (1. button in the picture) to instances of node-red on which the app logic actually run. Notice that to test the UI you have to click on the open in viewer link (2.)
We will use node-red-contrib-web-worldmap

To access the service go to http://127.0.0.1:1880/worldmap/

There are a number of services providing persistence in a simple way, such as firebase or parse, just to mention few of them. Actually both of them are much more than persistence services!!!

However, for the sake of simplicity, here we will use json-db-node-red

In this simple example, the json data from openweather are stored in the JsonDB


The following is the content of the .json file under ~/.node-red/JsonDB/.json

{"prova":{"weather":"Clouds","detail":"scattered clouds","tempk":289.399,"tempc"
:16.1,"humidity":91,"maxtemp":289.399,"mintemp":289.399,"windspeed":4.23,"winddi
rection":125.006,"location":"Trevi","sunrise":1462766140,"sunset":1462817874,"cl
ouds":44,"description":"The weather in Trevi at coordinates: 41.9, 12.49 is Clou
ds (scattered clouds)."}}

As you can see the path prova, specified as a parameter of the JsonDB, is  the JSON object. To access the fields is sufficient to write msg.payload.<name of the properiy> as an example msg.payload.weather will return Clouds.
1. Go to http://openweathermap.org/price and click on "Get API KEY and Start"


2. Follow the procedure to register and copy the API Key




4. Use the new node as in the picture below





// if the variable current_input1 exists it get the current values 
// otherwise it sets it to 0
var current_input1 = context.get("store_of_current_input1") || 0;
// if the variable current_input2 exists it get the current values 
// otherwise it sets it to 0
var current_input2 = context.get("store_of_current_input2") || 0;

// if the current message is of topic input1
if (msg.topic === "input1"){
    // set the variable current_input1 to the value in the 
    //msg.payload
    current_input1 = parseInt(msg.payload);
    // update the value of  the variable store_of_current_input1 
    //to the value of  current_input1
    context.set(("store_of_current_input1"),current_input1);

}

// if the current message is of topic input2
if (msg.topic === "input2"){
    // set the variable current_input2 to the value in the 
    //msg.payload
    current_input2 = parseInt(msg.payload);
    // update the value of  the variable store_of_current_input2  
    // to the value of  current_input2
    context.set(("store_of_current_input2"),current_input2);

}
  
// check if the condition holds

if (current_input1>10 && current_input2>10 ){
    msg.payload="alto";
}
else{
    msg.payload="basso";
}
return msg;




[{"id":"1b3c741.5f3e88c","type":"function","z":"967e1482.589018","name":"","func":"var current_input1 = context.get(\"store_of_current_input1\") || 0;\nvar current_input2 = context.get(\"store_of_current_input2\") || 0;\n\nif (msg.topic === \"input1\"){\n    current_input1 = parseInt(msg.payload);\n    context.set((\"store_of_current_input1\"),current_input1);\n\n}\n\nif (msg.topic === \"input2\"){\n    current_input2 = parseInt(msg.payload);\n    context.set((\"store_of_current_input2\"),current_input2);\n}\n    \n\n\nif (current_input1>10 && current_input2>10 ){\n    msg.payload=\"alto\";\n}\nelse{\n    msg.payload=\"basso\";\n}\nreturn msg;","outputs":1,"noerr":0,"x":369,"y":364,"wires":[["ea4b7c90.e24d7"]]}]
This simple flow checks whether the Input1 value is greater then 10. If yes it prints out the value alto, otherwise the value basso. 


Notice that since msg.payload is a string it must be parsed into an Integer to check if the condition holds.


if (parseInt(msg.payload)>10){
    msg.payload="alto";
}
else{
    msg.payload="basso";
}
return msg;

[{"id":"4f4135f7.fc1a5c","type":"ui_tab","z":"912f565f.b221e8","name":"Basic","icon":"dashboard","order":"1"},{"id":"301cc185.91e06e","type":"ui_text_input","z":"912f565f.b221e8","tab":"4f4135f7.fc1a5c","mode":"text","delay":300,"name":"Input1","topic":"","group":"","order":1,"x":152,"y":290,"wires":[["f680c1ca.0088e"]]},{"id":"f680c1ca.0088e","type":"function","z":"912f565f.b221e8","name":"Check Input1 >","func":"if (parseInt(msg.payload)>10){\n    msg.payload=\"alto\";\n}\nelse{\n    msg.payload=\"basso\";\n}\nreturn msg;","outputs":1,"noerr":0,"x":358,"y":290,"wires":[["a888e7e3.b61418"]]},{"id":"a888e7e3.b61418","type":"ui_text","z":"912f565f.b221e8","tab":"4f4135f7.fc1a5c","name":"Out","group":"","order":1,"format":"{{msg.payload}}","x":566,"y":291,"wires":[]}]


  • You have a virtual sensor at home providing data on  temperature (T) at regular intervals (SENSE)
  • Your local intelligence is the following (THINK)
    • if  T>TTh switch on the virtual air conditioning (ACT)
    • Notice that the thresholds TTh are initially set to arbitrary values 
  • The current value of T is delivered to a central server that builds the distribution of the collected temperature in the form of an histogram
  • If the mean M of the histogram is changed by 1% thens the threshold is set to the new mean

  • You have a virtual sensor at home providing data on humidity (H) and temperature (T) at regular intervals (SENSE)
  • Your local intelligence is the following (THINK)
    • if H>HTh and T>TTh switch on the virtual air conditioning (ACT)
    • Notice that the thresholds HTh and TTh are initially set to arbitrary values 
  • In the meanwhile you have a server running sentiment analysis to verify whether people  is actually confortable by the given thresholds
    • if sentiment positive then nothing
    • if AVERAGE sentiment negative then send a command over the Internet to your sensor at home to decrease HTh and TTh
    • For the sake of simplicity run sentiment analysis on the word "temperature"

NODE-RED FLOW

[{"id":"47daa254.fdd9dc","type":"dweetio in","z":"efcf45e2.677f98","thing":"papa_give_me_a_hammer","name":"Com RX by dweet","x":730.25,"y":186,"wires":[["1746c24.f5a653e"]]},{"id":"1746c24.f5a653e","type":"debug","z":"efcf45e2.677f98","name":"Actuate Time in your Room","active":false,"console":"false","complete":"payload","x":1026.250015258789,"y":52,"wires":[]},{"id":"55dd56bb.717278","type":"comment","z":"efcf45e2.677f98","name":"https://dweet.io/","info":"Ridiculously simple messaging (and alerts) for the Internet of Things.","x":618,"y":67,"wires":[]},{"id":"2aa86258.08aebe","type":"inject","z":"efcf45e2.677f98","name":"Sense Time in my Room","topic":"","payload":"Ciao funge?","payloadType":"str","repeat":"2","crontab":"","once":false,"x":222.5,"y":62.5,"wires":[["f2e262c4.559cc"]]},{"id":"f2e262c4.559cc","type":"dweetio out","z":"efcf45e2.677f98","thing":"papa_give_me_a_hammer","name":"Com TX by dweet","x":495.25000762939453,"y":185.25000190734863,"wires":[]}]

NODE-RED FLOW

[{"id":"d841eafa.45c728","type":"inject","z":"51acd361.27dd1c","name":"Sense Temp","topic":"temp","payload":"5","payloadType":"num","repeat":"","crontab":"","once":false,"x":193.25,"y":212.50000286102295,"wires":[["49d1d538.a03a1c"]]},{"id":"a5898d5e.54668","type":"inject","z":"51acd361.27dd1c","name":"Sense Hum","topic":"hum","payload":"3","payloadType":"num","repeat":"","crontab":"","once":false,"x":196,"y":364,"wires":[["49d1d538.a03a1c"]]},{"id":"49d1d538.a03a1c","type":"function","z":"51acd361.27dd1c","name":"Think","func":"// initialise the counter to 0 if it doesn't exist already\n// http://nodered.org/docs/writing-functions.html\n\nvar hum = context.get('hum')||false;\nvar temp = context.get('temp')||false;\n\nmsg.payload=\"false\";\n\nif (msg.topic==\"hum\"){\n    context.set('hum',true);\n    hum = true;\n}\n    \nif (msg.topic==\"temp\"){\n    context.set('temp',true);\n    temp = true;\n}\n\nmsg.payload = hum && temp;\nif (hum && temp){\n   context.set('hum',false);\n   context.set('temp',false);\n}\n    \nreturn msg;","outputs":1,"noerr":0,"x":329.00000381469727,"y":293.2500047683716,"wires":[["4ab8dff8.39a75"]]},{"id":"4ab8dff8.39a75","type":"debug","z":"51acd361.27dd1c","name":"Actuate","active":false,"console":"false","complete":"payload","x":501.00000762939453,"y":296.50000381469727,"wires":[]}]

NODE-RED FLOW

[{"id":"81b3adf4.11104","type":"inject","z":"d77e5dcf.c2e75","name":"temperature","topic":"","payload":"3","payloadType":"num","repeat":"","crontab":"","once":true,"x":121,"y":98,"wires":[["30c7b85c.6c1a48","52639a9b.f454a4"]]},{"id":"30c7b85c.6c1a48","type":"debug","z":"d77e5dcf.c2e75","name":"","active":false,"console":"false","complete":"payload","x":664,"y":112.16667175292969,"wires":[]},{"id":"52639a9b.f454a4","type":"switch","z":"d77e5dcf.c2e75","name":"","property":"payload","propertyType":"msg","rules":[{"t":"gt","v":"5","vt":"str"},{"t":"lt","v":"5","vt":"str"},{"t":"eq","v":"5","vt":"str"}],"checkall":"true","outputs":3,"x":165.1666717529297,"y":318.83331298828125,"wires":[["b71a791.d15ac88"],["c47cd42d.29eb08"],["95d61b4c.9d8078"]]},{"id":"b71a791.d15ac88","type":"function","z":"d77e5dcf.c2e75","name":"HIGH","func":"msg.payload=\"HIGH\"\nreturn msg;","outputs":1,"noerr":0,"x":432.66668701171875,"y":220.3333282470703,"wires":[["79b15dd3.59eb54"]]},{"id":"c47cd42d.29eb08","type":"function","z":"d77e5dcf.c2e75","name":"LOW","func":"msg.payload=\"LOW\"\nreturn msg;","outputs":1,"noerr":0,"x":441.8333435058594,"y":330.66668701171875,"wires":[["79b15dd3.59eb54"]]},{"id":"95d61b4c.9d8078","type":"function","z":"d77e5dcf.c2e75","name":"EQUAL","func":"msg.payload=\"EQUAL\"\nreturn msg;","outputs":1,"noerr":0,"x":450,"y":456,"wires":[["79b15dd3.59eb54"]]},{"id":"79b15dd3.59eb54","type":"debug","z":"d77e5dcf.c2e75","name":"","active":false,"console":"false","complete":"false","x":731,"y":312,"wires":[]}]

NODE-RED FLOW



[{"id":"50c61357.4b11bc","type":"ui_tab","z":"f36cb853.0c9348","name":"Arduino","icon":"dashboard","order":"1"},{"id":"4a44e8f0.b5bb18","type":"mqtt-broker","z":"f36cb853.0c9348","broker":"test.mosquitto.org","port":"1883","clientid":"","usetls":false,"verifyservercert":true,"compatmode":true,"keepalive":"15","cleansession":true,"willTopic":"","willQos":"0","willRetain":null,"willPayload":"","birthTopic":"","birthQos":"0","birthRetain":null,"birthPayload":""},{"id":"263112bf.d9ceee","type":"serial-port","z":"f36cb853.0c9348","serialport":"/dev/ttyACM0","serialbaud":"9600","databits":"8","parity":"none","stopbits":"1","newline":"\\n","bin":"false","out":"char","addchar":false},{"id":"323793ce.cdc86c","type":"serial in","z":"f36cb853.0c9348","name":"Arduino","serial":"263112bf.d9ceee","x":262,"y":296,"wires":[["1411049f.ebeefb","e07fc8d3.1f8038","44c2b041.bb3d5"]]},{"id":"1411049f.ebeefb","type":"debug","z":"f36cb853.0c9348","name":"","active":false,"console":"false","complete":"false","x":579,"y":428,"wires":[]},{"id":"e07fc8d3.1f8038","type":"dweetio out","z":"f36cb853.0c9348","thing":"123rrr456","name":"","x":582,"y":185,"wires":[]},{"id":"130c604c.ecf3a","type":"debug","z":"f36cb853.0c9348","name":"","active":false,"console":"false","complete":"false","x":566,"y":674,"wires":[]},{"id":"b326542d.4cd9a8","type":"dweetio in","z":"f36cb853.0c9348","thing":"123rrr456","name":"","x":246,"y":565,"wires":[["130c604c.ecf3a","74586874.55e498"]]},{"id":"44c2b041.bb3d5","type":"mqtt out","z":"f36cb853.0c9348","name":"mqtt","topic":"proviamoci","qos":"","retain":"","broker":"4a44e8f0.b5bb18","x":627,"y":341,"wires":[]},{"id":"40278716.bfd878","type":"mqtt in","z":"f36cb853.0c9348","name":"mqtt","topic":"proviamoci","broker":"4a44e8f0.b5bb18","x":625,"y":536,"wires":[["e0cc4553.1f33b8"]]},{"id":"e0cc4553.1f33b8","type":"debug","z":"f36cb853.0c9348","name":"","active":false,"console":"false","complete":"false","x":912,"y":607,"wires":[]},{"id":"74586874.55e498","type":"ui_gauge","z":"f36cb853.0c9348","tab":"50c61357.4b11bc","name":"Stream","group":"ACTUATOR","order":1,"format":"{{value}}","min":0,"max":"5","x":568,"y":761,"wires":[]},{"id":"93881fe2.d0da6","type":"ui_switch","z":"f36cb853.0c9348","tab":"50c61357.4b11bc","name":"Alarm Switch","topic":"","group":"SENSOR","order":1,"onvalue":"true","offvalue":"false","x":282,"y":868,"wires":[["67061152.5687c"]]},{"id":"3ea796f.19d846a","type":"serial out","z":"f36cb853.0c9348","name":"","serial":"263112bf.d9ceee","x":806,"y":867,"wires":[]},{"id":"67061152.5687c","type":"function","z":"f36cb853.0c9348","name":"switch to command","func":"if (msg.payload==\"true\") {\n    msg.payload='3';\n}\nelse {\n    msg.payload='4';\n}\nreturn msg;","outputs":1,"noerr":0,"x":555,"y":869,"wires":[["3ea796f.19d846a"]]}]

https://developer.ibm.com/bluemix/2015/11/02/analyze-tweets-in-30-minutes/

NODE-RED FLOW

[{"id":"18f221a3.9a936e","type":"ui_tab","z":"c293dba8.73c328","name":"Sentiment","icon":"dashboard","order":"1"},{"id":"6f99631.c65c09c","type":"twitter in","z":"c293dba8.73c328","twitter":"","tags":"art","user":"false","name":"","topic":"tweets","x":151.5,"y":307.5000042915344,"wires":[["da3c11e3.8e723"]]},{"id":"da3c11e3.8e723","type":"sentiment","z":"c293dba8.73c328","name":"","x":378,"y":341,"wires":[["8c26690d.faa578","678acb53.c92a84","a83df3b5.699e1"]]},{"id":"8c26690d.faa578","type":"debug","z":"c293dba8.73c328","name":"","active":false,"console":"false","complete":"false","x":602,"y":287,"wires":[]},{"id":"a83df3b5.699e1","type":"debug","z":"c293dba8.73c328","name":"","active":false,"console":"false","complete":"sentiment.score","x":631.7500076293945,"y":398.2500066757202,"wires":[]},{"id":"83d38220.e7cf3","type":"ui_chart","z":"c293dba8.73c328","tab":"18f221a3.9a936e","name":"","group":"","order":1,"interpolate":"linear","nodata":"No Data","removeOlder":1,"removeOlderUnit":"60","x":711.25,"y":518,"wires":[[],[]]},{"id":"678acb53.c92a84","type":"function","z":"c293dba8.73c328","name":"","func":"msg.payload=msg.sentiment.score;\nmsg.topic=\"xxx\";\nreturn msg;","outputs":1,"noerr":0,"x":533,"y":519.25,"wires":[["83d38220.e7cf3"]]}]


[{"id":"be2fe415.41d018","type":"ui_tab","z":"da4831fa.25b7d","name":"Home","icon":"dashboard","order":"1"},{"id":"3428f757.cbd708","type":"ui_text","z":"da4831fa.25b7d","tab":"be2fe415.41d018","name":"Alarm","group":"ACTUATOR","order":1,"format":"{{msg.payload}}","x":642,"y":500,"wires":[]},{"id":"ff1e5345.00e1b","type":"ui_slider","z":"da4831fa.25b7d","tab":"be2fe415.41d018","name":"TEMPERATURE:  ","topic":"","group":"SENSOR","order":"3","min":0,"max":10,"x":314,"y":654,"wires":[["33f7204e.cc08e"]]},{"id":"33f7204e.cc08e","type":"ui_gauge","z":"da4831fa.25b7d","tab":"be2fe415.41d018","name":"Stream","group":"ACTUATOR","order":1,"format":"{{value}}","min":0,"max":10,"x":685,"y":655,"wires":[]},{"id":"7ddba36f.82245c","type":"ui_chart","z":"da4831fa.25b7d","tab":"be2fe415.41d018","name":"Graph","group":"GRAPH","order":1,"interpolate":"linear","nodata":"No Data","removeOlder":1,"removeOlderUnit":"60","x":743,"y":789,"wires":[[],[]]},{"id":"3c33691.fc3cc96","type":"inject","z":"da4831fa.25b7d","name":"","topic":"","payload":"","payloadType":"date","repeat":"1","crontab":"","once":true,"x":315,"y":788,"wires":[["cea061.ff315fa"]]},{"id":"cea061.ff315fa","type":"function","z":"da4831fa.25b7d","name":"RND","func":"msg.payload = 100*Math.random();\nreturn msg;","outputs":1,"noerr":0,"x":510,"y":789,"wires":[["7ddba36f.82245c"]]},{"id":"96e257cc.691da8","type":"ui_switch","z":"da4831fa.25b7d","tab":"be2fe415.41d018","name":"Alarm Switch","topic":"","group":"SENSOR","order":1,"onvalue":"true","offvalue":"false","x":305,"y":498,"wires":[["3428f757.cbd708"]]},{"id":"c2f5f906.3d0a08","type":"comment","z":"da4831fa.25b7d","name":"http://127.0.0.1:1880/ui/","info":"http://127.0.0.1:1880/ui/","x":337,"y":402,"wires":[]}]
Droidscript is a convenient tool to implement Andorid applications. Why is this related to the IoT? Because you can easily control an Arduino via Droidscript  and thus provide access to the Internet through the mobile app. An example is here 
Our first experiment will exploit dweet.io.

Fast, free and ridiculously simple— it's like Twitter for social machines.
Thanks to the integration with freeboard also data visualization is very simple. 
Install the serial node available here



copy and past the following code as a new node

[{"id":"30027b17.72d55c","type":"serial-port","serialport":"/dev/ttyACM0","serialbaud":"9600","databits":"8","parity":"none","stopbits":"1","newline":"\\n","bin":"false","out":"char","addchar":false},{"id":"320157f5.4a3218","type":"serial in","name":"get sensor data","serial":"30027b17.72d55c","x":143.75,"y":190.75,"z":"aa1bdbb1.17fda8","wires":[["919ea5fa.6e6158","fffa749f.000588"]]},{"id":"919ea5fa.6e6158","type":"switch","name":"Analog Sensor Condition","property":"payload","rules":[{"t":"gt","v":"2.5"},{"t":"lte","v":"2.5"}],"checkall":"true","outputs":2,"x":403,"y":328,"z":"aa1bdbb1.17fda8","wires":[["96274206.69d8c"],["1064450d.ef9bbb"]]},{"id":"814c7529.7eb388","type":"serial out","name":"send command","serial":"30027b17.72d55c","x":431,"y":669,"z":"aa1bdbb1.17fda8","wires":[]},{"id":"768ea2e0.89715c","type":"inject","name":"ON","topic":"","payload":"3","payloadType":"string","repeat":"","crontab":"","once":false,"x":146,"y":771,"z":"aa1bdbb1.17fda8","wires":[["d164304a.2e9bd","814c7529.7eb388"]]},{"id":"d164304a.2e9bd","type":"debug","name":"","active":true,"console":"false","complete":"false","x":429,"y":577,"z":"aa1bdbb1.17fda8","wires":[]},{"id":"fffa749f.000588","type":"debug","name":"","active":false,"console":"false","complete":"false","x":344,"y":74,"z":"aa1bdbb1.17fda8","wires":[]},{"id":"589e1082.a761f","type":"serial out","name":"send command","serial":"30027b17.72d55c","x":910,"y":672,"z":"aa1bdbb1.17fda8","wires":[]},{"id":"f0b035d5.0f4fc8","type":"inject","name":"OFF","topic":"","payload":"4","payloadType":"string","repeat":"","crontab":"","once":false,"x":652,"y":778,"z":"aa1bdbb1.17fda8","wires":[["7b33944d.84cc6c","589e1082.a761f"]]},{"id":"7b33944d.84cc6c","type":"debug","name":"","active":true,"console":"false","complete":"false","x":902,"y":593,"z":"aa1bdbb1.17fda8","wires":[]},{"id":"96274206.69d8c","type":"function","name":"msg ON","func":"msg.payload=\"3\";\nreturn msg;","outputs":1,"noerr":0,"x":659,"y":219,"z":"aa1bdbb1.17fda8","wires":[["630a10ec.9cf5f","30d77156.cf288e"]]},{"id":"630a10ec.9cf5f","type":"debug","name":"","active":true,"console":"false","complete":"false","x":927,"y":97,"z":"aa1bdbb1.17fda8","wires":[]},{"id":"1064450d.ef9bbb","type":"function","name":"msg OFF","func":"msg.payload=\"4\";\nreturn msg;","outputs":1,"noerr":0,"x":680,"y":366,"z":"aa1bdbb1.17fda8","wires":[["956994c9.6a9668","30d77156.cf288e"]]},{"id":"956994c9.6a9668","type":"debug","name":"","active":true,"console":"false","complete":"false","x":901,"y":502,"z":"aa1bdbb1.17fda8","wires":[]},{"id":"30d77156.cf288e","type":"serial out","name":"send command","serial":"30027b17.72d55c","x":959,"y":279,"z":"aa1bdbb1.17fda8","wires":[]}]

Node-red is a visual tool for wiring the Internet of Things. 

Wiring??? Node-red allows us to connect (i.e. wire) devices (i.e. things) and services over the Internet.





Links: