Cannot get Tuya Integration to work

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.

1 Like

Do you have the temperature probes pluged into the unit? I spent a few hours trying to figure out how to add the other sensors, until I read someone elses posts about having to have them all plugged in when you start to configure for the first time.
-Patrick

Yep pretty sure I had them all plugged in. Haven’t tried for a while - maybe I will try again this weekend and will doubly make sure they were all plugged in.

You might find that you have the same issue as me and DJL9999. The post above on how to obtain the temperature values of the probes from DPs 107 might help

This is amazing. Wish I had seen this before spending a while figuring out how they were encoding the values by myself!

1 Like

I have not used node red before could someone tell me what I do with that code to get it to work for me?

So I got everything put into node red but when I run it I get this error from the function.
“RangeError [ERR_BUFFER_OUT_OF_BOUNDS]: Attempt to access memory outside buffer bounds”
Any ideas?

My tuya app shows my IBBQ-4T but there are no variables for the 4 probes. Not sure why. I can see some chinese stuff but they don’t seem to show temp values.

I don’t see 107…

image

I have the same issue as you. Did you get it resolved?

Where can I find this “manual DPS option” is this in Tuya app or dev or in Hassio?

Unfortunately not. Though I haven’t checked it since I posted here - Based on you having the same problem, I expect it to be the same. If I get a chance I’ll check it out again and confirm.

1 Like

I think you can add 107 manually within HA config when setting up the tuya - just going off memory so could be wrong.

So managed to see the 107 but it’s a negative number and only displays the probe1 temp.
image

I’m using Tuya Local which identified my Inkbird as “inkbird_bbq4t_thermometerv2.yaml”

In that yaml file I can see that it uses the DP107 and then splits it up to all other probes so not sure why it shows up as a negative number.

From Tuya loT debug of DP107 I see the following:

Time Device Event DP ID Event Details
12/21/2023 8:32 Report 探头温度1 wBwAAMAcAAAQHQAAwBwAAA==
12/21/2023 8:32 Report 探头温度1 wBwAAcAcAAEaHQAB1BwAAQ==
12/21/2023 8:32 Report 探头温度1 1BwAAMAcAAAaHQAA3hwAAA==
12/21/2023 8:31 Report 探头温度1 wBwAAcAcAAEaHQABwBwAAQ==
12/21/2023 8:31 Report 探头温度1 wBwAAMAcAAAaHQAAyhwAAA==
12/21/2023 8:30 Report 探头温度1 wBwAAcAcAAEQHQABwBwAAQ==

Even though it’s in chinese characters it is indeed DP107 as per the inspection of the page:
image

In Tuya.iot in your “project” you’ll find a Device-ID, with this you can “Traverse” the left menu, and find a "Complete list of DP’s for your devices , where there also is a ( Scaling ) Number, which you manually have to set( for various measurements, to get it right in i.e HA), when either setting up your devices, or clicking “Configure Device” in /Settings/Devices-Integrations.

I can’t remember exactly where ( long time since i’ve been in there, from what i know they have changed their site-structure ), but it’s in the bottom of the left Menu, in tuya.iot , and there are a few topis in regards to DP’s in here, with complete links/pic’s, Use the Search function

Or go here and check if this is still valid , the DP-list and other details is among the various sub-menu’s, go through, copy/past your device id, and you’ll see

PS: You just say “it’s not right” , so what is the correct temperature ) ( +1.6 ? +16 ? +160 ? ) this is what the scaling factor is for … In Tuya integrations this has to be "transformed into i.e ( multiply/devide 0,1 or 0,01 or 0.001 ) , or ( 10 or 100 or 1000 )

So I played with the “inkbird_bbq4t_thermometerv2.yaml" file and got the following (all I did is change the probe 2-3-4 from integer to type: base64):

image

Thing is when I test the probes with hot water I notice that the Hassio temp for Probe 4 is actually the Probe 1 of the device, Probe 2 matches Probe 2, the other probes make the negative numbers blink.

1 Like

1 and 3 could be “showing” the same, as 3 is just “rounded” to 1 digits … are you sure these 2 actually is configured/connected correct ?

EDIT: Try to change “output” to see if the “probes” actually is “Toasted” :slight_smile:

What i find strange is the masking in the yaml file. There are more digits in that string coming from the dp107 than in the mask. Will have to show you what i mean when i get back home.

For example probe 1 = FFFF 0000 0000 0000
but dp107 has = 0000 0000 0000 0000 0000 0000 digits in the string

ok, try to put all probes in same small bowl of boiled water, for 5min or so (don’t let the cables(rubber) into/near the water. this way you get a better idea, whether some needs to be calibrated, and if some is way off !
And when you get the result, from all probes, in same heated temperature, at the same time, you could have a look at this post, might help you to understand what you are seeing.

Hassio debuger give me:
"107": "1j0AAShBAAEIPgABNj0AAQ=="

So as per the link you provided from InkBirds tech:
I get the following from DP107: 1j0AAShBAAEIPgABNj0AAQ==
Converted to HEX: d6 3d 00 01 28 41 00 01 08 3e 00 01 36 3d 00 01

Which gives us:

Probe 1:

  • d6 3d 00 01 reversed → 01003dd6
  • converted to decimal: 16793046
  • 16793046/100,000 = 167.93 F which is 75 C

Probe 2:

  • 28 41 00 01 reversed → 01004128
  • converted to decimal: 16793896
  • 16793896/100,000 = 167.93 F which is 75 C

Probe 3:

  • 08 3e 00 01 reversed → 01003e08
  • converted to decimal: 16793096
  • 16793096/100,000 = 167.93 F which is 75 C

Probe 4:

  • 36 3d 00 01 reversed → 01003d36
  • converted to decimal: 16792886
  • 16792886/100,000 = 167.92 F which is 75 C

This matched all my probes inserted all at once into a cup of hot water (+/- 1C).

So in conclusion, I believe something is wrong with the conversion inside the yaml file. Since we can see that Tuya_Local debug log does indeed get the correct numbers from dp107 but hassio is not outputing them correctly.

In the yaml this is done:

    - id: 107
      type: base64
      name: sensor
      class: measurement
      optional: true
      mapping:
        - mask: FFFF000000000000
          endianness: little
          scale: 100
      unit: F

From my understanding:

  • mask: FFFF000000000000 it takes the first 4 HEX
  • endianness: little reverse the bytes
  • scale: 100 divide by 100

Code seems correct but for some reason Probe1 and Probe3 are not giving the correct measurement in hassio.

Ok, i don’t know where you get your “information” nor which “yaml” you refers to , but i think you should read this whole Topic ( Which actually has nothing to do whether Tuya-Local Integration Not working, but 1 common thing in the post here is IBBQ-4T …Configuration/setup) , and it turns out that both links to DP’s etc is here already, aswell as the info , in FEW post above, i linked you to, so have you considered enable 108,109,110 ?, or tried to “follow” more of the examples in here ?.