Mihai Popa
Published © Apache-2.0

BeaconHome

BeaconHome - the "home" acting as a beacon using Fermion: BLE Sensor Beacon and digital/analog sensors

IntermediateFull instructions provided2 hours277
BeaconHome

Things used in this project

Hardware components

DFRobot Fermion: BLE Sensor Beacon
×3
DFRobot Fermion: SHT40 Temperature & Humidity Sensor
×1
DFRobot Fermion: ICP-10111 Pressure Sensor
×1
Gravity: Analog Ambient Light Sensor For Arduino
DFRobot Gravity: Analog Ambient Light Sensor For Arduino
×1
Gravity: Analog Soil Moisture Sensor For Arduino
DFRobot Gravity: Analog Soil Moisture Sensor For Arduino
×1
Microchip MCP9700
×1
FireBeetle ESP32-E IoT Microcontroller with Header (Supports Wi-Fi & Bluetooth)
DFRobot FireBeetle ESP32-E IoT Microcontroller with Header (Supports Wi-Fi & Bluetooth)
×1
ESP8266 ESP-01
Espressif ESP8266 ESP-01
×1
esp8266 UART programmer adapter
×1
esp8266 power adapter
×1
usb to serial adapter working at 3.3V
×1
Raspberry Pi Zero
Raspberry Pi Zero
×1

Software apps and online services

Raspberry Pi OS (Legacy) Lite
Arduino IDE
Arduino IDE
InPlay Inc NanoBeaconConfigTool_V3.2.11
Node-RED
Node-RED
Tinkercad
Autodesk Tinkercad
Fritzing

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)
Electronic specific tools (generic)

Story

Read more

Custom parts and enclosures

BLE beacon case for analog sensors.zip

Case used for analog sensors

BLE beacon case for digital sensors.zip

Case used for digital sensors

Schematics

IN100 datasheet

IN100 datasheet

Connection between ESP32 and ESP8266

Connection between ESP32 and ESP8266

Code

Analog sensors.cfg

JSON
BLE Beacon Analog sensors configuration used with InPlay Inc NanoBeacon™ Config Tool
{
    "version": "3.13",
    "advSet": [
        {
            "id": 0,
            "bdAddr": "060504030201",
            "addrType": "static",
            "addrKey": 0,
            "staticAddrGen": 1,
            "addrGenInterval": 90,
            "interval": 5000,
            "authEn": 0,
            "authKey": 0,
            "authSaltType": 2,
            "authSaltValue": 0,
            "authEaxCountType": 0,
            "authEaxCountValue": 0,
            "ui_format": "custom",
            "uid2tlm_ratio": 0.0,
            "eddystoneTxPower": 0,
            "chCtrl": 0,
            "advModeTrigEn": 0,
            "is1MPhy": 1,
            "phyRate": "1M",
            "isStandardBle": 1,
            "cte": 0,
            "cteLen": 0,
            "randomDlyType": 0,
            "payloadVer": 3,
            "payload": [
                {
                    "len": 7,
                    "type": 9,
                    "data": "416e616c6f67"
                },
                {
                    "len": 12,
                    "type": 255,
                    "data": "0505<ADC CH2 2byte 1 0><VCC 1byte 0 0><TEMP 2byte 1 0><ADC CH0 2byte 1 0><ADC CH1 2byte 1 0>"
                }
            ]
        }
    ],
    "txSetting": {
        "txPower": -1,
        "txPaGain": -1,
        "sleepAftTx": 1,
        "uartSingleWire": 0,
        "uartPinSel": 0,
        "xoCap": 12,
        "xoStableTime": 36,
        "xoGm": 16,
        "ch0": 37,
        "ch1": 38,
        "ch2": 39,
        "key0": "000102030405060708090a0b0c0d0e0f"
    },
    "gpio": [
        {
            "id": 0,
            "digital": "default",
            "pu-pd": 1,
            "wakeup": "disable",
            "advTrig": "disable",
            "latch": 0,
            "maskb": 0
        },
        {
            "id": 1,
            "digital": "default",
            "pu-pd": 1,
            "wakeup": "disable",
            "advTrig": "disable",
            "latch": 0,
            "maskb": 0
        },
        {
            "id": 2,
            "digital": "default",
            "pu-pd": 1,
            "wakeup": "disable",
            "advTrig": "disable",
            "latch": 0,
            "maskb": 0
        },
        {
            "id": 3,
            "digital": "default",
            "pu-pd": 1,
            "wakeup": "disable",
            "advTrig": "disable",
            "latch": 0,
            "maskb": 0
        },
        {
            "id": 4,
            "digital": "disable",
            "pu-pd": 0,
            "wakeup": "disable",
            "advTrig": "disable",
            "latch": 1,
            "maskb": 0
        },
        {
            "id": 5,
            "digital": "disable",
            "pu-pd": 0,
            "wakeup": "disable",
            "advTrig": "disable",
            "latch": 1,
            "maskb": 0
        },
        {
            "id": 6,
            "digital": "disable",
            "pu-pd": 0,
            "wakeup": "disable",
            "advTrig": "disable",
            "latch": 1,
            "maskb": 0
        },
        {
            "id": 7,
            "digital": "default",
            "pu-pd": 1,
            "wakeup": "disable",
            "advTrig": "disable",
            "latch": 0,
            "maskb": 0
        }
    ],
    "vccUnit": 0.03125,
    "tempUnit": 0.01,
    "adc": [
        {
            "ch": 0,
            "enable": 1,
            "vddCtrlEn": 0,
            "gndCtrlEn": 0,
            "skipSample": 2,
            "avgSample": 16,
            "sampleInterval": 4,
            "delayStart": 4,
            "delaySample": 13,
            "unitLsb": 0.00078125,
            "valueV14": 1.4,
            "valueV04": 0.4
        },
        {
            "ch": 1,
            "enable": 1,
            "vddCtrlEn": 0,
            "gndCtrlEn": 0,
            "skipSample": 2,
            "avgSample": 16,
            "sampleInterval": 4,
            "delayStart": 4,
            "delaySample": 13,
            "unitLsb": 0.00078125,
            "valueV14": 1.4,
            "valueV04": 0.4
        },
        {
            "ch": 2,
            "enable": 1,
            "vddCtrlEn": 0,
            "gndCtrlEn": 0,
            "skipSample": 2,
            "avgSample": 16,
            "sampleInterval": 4,
            "delayStart": 4,
            "delaySample": 13,
            "unitLsb": 0.001,
            "valueV14": 2.898,
            "valueV04": 0.828
        },
        {
            "ch": 3,
            "enable": 0
        }
    ],
    "calibration": {},
    "i2c": {
        "coldBootEn": 0,
        "warmBootEn": 0
    },
    "i2c2": {
        "coldBootEn": 0,
        "warmBootEn": 0
    },
    "i2c3": {
        "coldBootEn": 0,
        "warmBootEn": 0
    },
    "pulse": {
        "enable": 0
    },
    "qdec": {
        "enable": 0,
        "runGpioEdgeDetect": 0,
        "clearCount": 0,
        "endCode": 15,
        "twoStep": 0,
        "interval": 999,
        "timeout": 1999,
        "gpio": [],
        "code": []
    },
    "wdt": {
        "timerWraparound": 0,
        "enable": 0,
        "wakeupChip": 0,
        "initValue": 30
    },
    "edgeCount": {
        "enable": 0
    },
    "sqWave": {
        "en": 0
    },
    "rtc": {
        "enable": 0,
        "clock": 0,
        "type": 0
    },
    "regSetting": [
        "write: 0 1 3 3480 2010000",
        "write: 0 1 3 3484 3030002",
        "write: 0 1 1 34c8 102",
        "write: 0 1 3 3494 10020018",
        "write: 3 1 0 1084 0",
        "write: 3 1 0 11C8 0",
        "write: 3 1 0 1c44 c6",
        "write: 3 1 0 1ad0 58",
        "write: 3 1 1 1d04 731",
        "write: 0 1 0 3240 42",
        "write: 0 1 0 3500 03"
    ],
    "regSettingCust": [],
    "settingPolice": 0,
    "regValTrigEn": 0
}

Node-red Flow setup

