20/01/2023

NodeRED para torpes

Por admin

Hoy vamos a dar nuestros primeros pasos en automatizaci贸n. Hoy vamos a dar nuestros primeros pasos con Node-RED, Node-RED para torpes: Vamos a ver como podemos hacer paneles y pantallas personalizadas para mostrar los datos de navegaci贸n que queramos, como podemos generar alertas para que el barco nos avise mediante voz ante situaciones peligrosas mientras navegamos y, sobre todo, como hacer que nos pueda mandar mensajes de WhatsApp autom谩ticamente ante este tipo de situaciones, por ejemplo si nos intentan robar el barco o las condiciones meteorol贸gicas son muy duras, etc.. Una forma nueva y muy potente de explotar las posibilidades de nuestra Raspberry u ordenador de a bordo.

Los pasos que hemos seguido en el video para poner todo esto en marcha han sido:

  • Instalar Node-RED
    • Abrir el signalK
    • Hacer login, esquina superior derecha, con el usuario admin contrase帽a admin
    • Pinchar en App Store
    • Pinchar en Available
    • Buscar el plugin signalk-node-red
    • Instalarlo (Icono de la derecha)
  • Actualizar Node JS
    • Abrimos una ventana de terminal y ejecutamos los siguientes comandos:
      • node -v
      • sudo npm install -g n
      • sudo n latest
      • node -v
    • Reiniciamos nuestro ordenador o raspberry
  • Agregar a la paleta los nodos de Dashboard (node-red-dashboard)
  • Agregar a la paleta el nodo para enviar mensajes de Whatsapp (node-red-contrib-whatsapp-cmb)
  • Pintar nuestros flujos, como los ejemplos que os dejo a continuaci贸n, o importarlos en vuestro Node-RED para jugar con ellos:
    • En la esquina superior derecha del Node-RED tenemos la opci贸n importar que nos permitir谩 subir el fichero o copiar el c贸digo que os ponemos debajo de cada ejemplo.

En el video ten茅is todos los detalles y creamos una serie de flujos de ejemplos que os dejo a continuaci贸n:

Hola mundo o Tierra a la vista

Un muy sencillo ejemplo con un nodo fuente de datos Inject con un mensaje y uno Debug para pintarlo.

[
    {
        "id": "161f02581169f0e5",
        "type": "tab",
        "label": "Hola Mundo",
        "disabled": false,
        "info": "",
        "env": []
    },
    {
        "id": "177fdee73759e355",
        "type": "inject",
        "z": "161f02581169f0e5",
        "name": "Tierra a la vista",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "Tierra a la vista!",
        "payloadType": "str",
        "x": 140,
        "y": 80,
        "wires": [
            [
                "d2d9c805a1fdbfc3"
            ]
        ]
    },
    {
        "id": "d2d9c805a1fdbfc3",
        "type": "debug",
        "z": "161f02581169f0e5",
        "name": "",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "statusVal": "",
        "statusType": "auto",
        "x": 450,
        "y": 100,
        "wires": []
    }
]

Pod茅is bajaros el ejemplo aqu铆

Datos del barco con aviso por voz y Whatsapp

Un ejemplo que tiene un poco de todo, recoger datos de Signalk, transformar algunos de los datos, mandarlos a un dashboard e incluso generar alerta por voz y por whatsapp en caso de mucho viento.

