Hi @DJL9999. I’m not sure if you already have found a solution however I received a response from Inkbird (after many back and forwards).
They stated “The following is the engineer’s explanation:
ZBoAAIAbAACUGwAAHBsAAA== <— Value held in DPs107
Base64 decoding obtained
CC 1A 00 00 80 1B 00 00 94 1B 00 00 1C 1B 00 00 00
4 bytes per temperature.
CC 1A 00 00 Probe 1 Temperature 80 1B 00 00 Probe 2 Temperature, and so on
The transmission data is in small end mode and converted to decimal.
00001ACC converted to decimal to 6860
6860/100=68.6 F Fahrenheit”
Based on that information, I have used NodeRed to decode the Base64 string and output 4 temperature values to HomeAssistant. Below is the flow which you can import. It is in Celsius as the entity state, but also outputs Fahrenheit as an attribute. I thought I would share this in case it helps you or others.
NodeRed Flow:
[
{
"id": "7066186d409631ab",
"type": "tab",
"label": "IBBQ Temp",
"disabled": false,
"info": "",
"env": []
},
{
"id": "8b23198e06f322f9",
"type": "server-state-changed",
"z": "7066186d409631ab",
"name": "Get temp from Probe 1 field",
"server": "56676c55.140b84",
"version": 3,
"exposeToHomeAssistant": false,
"haConfig": [
{
"property": "name",
"value": ""
},
{
"property": "icon",
"value": ""
}
],
"entityidfilter": "sensor.ibbq_probe_1",
"entityidfiltertype": "exact",
"outputinitially": true,
"state_type": "str",
"haltifstate": "",
"halt_if_type": "str",
"halt_if_compare": "is",
"outputs": 1,
"output_only_on_state_change": false,
"for": 0,
"forType": "num",
"forUnits": "minutes",
"ignorePrevStateNull": false,
"ignorePrevStateUnknown": false,
"ignorePrevStateUnavailable": false,
"ignoreCurrentStateUnknown": false,
"ignoreCurrentStateUnavailable": false,
"outputProperties": [
{
"property": "payload",
"propertyType": "msg",
"value": "",
"valueType": "entityState"
},
{
"property": "data",
"propertyType": "msg",
"value": "",
"valueType": "eventData"
},
{
"property": "topic",
"propertyType": "msg",
"value": "",
"valueType": "triggerId"
}
],
"x": 120,
"y": 200,
"wires": [
[
"76400e190d0614fe"
]
]
},
{
"id": "76400e190d0614fe",
"type": "function",
"z": "7066186d409631ab",
"name": "Calc Base64 values into 4 temp values",
"func": "// Output 'Not Connected' if the device is unavailable\nif (msg.payload === 'unavailable') {\n for (let i = 0; i < 4; i++) {\n msg[`ibbq_temp${i + 1}`] = \"Not Connected\";\n msg[`ibbq_temp${i + 1}_fahrenheit`] = \"Not Connected\";\n }\n return msg;\n}\n\n// Decode the payload from base64 format\nconst decodedBytes = Buffer.from(msg.payload, 'base64');\nconst temperatureBytes = [];\n\n// Split the decoded payload into temperature bytes\nfor (let i = 0; i < decodedBytes.length; i += 4) {\n temperatureBytes.push(decodedBytes.slice(i, i + 4));\n}\n\nconst celsiusTemperatures = [];\nconst fahrenheitTemperatures = [];\nlet allNotConnected = true;\n\n// Convert temperature bytes to Celsius and Fahrenheit and store in the message\nfor (let i = 0; i < 4; i++) {\n const sensorName = `ibbq_temp${i + 1}`;\n \n if (i < temperatureBytes.length) {\n const fahrenheit = temperatureBytes[i].readInt32LE(0) / 100;\n const celsius = (fahrenheit - 32) * 5 / 9;\n //If the result is greater than 1000, then the probe isn't connected\n if (celsius <= 1000) {\n msg[sensorName] = Math.round(celsius * 100) / 100; // Output Celsius as integer\n msg[`${sensorName}_fahrenheit`] = Math.round(fahrenheit * 100) / 100; // Output Fahrenheit as integer\n celsiusTemperatures.push(Math.round(celsius * 100) / 100);\n fahrenheitTemperatures.push(Math.round(fahrenheit * 100) / 100);\n allNotConnected = false;\n } else {\n msg[sensorName] = \"Not Connected\";\n msg[`${sensorName}_fahrenheit`] = \"Not Connected\";\n celsiusTemperatures.push(\"Not Connected\");\n fahrenheitTemperatures.push(\"Not Connected\");\n }\n } else {\n msg[sensorName] = \"Not Connected\";\n msg[`${sensorName}_fahrenheit`] = \"Not Connected\";\n celsiusTemperatures.push(\"Not Connected\");\n fahrenheitTemperatures.push(\"Not Connected\");\n }\n}\n\n// If all sensors are 'Not Connected', drop the message\nif (allNotConnected) {\n return null;\n}\n\nreturn msg;\n",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 450,
"y": 200,
"wires": [
[
"849ca070314689ca",
"ef9821e26f3e8b18",
"6de16712f21ab4ee",
"05c988feb9705ac2"
]
]
},
{
"id": "849ca070314689ca",
"type": "ha-api",
"z": "7066186d409631ab",
"name": "Set Probe 1",
"server": "56676c55.140b84",
"version": 1,
"debugenabled": false,
"protocol": "http",
"method": "post",
"path": "/states/sensor.ibbq_temp1",
"data": "{\"state\":\"{{ibbq_temp1}}\",\"attributes\":{\"icon\":\"mdi:temperature-celsius\",\"friendly_name\":\"IBBQ Probe 1\",\"fahrenheit\":\"{{ibbq_temp1_fahrenheit}}\"}}",
"dataType": "json",
"responseType": "json",
"outputProperties": [
{
"property": "payload",
"propertyType": "msg",
"value": "",
"valueType": "results"
}
],
"x": 750,
"y": 140,
"wires": [
[]
]
},
{
"id": "ef9821e26f3e8b18",
"type": "ha-api",
"z": "7066186d409631ab",
"name": "Set Probe 2",
"server": "56676c55.140b84",
"version": 1,
"debugenabled": false,
"protocol": "http",
"method": "post",
"path": "/states/sensor.ibbq_temp2",
"data": "{\"state\":\"{{ibbq_temp2}}\",\"attributes\":{\"icon\":\"mdi:temperature-celsius\",\"friendly_name\":\"IBBQ Probe 2\",\"fahrenheit\":\"{{ibbq_temp2_fahrenheit}}\"}}",
"dataType": "json",
"responseType": "json",
"outputProperties": [
{
"property": "payload",
"propertyType": "msg",
"value": "",
"valueType": "results"
}
],
"x": 750,
"y": 200,
"wires": [
[]
]
},
{
"id": "6de16712f21ab4ee",
"type": "ha-api",
"z": "7066186d409631ab",
"name": "Set Probe 3",
"server": "56676c55.140b84",
"version": 1,
"debugenabled": false,
"protocol": "http",
"method": "post",
"path": "/states/sensor.ibbq_temp3",
"data": "{\"state\":\"{{ibbq_temp3}}\",\"attributes\":{\"icon\":\"mdi:temperature-celsius\",\"friendly_name\":\"IBBQ Probe 3\",\"fahrenheit\":\"{{ibbq_temp3_fahrenheit}}\"}}",
"dataType": "json",
"responseType": "json",
"outputProperties": [
{
"property": "payload",
"propertyType": "msg",
"value": "",
"valueType": "results"
}
],
"x": 750,
"y": 260,
"wires": [
[]
]
},
{
"id": "05c988feb9705ac2",
"type": "ha-api",
"z": "7066186d409631ab",
"name": "Set Probe 4",
"server": "56676c55.140b84",
"version": 1,
"debugenabled": false,
"protocol": "http",
"method": "post",
"path": "/states/sensor.ibbq_temp4",
"data": "{\"state\":\"{{ibbq_temp4}}\",\"attributes\":{\"icon\":\"mdi:temperature-celsius\",\"friendly_name\":\"IBBQ Probe 4\",\"fahrenheit\":\"{{ibbq_temp4_fahrenheit}}\"}}",
"dataType": "json",
"responseType": "json",
"outputProperties": [
{
"property": "payload",
"propertyType": "msg",
"value": "",
"valueType": "results"
}
],
"x": 750,
"y": 320,
"wires": [
[]
]
},
{
"id": "56676c55.140b84",
"type": "server",
"name": "Home Assistant",
"version": 1,
"legacy": false,
"addon": false,
"rejectUnauthorizedCerts": false,
"ha_boolean": "y|yes|true|on|home|open",
"connectionDelay": false,
"cacheJson": true
}
]
In summary, NodeRed uses an Event State node to watch for changes of [sensor.ibbq_probe_1 - which is DPS 107] which connects to the function node which processes using the following:
// Output 'Not Connected' if the device is unavailable
if (msg.payload === 'unavailable') {
for (let i = 0; i < 4; i++) {
msg[`ibbq_temp${i + 1}`] = "Not Connected";
msg[`ibbq_temp${i + 1}_fahrenheit`] = "Not Connected";
}
return msg;
}
// Decode the payload from base64 format
const decodedBytes = Buffer.from(msg.payload, 'base64');
const temperatureBytes = [];
// Split the decoded payload into temperature bytes
for (let i = 0; i < decodedBytes.length; i += 4) {
temperatureBytes.push(decodedBytes.slice(i, i + 4));
}
const celsiusTemperatures = [];
const fahrenheitTemperatures = [];
let allNotConnected = true;
// Convert temperature bytes to Celsius and Fahrenheit and store in the message
for (let i = 0; i < 4; i++) {
const sensorName = `ibbq_temp${i + 1}`;
if (i < temperatureBytes.length) {
const fahrenheit = temperatureBytes[i].readInt32LE(0) / 100;
const celsius = (fahrenheit - 32) * 5 / 9;
//If the result is greater than 1000, then the probe isn't connected
if (celsius <= 1000) {
msg[sensorName] = Math.round(celsius * 100) / 100; // Output Celsius as integer
msg[`${sensorName}_fahrenheit`] = Math.round(fahrenheit * 100) / 100; // Output Fahrenheit as integer
celsiusTemperatures.push(Math.round(celsius * 100) / 100);
fahrenheitTemperatures.push(Math.round(fahrenheit * 100) / 100);
allNotConnected = false;
} else {
msg[sensorName] = "Not Connected";
msg[`${sensorName}_fahrenheit`] = "Not Connected";
celsiusTemperatures.push("Not Connected");
fahrenheitTemperatures.push("Not Connected");
}
} else {
msg[sensorName] = "Not Connected";
msg[`${sensorName}_fahrenheit`] = "Not Connected";
celsiusTemperatures.push("Not Connected");
fahrenheitTemperatures.push("Not Connected");
}
}
// If all sensors are 'Not Connected', drop the message
if (allNotConnected) {
return null;
}
return msg;
The function node then writes to HomeAssistant via an API node.