Инструменты пользователя

Инструменты сайта


iot:software:node-red:flows:energy_monitoring:temperature_telemetry

Запись данных нескольких DS18B20 в Node-RED

Это микроскопический поток собран для сохранения температуры с нескольких датчиков DS18B20, подключенных к TOMZN TOB15-63 WIFI, в базу данных SQLite.

Примечательное в нем то, что:

  • во-первых, датчиков два, которые передают данные в одном JSON-сообщении, т.е. «DS18B20-1» и «DS18B20-2», что, из-за дефиса в названии, вызывает некоторые проблемы при навигации по структуре,
  • а, во-вторых, сохраняются средние значения за период, а не все подряд, что заставило мозг покипеть и подумать – датчиков же два, а сообщение одно.

К слову, я теперь знаю минимум 3 варианта, которые работают в разных случаях:

  1. «payload["DS18B20-1"].Temperature»;
  2. «payload[\"DS18B20-1\"].Temperature»;
    • «(return JSON.parse(message)[\"DS18B20-1\"].Temperature)»;
  3. «payload.'DS18B20-1'.Temperature».

Нестандартные узлы

В этой цепочке используются следующие узлы, которых нет в стандартной поставке:

Описание работы цепочки

На входе получаем сообщение в таком формате:

{
    "Time": "2023-11-08T01:26:00",
        "DS18B20-1": { "Id": "XXXXXXXXXXXA", "Temperature": 25.9 },
        "DS18B20-2": { "Id": "XXXXXXXXXXXB", "Temperature": 30.5 },
    "TempUnit": "C"
}

Далее избавляемся от вышеуказанной проблемы с именованием и отправляем его в два узла типа «join», которые настроены на одинаковую задержку, по истечении которой выдают каждый свое сообщение с массивом температур.

Потом, используя функцию «$sift()», удаляем из сообщений объект, не содержащий массив1), и отправляем в очередной «join» для воссоединения.

Скриншот потока

И, наконец, записываем в базу данных среднее значение и строку с «сырыми» значениями так, на всякий случай.

Пример базы данных

Код для загрузки

temperature-telemetry.json
[
    {
        "id": "9d49ddabe57a8cb8",
        "type": "group",
        "z": "f89b7d5f97f15ff4",
        "name": "Телеметрия выключателя и реле",
        "style": {
            "label": true
        },
        "nodes": [
            "a2c811674f1c0dde",
            "70a369889433087c",
            "5e106eab8898f103",
            "8e3cd7e7430dbc2a",
            "da23a000eb4aae7e",
            "11441d72fe0d057e",
            "d35b809e8fd37cdf",
            "f98768677da7270d",
            "19836a13dc449ced"
        ],
        "x": 14,
        "y": 19,
        "w": 932,
        "h": 202
    },
    {
        "id": "a2c811674f1c0dde",
        "type": "mqtt in",
        "z": "f89b7d5f97f15ff4",
        "g": "9d49ddabe57a8cb8",
        "name": "Датчики реле",
        "topic": "circuitbreaker_0B6A01/tele/SENSOR",
        "qos": "2",
        "datatype": "json",
        "broker": "1765f6372ba832dc",
        "nl": false,
        "rap": false,
        "inputs": 0,
        "x": 110,
        "y": 60,
        "wires": [
            [
                "d35b809e8fd37cdf"
            ]
        ]
    },
    {
        "id": "70a369889433087c",
        "type": "sqlite",
        "z": "f89b7d5f97f15ff4",
        "g": "9d49ddabe57a8cb8",
        "mydb": "eef0d82a72a3359e",
        "sqlquery": "msg.topic",
        "sql": "",
        "name": "Запись в базу данных",
        "x": 440,
        "y": 180,
        "wires": [
            []
        ]
    },
    {
        "id": "5e106eab8898f103",
        "type": "change",
        "z": "f89b7d5f97f15ff4",
        "g": "9d49ddabe57a8cb8",
        "name": "Подготовка за проса к базе",
        "rules": [
            {
                "t": "set",
                "p": "topic",
                "pt": "msg",
                "to": "\"INSERT INTO telemetry ( timestamp, breaker_avg, relay_avg, breaker_raw, relay_raw ) VALUES ( \\\"\" & $now( '[Y0001]-[M01]-[D01] [H01]:[m01]:[s01]', '+1000' ) & \"\\\", \" & $round( $average( temperature.breaker ), 2 ) & \", \" & $round( $average( temperature.relay ), 2 ) & \", \\\"\" & $join( temperature.breaker.$string(), \", \" ) & \"\\\", \\\"\" & $join( temperature.relay.$string(), \", \" ) & \"\\\" )\"",
                "tot": "jsonata"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 160,
        "y": 180,
        "wires": [
            [
                "70a369889433087c"
            ]
        ]
    },
    {
        "id": "8e3cd7e7430dbc2a",
        "type": "join",
        "z": "f89b7d5f97f15ff4",
        "g": "9d49ddabe57a8cb8",
        "name": "Накопление (выключатель)",
        "mode": "custom",
        "build": "array",
        "property": "temperature.breaker",
        "propertyType": "msg",
        "key": "topic",
        "joiner": "\\n",
        "joinerType": "str",
        "accumulate": false,
        "timeout": "600",
        "count": "",
        "reduceRight": false,
        "reduceExp": "",
        "reduceInit": "",
        "reduceInitType": "",
        "reduceFixup": "",
        "x": 580,
        "y": 120,
        "wires": [
            [
                "19836a13dc449ced"
            ]
        ]
    },
    {
        "id": "da23a000eb4aae7e",
        "type": "join",
        "z": "f89b7d5f97f15ff4",
        "g": "9d49ddabe57a8cb8",
        "name": "Накопление (реле)",
        "mode": "custom",
        "build": "array",
        "property": "temperature.relay",
        "propertyType": "msg",
        "key": "topic",
        "joiner": "\\n",
        "joinerType": "str",
        "accumulate": false,
        "timeout": "600",
        "count": "",
        "reduceRight": false,
        "reduceExp": "",
        "reduceInit": "",
        "reduceInitType": "",
        "reduceFixup": "",
        "x": 570,
        "y": 60,
        "wires": [
            [
                "19836a13dc449ced"
            ]
        ]
    },
    {
        "id": "11441d72fe0d057e",
        "type": "join",
        "z": "f89b7d5f97f15ff4",
        "g": "9d49ddabe57a8cb8",
        "name": "Объединение",
        "mode": "custom",
        "build": "merged",
        "property": "temperature",
        "propertyType": "msg",
        "key": "payload[\"DS18B20-1\"].Id",
        "joiner": "\\n",
        "joinerType": "str",
        "accumulate": false,
        "timeout": "",
        "count": "2",
        "reduceRight": false,
        "reduceExp": "",
        "reduceInit": "",
        "reduceInitType": "num",
        "reduceFixup": "",
        "x": 840,
        "y": 120,
        "wires": [
            [
                "5e106eab8898f103"
            ]
        ]
    },
    {
        "id": "d35b809e8fd37cdf",
        "type": "change",
        "z": "f89b7d5f97f15ff4",
        "g": "9d49ddabe57a8cb8",
        "name": "Подготовка нагрузки",
        "rules": [
            {
                "t": "set",
                "p": "temperature.breaker",
                "pt": "msg",
                "to": "payload[\"DS18B20-1\"].Temperature",
                "tot": "msg"
            },
            {
                "t": "set",
                "p": "temperature.relay",
                "pt": "msg",
                "to": "payload[\"DS18B20-2\"].Temperature",
                "tot": "msg"
            },
            {
                "t": "delete",
                "p": "payload",
                "pt": "msg"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 320,
        "y": 60,
        "wires": [
            [
                "da23a000eb4aae7e",
                "8e3cd7e7430dbc2a"
            ]
        ]
    },
    {
        "id": "f98768677da7270d",
        "type": "comment",
        "z": "f89b7d5f97f15ff4",
        "g": "9d49ddabe57a8cb8",
        "name": "Среднее значение за 10 минут (600)",
        "info": "",
        "x": 250,
        "y": 120,
        "wires": []
    },
    {
        "id": "19836a13dc449ced",
        "type": "change",
        "z": "f89b7d5f97f15ff4",
        "g": "9d49ddabe57a8cb8",
        "name": "Отсеивание лишнего",
        "rules": [
            {
                "t": "set",
                "p": "temperature",
                "pt": "msg",
                "to": "temperature.$sift( function( $v ) { $type( $v ) = \"array\" } )",
                "tot": "jsonata"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 820,
        "y": 60,
        "wires": [
            [
                "11441d72fe0d057e"
            ]
        ]
    },
    {
        "id": "1765f6372ba832dc",
        "type": "mqtt-broker",
        "name": "localhost",
        "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": "eef0d82a72a3359e",
        "type": "sqlitedb",
        "db": "/home/nikolay/.node-red/databases/electricity/circuitbreaker.db",
        "mode": "RWC"
    }
]

Дисклеймер

  • Использование материалов данной базы знаний разрешено на условиях лицензии, указанной внизу каждой страницы! При использовании материалов активная гиперссылка на соответствующую страницу данной базы знаний обязательна!
  • Автор не несет и не может нести какую либо ответственность за последствия использования материалов, размещенных в данной базе знаний. Все материалы предоставляются по принципу «как есть». Используйте их исключительно на свой страх и риск.
  • Все высказывания, мысли или идеи автора, размещенные в материалах данной базе знаний, являются исключительно его личным субъективным мнением и могут не совпадать с мнением читателей!
  • При размещении ссылок в данной базе знаний на интернет-страницы третьих лиц автор не несет ответственности за их техническую функциональность (особенно отсутствие вирусов) и содержание! При обнаружении таких ссылок, можно и желательно сообщить о них в комментариях к соответствующей статье.
1)
Вот над этой короткой строчкой я бился чуть ли не сутки! – да, можно было добавить два узла на каждый поток, чтобы они удаляли именно свой, заранее известный, объект, но это не красиво!

Обсуждение

Ваш комментарий:
T J G V U​ X R M J P W E J L P Y
 
Последнее изменение: 2023/11/08 11:40 — Николай Солошин