Guest User

Local Metrics & Logic

a guest
Sep 10th, 2025
63
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
JSON 19.69 KB | Source Code | 0 0
  1. [
  2.   {
  3.     "id": "tab_1",
  4.     "type": "tab",
  5.     "label": "Local Metrics & Logic",
  6.     "disabled": false,
  7.     "info": "",
  8.     "env": []
  9.   },
  10.   {
  11.     "id": "node_1",
  12.     "type": "inject",
  13.     "z": "tab_1",
  14.     "name": "Poll Sensor API",
  15.     "props": [
  16.       {
  17.         "p": "payload"
  18.       },
  19.       {
  20.         "p": "topic",
  21.         "vt": "str"
  22.       }
  23.     ],
  24.     "repeat": "60",
  25.     "crontab": "",
  26.     "once": true,
  27.     "onceDelay": 0.1,
  28.     "topic": "",
  29.     "payload": "",
  30.     "payloadType": "date",
  31.     "x": 120,
  32.     "y": 580,
  33.     "wires": [
  34.       [
  35.         "node_2"
  36.       ]
  37.     ]
  38.   },
  39.   {
  40.     "id": "node_2",
  41.     "type": "http request",
  42.     "z": "tab_1",
  43.     "name": "Get Channels from API",
  44.     "method": "GET",
  45.     "ret": "txt",
  46.     "paytoqs": "ignore",
  47.     "url": "https://api.example.com/channels?account_key=REDACTED_ACCOUNT_KEY",
  48.     "tls": "",
  49.     "persist": false,
  50.     "proxy": "",
  51.     "insecureHTTPParser": false,
  52.     "authType": "",
  53.     "senderr": false,
  54.     "headers": [],
  55.     "x": 320,
  56.     "y": 580,
  57.     "wires": [
  58.       [
  59.         "node_3"
  60.       ]
  61.     ]
  62.   },
  63.   {
  64.     "id": "node_3",
  65.     "type": "json",
  66.     "z": "tab_1",
  67.     "name": "Parse JSON",
  68.     "property": "payload",
  69.     "action": "",
  70.     "pretty": false,
  71.     "x": 510,
  72.     "y": 580,
  73.     "wires": [
  74.       [
  75.         "node_4"
  76.       ]
  77.     ]
  78.   },
  79.   {
  80.     "id": "node_5",
  81.     "type": "influxdb batch",
  82.     "z": "tab_1",
  83.     "influxdb": "influxdb_node",
  84.     "precision": "ns",
  85.     "retentionPolicy": "",
  86.     "name": "Batch Push to InfluxDB",
  87.     "database": "metrics_db",
  88.     "precisionV18FluxV20": "ns",
  89.     "retentionPolicyV18Flux": "",
  90.     "x": 1630,
  91.     "y": 560,
  92.     "wires": []
  93.   },
  94.   {
  95.     "id": "node_6",
  96.     "type": "switch",
  97.     "z": "tab_1",
  98.     "name": "Zone Router",
  99.     "property": "payload.tags.zone",
  100.     "propertyType": "msg",
  101.     "rules": [
  102.       {
  103.         "t": "eq",
  104.         "v": "zone_weather",
  105.         "vt": "str"
  106.       },
  107.       {
  108.         "t": "eq",
  109.         "v": "zone_prod1",
  110.         "vt": "str"
  111.       },
  112.       {
  113.         "t": "eq",
  114.         "v": "zone_prod2",
  115.         "vt": "str"
  116.       },
  117.       {
  118.         "t": "eq",
  119.         "v": "zone_prep",
  120.         "vt": "str"
  121.       },
  122.       {
  123.         "t": "eq",
  124.         "v": "zone_server",
  125.         "vt": "str"
  126.       },
  127.       {
  128.         "t": "eq",
  129.         "v": "zone_equipment",
  130.         "vt": "str"
  131.       },
  132.       {
  133.         "t": "else"
  134.       }
  135.     ],
  136.     "checkall": "false",
  137.     "repair": false,
  138.     "outputs": 7,
  139.     "x": 1130,
  140.     "y": 560,
  141.     "wires": [
  142.       [
  143.         "node_7"
  144.       ],
  145.       [
  146.         "node_7"
  147.       ],
  148.       [
  149.         "node_7"
  150.       ],
  151.       [
  152.         "node_7"
  153.       ],
  154.       [
  155.         "node_7"
  156.       ],
  157.       [
  158.         "node_7"
  159.       ],
  160.       [
  161.         "node_7"
  162.       ]
  163.     ]
  164.   },
  165.   {
  166.     "id": "node_8",
  167.     "type": "function",
  168.     "z": "tab_1",
  169.     "name": "Split Measurements",
  170.     "func": "// Split the payload array into separate messages with parts for Join\nvar msgs = [];\nvar originalId = msg._msgid; // Keep the original msg ID\nvar count = msg.payload.length;\nfor (let i = 0; i < count; i++) {\n msgs.push({\n payload: msg.payload[i],\n parts: {\n id: originalId,\n index: i,\n count: count,\n type: 'array'\n }\n });\n}\nreturn [msgs];",
  171.     "outputs": 1,
  172.     "timeout": 0,
  173.     "noerr": 0,
  174.     "initialize": "",
  175.     "finalize": "",
  176.     "libs": [],
  177.     "x": 940,
  178.     "y": 560,
  179.     "wires": [
  180.       [
  181.         "node_6"
  182.       ]
  183.     ]
  184.   },
  185.   {
  186.     "id": "node_7",
  187.     "type": "join",
  188.     "z": "tab_1",
  189.     "name": "Compile Batch Report",
  190.     "mode": "auto",
  191.     "build": "object",
  192.     "property": "payload",
  193.     "propertyType": "msg",
  194.     "key": "topic",
  195.     "joiner": "\\n",
  196.     "joinerType": "str",
  197.     "useparts": false,
  198.     "accumulate": true,
  199.     "timeout": "",
  200.     "count": "",
  201.     "reduceRight": false,
  202.     "reduceExp": "",
  203.     "reduceInit": "",
  204.     "reduceInitType": "",
  205.     "reduceFixup": "",
  206.     "x": 1400,
  207.     "y": 560,
  208.     "wires": [
  209.       [
  210.         "node_5"
  211.       ]
  212.     ]
  213.   },
  214.   {
  215.     "id": "node_9",
  216.     "type": "mqtt out",
  217.     "z": "tab_1",
  218.     "name": "MQTT Push to HA",
  219.     "topic": "",
  220.     "qos": "0",
  221.     "retain": "",
  222.     "respTopic": "",
  223.     "contentType": "",
  224.     "userProps": "",
  225.     "correl": "",
  226.     "expiry": "",
  227.     "broker": "mqtt_node",
  228.     "x": 930,
  229.     "y": 600,
  230.     "wires": []
  231.   },
  232.   {
  233.     "id": "node_10",
  234.     "type": "inject",
  235.     "z": "tab_1",
  236.     "name": "Derive Wind&Moon - Trigger",
  237.     "props": [
  238.       {
  239.         "p": "payload"
  240.       }
  241.     ],
  242.     "repeat": "60",
  243.     "crontab": "",
  244.     "once": true,
  245.     "onceDelay": 0.1,
  246.     "topic": "",
  247.     "payload": "",
  248.     "payloadType": "date",
  249.     "x": 170,
  250.     "y": 640,
  251.     "wires": [
  252.       [
  253.         "node_11"
  254.       ]
  255.     ]
  256.   },
  257.   {
  258.     "id": "node_11",
  259.     "type": "function",
  260.     "z": "tab_1",
  261.     "name": "Derive Wind & Moon Sensors",
  262.     "func": "// Node-RED function: \"Derive Wind & Moon Sensors\"\n// This function expects global.sensorData to contain the latest weather fields.\n// Outputs:\n// 1 -> Discovery messages (array of discovery msg objects) [wired to MQTT Push to HA]\n// 2 -> State messages (array of state msg objects) [wired to MQTT Push to HA]\n\n// --- read sensor data stored by your flow ---\nconst fields = global.get('sensorData') || {};\n\n// helper: convert degrees to cardinal (16 points for detail)\nfunction degToCardinal(deg) {\n if (typeof deg !== 'number' || isNaN(deg)) return 'VAR';\n const dirs = ['N','NNE','NE','ENE','E','ESE','SE','SSE','S','SSW','SW','WSW','W','WNW','NW','NNW'];\n const idx = Math.round(((deg % 360) / 22.5) % 16);\n return dirs[idx];\n}\n\n// helper: moon phase (8-phase)\nfunction getMoonPhase() {\n const now = new Date();\n const baseDate = new Date(2001, 0, 1);\n const diff = now.getTime() - baseDate.getTime();\n const days = diff / (1000 * 60 * 60 * 24);\n const lunations = 0.20439731 + (days * 0.03386319269);\n const pos = lunations % 1;\n const index = Math.floor(pos * 8 + 0.5) % 8;\n const phases = [\"New Moon\",\"Waxing Crescent\",\"First Quarter\",\"Waxing Gibbous\",\"Full Moon\",\"Waning Gibbous\",\"Last Quarter\",\"Waning Crescent\"];\n return phases[index];\n}\n\nlet degHistory = flow.get('wind_deg_history') || [];\nconst wdCandidates = ['wind_direction','winddir','wind_dir','winddir_deg'];\nlet rawDeg = NaN;\nfor (let k of wdCandidates) {\n if (k in fields && fields[k] !== null && fields[k] !== undefined) {\n const v = parseFloat(fields[k]);\n if (!isNaN(v)) { rawDeg = v; break;\n }\n }\n}\nif (!isNaN(rawDeg)) {\n degHistory.push(rawDeg);\n if (degHistory.length > 5) degHistory.shift();\n flow.set('wind_deg_history', degHistory);\n}\nconst smoothedDeg = degHistory.length > 0 ? degHistory.reduce((a, b) => a + b, 0) / degHistory.length : rawDeg;\nconst cardinal = degToCardinal(smoothedDeg);\nconst moonPhase = getMoonPhase();\n\nlet speedHistory = flow.get('wind_speed_history') || [];\nconst currentSpeed = parseFloat(fields.wind_speed) || 0;\nconst currentTime = Date.now();\nif (!isNaN(currentSpeed)) {\n speedHistory.push({ time: currentTime, speed: currentSpeed });\n speedHistory = speedHistory.filter(entry => currentTime - entry.time <= 600000);\n flow.set('wind_speed_history', speedHistory);\n}\nconst derivedGust = speedHistory.length > 0 ? Math.max(...speedHistory.map(entry => entry.speed)) : currentSpeed;\n\nconst discoverySentWind = flow.get('discovery_sent_wind_cardinal') || false;\nconst discoverySentWindSmooth = flow.get('discovery_sent_wind_smooth') || false;\nconst discoverySentWindGust = flow.get('discovery_sent_wind_gust') || false;\nconst discoverySentMoon = flow.get('discovery_sent_moon_phase') || false;\n\nconst arrayForDiscovery = [];\nif (!discoverySentWind) {\n const payload = {\n name: \"Sensor Node Wind Direction (Cardinal)\",\n unique_id: \"sensor_node_wind_dir_letter\",\n object_id: \"sensor_node_wind_dir_letter\",\n state_topic: \"nodered/zone_weather/wind_dir_letter\",\n icon: \"mdi:compass\",\n device: {\n identifiers: [\"sensor_node\"],\n name: \"Sensor Node\",\n manufacturer: \"SensorVendor\"\n }\n };\n arrayForDiscovery.push({ topic: 'homeassistant/sensor/sensor_node_wind_dir_letter/config', payload: JSON.stringify(payload), retain: true });\n flow.set('discovery_sent_wind_cardinal', true);\n}\nif (!discoverySentWindSmooth) {\n const payload = {\n name: \"Sensor Node Wind Direction (Smoothed)\",\n unique_id: \"sensor_node_wind_direction_smoothed\",\n object_id: \"sensor_node_wind_direction_smoothed\",\n state_topic: \"nodered/zone_weather/wind_direction_smoothed\",\n unit_of_measurement: \"°\",\n icon: \"mdi:compass\",\n device: {\n identifiers: [\"sensor_node\"],\n name: \"Sensor Node\",\n manufacturer: \"SensorVendor\"\n }\n };\n arrayForDiscovery.push({ topic: 'homeassistant/sensor/sensor_node_wind_direction_smoothed/config', payload: JSON.stringify(payload), retain: true });\n flow.set('discovery_sent_wind_smooth', true);\n}\nif (!discoverySentWindGust) {\n const payload = {\n name: \"Sensor Node Wind Gust (Derived)\",\n unique_id: \"sensor_node_wind_gust_derived\",\n object_id: \"sensor_node_wind_gust_derived\",\n state_topic: \"nodered/zone_weather/wind_gust_derived\",\n unit_of_measurement: \"km/h\",\n device_class: \"wind_speed\",\n icon: \"mdi:weather-windy-variant\",\n device: {\n identifiers: [\"sensor_node\"],\n name: \"Sensor Node\",\n manufacturer: \"SensorVendor\"\n }\n };\n arrayForDiscovery.push({ topic: 'homeassistant/sensor/sensor_node_wind_gust_derived/config', payload: JSON.stringify(payload), retain: true });\n flow.set('discovery_sent_wind_gust', true);\n}\nif (!discoverySentMoon) {\n const payload = {\n name: \"Sensor Node Moon Phase\",\n unique_id: \"sensor_node_moon_phase\",\n object_id: \"sensor_node_moon_phase\",\n state_topic: \"nodered/zone_weather/moon_phase\",\n icon: \"mdi:weather-night\",\n device: {\n identifiers: [\"sensor_node\"],\n name: \"Sensor Node\",\n manufacturer: \"SensorVendor\"\n }\n };\n arrayForDiscovery.push({ topic: 'homeassistant/sensor/sensor_node_moon_phase/config', payload: JSON.stringify(payload), retain: true });\n flow.set('discovery_sent_moon_phase', true);\n}\n\nconst arrayForState = [];\narrayForState.push({ topic: 'nodered/zone_weather/wind_dir_letter', payload: String(cardinal) });\narrayForState.push({ topic: 'nodered/zone_weather/wind_direction_smoothed', payload: String(smoothedDeg) });\narrayForState.push({ topic: 'nodered/zone_weather/wind_gust_derived', payload: String(derivedGust) });\narrayForState.push({ topic: 'nodered/zone_weather/moon_phase', payload: String(moonPhase) });\n\nreturn [ (arrayForDiscovery.length ? arrayForDiscovery : null), arrayForState ];",
  263.     "outputs": 2,
  264.     "timeout": 0,
  265.     "noerr": 0,
  266.     "initialize": "",
  267.     "finalize": "",
  268.     "libs": [],
  269.     "x": 450,
  270.     "y": 640,
  271.     "wires": [
  272.       [
  273.         "node_9"
  274.       ],
  275.       [
  276.         "node_9"
  277.       ]
  278.     ]
  279.   },
  280.   {
  281.     "id": "node_4",
  282.     "type": "function",
  283.     "z": "tab_1",
  284.     "name": "Process Sensor Data",
  285.     "func": "// Process Sensor Data (sanitized)\n// Output 1: Influx payload (only when new timestamp / new data for channel)\n// Output 2: MQTT discovery + state messages for Home Assistant (always sends updated values on change)\n\nfunction getSensorDetails(key) {\n  const details = {\n    'temperature': { name: 'Temperature', class: 'temperature', unit: '°C' },\n    'r_h': { name: 'Humidity', class: 'humidity', unit: '%' },\n    'air_pressure': { name: 'Air Pressure', class: 'pressure', unit: 'hPa' },\n    'wind_speed': { name: 'Wind Speed', class: 'wind_speed', unit: 'km/h' },\n    'wind_direction': { name: 'Wind Direction', class: 'None', unit: '°' },\n    'rainfall': { name: 'Rainfall Total', class: 'precipitation', unit: 'mm' },\n    'rain_delta': { name: 'Rainfall Delta', class: 'precipitation', unit: 'mm' },\n    'rain_rate': { name: 'Rainfall Rate', class: 'precipitation_intensity', unit: 'mm/h' },\n    'dew_point_temp': { name: 'Dew Point', class: 'temperature', unit: '°C' },\n    'external_light': { name: 'Light Level', class: 'illuminance', unit: 'lx' },\n    'socket_power': { name: 'Power', class: 'power', unit: 'W' },\n    'socket_voltage': { name: 'Voltage', class: 'voltage', unit: 'V' },\n    'socket_current': { name: 'Current', class: 'current', unit: 'A' },\n    'switch_status': { name: 'Switch', class: 'switch', unit: '' },\n    'in_use': { name: 'In Use', class: 'power' },\n    'optimal_state': { name: 'Optimal State', class: 'None' },\n    'storm_incoming': { name: 'Storm Incoming', class: 'problem' },\n    'fog_risk': { name: 'Fog Risk', class: 'problem' },\n    'frost_risk': { name: 'Frost Risk', class: 'problem' },\n    'wind_damage_risk': { name: 'Wind Damage Risk', class: 'problem' },\n    'check_cooker': { name: 'Check Cooker', class: 'problem' },\n    'check_humidifier': { name: 'Check Humidifier', class: 'problem' },\n    'temp_alert_level': { name: 'Temperature Alert Level', class: 'None' },\n    'rh_alert_level': { name: 'Humidity Alert Level', class: 'None' },\n    'co2_alert_level': { name: 'CO2 Alert Level', class: 'None' },\n    'toxic_hazard_level': { name: 'Toxic Hazard Level', class: 'None' }\n  };\n  return details[key] || { name: key.replace(/_/g, ' ').replace(/\\b\\w/g, l => l.toUpperCase()), class: 'None', unit: '' };\n}\n\nif (!msg.payload || msg.payload.result !== \"success\") {\n  return null;\n}\n\nvar lastTimestamps = flow.get('lastTimestamps') || {};\nvar discoverySent = flow.get('discoverySent') || {};\nvar prevStates = flow.get('lastStates') || {};\n\nvar channels = msg.payload.channels || [];\nvar measurementsForInflux = [];\nvar messagesForHA = [];\n\nfor (var c = 0; c < channels.length; c++) {\n  var channel = channels[c];\n  var channel_id = channel.channel_id;\n  var room = channel.name || 'unknown';\n\n  // timestamp (use channel.last_entry_date if present, otherwise now)\n  var timestamp = channel.last_entry_date ? new Date(channel.last_entry_date).getTime() * 1000000 : Date.now() * 1000000;\n  var isNewTimestamp = (lastTimestamps[channel_id] !== timestamp);\n  if (isNewTimestamp) {\n    lastTimestamps[channel_id] = timestamp;\n  }\n\n  // parse last_values robustly (coerce numeric strings to numbers)\n  var last_values = {};\n  try {\n    last_values = JSON.parse(channel.last_values || \"{}\");\n  } catch (e) {\n    last_values = {};\n  }\n\n  var zone = (room || 'unknown').toLowerCase().trim().replace(/ /g, '_');\n  var fields = {};\n  for (var i = 1; i <= 15; i++) {\n    var label = channel['field' + i];\n    if (!label) continue;\n    var value_obj = last_values['field' + i];\n    if (!value_obj || value_obj.value === undefined || value_obj.value === null) continue;\n\n    var normalized_label = label.toLowerCase().replace(/[/ ]/g, '_');\n\n    var coerced = Number(value_obj.value);\n    if (!isNaN(coerced)) {\n      fields[normalized_label] = coerced;\n    } else {\n      fields[normalized_label] = value_obj.value;\n    }\n  }\n\n  // Correct a common pressure scale issue\n  if ('air_pressure' in fields && fields.air_pressure > 50 && fields.air_pressure < 200) {\n    fields.air_pressure = fields.air_pressure * 10;\n  }\n  // Explicitly set wind_speed to 0 if the field is not present.\n  if (!('wind_speed' in fields)) {\n    fields.wind_speed = 0;\n  }\n\n  if (zone === 'zone_weather' && 'wind_speed' in fields) {\n    fields.wind_speed = fields.wind_speed * 3.6;\n  }\n\n  if (zone === 'zone_weather') {\n    var syncMinutes = 1;\n    var reported = 0;\n\n    if ('rainfall' in fields) {\n      reported = Number(fields.rainfall) || 0;\n    } else if ('rain' in fields) {\n      reported = Number(fields.rain) || 0;\n    } else if ('rain_mm' in fields) {\n      reported = Number(fields.rain_mm) || 0;\n    } else {\n      reported = 0;\n    }\n\n    fields.rain_delta = reported;\n    fields.rain_rate = (reported > 0) ? (reported * (60 / syncMinutes)) : 0;\n    global.set('sensorData', fields);\n  }\n\n  var derived = {};\n  if (zone === 'zone_weather') {\n    var dryTemp = (fields.dry_bulb_temp !== undefined) ? fields.dry_bulb_temp : (fields.temperature !== undefined ? fields.temperature : undefined);\n    derived.fog_risk = !!(fields.r_h > 95 && (fields.wind_speed || 0) < 5 && dryTemp !== undefined && Math.abs(dryTemp - (fields.dew_point_temp || 0)) < 2);\n    derived.frost_risk = !!(dryTemp !== undefined && dryTemp < 2);\n    derived.wind_damage_risk = !!((fields.wind_speed || 0) > 40);\n  }\n\n  var allMetrics = Object.assign({}, fields, derived);\n\n  for (const [key, value] of Object.entries(allMetrics)) {\n    const details = getSensorDetails(key);\n    const component = (typeof value === 'boolean') ? 'binary_sensor' : 'sensor';\n    const sensorId = `sensor_node_${zone}_${key}`;\n    const stateTopic = `nodered/${zone}/${key}`;\n\n    if (!discoverySent[sensorId]) {\n      const discoveryPayload = {\n        name: `${room} ${details.name}`,\n        unique_id: sensorId,\n        object_id: sensorId,\n        state_topic: stateTopic,\n        device_class: (details.class && details.class !== 'None') ? details.class : undefined,\n        unit_of_measurement: details.unit && details.unit !== '' ? details.unit : undefined,\n        state_class: (typeof value === 'number') ? 'measurement' : undefined,\n        device: {\n          identifiers: [`sensor_node_${channel_id}`],\n          name: room,\n          manufacturer: 'SensorVendor'\n        }\n      };\n      messagesForHA.push({ topic: `homeassistant/${component}/${sensorId}/config`, payload: JSON.stringify(discoveryPayload), retain: true });\n      discoverySent[sensorId] = true;\n    }\n\n    let stateValue = (typeof value === 'boolean') ? (value ? 'ON' : 'OFF') : value;\n    const prev = prevStates[sensorId];\n    const changed = String(prev) !== String(stateValue);\n    if (isNewTimestamp || changed) {\n      messagesForHA.push({ topic: stateTopic, payload: String(stateValue) });\n      prevStates[sensorId] = stateValue;\n    }\n  }\n\n  if (isNewTimestamp && Object.keys(fields).length > 0) {\n    let influxMetrics = Object.assign({}, allMetrics);\n    measurementsForInflux.push({\n      measurement: \"sensor_metrics\",\n      tags: { room: room || \"unknown\", zone: zone, channel_id: channel_id },\n      fields: influxMetrics,\n      timestamp: timestamp\n    });\n  }\n}\n\nflow.set('lastTimestamps', lastTimestamps);\nflow.set('discoverySent', discoverySent);\nflow.set('lastStates', prevStates);\n\nvar out1 = (measurementsForInflux.length > 0) ? { payload: measurementsForInflux } : null;\nvar out2 = (messagesForHA.length > 0) ? messagesForHA : null;\n\nreturn [out1, out2];",
  286.     "outputs": 2,
  287.     "timeout": 0,
  288.     "noerr": 0,
  289.     "initialize": "",
  290.     "finalize": "",
  291.     "libs": [],
  292.     "x": 700,
  293.     "y": 580,
  294.     "wires": [
  295.       [
  296.         "node_8"
  297.       ],
  298.       [
  299.         "node_9"
  300.       ]
  301.     ]
  302.   },
  303.   {
  304.     "id": "influxdb_node",
  305.     "type": "influxdb",
  306.     "hostname": "influxdb-host",
  307.     "port": "8086",
  308.     "protocol": "http",
  309.     "database": "metrics_db",
  310.     "name": "InfluxDB",
  311.     "usetls": false,
  312.     "tls": "",
  313.     "influxdbVersion": "1.x",
  314.     "url": "http://influxdb-host:8086",
  315.     "timeout": "10",
  316.     "rejectUnauthorized": false
  317.   },
  318.   {
  319.     "id": "mqtt_node",
  320.     "type": "mqtt-broker",
  321.     "name": "MQTT Broker",
  322.     "broker": "mqtt-broker-host",
  323.     "port": "1883",
  324.     "clientid": "",
  325.     "autoConnect": true,
  326.     "usetls": false,
  327.     "protocolVersion": "5",
  328.     "keepalive": "60",
  329.     "cleansession": true,
  330.     "autoUnsubscribe": true,
  331.     "birthTopic": "",
  332.     "birthQos": "0",
  333.     "birthRetain": "false",
  334.     "birthPayload": "",
  335.     "birthMsg": {},
  336.     "closeTopic": "",
  337.     "closeQos": "0",
  338.     "closeRetain": "false",
  339.     "closePayload": "",
  340.     "closeMsg": {},
  341.     "willTopic": "",
  342.     "willQos": "0",
  343.     "willRetain": "false",
  344.     "willPayload": "",
  345.     "willMsg": {},
  346.     "userProps": "",
  347.     "sessionExpiry": ""
  348.   }
  349. ]
  350.  
Advertisement
Add Comment
Please, Sign In to add comment