Sanne 'SpuQ' Santens
Published © GPL3+

IoT with Edgeberry - Part 3: First IoT project

In part 3, we're connecting a button to one Edgeberry device with an LED on another Edgeberry device through the internet.

IntermediateFull instructions provided1 hour59
IoT with Edgeberry - Part 3: First IoT project

Story

Read more

Code

Device 1 Flow

JSON
This is the Node-RED flow for Device 1
[
    {
        "id": "9f33102487ab7468",
        "type": "rpi-gpio out",
        "z": "e6f0c418d7ddc4e9",
        "name": "Digital Out 2",
        "pin": "21",
        "set": true,
        "level": "0",
        "freq": "",
        "out": "out",
        "bcm": true,
        "x": 490,
        "y": 240,
        "wires": []
    },
    {
        "id": "132d91253d6babb8",
        "type": "global-config",
        "env": [],
        "modules": {
            "node-red-node-pi-gpio": "2.0.6"
        }
    }
]

Cloud Application Flow

JSON
The Node-RED flow with the dashboard for the application running in the cloud
[
    {
        "id": "6051a0a58f8d8c1e",
        "type": "tab",
        "label": "Cloud Application",
        "disabled": false,
        "info": "",
        "env": []
    },
    {
        "id": "c1bdc2dc5a9b24de",
        "type": "devicehub-device",
        "z": "6051a0a58f8d8c1e",
        "name": "Edgeberry Device 2",
        "hub": "fc95fc9caa5364e5",
        "deviceName": "EDGB-A096",
        "x": 690,
        "y": 200,
        "wires": [
            []
        ]
    },
    {
        "id": "93a64fa1969f4b39",
        "type": "devicehub-device",
        "z": "6051a0a58f8d8c1e",
        "name": "Edgeberry Device 1",
        "hub": "fc95fc9caa5364e5",
        "deviceName": "EDGB-9179",
        "x": 250,
        "y": 200,
        "wires": [
            [
                "b2fb118cc46ea818"
            ]
        ]
    },
    {
        "id": "b2fb118cc46ea818",
        "type": "function",
        "z": "6051a0a58f8d8c1e",
        "name": "Switch logic",
        "func": "// Only pass telemetry\nif (msg.messageType === \"telemetry\" && msg.payload.data.device == \"switch\") {\n    let newmsg = {};\n    newmsg.action = \"sendMessage\";\n    newmsg.payload = {\n        value: msg.payload.data.value,\n        device: msg.payload.data.device\n    }\n\n    return newmsg;\n}\nreturn null;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 470,
        "y": 200,
        "wires": [
            [
                "c1bdc2dc5a9b24de",
                "9d7e86eedbd1c02d"
            ]
        ]
    },
    {
        "id": "c91fcbdc83459b0f",
        "type": "function",
        "z": "6051a0a58f8d8c1e",
        "name": "Direct Method formatting",
        "func": "msg.action = \"callDirectMethod\";\nmsg.methodName = \"identify\";\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 370,
        "y": 100,
        "wires": [
            [
                "c1bdc2dc5a9b24de"
            ]
        ]
    },
    {
        "id": "2b2ffa9d730a7712",
        "type": "ui-button",
        "z": "6051a0a58f8d8c1e",
        "group": "132c986ec22a160e",
        "name": "Identify Device 2",
        "label": "Identify Device 2",
        "order": 10,
        "width": 0,
        "height": 0,
        "emulateClick": false,
        "tooltip": "",
        "color": "",
        "bgcolor": "",
        "className": "",
        "icon": "",
        "iconPosition": "left",
        "payload": "",
        "payloadType": "str",
        "topic": "topic",
        "topicType": "msg",
        "buttonColor": "",
        "textColor": "",
        "iconColor": "",
        "enableClick": true,
        "enablePointerdown": false,
        "pointerdownPayload": "",
        "pointerdownPayloadType": "str",
        "enablePointerup": false,
        "pointerupPayload": "",
        "pointerupPayloadType": "str",
        "x": 130,
        "y": 100,
        "wires": [
            [
                "c91fcbdc83459b0f"
            ]
        ]
    },
    {
        "id": "4c69b8695a3953de",
        "type": "function",
        "z": "6051a0a58f8d8c1e",
        "name": "Direct Method formatting",
        "func": "msg.action = \"callDirectMethod\";\nmsg.methodName = \"identify\";\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 370,
        "y": 60,
        "wires": [
            [
                "93a64fa1969f4b39"
            ]
        ]
    },
    {
        "id": "b575e6e241118b86",
        "type": "ui-button",
        "z": "6051a0a58f8d8c1e",
        "group": "132c986ec22a160e",
        "name": "Identify Device 1",
        "label": "Identify Device 1",
        "order": 9,
        "width": 0,
        "height": 0,
        "emulateClick": false,
        "tooltip": "",
        "color": "",
        "bgcolor": "",
        "className": "",
        "icon": "",
        "iconPosition": "left",
        "payload": "",
        "payloadType": "str",
        "topic": "topic",
        "topicType": "msg",
        "buttonColor": "",
        "textColor": "",
        "iconColor": "",
        "enableClick": true,
        "enablePointerdown": false,
        "pointerdownPayload": "",
        "pointerdownPayloadType": "str",
        "enablePointerup": false,
        "pointerupPayload": "",
        "pointerupPayloadType": "str",
        "x": 130,
        "y": 60,
        "wires": [
            [
                "4c69b8695a3953de"
            ]
        ]
    },
    {
        "id": "bf88dc30f04c6787",
        "type": "function",
        "z": "6051a0a58f8d8c1e",
        "name": "Cloud-to-Device formatting",
        "func": "msg.action = \"sendMessage\"\nmsg.payload = {\"testkey\":\"This is a Cloud-to-Device test message\"}\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 360,
        "y": 340,
        "wires": [
            [
                "93a64fa1969f4b39"
            ]
        ]
    },
    {
        "id": "ecdb2bbb675e9cd5",
        "type": "ui-button",
        "z": "6051a0a58f8d8c1e",
        "group": "132c986ec22a160e",
        "name": "Cloud-to-Device",
        "label": "Cloud-to-Device",
        "order": 8,
        "width": 0,
        "height": 0,
        "emulateClick": false,
        "tooltip": "",
        "color": "",
        "bgcolor": "",
        "className": "",
        "icon": "",
        "iconPosition": "left",
        "payload": "",
        "payloadType": "str",
        "topic": "topic",
        "topicType": "msg",
        "buttonColor": "#0007FF",
        "textColor": "",
        "iconColor": "",
        "enableClick": true,
        "enablePointerdown": false,
        "pointerdownPayload": "",
        "pointerdownPayloadType": "str",
        "enablePointerup": false,
        "pointerupPayload": "",
        "pointerupPayloadType": "str",
        "x": 120,
        "y": 340,
        "wires": [
            [
                "bf88dc30f04c6787"
            ]
        ]
    },
    {
        "id": "9d7e86eedbd1c02d",
        "type": "ui-template",
        "z": "6051a0a58f8d8c1e",
        "group": "132c986ec22a160e",
        "page": "",
        "ui": "",
        "name": "Indicator",
        "order": 12,
        "width": 0,
        "height": 0,
        "head": "",
        "format": "<template>\n  <v-card\n    class=\"d-flex align-center justify-space-between pa-3 rounded-lg elevation-1 ff-state-card\"\n  >\n    <div class=\"text-body-2 text-medium-emphasis\">\n      {{ label }}\n    </div>\n\n    <v-chip\n      class=\"state-chip\"\n      :color=\"isOn ? 'success' : 'error'\"\n      :variant=\"isOn ? 'elevated' : 'flat'\"\n      size=\"small\"\n    >\n      {{ isOn ? 'ON' : 'OFF' }}\n    </v-chip>\n  </v-card>\n</template>\n\n<script>\nexport default {\n  data () {\n    return {\n      isOn: false,\n      label: 'Switch'\n    }\n  },\n\n  mounted () {\n    this.updateFromMsg(this.msg)\n  },\n\n  watch: {\n    msg: {\n      handler (newMsg) {\n        this.updateFromMsg(newMsg)\n      },\n      deep: true\n    }\n  },\n\n  methods: {\n    updateFromMsg (msg) {\n      if (!msg || !msg.payload) return\n\n      const raw = msg.payload.value\n      const s = String(raw).trim().toLowerCase()\n\n      // Accept 1/0, true/false, \"1\"/\"0\", \"on\"/\"off\"\n      this.isOn =\n        raw === true ||\n        raw === 1 ||\n        s === '1' ||\n        s === 'true' ||\n        s === 'on'\n\n      // Optional label from payload/device/topic if you expand later\n      if (msg.payload.device) this.label = msg.payload.device\n      else if (msg.topic) this.label = msg.topic\n    }\n  }\n}\n</script>\n\n<style>\n.ff-state-card {\n  min-width: 200px;\n}\n\n.state-chip {\n  font-weight: 600;\n  letter-spacing: 0.06em;\n}\n</style>",
        "storeOutMessages": true,
        "passthru": true,
        "resendOnRefresh": true,
        "templateScope": "local",
        "className": "",
        "x": 660,
        "y": 260,
        "wires": [
            []
        ]
    },
    {
        "id": "fc95fc9caa5364e5",
        "type": "devicehub-config",
        "name": "",
        "host": "localhost",
        "port": "8090",
        "secure": false
    },
    {
        "id": "132c986ec22a160e",
        "type": "ui-group",
        "name": "IoT Demo",
        "page": "e0cebea875c68ec6",
        "width": 6,
        "height": 1,
        "order": 1,
        "showTitle": true,
        "className": "",
        "visible": "true",
        "disabled": "false",
        "groupType": "default"
    },
    {
        "id": "e0cebea875c68ec6",
        "type": "ui-page",
        "name": "IoT Demo",
        "ui": "9d29ee82a1080a1e",
        "path": "/",
        "icon": "home",
        "layout": "grid",
        "theme": "0c6ddb724b9b3e45",
        "breakpoints": [
            {
                "name": "Default",
                "px": "0",
                "cols": "3"
            },
            {
                "name": "Tablet",
                "px": "576",
                "cols": "6"
            },
            {
                "name": "Small Desktop",
                "px": "768",
                "cols": "9"
            },
            {
                "name": "Desktop",
                "px": "1024",
                "cols": "12"
            }
        ],
        "order": 1,
        "className": "",
        "visible": "true",
        "disabled": "false"
    },
    {
        "id": "9d29ee82a1080a1e",
        "type": "ui-base",
        "name": "My Dashboard",
        "path": "/dashboard",
        "appIcon": "",
        "includeClientData": true,
        "acceptsClientConfig": [
            "ui-notification",
            "ui-control"
        ],
        "showPathInSidebar": false,
        "headerContent": "page",
        "navigationStyle": "default",
        "titleBarStyle": "default",
        "showReconnectNotification": true,
        "notificationDisplayTime": 1,
        "showDisconnectNotification": true,
        "allowInstall": false
    },
    {
        "id": "0c6ddb724b9b3e45",
        "type": "ui-theme",
        "name": "Default Theme",
        "colors": {
            "surface": "#ffffff",
            "primary": "#0094CE",
            "bgPage": "#eeeeee",
            "groupBg": "#ffffff",
            "groupOutline": "#cccccc"
        },
        "sizes": {
            "density": "default",
            "pagePadding": "12px",
            "groupGap": "12px",
            "groupBorderRadius": "4px",
            "widgetGap": "12px"
        }
    },
    {
        "id": "1f7619664704989e",
        "type": "global-config",
        "env": [],
        "modules": {
            "@edgeberry/devicehub-node-red-contrib": "1.8.1",
            "@flowfuse/node-red-dashboard": "1.29.0"
        }
    }
]