JSON
Setup for Node-red and UI
[
    {
        "id": "e304fa4e58cbecd1",
        "type": "tab",
        "label": "Flow 2",
        "disabled": false,
        "info": "",
        "env": []
    },
    {
        "id": "efdbe5c6c654a12d",
        "type": "mqtt in",
        "z": "e304fa4e58cbecd1",
        "name": "",
        "topic": "esp32/altitude",
        "qos": "2",
        "datatype": "auto-detect",
        "broker": "590e3ceaadf4028f",
        "nl": false,
        "rap": true,
        "rh": 0,
        "inputs": 0,
        "x": 110,
        "y": 140,
        "wires": [
            [
                "42a78e3759f2b063"
            ]
        ]
    },
    {
        "id": "f79063db513de7da",
        "type": "mqtt in",
        "z": "e304fa4e58cbecd1",
        "name": "",
        "topic": "esp32/AnalogExternalTempInteger",
        "qos": "2",
        "datatype": "auto-detect",
        "broker": "590e3ceaadf4028f",
        "nl": false,
        "rap": true,
        "rh": 0,
        "inputs": 0,
        "x": 180,
        "y": 340,
        "wires": [
            [
                "ba37a2b88a0ed90c"
            ]
        ]
    },
    {
        "id": "6ce73293a358dbfc",
        "type": "ui_chart",
        "z": "e304fa4e58cbecd1",
        "name": "",
        "group": "797ca08f74dee60b",
        "order": 2,
        "width": 5,
        "height": 4,
        "label": "MCP9700 temp",
        "chartType": "line",
        "legend": "false",
        "xformat": "HH:mm:ss",
        "interpolate": "linear",
        "nodata": "",
        "dot": false,
        "ymin": "",
        "ymax": "",
        "removeOlder": 1,
        "removeOlderPoints": "",
        "removeOlderUnit": "3600",
        "cutout": 0,
        "useOneColor": false,
        "useUTC": false,
        "colors": [
            "#1f77b4",
            "#aec7e8",
            "#ff7f0e",
            "#2ca02c",
            "#98df8a",
            "#d62728",
            "#ff9896",
            "#9467bd",
            "#c5b0d5"
        ],
        "outputs": 1,
        "useDifferentColor": false,
        "className": "",
        "x": 920,
        "y": 340,
        "wires": [
            []
        ]
    },
    {
        "id": "42a78e3759f2b063",
        "type": "ui_gauge",
        "z": "e304fa4e58cbecd1",
        "name": "",
        "group": "35c4ebb396aeece3",
        "order": 3,
        "width": 6,
        "height": 4,
        "gtype": "gage",
        "title": "Altitude",
        "label": "meters",
        "format": "{{value}}",
        "min": 0,
        "max": "500",
        "colors": [
            "#00b500",
            "#e6e600",
            "#ca3838"
        ],
        "seg1": "",
        "seg2": "",
        "diff": false,
        "className": "",
        "x": 480,
        "y": 140,
        "wires": []
    },
    {
        "id": "e779a2ce1a81c8be",
        "type": "mqtt in",
        "z": "e304fa4e58cbecd1",
        "name": "",
        "topic": "esp32/analog_batteryVoltage",
        "qos": "2",
        "datatype": "auto-detect",
        "broker": "590e3ceaadf4028f",
        "nl": false,
        "rap": true,
        "rh": 0,
        "inputs": 0,
        "x": 160,
        "y": 600,
        "wires": [
            [
                "e03f1b02372b5906"
            ]
        ]
    },
    {
        "id": "14fbf550ef98e783",
        "type": "mqtt in",
        "z": "e304fa4e58cbecd1",
        "name": "",
        "topic": "esp32/analog_MoistureData",
        "qos": "2",
        "datatype": "auto-detect",
        "broker": "590e3ceaadf4028f",
        "nl": false,
        "rap": true,
        "rh": 0,
        "inputs": 0,
        "x": 160,
        "y": 660,
        "wires": [
            [
                "e89e5e3272c488f4"
            ]
        ]
    },
    {
        "id": "132efbee9efb80d8",
        "type": "mqtt in",
        "z": "e304fa4e58cbecd1",
        "name": "",
        "topic": "esp32/analog_LightData",
        "qos": "2",
        "datatype": "auto-detect",
        "broker": "590e3ceaadf4028f",
        "nl": false,
        "rap": true,
        "rh": 0,
        "inputs": 0,
        "x": 150,
        "y": 720,
        "wires": [
            [
                "e53a0c823775a55e"
            ]
        ]
    },
    {
        "id": "e03f1b02372b5906",
        "type": "ui_gauge",
        "z": "e304fa4e58cbecd1",
        "name": "",
        "group": "797ca08f74dee60b",
        "order": 7,
        "width": 4,
        "height": 4,
        "gtype": "gage",
        "title": "Battery voltage",
        "label": "volts",
        "format": "{{value}}",
        "min": 0,
        "max": "3.5",
        "colors": [
            "#ec0e6e",
            "#b4ee5d",
            "#3acb6a"
        ],
        "seg1": "",
        "seg2": "",
        "diff": false,
        "className": "",
        "x": 500,
        "y": 600,
        "wires": []
    },
    {
        "id": "e89e5e3272c488f4",
        "type": "ui_gauge",
        "z": "e304fa4e58cbecd1",
        "name": "",
        "group": "797ca08f74dee60b",
        "order": 6,
        "width": 4,
        "height": 4,
        "gtype": "gage",
        "title": "Moisture sensor",
        "label": "units",
        "format": "{{value}}",
        "min": 0,
        "max": "2000",
        "colors": [
            "#00b500",
            "#e6e600",
            "#ca3838"
        ],
        "seg1": "",
        "seg2": "",
        "diff": false,
        "className": "",
        "x": 500,
        "y": 660,
        "wires": []
    },
    {
        "id": "e53a0c823775a55e",
        "type": "ui_gauge",
        "z": "e304fa4e58cbecd1",
        "name": "",
        "group": "797ca08f74dee60b",
        "order": 5,
        "width": 4,
        "height": 4,
        "gtype": "gage",
        "title": "Light sensor",
        "label": "units",
        "format": "{{value}}",
        "min": "0",
        "max": "2000",
        "colors": [
            "#00b500",
            "#e6e600",
            "#ca3838"
        ],
        "seg1": "",
        "seg2": "",
        "diff": false,
        "className": "",
        "x": 490,
        "y": 720,
        "wires": []
    },
    {
        "id": "ad1c8bf84ba5773b",
        "type": "mqtt in",
        "z": "e304fa4e58cbecd1",
        "name": "",
        "topic": "esp32/temperature",
        "qos": "2",
        "datatype": "auto-detect",
        "broker": "590e3ceaadf4028f",
        "nl": false,
        "rap": true,
        "rh": 0,
        "inputs": 0,
        "x": 130,
        "y": 80,
        "wires": [
            [
                "9212e6e74813e158",
                "a062287a56ea6b17"
            ]
        ]
    },
    {
        "id": "9212e6e74813e158",
        "type": "ui_gauge",
        "z": "e304fa4e58cbecd1",
        "name": "",
        "group": "35c4ebb396aeece3",
        "order": 1,
        "width": 6,
        "height": 4,
        "gtype": "gage",
        "title": "Temperature",
        "label": "C",
        "format": "{{value}}",
        "min": 0,
        "max": "60",
        "colors": [
            "#00b500",
            "#e6e600",
            "#ca3838"
        ],
        "seg1": "",
        "seg2": "",
        "diff": false,
        "className": "",
        "x": 490,
        "y": 80,
        "wires": []
    },
    {
        "id": "a062287a56ea6b17",
        "type": "ui_chart",
        "z": "e304fa4e58cbecd1",
        "name": "",
        "group": "35c4ebb396aeece3",
        "order": 2,
        "width": 6,
        "height": 4,
        "label": "Temperature",
        "chartType": "line",
        "legend": "false",
        "xformat": "HH:mm:ss",
        "interpolate": "linear",
        "nodata": "",
        "dot": false,
        "ymin": "",
        "ymax": "",
        "removeOlder": 1,
        "removeOlderPoints": "",
        "removeOlderUnit": "3600",
        "cutout": 0,
        "useOneColor": false,
        "useUTC": false,
        "colors": [
            "#1f77b4",
            "#aec7e8",
            "#ff7f0e",
            "#2ca02c",
            "#98df8a",
            "#d62728",
            "#ff9896",
            "#9467bd",
            "#c5b0d5"
        ],
        "outputs": 1,
        "useDifferentColor": false,
        "className": "",
        "x": 490,
        "y": 40,
        "wires": [
            []
        ]
    },
    {
        "id": "843e4a24401f9145",
        "type": "ui_gauge",
        "z": "e304fa4e58cbecd1",
        "name": "",
        "group": "797ca08f74dee60b",
        "order": 1,
        "width": 7,
        "height": 4,
        "gtype": "gage",
        "title": "MCP9700 temp",
        "label": "C",
        "format": "{{value}}",
        "min": 0,
        "max": "50",
        "colors": [
            "#00b500",
            "#e6e600",
            "#ca3838"
        ],
        "seg1": "",
        "seg2": "",
        "diff": false,
        "className": "",
        "x": 920,
        "y": 400,
        "wires": []
    },
    {
        "id": "af2bd4c95af86eee",
        "type": "mqtt in",
        "z": "e304fa4e58cbecd1",
        "name": "",
        "topic": "esp32/atmospheric_pressure",
        "qos": "2",
        "datatype": "auto-detect",
        "broker": "590e3ceaadf4028f",
        "nl": false,
        "rap": true,
        "rh": 0,
        "inputs": 0,
        "x": 160,
        "y": 200,
        "wires": [
            [
                "4719b65865ab77db"
            ]
        ]
    },
    {
        "id": "4719b65865ab77db",
        "type": "function",
        "z": "e304fa4e58cbecd1",
        "name": "Convert Pa in mmHg",
        "func": "// Preia valoarea presiunii din mesaj\nvar pressurePa = msg.payload;\n\n// Transform valoarea din Pa n mmHg\nvar pressureMmHg = Math.round(pressurePa / 133.3223684);\n\n// Creeaz un nou mesaj cu valoarea transformat\nmsg.payload = pressureMmHg;\n\n// Returneaz mesajul\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 340,
        "y": 260,
        "wires": [
            [
                "76d89e8d970f05e3"
            ]
        ]
    },
    {
        "id": "76d89e8d970f05e3",
        "type": "ui_gauge",
        "z": "e304fa4e58cbecd1",
        "name": "",
        "group": "35c4ebb396aeece3",
        "order": 4,
        "width": 6,
        "height": 4,
        "gtype": "gage",
        "title": "Atmospheric pressure",
        "label": "mmHg",
        "format": "{{value}}",
        "min": "700",
        "max": "800",
        "colors": [
            "#b30012",
            "#e6e600",
            "#04fb21"
        ],
        "seg1": "740",
        "seg2": "760",
        "diff": false,
        "className": "",
        "x": 520,
        "y": 200,
        "wires": []
    },
    {
        "id": "ba37a2b88a0ed90c",
        "type": "function",
        "z": "e304fa4e58cbecd1",
        "name": "Combine integer and decimal for external temp sensor",
        "func": "// Verific dac flow context are deja datele pentru partea ntreag i partea zecimal\nlet partIntreaga = flow.get('partIntreaga') || null;\nlet partZecimala = flow.get('partZecimala') || null;\n\nif (msg.topic === \"esp32/AnalogExternalTempInteger\") {\n    partIntreaga = msg.payload;\n    flow.set('partIntreaga', partIntreaga);\n} else if (msg.topic === \"esp32/AnalogExternalTempDecimal\") {\n    partZecimala = msg.payload;\n    flow.set('partZecimala', partZecimala);\n}\n\n// Dac ambele pri sunt disponibile, combin-le\nif (partIntreaga !== null && partZecimala !== null) {\n    let numarComplet = parseFloat(partIntreaga + '.' + partZecimala);\n\n    // Reseteaz prile n flow context\n    flow.set('partIntreaga', null);\n    flow.set('partZecimala', null);\n\n    // Trimite numrul complet pentru afiare\n    msg.payload = numarComplet;\n    return msg;\n} else {\n    // Dac nu avem nc ambele pri, nu trimitem nimic\n    return null;\n}\n",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 580,
        "y": 360,
        "wires": [
            [
                "6ce73293a358dbfc",
                "843e4a24401f9145"
            ]
        ]
    },
    {
        "id": "cb456cd7124c3af4",
        "type": "mqtt in",
        "z": "e304fa4e58cbecd1",
        "name": "",
        "topic": "esp32/AnalogExternalTempDecimal",
        "qos": "2",
        "datatype": "auto-detect",
        "broker": "590e3ceaadf4028f",
        "nl": false,
        "rap": true,
        "rh": 0,
        "inputs": 0,
        "x": 180,
        "y": 400,
        "wires": [
            [
                "ba37a2b88a0ed90c"
            ]
        ]
    },
    {
        "id": "fa96a33041c9425f",
        "type": "mqtt in",
        "z": "e304fa4e58cbecd1",
        "name": "",
        "topic": "esp32/AnalogInternalTempInteger",
        "qos": "2",
        "datatype": "auto-detect",
        "broker": "590e3ceaadf4028f",
        "nl": false,
        "rap": true,
        "rh": 0,
        "inputs": 0,
        "x": 170,
        "y": 460,
        "wires": [
            [
                "7ca2d5244f392948"
            ]
        ]
    },
    {
        "id": "fa243e4ba081f644",
        "type": "mqtt in",
        "z": "e304fa4e58cbecd1",
        "name": "",
        "topic": "esp32/AnalogInternalTempDecimal",
        "qos": "2",
        "datatype": "auto-detect",
        "broker": "590e3ceaadf4028f",
        "nl": false,
        "rap": true,
        "rh": 0,
        "inputs": 0,
        "x": 180,
        "y": 520,
        "wires": [
            [
                "7ca2d5244f392948"
            ]
        ]
    },
    {
        "id": "7ca2d5244f392948",
        "type": "function",
        "z": "e304fa4e58cbecd1",
        "name": "Combine integer and decimal for interna temp sensor",
        "func": "// Verific dac flow context are deja datele pentru partea ntreag i partea zecimal\nlet partIntreaga = flow.get('partIntreaga') || null;\nlet partZecimala = flow.get('partZecimala') || null;\n\nif (msg.topic === \"esp32/AnalogInternalTempInteger\") {\n    partIntreaga = msg.payload;\n    flow.set('partIntreaga', partIntreaga);\n} else if (msg.topic === \"esp32/AnalogInternalTempDecimal\") {\n    partZecimala = msg.payload;\n    flow.set('partZecimala', partZecimala);\n}\n\n// Dac ambele pri sunt disponibile, combin-le\nif (partIntreaga !== null && partZecimala !== null) {\n    let numarComplet = parseFloat(partIntreaga + '.' + partZecimala);\n\n    // Reseteaz prile n flow context\n    flow.set('partIntreaga', null);\n    flow.set('partZecimala', null);\n\n    // Trimite numrul complet pentru afiare\n    msg.payload = numarComplet;\n    return msg;\n} else {\n    // Dac nu avem nc ambele pri, nu trimitem nimic\n    return null;\n}",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 580,
        "y": 480,
        "wires": [
            [
                "4ff3829940597873",
                "e781571db5355b78"
            ]
        ]
    },
    {
        "id": "e781571db5355b78",
        "type": "ui_gauge",
        "z": "e304fa4e58cbecd1",
        "name": "",
        "group": "797ca08f74dee60b",
        "order": 3,
        "width": 7,
        "height": 4,
        "gtype": "gage",
        "title": "Internal beacon temp",
        "label": "C",
        "format": "{{value}}",
        "min": 0,
        "max": "50",
        "colors": [
            "#00b500",
            "#e6e600",
            "#ca3838"
        ],
        "seg1": "",
        "seg2": "",
        "diff": false,
        "className": "",
        "x": 940,
        "y": 520,
        "wires": []
    },
    {
        "id": "4ff3829940597873",
        "type": "ui_chart",
        "z": "e304fa4e58cbecd1",
        "name": "",
        "group": "797ca08f74dee60b",
        "order": 4,
        "width": 5,
        "height": 4,
        "label": "Internal beacon temp",
        "chartType": "line",
        "legend": "false",
        "xformat": "HH:mm:ss",
        "interpolate": "linear",
        "nodata": "",
        "dot": false,
        "ymin": "",
        "ymax": "",
        "removeOlder": 1,
        "removeOlderPoints": "",
        "removeOlderUnit": "3600",
        "cutout": 0,
        "useOneColor": false,
        "useUTC": false,
        "colors": [
            "#1f77b4",
            "#aec7e8",
            "#ff7f0e",
            "#2ca02c",
            "#98df8a",
            "#d62728",
            "#ff9896",
            "#9467bd",
            "#c5b0d5"
        ],
        "outputs": 1,
        "useDifferentColor": false,
        "className": "",
        "x": 940,
        "y": 460,
        "wires": [
            []
        ]
    },
    {
        "id": "5843d70aaa5ff3b0",
        "type": "mqtt in",
        "z": "e304fa4e58cbecd1",
        "name": "",
        "topic": "esp32/sht40_temperature",
        "qos": "2",
        "datatype": "auto-detect",
        "broker": "590e3ceaadf4028f",
        "nl": false,
        "rap": true,
        "rh": 0,
        "inputs": 0,
        "x": 150,
        "y": 820,
        "wires": [
            [
                "8dbf113aac34ead1",
                "27b45588fe35f85a",
                "0cb4895a9905657a"
            ]
        ]
    },
    {
        "id": "14bbc828829b30e9",
        "type": "mqtt in",
        "z": "e304fa4e58cbecd1",
        "name": "",
        "topic": "esp32/sht40_humidity",
        "qos": "2",
        "datatype": "auto-detect",
        "broker": "590e3ceaadf4028f",
        "nl": false,
        "rap": true,
        "rh": 0,
        "inputs": 0,
        "x": 140,
        "y": 960,
        "wires": [
            [
                "d11c433c9e47e93a",
                "0cb4895a9905657a"
            ]
        ]
    },
    {
        "id": "0cb4895a9905657a",
        "type": "function",
        "z": "e304fa4e58cbecd1",
        "name": "Calculate ITU and DEW",
        "func": "// Stocarea valorilor primite n contextul de flux\nif (msg.topic === \"esp32/sht40_temperature\") {\n    flow.set(\"temperature\", parseFloat(msg.payload));\n} else if (msg.topic === \"esp32/sht40_humidity\") {\n    flow.set(\"humidity\", parseFloat(msg.payload));\n}\n\n// Obinerea valorilor din context\nvar temperature = flow.get(\"temperature\");\nvar humidity = flow.get(\"humidity\");\n\n// Calcularea punctului de rou i a factorului de confort\nif (temperature !== undefined && humidity !== undefined) {\n    // Calcularea punctului de rou\n    var dewPoint = temperature - ((100 - humidity) / 5);\n\n    // Calcularea factorului de confort (indicele de cldur)\n    var heatIndex = temperature - ((0.55 - 0.0055 * humidity) * (temperature - 14.5));\n\n    // Trimiterea rezultatelor n dou mesaje separate\n    var msg1 = { topic: \"dewPoint\", payload: dewPoint.toFixed(2) };\n    var msg2 = { topic: \"heatIndex\", payload: heatIndex.toFixed(2) };\n\n    return [msg1, msg2];\n} else {\n    return null; // Dac nu avem ambele valori, nu trimitem nimic\n}\n",
        "outputs": 2,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 430,
        "y": 900,
        "wires": [
            [
                "20273cb17d411f08"
            ],
            [
                "7afb545880a6dae1"
            ]
        ]
    },
    {
        "id": "27b45588fe35f85a",
        "type": "ui_gauge",
        "z": "e304fa4e58cbecd1",
        "name": "",
        "group": "8d899e0618059e63",
        "order": 1,
        "width": 7,
        "height": 4,
        "gtype": "gage",
        "title": "Temperature",
        "label": "C",
        "format": "{{value}}",
        "min": 0,
        "max": "50",
        "colors": [
            "#00b500",
            "#e6e600",
            "#ca3838"
        ],
        "seg1": "",
        "seg2": "",
        "diff": false,
        "className": "",
        "x": 490,
        "y": 840,
        "wires": []
    },
    {
        "id": "8dbf113aac34ead1",
        "type": "ui_chart",
        "z": "e304fa4e58cbecd1",
        "name": "",
        "group": "8d899e0618059e63",
        "order": 2,
        "width": 5,
        "height": 4,
        "label": "Temperature",
        "chartType": "line",
        "legend": "false",
        "xformat": "HH:mm:ss",
        "interpolate": "linear",
        "nodata": "",
        "dot": false,
        "ymin": "",
        "ymax": "",
        "removeOlder": 1,
        "removeOlderPoints": "",
        "removeOlderUnit": "3600",
        "cutout": 0,
        "useOneColor": false,
        "useUTC": false,
        "colors": [
            "#1f77b4",
            "#aec7e8",
            "#ff7f0e",
            "#2ca02c",
            "#98df8a",
            "#d62728",
            "#ff9896",
            "#9467bd",
            "#c5b0d5"
        ],
        "outputs": 1,
        "useDifferentColor": false,
        "className": "",
        "x": 490,
        "y": 780,
        "wires": [
            []
        ]
    },
    {
        "id": "d11c433c9e47e93a",
        "type": "ui_gauge",
        "z": "e304fa4e58cbecd1",
        "name": "",
        "group": "8d899e0618059e63",
        "order": 3,
        "width": 12,
        "height": 4,
        "gtype": "gage",
        "title": "Humidity",
        "label": "%RH",
        "format": "{{value}}",
        "min": 0,
        "max": "100",
        "colors": [
            "#dbf070",
            "#0dfd69",
            "#fd0808"
        ],
        "seg1": "50",
        "seg2": "80",
        "diff": false,
        "className": "",
        "x": 480,
        "y": 960,
        "wires": []
    },
    {
        "id": "20273cb17d411f08",
        "type": "ui_gauge",
        "z": "e304fa4e58cbecd1",
        "name": "",
        "group": "8d899e0618059e63",
        "order": 4,
        "width": 6,
        "height": 4,
        "gtype": "gage",
        "title": "DEW point",
        "label": "units",
        "format": "{{value}}",
        "min": "-10",
        "max": "40",
        "colors": [
            "#d0f80d",
            "#0af539",
            "#fb8e8e"
        ],
        "seg1": "",
        "seg2": "",
        "diff": false,
        "className": "",
        "x": 690,
        "y": 860,
        "wires": []
    },
    {
        "id": "7afb545880a6dae1",
        "type": "ui_gauge",
        "z": "e304fa4e58cbecd1",
        "name": "",
        "group": "8d899e0618059e63",
        "order": 5,
        "width": 6,
        "height": 4,
        "gtype": "gage",
        "title": "Confort factor ITU",
        "label": "",
        "format": "{{value}} C",
        "min": 0,
        "max": "100",
        "colors": [
            "#b4ea1f",
            "#00e663",
            "#f92424"
        ],
        "seg1": "40",
        "seg2": "80",
        "diff": false,
        "className": "",
        "x": 710,
        "y": 920,
        "wires": []
    },
    {
        "id": "590e3ceaadf4028f",
        "type": "mqtt-broker",
        "name": "",
        "broker": "localhost",
        "port": "1883",
        "clientid": "",
        "autoConnect": true,
        "usetls": false,
        "protocolVersion": "4",
        "keepalive": "60",
        "cleansession": true,
        "autoUnsubscribe": true,
        "birthTopic": "",
        "birthQos": "0",
        "birthRetain": "false",
        "birthPayload": "",
        "birthMsg": {},
        "closeTopic": "",
        "closeQos": "0",
        "closeRetain": "false",
        "closePayload": "",
        "closeMsg": {},
        "willTopic": "",
        "willQos": "0",
        "willRetain": "false",
        "willPayload": "",
        "willMsg": {},
        "userProps": "",
        "sessionExpiry": ""
    },
    {
        "id": "797ca08f74dee60b",
        "type": "ui_group",
        "name": "Analog sensors: MCP9700, Light and Moisture",
        "tab": "996774836996b55a",
        "order": 1,
        "disp": true,
        "width": "12",
        "collapse": false,
        "className": ""
    },
    {
        "id": "35c4ebb396aeece3",
        "type": "ui_group",
        "name": "Digital sensor: ICP10111",
        "tab": "996774836996b55a",
        "order": 1,
        "disp": true,
        "width": "12",
        "collapse": false,
        "className": ""
    },
    {
        "id": "8d899e0618059e63",
        "type": "ui_group",
        "name": "Digital sensor: SHT40",
        "tab": "996774836996b55a",
        "order": 3,
        "disp": true,
        "width": 12,
        "collapse": false,
        "className": ""
    },
    {
        "id": "996774836996b55a",
        "type": "ui_tab",
        "name": "DFRobot",
        "icon": "dashboard",
        "disabled": false,
        "hidden": false
    }
]

