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