Device 2 Flow

JSON
The flow for the second device
[
    {
        "id": "f9326a666c8ff65e",
        "type": "tab",
        "label": "Device 2",
        "disabled": false,
        "info": "",
        "env": []
    },
    {
        "id": "c45d24ed89091598",
        "type": "rpi-gpio out",
        "z": "f9326a666c8ff65e",
        "name": "Digital Out 3",
        "pin": "13",
        "set": false,
        "level": "0",
        "freq": "",
        "out": "out",
        "bcm": true,
        "x": 470,
        "y": 120,
        "wires": []
    },
    {
        "id": "562eca5e87c0f2f5",
        "type": "edgeberry",
        "z": "f9326a666c8ff65e",
        "name": "",
        "x": 130,
        "y": 120,
        "wires": [
            [
                "7a8fcac45f2acb99",
                "086796fc9b9980b6"
            ]
        ]
    },
    {
        "id": "7a8fcac45f2acb99",
        "type": "function",
        "z": "f9326a666c8ff65e",
        "name": "Convertor",
        "func": "if( msg.payload.device === \"switch\"){\n    msg.payload = msg.payload.value;\n    return msg;\n}",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 300,
        "y": 120,
        "wires": [
            [
                "c45d24ed89091598"
            ]
        ]
    },
    {
        "id": "086796fc9b9980b6",
        "type": "debug",
        "z": "f9326a666c8ff65e",
        "name": "debug 1",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "statusVal": "",
        "statusType": "auto",
        "x": 300,
        "y": 40,
        "wires": []
    },
    {
        "id": "f9ecc50da5075bb5",
        "type": "global-config",
        "env": [],
        "modules": {
            "node-red-node-pi-gpio": "2.0.6",
            "@edgeberry/device-node-red-contrib": "3.3.0"
        }
    }
]

Edgeberry Edge Explorer Hardware Cartridge

The Hardware Cartridge used in this tutorial, providing your Edgeberry device with I/O compatible with several breakout ecosystems, like Elecrow's Crowtail.

Credits

Sanne 'SpuQ' Santens
5 projects • 1 follower

Comments