ICP10111.cfg

JSON
BLE Beacon ICP10111 sensor configuration used with InPlay Inc NanoBeacon™ Config Tool
{
    "version": "3.12",
    "advSet": [
        {
            "id": 0,
            "bdAddr": "060504030201",
            "addrType": "public",
            "addrKey": 0,
            "staticAddrGen": 1,
            "addrGenInterval": 90,
            "interval": 1000,
            "authEn": 0,
            "authKey": 0,
            "authSaltType": 2,
            "authSaltValue": 0,
            "authEaxCountType": 0,
            "authEaxCountValue": 0,
            "ui_format": "custom",
            "uid2tlm_ratio": 0.0,
            "eddystoneTxPower": 0,
            "chCtrl": 0,
            "advModeTrigEn": 0,
            "is1MPhy": 1,
            "phyRate": "1M",
            "isStandardBle": 1,
            "cte": 0,
            "cteLen": 0,
            "randomDlyType": 0,
            "payloadVer": 3,
            "payload": [
                {
                    "len": 9,
                    "type": 9,
                    "data": "4943503130313131"
                },
                {
                    "len": 17,
                    "type": 255,
                    "data": "0505<I2C1R0 14byte 0 0>"
                }
            ]
        }
    ],
    "txSetting": {
        "txPower": 0,
        "txPaGain": -1,
        "sleepAftTx": 1,
        "uartSingleWire": 0,
        "uartPinSel": 0,
        "xoCap": 12,
        "xoStableTime": 36,
        "xoGm": 16,
        "ch0": 37,
        "ch1": 38,
        "ch2": 39,
        "key0": "000102030405060708090a0b0c0d0e0f"
    },
    "gpio": [
        {
            "id": 0,
            "digital": "default",
            "pu-pd": 1,
            "wakeup": "disable",
            "advTrig": "disable",
            "latch": 0,
            "maskb": 0
        },
        {
            "id": 1,
            "digital": "default",
            "pu-pd": 1,
            "wakeup": "disable",
            "advTrig": "disable",
            "latch": 0,
            "maskb": 0
        },
        {
            "id": 2,
            "digital": "default",
            "pu-pd": 1,
            "wakeup": "disable",
            "advTrig": "disable",
            "latch": 0,
            "maskb": 0
        },
        {
            "id": 3,
            "digital": "default",
            "pu-pd": 1,
            "wakeup": "disable",
            "advTrig": "disable",
            "latch": 0,
            "maskb": 0
        },
        {
            "id": 4,
            "digital": "default",
            "pu-pd": 1,
            "wakeup": "disable",
            "advTrig": "disable",
            "latch": 0,
            "maskb": 0
        },
        {
            "id": 5,
            "digital": "default",
            "pu-pd": 1,
            "wakeup": "disable",
            "advTrig": "disable",
            "latch": 0,
            "maskb": 0
        },
        {
            "id": 6,
            "digital": "default",
            "pu-pd": 1,
            "wakeup": "disable",
            "advTrig": "disable",
            "latch": 0,
            "maskb": 0
        },
        {
            "id": 7,
            "digital": "default",
            "pu-pd": 1,
            "wakeup": "disable",
            "advTrig": "disable",
            "latch": 0,
            "maskb": 0
        }
    ],
    "vccUnit": 0.03125,
    "tempUnit": 0.01,
    "adc": [
        {
            "ch": 0,
            "enable": 0
        },
        {
            "ch": 1,
            "enable": 0
        },
        {
            "ch": 2,
            "enable": 0
        },
        {
            "ch": 3,
            "enable": 0
        }
    ],
    "calibration": {},
    "i2c": {
        "sw0PwrCtl": 0,
        "coldBootEn": 1,
        "warmBootEn": 1,
        "sclPin": 7,
        "sdaPin": 3,
        "addrBit": 7,
        "speed": 100,
        "slvAddr": 99,
        "memStoreLen": 14,
        "memStoreOffset": 0,
        "cmd": [
            "i2c tx: 3 c5",
            "i2c tx: 3 95",
            "i2c tx: 3 0",
            "i2c tx: 3 66",
            "i2c tx: 3 9c",
            "i2c null:",
            "i2c tx: 3 c7",
            "i2c tx: 3 f7",
            "i2c null:",
            "i2c rx: 3",
            "i2c rx: 3",
            "i2c null:",
            "i2c tx: 3 c7",
            "i2c tx: 3 f7",
            "i2c null:",
            "i2c rx: 3",
            "i2c rx: 3",
            "i2c null:",
            "i2c tx: 3 c7",
            "i2c tx: 3 f7",
            "i2c null:",
            "i2c rx: 3",
            "i2c rx: 3",
            "i2c null:",
            "i2c tx: 3 c7",
            "i2c tx: 3 f7",
            "i2c null:",
            "i2c rx: 3",
            "i2c rx: 3",
            "i2c null:",
            "i2c wait: 3 1 8",
            "i2c tx: 3 68",
            "i2c tx: 3 25",
            "i2c null:",
            "i2c wait: 3 1 37",
            "i2c rx: 3",
            "i2c rx: 3",
            "i2c null:",
            "i2c tx: 3 48",
            "i2c tx: 3 a3",
            "i2c null:",
            "i2c wait: 3 1 37",
            "i2c rx: 3",
            "i2c rx: 3",
            "i2c rx: 3",
            "i2c rx: 3",
            "i2c null:"
        ]
    },
    "i2c2": {
        "coldBootEn": 0,
        "warmBootEn": 0
    },
    "i2c3": {
        "coldBootEn": 0,
        "warmBootEn": 0
    },
    "pulse": {
        "enable": 0
    },
    "qdec": {
        "enable": 0,
        "runGpioEdgeDetect": 0,
        "clearCount": 0,
        "endCode": 15,
        "twoStep": 0,
        "interval": 999,
        "timeout": 1999,
        "gpio": [],
        "code": []
    },
    "wdt": {
        "timerWraparound": 0,
        "enable": 0,
        "wakeupChip": 0,
        "initValue": 30
    },
    "edgeCount": {
        "enable": 0
    },
    "sqWave": {
        "en": 0
    },
    "rtc": {
        "enable": 0,
        "clock": 0,
        "type": 0
    },
    "regSetting": [
        "write: 0 1 3 3480 2010000",
        "write: 0 1 3 3484 3030002",
        "write: 0 1 1 34c8 102",
        "write: 0 1 3 3494 10020018",
        "write: 3 1 0 1084 0",
        "write: 3 1 0 11C8 0",
        "write: 3 1 0 1c44 c6",
        "write: 3 1 0 1ad0 58",
        "write: 3 1 1 1d04 731",
        "write: 0 1 0 3240 42",
        "write: 0 1 0 3500 03"
    ],
    "regSettingCust": [],
    "settingPolice": 0
}

