## 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) * ...
## Questions?
## 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**)