[
    {
        "id": "07dcb5fc54fd37c8",
        "type": "tab",
        "label": "Datos barco",
        "disabled": false,
        "info": "",
        "env": []
    },
    {
        "id": "a0035b1a88d6f458",
        "type": "signalk-input-handler",
        "z": "07dcb5fc54fd37c8",
        "name": "Velocidad de viento",
        "context": "vessels.self",
        "path": "environment.wind.speedApparent",
        "source": "",
        "x": 110,
        "y": 40,
        "wires": [
            [
                "9876a44d5d23573f"
            ]
        ]
    },
    {
        "id": "37a09f1c536dd984",
        "type": "debug",
        "z": "07dcb5fc54fd37c8",
        "name": "",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "statusVal": "",
        "statusType": "auto",
        "x": 330,
        "y": 160,
        "wires": []
    },
    {
        "id": "9876a44d5d23573f",
        "type": "delay",
        "z": "07dcb5fc54fd37c8",
        "name": "1 mensaje cada 2 seg",
        "pauseType": "rate",
        "timeout": "5",
        "timeoutUnits": "seconds",
        "rate": "1",
        "nbRateUnits": "2",
        "rateUnits": "second",
        "randomFirst": "1",
        "randomLast": "5",
        "randomUnits": "seconds",
        "drop": true,
        "allowrate": false,
        "outputs": 1,
        "x": 120,
        "y": 100,
        "wires": [
            [
                "015988ea3b8f3d66"
            ]
        ]
    },
    {
        "id": "015988ea3b8f3d66",
        "type": "function",
        "z": "07dcb5fc54fd37c8",
        "name": "Pasar a nudos",
        "func": "msg.payload = msg.payload * 1.9438;\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 100,
        "y": 160,
        "wires": [
            [
                "37a09f1c536dd984",
                "12348ebeb192f575",
                "94cdf5cd21ae441e"
            ]
        ]
    },
    {
        "id": "ea69e029774db002",
        "type": "signalk-input-handler",
        "z": "07dcb5fc54fd37c8",
        "name": "Velocidad",
        "context": "vessels.self",
        "path": "navigation.speedOverGround",
        "source": "",
        "x": 90,
        "y": 240,
        "wires": [
            [
                "e28ebf1458669ff7"
            ]
        ]
    },
    {
        "id": "e28ebf1458669ff7",
        "type": "function",
        "z": "07dcb5fc54fd37c8",
        "name": "Pasar a nudos",
        "func": "msg.payload = msg.payload * 1.9438;\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 300,
        "y": 240,
        "wires": [
            [
                "f6c5b457d92d7318"
            ]
        ]
    },
    {
        "id": "f019a20b50a12596",
        "type": "signalk-input-handler",
        "z": "07dcb5fc54fd37c8",
        "name": "Rumbo",
        "context": "vessels.self",
        "path": "steering.autopilot.target.headingMagnetic",
        "source": "",
        "x": 80,
        "y": 300,
        "wires": [
            [
                "e434f194ebeee4af"
            ]
        ]
    },
    {
        "id": "eb0340d8fd2316b6",
        "type": "signalk-input-handler",
        "z": "07dcb5fc54fd37c8",
        "name": "Escora",
        "context": "vessels.self",
        "path": "navigation.attitude.roll",
        "source": "",
        "x": 90,
        "y": 360,
        "wires": [
            [
                "39fdad93712d85cf"
            ]
        ]
    },
    {
        "id": "83214682801dee54",
        "type": "signalk-input-handler",
        "z": "07dcb5fc54fd37c8",
        "name": "Posicion rueda",
        "context": "vessels.self",
        "path": "steering.rudderAngle",
        "source": "",
        "x": 130,
        "y": 420,
        "wires": [
            [
                "6269a9028a98a5e4"
            ]
        ]
    },
    {
        "id": "12348ebeb192f575",
        "type": "ui_text",
        "z": "07dcb5fc54fd37c8",
        "group": "71a54d9ab2b12973",
        "order": 4,
        "width": 0,
        "height": 0,
        "name": "",
        "label": "Viento",
        "format": "{{msg.payload}}",
        "layout": "row-left",
        "className": "",
        "x": 310,
        "y": 200,
        "wires": []
    },
    {
        "id": "f6c5b457d92d7318",
        "type": "ui_text",
        "z": "07dcb5fc54fd37c8",
        "group": "71a54d9ab2b12973",
        "order": 5,
        "width": 0,
        "height": 0,
        "name": "",
        "label": "Velocidad",
        "format": "{{msg.payload}}",
        "layout": "row-spread",
        "className": "",
        "x": 480,
        "y": 260,
        "wires": []
    },
    {
        "id": "e434f194ebeee4af",
        "type": "ui_gauge",
        "z": "07dcb5fc54fd37c8",
        "name": "",
        "group": "71a54d9ab2b12973",
        "order": 6,
        "width": 0,
        "height": 0,
        "gtype": "gage",
        "title": "gauge",
        "label": "rad",
        "format": "{{value}}",
        "min": 0,
        "max": "6",
        "colors": [
            "#00b500",
            "#e6e600",
            "#ca3838"
        ],
        "seg1": "",
        "seg2": "",
        "className": "",
        "x": 280,
        "y": 320,
        "wires": []
    },
    {
        "id": "39fdad93712d85cf",
        "type": "ui_gauge",
        "z": "07dcb5fc54fd37c8",
        "name": "",
        "group": "71a54d9ab2b12973",
        "order": 7,
        "width": 0,
        "height": 0,
        "gtype": "gage",
        "title": "Escora",
        "label": "units",
        "format": "{{value}}",
        "min": "-3.14",
        "max": "3.14",
        "colors": [
            "#00b500",
            "#e6e600",
            "#ca3838"
        ],
        "seg1": "",
        "seg2": "",
        "className": "",
        "x": 270,
        "y": 360,
        "wires": []
    },
    {
        "id": "6269a9028a98a5e4",
        "type": "ui_gauge",
        "z": "07dcb5fc54fd37c8",
        "name": "",
        "group": "71a54d9ab2b12973",
        "order": 7,
        "width": 0,
        "height": 0,
        "gtype": "gage",
        "title": "Rueda",
        "label": "units",
        "format": "{{value}}",
        "min": "-3.14",
        "max": "3.14",
        "colors": [
            "#00b500",
            "#e6e600",
            "#ca3838"
        ],
        "seg1": "",
        "seg2": "",
        "className": "",
        "x": 330,
        "y": 420,
        "wires": []
    },
    {
        "id": "94cdf5cd21ae441e",
        "type": "switch",
        "z": "07dcb5fc54fd37c8",
        "name": "Mayor de 40 Nudos",
        "property": "payload",
        "propertyType": "msg",
        "rules": [
            {
                "t": "gt",
                "v": "40",
                "vt": "num"
            }
        ],
        "checkall": "true",
        "repair": false,
        "outputs": 1,
        "x": 380,
        "y": 100,
        "wires": [
            [
                "6e878fbea8f3e2ad"
            ]
        ]
    },
    {
        "id": "6e878fbea8f3e2ad",
        "type": "delay",
        "z": "07dcb5fc54fd37c8",
        "name": "Recuerda cada 5 segundos",
        "pauseType": "rate",
        "timeout": "5",
        "timeoutUnits": "seconds",
        "rate": "1",
        "nbRateUnits": "10",
        "rateUnits": "second",
        "randomFirst": "1",
        "randomLast": "5",
        "randomUnits": "seconds",
        "drop": true,
        "allowrate": false,
        "outputs": 1,
        "x": 630,
        "y": 100,
        "wires": [
            [
                "947ad201319c5daf"
            ]
        ]
    },
    {
        "id": "947ad201319c5daf",
        "type": "template",
        "z": "07dcb5fc54fd37c8",
        "name": "Texto aviso",
        "field": "payload",
        "fieldType": "msg",
        "format": "handlebars",
        "syntax": "mustache",
        "template": "Hace mucho viento, concretamente {{payload}} nudos!",
        "output": "str",
        "x": 540,
        "y": 160,
        "wires": [
            [
                "3cabbce69b131b09",
                "6a0c87d8d99590bc"
            ]
        ]
    },
    {
        "id": "3cabbce69b131b09",
        "type": "ui_audio",
        "z": "07dcb5fc54fd37c8",
        "name": "Pasalo a voz",
        "group": "a665042e96b81a56",
        "voice": "",
        "always": true,
        "x": 720,
        "y": 160,
        "wires": []
    },
    {
        "id": "6a0c87d8d99590bc",
        "type": "node-red-contrib-whatsapp-cmb-send-message",
        "z": "07dcb5fc54fd37c8",
        "name": "Whatsapp a mi movil",
        "account": "1c5f6bf53aa41990",
        "text": "payload",
        "inputtypemessage": "msg",
        "rejectssl": false,
        "x": 700,
        "y": 360,
        "wires": [
            []
        ]
    },
    {
        "id": "71a54d9ab2b12973",
        "type": "ui_group",
        "name": "Default",
        "tab": "4da9901f85b64b5b",
        "order": 1,
        "disp": true,
        "width": "6",
        "collapse": false,
        "className": ""
    },
    {
        "id": "a665042e96b81a56",
        "type": "ui_group",
        "name": "Group 2",
        "tab": "4da9901f85b64b5b",
        "order": 2,
        "disp": true,
        "width": 6
    },
    {
        "id": "1c5f6bf53aa41990",
        "type": "node-red-contrib-whatsapp-cmb-account",
        "name": "Mi movil"
    },
    {
        "id": "4da9901f85b64b5b",
        "type": "ui_tab",
        "name": "Home",
        "icon": "dashboard",
        "disabled": false,
        "hidden": false
    }
]