SHT40.cfg

JSON
BLE Beacon SHT40 sensor configuration used with InPlay Inc NanoBeacon™ Config Tool
{
    "version": "3.12",
    "advSet": [
        {
            "id": 0,
            "bdAddr": "060504030201",
            "addrType": "public",
            "addrKey": 0,
            "staticAddrGen": 1,
            "addrGenInterval": 90,
            "interval": 5000,
            "authEn": 0,
            "authKey": 0,
            "authSaltType": 2,
            "authSaltValue": 0,
            "authEaxCountType": 0,
            "authEaxCountValue": 0,
            "ui_format": "custom",
            "uid2tlm_ratio": 0.0,
            "eddystoneTxPower": 0,
            "chCtrl": 0,
            "advModeTrigEn": 0,
            "is1MPhy": 1,
            "phyRate": "1M",
            "isStandardBle": 1,
            "cte": 0,
            "cteLen": 0,
            "randomDlyType": 0,
            "payloadVer": 3,
            "payload": [
                {
                    "len": 6,
                    "type": 9,
                    "data": "5348543430"
                },
                {
                    "len": 8,
                    "type": 255,
                    "data": "0505<I2C1R0 5byte 0 0>"
                }
            ]
        }
    ],
    "txSetting": {
        "txPower": 0,
        "txPaGain": -1,
        "sleepAftTx": 1,
        "uartSingleWire": 0,
        "uartPinSel": 0,
        "xoCap": 12,
        "xoStableTime": 36,
        "xoGm": 16,
        "ch0": 37,
        "ch1": 38,
        "ch2": 39,
        "key0": "000102030405060708090a0b0c0d0e0f"
    },
    "gpio": [
        {
            "id": 0,
            "digital": "default",
            "pu-pd": 1,
            "wakeup": "disable",
            "advTrig": "disable",
            "latch": 0,
            "maskb": 0
        },
        {
            "id": 1,
            "digital": "default",
            "pu-pd": 1,
            "wakeup": "disable",
            "advTrig": "disable",
            "latch": 0,
            "maskb": 0
        },
        {
            "id": 2,
            "digital": "default",
            "pu-pd": 1,
            "wakeup": "disable",
            "advTrig": "disable",
            "latch": 0,
            "maskb": 0
        },
        {
            "id": 3,
            "digital": "default",
            "pu-pd": 1,
            "wakeup": "disable",
            "advTrig": "disable",
            "latch": 0,
            "maskb": 0
        },
        {
            "id": 4,
            "digital": "default",
            "pu-pd": 1,
            "wakeup": "disable",
            "advTrig": "disable",
            "latch": 0,
            "maskb": 0
        },
        {
            "id": 5,
            "digital": "default",
            "pu-pd": 1,
            "wakeup": "disable",
            "advTrig": "disable",
            "latch": 0,
            "maskb": 0
        },
        {
            "id": 6,
            "digital": "oeHigh",
            "pu-pd": 1,
            "wakeup": "disable",
            "advTrig": "disable",
            "latch": 1,
            "maskb": 0
        },
        {
            "id": 7,
            "digital": "default",
            "pu-pd": 1,
            "wakeup": "disable",
            "advTrig": "disable",
            "latch": 0,
            "maskb": 0
        }
    ],
    "vccUnit": 0.03125,
    "tempUnit": 0.01,
    "adc": [
        {
            "ch": 0,
            "enable": 0
        },
        {
            "ch": 1,
            "enable": 0
        },
        {
            "ch": 2,
            "enable": 0
        },
        {
            "ch": 3,
            "enable": 0
        }
    ],
    "calibration": {},
    "i2c": {
        "sw0PwrCtl": 1,
        "coldBootEn": 1,
        "warmBootEn": 1,
        "sclPin": 7,
        "sdaPin": 3,
        "addrBit": 7,
        "speed": 100,
        "slvAddr": 68,
        "memStoreLen": 5,
        "memStoreOffset": 0,
        "cmd": [
            "i2c tx: 3 fd",
            "i2c null:",
            "i2c wait: 3 1 4e",
            "i2c rx: 3",
            "i2c rx: 3",
            "i2c rx: 3",
            "i2c rx: 3",
            "i2c rx: 3",
            "i2c null:"
        ]
    },
    "i2c2": {
        "coldBootEn": 0,
        "warmBootEn": 0
    },
    "i2c3": {
        "coldBootEn": 0,
        "warmBootEn": 0
    },
    "pulse": {
        "enable": 0
    },
    "qdec": {
        "enable": 0,
        "runGpioEdgeDetect": 0,
        "clearCount": 0,
        "endCode": 15,
        "twoStep": 0,
        "interval": 999,
        "timeout": 1999,
        "gpio": [],
        "code": []
    },
    "wdt": {
        "timerWraparound": 0,
        "enable": 0,
        "wakeupChip": 0,
        "initValue": 30
    },
    "edgeCount": {
        "enable": 0
    },
    "sqWave": {
        "en": 0
    },
    "rtc": {
        "enable": 0,
        "clock": 0,
        "type": 0
    },
    "regSetting": [
        "write: 0 1 3 3480 2010000",
        "write: 0 1 3 3484 3030002",
        "write: 0 1 1 34c8 102",
        "write: 0 1 3 3494 10020018",
        "write: 3 1 0 1084 0",
        "write: 3 1 0 11C8 0",
        "write: 3 1 0 1c44 c6",
        "write: 3 1 0 1ad0 58",
        "write: 3 1 1 1d04 731",
        "write: 0 1 0 3240 42",
        "write: 0 1 0 3500 03"
    ],
    "regSettingCust": [],
    "settingPolice": 0
}

