## Node-RED 101
#### How to create a solution for hackathons without writing a single line of code
[Miroslav "mirek" Biňas](https://bletvaska.github.io)
/ [**Citython 2022**](https://www.citython.sk/)
[![mirek](images/mirek.na.hackathone.jpg)](https://bletvaska.github.io)
## Traditional Hackathon Use Case
notes:
* ukradnut data, spracovat ich, poskytnut pouzivatelom
* stiahneme informácie o letoch nad slovenskom pomocou komunikačného protokolu HTTP
* spracujeme ich a zobrazíme ich na vlastnej mape
* zautomatizujeme proces sťahovania a aktualizácie údajov na mape
* získané údaje prepošleme ďalej pomocou komunikačného protokolu MQTT
* údaje začneme lokálne ukladať
* poskytneme ich ďalej pomocou REST API
* urobíme jednoduchú webovú stránku
* budem robit nazivo a samozrejme budem podvadzat
## It's all about **data**!
[![Node-RED Logo](images/logo-node.red.png)](https://nodered.org)
## 1. Collecting Data
notes:
* running
```bash
$ docker container run --publish 1880:1880 --name nodered --volume $(pwd)/data:/data --rm nodered/node-red
```
[![Antik](images/logo-antik.png)](https://www.antik.sk/)
https://gbfs.sharing.antik.sk/v2/antiksharing_ke/gbfs.json
![Zber údajov](images/01.retrieve.data.png)
## The Message
```json
{
"_msgid": "89cbb063.7f7a7",
"payload": "Hello world!",
"topic": "Greetings!"
}
```
## 2. Presenting the Data
[![node-red-contrib-web-worldmap](images/worldmap.node.gif)](https://flows.nodered.org/node/node-red-contrib-web-worldmap)
[node-red-contrib-web-worldmap](https://flows.nodered.org/node/node-red-contrib-web-worldmap)
notes:
* nainstalujeme plugin worldmap
* nastavit zemepisnu vysku a sirku, zoom level na hodnotu 8
* nainstalujeme plugin pre handlebars
## Template for Data Processing
```json
[
{{#each data.bikes }}
{
"lon": {{ lon }},
"lat": {{ lat }},
"name": "{{ bike_id }}",
"is_reserved": "{{ is_reserved }}",
"is_disabled": "{{ is_disabled }}",
"icon": "fa-bicycle",
"ttl": 60,
"layer": "bikes"
}
{{#unless @last}},{{/unless}}
{{/each}}
]
```
![Data presentation](images/02.presenting.data.png)
[![The OpenSky Network](images/logo-opensky.png)](https://openskynetwork.github.io/opensky-api/index.html)
https://opensky-network.org/api/states/all?lamin=47.4912&lomin=16.4517&lamax=49.8981&lomax=25.9378
## Template
```json
[
{{#each states}}
{
"name": "{{0}}",
"icao24": "{{0}}",
"callsign": "{{1}}",
"origin_country": "{{2}}",
"lon": {{5}},
"lat": {{6}},
"icon": "plane",
"speed": {{9}},
"last_contact": {{4}},
"heading": {{10}},
"ttl": 60,
"layer": "flights"
}
{{#unless @last}},{{/unless}}
{{/each}}
]
```
## 3. Updating Data
notes:
* nechame udaje stahovat napr. kazdych 10s
* cron job / systemd timers
* udaje budeme aktualizovat kazdych 5s, ale netreba zabudnut na cakanie 6s na zaciatku kvoli inicializacii mapy
![Updating Data](images/03.updating.data.png)
## 4. Publishing Data with MQTT
notes:
* MQTT je jeden zo zakladnych komunikacnych protokolov v IoT rieseniach
* pouzijeme `broker.hivemq.com:1883` a topic `ossconf/flights`
![Publishing Data](images/04.publishing.data.with.mqtt.png)
## 5. REST API
* HTTP protocol
* endpoint: `/api/bikes/:bikeid`
notes:
## Local Database
* REST API must return data immediately after receiving a request
* db as global variable
* simple dictionary (`key-value` store)
```json
{
{{#each this}}
"{{ name }}": {
"lon": {{ lon }},
"lat": {{ lat }},
"bike_id": "{{ name }}",
"is_reserved": "{{ is_reserved }}",
"is_disabled": "{{ is_disabled }}"
}
{{#unless @last}},{{/unless}}
{{/each}}
}
```
notes:
* vysledok vlozime pomocou uzla `CHANGE` do premennej `global.bikes = msg.payload`
![Storing the Data](images/05.storing.data.png)
![REST API](images/06.rest.api.png)
notes:
* `CHANGE` uzol urobi `msg.payload = global.bikes[msg.req.params.bikeid]`
## Testing the REST API
http://localhost:1880/api/bikes/:bikeid
## 6. Web Page
(similar to REST API)
notes:
```html
<h1>Bike {{payload.name}}</h1>
<ul>
<li>
<b>Longitude</b>: {{ payload.lon }}
</li>
<li>
<b>Latitude</b>: {{ payload.lat }}
</li>
<li>
<b>Is Reserver</b>: {{ payload.is_reserved }}
</li>
<li>
<b>Is Disabled</b>: {{ payload.is_disabled }}
</li>
</ul>
```
notes:
* vysledok vlozime pomocou uzla `CHANGE` do premennej `global.flights = msg.payload`
![Web Page](images/07.web.page.png)
notes:
* `SWITCH`:
* `property = global.flights`
* `has key = msg.req.params.flight`
* `otherwise`
* `CHANGE`
* `msg.payload = global.flights[msg.req.params.flight]`
## What else can Node-RED do?
* websockets
* connected hw
* dashboards
* integration with DBS
* integration with external services
* own functions as nodes (JavaScript, Python)
* ...
## Resources
* [Node-RED Homepage](https://nodered.org)
* [FRED: Front End For Node-RED](https://fred.sensetecnic.com)
* [The Result Flow](resources/flows-bikes.json)
* [Node-RED YouTube Channel](https://www.youtube.com/channel/UCQaB8NXBEPod7Ab8PPCLLAA)
![qr code](https://api.qrserver.com/v1/create-qr-code/?data=https://bit.ly/3Ny4cmn&size=300x300)
(**https://bit.ly/3Ny4cmn**)