Pod茅is bajaros el ejemplo aqu铆

Aviso al zarpar o amarrar

Un ejemplo muy sencillo de como con un nodo GeofenceSwitch de signalK un par de nodos t茅mplate con los mensajes a mandar al zarpar y al regresar y un filtro de cambios para asegurarnos que solo enviamos un mensaje cada vez, conectados a un nodo Whatsapp nos mandar谩 un mensaje cada vez que zarpemos o regresemos a puerto. O lo haga el barco solo porque nos hayan robado..

[
    {
        "id": "67261a8ad0bd24ad",
        "type": "tab",
        "label": "Robo Barco",
        "disabled": false,
        "info": "",
        "env": []
    },
    {
        "id": "a4b8b0b2af621d18",
        "type": "template",
        "z": "67261a8ad0bd24ad",
        "name": "El barco ha zarpado",
        "field": "payload",
        "fieldType": "msg",
        "format": "handlebars",
        "syntax": "mustache",
        "template": "Atenci贸n! El barco acaba de zarpar del puerto",
        "output": "str",
        "x": 580,
        "y": 100,
        "wires": [
            [
                "10737777187085d3"
            ]
        ]
    },
    {
        "id": "7db2dc4c27cece13",
        "type": "node-red-contrib-whatsapp-cmb-send-message",
        "z": "67261a8ad0bd24ad",
        "name": "Aviso a mi movil",
        "account": "1c5f6bf53aa41990",
        "text": "payload",
        "inputtypemessage": "msg",
        "rejectssl": false,
        "x": 580,
        "y": 340,
        "wires": [
            []
        ]
    },
    {
        "id": "fe7907ec03026667",
        "type": "debug",
        "z": "67261a8ad0bd24ad",
        "name": "",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "statusVal": "",
        "statusType": "auto",
        "x": 470,
        "y": 200,
        "wires": []
    },
    {
        "id": "a940b24e0125c890",
        "type": "signalk-geofence",
        "z": "67261a8ad0bd24ad",
        "name": "En puerto",
        "mode": "sendChanges",
        "context": "vessels.self",
        "period": "10000",
        "myposition": false,
        "lat": "43.427643333333336",
        "lon": "-3.8064216666666666",
        "distance": "50",
        "x": 100,
        "y": 40,
        "wires": [
            [
                "ee1bbbaa26b7afe1"
            ],
            [
                "a4b8b0b2af621d18"
            ],
            [
                "fe7907ec03026667"
            ]
        ]
    },
    {
        "id": "ee1bbbaa26b7afe1",
        "type": "template",
        "z": "67261a8ad0bd24ad",
        "name": "El barco ha regresado",
        "field": "payload",
        "fieldType": "msg",
        "format": "handlebars",
        "syntax": "mustache",
        "template": "Atenci贸n! El barco acaba de regresar al puerto",
        "output": "str",
        "x": 580,
        "y": 40,
        "wires": [
            [
                "10737777187085d3"
            ]
        ]
    },
    {
        "id": "10737777187085d3",
        "type": "rbe",
        "z": "67261a8ad0bd24ad",
        "name": "Solo cambios de estado",
        "func": "rbe",
        "gap": "",
        "start": "",
        "inout": "out",
        "septopics": true,
        "property": "payload",
        "topi": "topic",
        "x": 810,
        "y": 220,
        "wires": [
            [
                "7db2dc4c27cece13"
            ]
        ]
    },
    {
        "id": "1c5f6bf53aa41990",
        "type": "node-red-contrib-whatsapp-cmb-account",
        "name": "Mi movil"
    }
]

Pod茅is bajaros el ejemplo aqu铆