Cod_final.ino

C/C++
Code used on ESP32-E to collect data from BLE BEacons and send then to Node-red
#include <Arduino.h>
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEScan.h>
#include <BLEAdvertisedDevice.h>

#define ENDIAN_CHANGE_U16(x) ((((x)&0xFF00) >> 8) + (((x)&0xFF) << 8))

#define RXD2 16 //communication using Serial2
#define TXD2 17 //communication using Serial

//connection to local wifi to send data to Node-Red:
const char* ssid           = "xxxx";  //WiFi SSID to connect to send data to Node-Red
const char* pass           = "xxxx";  //WiFi pass to connect to send data to Node-Red
const char* mqtt_client_id = "xxxx";  //MQTT client ID used by Node-red
const char* mqtt_user      = "xxxx";  //MQTT user for Node-Red; see Node-Red documentation
const char* mqtt_pass      = "xxxx";  //MQTT pass for Node-Red; see Node-Red documentation
const char* mqtt_host      = "xxxx";  //MQTT host for Node-Red; see Node-Red documentation
char finalTopic_wifi[200];            //used to send the complete string to Node-Red 


//variables used for several timers:
unsigned long interval_1 = 30000;             //used to send the data to Node-Red via WiFi; (30000 = 30000ms)
unsigned long timer_1 = 0;                    //used to send data at every 30 seconds (30000 = 30000ms)
uint32_t timer = millis();

//variable used for SHT40 sensor:
float TemperatureData, HumidityData;
float Temperature, Humidity;
float SHT40_temperature, SHT40_humidity;

//variable used for Analog sensors:
int ExternalTempData;
int InternalTempData;
int BatteryData;
int MoistureData;
int LightData;
int AnalogExternalTempInteger;
int AnalogExternalTempDecimal;
int AnalogInternalTempInteger;
int AnalogInternalTempDecimal;
float batteryVoltage;

//variable used to transfer data to MQTT for ICP10111
float ICP10111_temperature;
float ICP10111_elevation;
float ICP10111_airPressure;

//variables, structures and functions used for ICP10111 sensor:
/**
 * @struct  sInvInvpres_t
 * @brief   Store the calculated data
 */
typedef struct {
  float sensorConstants[4]; // OTP values
  float pPaCalib[3];
  float LUTLower;
  float LUTUpper;
  float quadrFactor;
  float offstFactor;
}sInvInvpres_t;

/**
 * @struct sGetTempAndAirPressure_t
 * @brief Save the temperature and air pressure data
 */
typedef struct {
  float temp;
  float airPressure;
  float elevation;
}sGetTempAndAirPressure_t;
/**
 * @struct sInitialData_t
 * @brief Store initial check data
 */
typedef struct {
  float s1;
  float s2;
  float s3;
}sInitialData_t;
/**
 * @struct sUltimatelyData_t
 * @brief Store ultimate check data
 */
typedef struct {
  float A;
  float B;
  float C;
}sUltimatelyData_t;

/**
* @enum eWorkPattern_t
* @brief Work mode select
*/
typedef enum {
  eLowPower_P = 0x401A, /**<Low Power Mode Conversion Time: 1.8ms  Pressure RMS Noise:3.2Pa*/
  eNormal_P = 0x48A3, /**<Normal Mode Conversion Time:6.3ms Pressure RMS Noise:1.6Pa*/
  eLowNoise_P = 0x5059, /**<Low Noise Mode Conversion Time:23.8ms  Pressure RMS Noise:0.8Pa*/
  eUltraLowNoise_P = 0x58E0, /**<Ultra Low Noise Mode Conversion Time:94.5  Pressure RMS Noise:0.4Pa*/
  eLowPower_T = 0x609C,
  eNormal_T = 0x6825,
  eLowNoise_T = 0x70DF,
  eUltraLowNoise_T = 0x7866,
}eWorkPattern_t;

sInvInvpres_t _dataStorage;
sInvInvpres_t* _d = &_dataStorage;

sGetTempAndAirPressure_t _tempAndAirPressure;
sGetTempAndAirPressure_t* _t = &_tempAndAirPressure;

sInitialData_t _inputData;
sInitialData_t* _i = &_inputData;

sUltimatelyData_t _outData;
sUltimatelyData_t* _o = &_outData;

bool optSetFlag = false;

//fucntions used for ICP1011 sensor:
void initBase(sInvInvpres_t* s, short* otp)
{
  for (uint8_t i = 0; i < 4; i++) {
    s->sensorConstants[i] = otp[i];
  }
  s->pPaCalib[0] = 45000.0;
  s->pPaCalib[1] = 80000.0;
  s->pPaCalib[2] = 105000.0;
  s->LUTLower = 3.5 * ((uint32_t)1 << 20);
  s->LUTUpper = 11.5 * ((uint32_t)1 << 20);
  s->quadrFactor = 1 / 16777216.0;
  s->offstFactor = 2048.0;
}

void calculateConversionConstants(float* pPa, sInitialData_t* i)
{
  _o->C = (i->s1 * i->s2 * (pPa[0] - pPa[1]) + \
    i->s2 * i->s3 * (pPa[1] - pPa[2]) + \
    i->s3 * i->s1 * (pPa[2] - pPa[0])) / \
    (i->s3 * (pPa[0] - pPa[1]) + i->s1 * (pPa[1] - pPa[2]) + \
      i->s2 * (pPa[2] - pPa[0]));
  _o->A = (pPa[0] * i->s1 - pPa[1] * i->s2 - (pPa[1] - pPa[0]) * _o->C) / (i->s1 - i->s2);
  _o->B = (pPa[0] - _o->A) * (i->s1 + _o->C);
}

void getTempAndAirPressure(uint16_t _temp, uint32_t _airPressure)
{
  float t;
  // temperature
  t = (float)(_temp - 32768);
  _i->s1 = _d->LUTLower + (float)(_d->sensorConstants[0] * t * t) * _d->quadrFactor;
  _i->s2 = _d->offstFactor * _d->sensorConstants[3] + (float)(_d->sensorConstants[1] * t * t) * _d->quadrFactor;
  _i->s3 = _d->LUTUpper + (float)(_d->sensorConstants[2] * t * t) * _d->quadrFactor;
  calculateConversionConstants(_d->pPaCalib, _i);

  // pressure
  _t->airPressure = _o->A + (_o->B / (_o->C + _airPressure));
  _t->temp = -45.f + 175.f / 65536.f * _temp;

  // altitude
  _t->elevation = 44330 * (1.0 - pow((_t->airPressure / 100.0) / 1015.0, 0.1903));
}

int scanTime = 5; // In seconds
BLEScan *pBLEScan;

class MyAdvertisedDeviceCallbacks : public BLEAdvertisedDeviceCallbacks {
  void onResult(BLEAdvertisedDevice advertisedDevice) {
    if (advertisedDevice.haveName()) {
      std:: string deviceName = advertisedDevice.getName().c_str(); // Convert to std::string
 //     Serial.print("Device name: ");
 //     Serial.println(deviceName.c_str());

      if (deviceName == "Analog")
      {
        Serial.print("Device name: ");
        Serial.println(deviceName.c_str());
        
        std::string strManufacturerData = advertisedDevice.getManufacturerData().c_str(); // Convert to std::string
        uint8_t cManufacturerData[100];
        strManufacturerData.copy((char *)cManufacturerData, strManufacturerData.length(), 0);
        Serial.printf("Manufacturer Data Length: %d ", strManufacturerData.length());

        for (size_t i = 0; i < strManufacturerData.length(); i++) 
        {
          Serial.printf("[%X]", cManufacturerData[i]);
        }
        Serial.println();


      //read RAW data and extract the last 10 bytes:
      // Advertisement Data (Raw Data)
      uint8_t* advData = advertisedDevice.getPayload();
      size_t advLength = advertisedDevice.getPayloadLength();
      
      // Convertim advData ntr-un std::string
      std::string advDataStr((char*)advData, advLength);

      // Extrage doar ultimii 11 octei (sau mai puin, dac lungimea este mai mic)
      size_t startIdx = (advLength > 11) ? (advLength - 11) : 0;
      size_t numBytes = (advLength > 11) ? 11 : advLength;
      
      std::string usefulData = advDataStr.substr(startIdx, numBytes);
      
      Serial.printf("Useful Data Length: %d", usefulData.length());
//      Serial.printf("Useful Data Length: %d\n", usefulData.length());
//      Serial.println();
//      Serial.print("Useful Data: ");
      for (size_t i = 0; i < usefulData.length(); i++) 
      {
        Serial.printf("[%02X]", (unsigned char)usefulData[i]);
      }
      Serial.println();

        // Getting raw data from 
        int ExternalTempData = float((usefulData[2] << 8 | usefulData[3]));
            BatteryData      = int(usefulData[4]);
        int InternalTempData = float(usefulData[5] << 8 | usefulData[6]);
            MoistureData     = int(usefulData[7] << 8 | usefulData[8]); 
            LightData        = int(usefulData[9] << 8 | usefulData[10]);

        ExternalTempData = ExternalTempData - 500; 
        
        float scaling_factor = 32.9; //is calculated from: 2.9V/88, where 88 is the value sent by the BLE Beacon ADC
              batteryVoltage = BatteryData * scaling_factor / 1000.0;
                
        int ExternalTempInteger = ExternalTempData / 10; 
        int ExternalTempDecimal = ExternalTempData % 10;
                  
        int BatteryInteger = BatteryData / 100;
        int BatteryDecimal = BatteryData % 100;

        int InternalTempInteger = InternalTempData / 100;
        int InternalTempDecimal = InternalTempData % 100;

        AnalogExternalTempInteger = ExternalTempInteger;
        AnalogExternalTempDecimal = ExternalTempDecimal;
        AnalogInternalTempInteger = InternalTempInteger;
        AnalogInternalTempDecimal = InternalTempDecimal;

        //Display data:       
        Serial.println();

        //display external temp sensor value:
        Serial.print("ExternalTemp: ");         
        Serial.print(ExternalTempInteger); 
        Serial.print(",");            
        Serial.print(ExternalTempDecimal);   Serial.println(" "); 

        //Display battery voltage
        Serial.print("Battery voltage: ");
        Serial.print(batteryVoltage);
        Serial.println(" V");

        //display internal temp sensor value:
        Serial.print("InternalTemp: ");         
        Serial.print(InternalTempInteger); 
        Serial.print(",");       
        if (InternalTempDecimal < 10)
          {
            Serial.print("0");
          }       
        Serial.print(InternalTempDecimal);   Serial.println(" "); 

        //Display moisture sensor value:
        Serial.print("Moisture sensor value: ");
        Serial.println(MoistureData);

        //Display Light sensor value:
        Serial.print("Light sensor value: ");
        Serial.println(LightData);
                  
        Serial.println("------------------");      
      }
      
      else if (deviceName == "SHT40") 
      {
        Serial.print("Device name: ");
        Serial.println(deviceName.c_str());
        
        std::string strManufacturerData = advertisedDevice.getManufacturerData().c_str(); // Convert to std::string
        uint8_t cManufacturerData[100];
        strManufacturerData.copy((char *)cManufacturerData, strManufacturerData.length(), 0);
        Serial.printf("Manufacturer Data Length: %d ", strManufacturerData.length());

        for (size_t i = 0; i < strManufacturerData.length(); i++) 
        {
          Serial.printf("[%X]", cManufacturerData[i]);
        }

        // Getting raw data from SHT40
        TemperatureData = int(cManufacturerData[2] << 8 | cManufacturerData[3]);
        HumidityData = int(cManufacturerData[5] << 8 | cManufacturerData[6]);

        // Convert raw data into temperature and humidity data
        Temperature = (175 * TemperatureData / 65535) - 45;
        Humidity = (125 * HumidityData / 65535) - 6;

        SHT40_temperature = Temperature;
        SHT40_humidity = Humidity;

        Serial.println();
        Serial.print("TemperatureData: ");
        Serial.print(Temperature);
        Serial.println("");
        Serial.print("HumidityData: ");
        Serial.print(Humidity);
        Serial.println("%");
        Serial.println("------------------");
      }

      else if (deviceName == "ICP10111") 
      {
        Serial.print("Device name: ");
        Serial.println(advertisedDevice.getName().c_str());
        
        std::string strManufacturerData = advertisedDevice.getManufacturerData().c_str(); // Convert to std::string

        uint8_t cManufacturerData[100];
        strManufacturerData.copy((char *)cManufacturerData, strManufacturerData.length(), 0);        
        Serial.printf("strManufacturerData: %d ", strManufacturerData.length());

        for (int i = 0; i < strManufacturerData.length(); i++) {
          Serial.printf("[%X]", cManufacturerData[i]);
        }
        Serial.println();


      //read RAW data and extract the last 14 bytes:
      // Advertisement Data (Raw Data)
      uint8_t* advData = advertisedDevice.getPayload();
      size_t advLength = advertisedDevice.getPayloadLength();
      
      // Convertim advData ntr-un std::string
      std::string advDataStr((char*)advData, advLength);

      // Extrage doar ultimii 16 octei (sau mai puin, dac lungimea este mai mic)
      size_t startIdx = (advLength > 16) ? (advLength - 16) : 0;
      size_t numBytes = (advLength > 16) ? 16 : advLength;
      
      std::string usefulData = advDataStr.substr(startIdx, numBytes);
      
      Serial.printf("Useful Data Length: %d\n", usefulData.length());
      Serial.print("Useful Data: ");
      for (size_t i = 0; i < usefulData.length(); i++) 
      {
        Serial.printf("[%02X]", (unsigned char)usefulData[i]);
      }
      Serial.println();       
      //end of read raw data
        
        if (!optSetFlag) {   //Initialize calibration data
          short out[4];
          for (uint8_t i = 0; i < 4; i++) {
            out[i] = usefulData[i * 2 + 2] << 8 | usefulData[i * 2 + 3];
          }
          initBase(_d, out);
          optSetFlag = true;
        }

        //Get raw data from ICP10111
        uint16_t temp = (uint16_t)usefulData[10] << 8 | usefulData[11];
        uint32_t airPressure = (uint32_t)usefulData[12] << 16 | (uint32_t)usefulData[13] << 8 | (uint32_t)usefulData[15];

        //Convert raw data:
        getTempAndAirPressure(temp, airPressure);

        ICP10111_temperature = _t->temp;
        ICP10111_elevation   = _t->elevation;
        ICP10111_airPressure = _t->airPressure;

        Serial.println();
        Serial.print("Read air pressure:"); 
        Serial.print(_t->airPressure);
        Serial.println("Pa");
        Serial.print("Read temperature:");// Serial.print(temp);
        Serial.print(_t->temp);
        Serial.println("C");
        Serial.print("Read altitude:");
        Serial.print(_t->elevation);
        Serial.println("m");
        Serial.println("------------------");     
      }
      
    }
  }
};

void setup() {
  Serial.begin(115200);
  Serial.println("Scanning...");

  Serial2.begin(9600, SERIAL_8N1, RXD2, TXD2); //comunication via Serial2 
  Serial.println("Comunication with ESP8266-01 is open...");  

  connect_to_local_wifi();

  BLEDevice::init("");
  pBLEScan = BLEDevice::getScan(); // create new scan
  pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
  pBLEScan->setActiveScan(true); // active scan uses more power, but get results faster
  pBLEScan->setInterval(100);
  pBLEScan->setWindow(99); // less or equal setInterval value
}

void read_data_from_serial2()
{
    while (Serial2.available() > 0)
    {      
      String citire = Serial2.readString();
      Serial.print("Response: ");
      Serial.println(citire);
    }
}

void connect_to_local_wifi()
{
  //Verify disponibility of ESP8266-01:
    Serial2.println("AT");
    Serial.println("AT");
    read_data_from_serial2();
    delay(1000); 
  //Reset ESP8266-01:
    Serial2.println("AT+RST");
    Serial.println("AT+RST");    
    read_data_from_serial2();
    delay(2000); 
  //Set ESP8266 mode 3 = access point and station mode   
    Serial2.println("AT+CWMODE=3");
    Serial.println("AT+CWMODE=3");    
    read_data_from_serial2();
    delay(5000);
    String command = "AT+CWJAP=\"";
    command += ssid;
    command += "\",\"";
    command += pass;
    command += "\"";
    Serial2.println(command);
    Serial.println(command);    
    read_data_from_serial2();
    delay(5000);
    Serial2.println("AT+CIFSR");           //connect to AP
    Serial.println("AT+CIFSR");           //connect to AP    
    read_data_from_serial2();
    delay(100); 
}

void send_mqtt_data_to_node_red()
{
    sprintf(finalTopic_wifi, "AT+MQTTUSERCFG=0,1,\"%s\",\"%s\",\"%s\",0,0,\"\"", mqtt_client_id, mqtt_user, mqtt_pass);
    Serial2.println(finalTopic_wifi);  
    Serial.println(finalTopic_wifi); 
    read_data_from_serial2(); 
    delay(500);

    memset(finalTopic_wifi, '\0', sizeof(finalTopic_wifi));       //reset the string   
     
    sprintf(finalTopic_wifi, "AT+MQTTCONN=0,\"%s\",1883,1", mqtt_host);
    Serial2.println(finalTopic_wifi);
    Serial.println(finalTopic_wifi);
    read_data_from_serial2();
    delay(500);   

    Serial.println("Send data from analog sensors: ");

    //send Mmqtt messages with data from MCP9700 and internal sensors:
    Serial2.println("AT+MQTTPUB=0,\"esp32/analog_batteryVoltage\",\"" + String(batteryVoltage) + "\",1,0");
    Serial.println("AT+MQTTPUB=0,\"esp32/analog_batteryVoltage\",\"" + String(batteryVoltage) + "\",1,0");
    read_data_from_serial2();
    delay(500);
    
    Serial2.println("AT+MQTTPUB=0,\"esp32/analog_MoistureData\",\"" + String(round(MoistureData)) + "\",1,0");
    Serial.println("AT+MQTTPUB=0,\"esp32/analog_MoistureData\",\"" + String(MoistureData) + "\",1,0");
    read_data_from_serial2();
    delay(500);

    Serial2.println("AT+MQTTPUB=0,\"esp32/analog_LightData\",\"" + String(round(LightData)) + "\",1,0");
    Serial.println("AT+MQTTPUB=0,\"esp32/analog_LightData\",\"" + String(LightData) + "\",1,0");
    read_data_from_serial2();
    delay(500);
    
    Serial2.println("AT+MQTTPUB=0,\"esp32/AnalogExternalTempInteger\",\"" + String(round(AnalogExternalTempInteger)) + "\",1,0");
    Serial.println("AT+MQTTPUB=0,\"esp32/AnalogExternalTempInteger\",\"" + String(AnalogExternalTempInteger) + "\",1,0");
    read_data_from_serial2();
    delay(500);

    Serial2.println("AT+MQTTPUB=0,\"esp32/AnalogExternalTempDecimal\",\"" + String(round(AnalogExternalTempDecimal)) + "\",1,0");
    Serial.println("AT+MQTTPUB=0,\"esp32/AnalogExternalTempDecimal\",\"" + String(AnalogExternalTempDecimal) + "\",1,0");
    read_data_from_serial2();
    delay(500);    

    Serial2.println("AT+MQTTPUB=0,\"esp32/AnalogInternalTempInteger\",\"" + String(round(AnalogInternalTempInteger)) + "\",1,0");
    Serial.println("AT+MQTTPUB=0,\"esp32/AnalogInternalTempInteger\",\"" + String(AnalogInternalTempInteger) + "\",1,0");
    read_data_from_serial2();
    delay(500);

    Serial2.println("AT+MQTTPUB=0,\"esp32/AnalogInternalTempDecimal\",\"" + String(round(AnalogInternalTempDecimal)) + "\",1,0");
    Serial.println("AT+MQTTPUB=0,\"esp32/AnalogInternalTempDecimal\",\"" + String(AnalogInternalTempDecimal) + "\",1,0");
    read_data_from_serial2();
    delay(500);

    Serial2.println("AT+MQTTPUB=0,\"esp32/sh40_temperature\",\"" + String(round(SHT40_temperature)) + "\",1,0");
    Serial.println("AT+MQTTPUB=0,\"esp32/sht40_temperature\",\"" + String(SHT40_temperature) + "\",1,0");
    read_data_from_serial2();
    delay(500);

    Serial.println("Send data from digital SHT40 sensor: ");
    
    //send Mmqtt messages with data from SHT40:
    Serial2.println("AT+MQTTPUB=0,\"esp32/sh40_temperature\",\"" + String(SHT40_temperature) + "\",1,0");
    Serial.println("AT+MQTTPUB=0,\"esp32/sht40_temperature\",\"" + String(SHT40_temperature) + "\",1,0");
    read_data_from_serial2();
    delay(500);

    Serial2.println("AT+MQTTPUB=0,\"esp32/sht40_humidity\",\"" + String(SHT40_humidity) + "\",1,0");
    Serial.println("AT+MQTTPUB=0,\"esp32/sht40_humidity\",\"" + String(SHT40_humidity) + "\",1,0");
    read_data_from_serial2();
    delay(500);    

    Serial.println("Send data from digital ICP10111 sensor: ");
    
    //send Mmqtt messages with data from ICP10111:
    Serial2.println("AT+MQTTPUB=0,\"esp32/temperature\",\"" + String(ICP10111_temperature) + "\",1,0");
    Serial.println("AT+MQTTPUB=0,\"esp32/temperature\",\"" + String(ICP10111_temperature) + "\",1,0");
    read_data_from_serial2();
    delay(500);

    Serial2.println("AT+MQTTPUB=0,\"esp32/altitude\",\"" + String(ICP10111_elevation) + "\",1,0");
    Serial.println("AT+MQTTPUB=0,\"esp32/altitude\",\"" + String(ICP10111_elevation) + "\",1,0");
    read_data_from_serial2();
    delay(500);

    Serial2.println("AT+MQTTPUB=0,\"esp32/atmospheric_pressure\",\"" + String(ICP10111_airPressure) + "\",1,0");
    Serial.println("AT+MQTTPUB=0,\"esp32/atmospheric_pressure\",\"" + String(ICP10111_airPressure) + "\",1,0");
    read_data_from_serial2();
    delay(500);      
}



void loop() {
  BLEScanResults *foundDevices = pBLEScan->start(scanTime, false);
  Serial.print("Devices found: ");
  Serial.println(foundDevices->getCount());
  pBLEScan->clearResults(); // delete results from BLEScan buffer to release memory
  delay(2000); //2 sec pause
  
//send data to Node-Red with lower rate than are displayed serial console:
  if (millis() - timer_1 > interval_1)
  {
    timer_1 = millis(); 
    send_mqtt_data_to_node_red(); //send data to Node-Red
  }
}

v0.9.2.2 AT Firmware.bin

C/C++
Firmware used to send AT command for MQTT over WiFi
No preview (download only).

esp8266_flasher.exe

C/C++
Application used to update the software in ESP8266-01
No preview (download only).

Credits

Mihai Popa
10 projects • 9 followers
I am working as test engineer for navigation systems in auto industry. I am passionate about science, IoT, ML, MCU programming, SF movies.

Comments