logo elektroda
logo elektroda
X
logo elektroda
Dostępna jest polska wersja

Czy wolisz polską wersję strony elektroda?

Nie, dziękuję Przekieruj mnie tam

How to send measurements from TuyaMCU battery-powered thermometer to HTTP server?

p.kaczmarek2  10 3222 Cool? (+3)
📢 Listen (AI):

TL;DR

  • Sends temperature and humidity from a TuyaMCU battery-powered CB3S/BK7231N sensor flashed with OpenBK7231 to an arbitrary HTTP server using GET requests.
  • Uses `addEventHandler OnChannelChange` to trigger `SendGet` on channel 1 and channel 2, plus a `waitFor WiFiState 4` startup request and PHP logging script.
  • The setup links TuyaMCU DPIDs 1, 2, 3, 17, and 18, sets the UART baud rate to 115200, and divides temperature by 10.
  • Collected logs show repeated timestamps with temperature and humidity values, proving the logger works independently of Home Assistant.
  • TuyaMCU sends readings only when values change, so temperature and humidity do not always arrive together.
Generated by the language model.
PHP script snippet for logging data from the TuyaMCU sensor.
Here I will show you how to send measurements (temperature and humidity) from TuyaMCU battery-powered sensor to arbitrary HTTP server via GET request. Following implementation will work independently from Home Assistant and will allow you to create fully customizable data logger. For the sake of presentation, I will use the device described here:
[CB3S/BK7231N] Temperature/Humidity Sensor with TuyaMCU - Diagram, Reverse Enginering
I am assuming here that device is already flashed with OBK.

Following topic was created with @DeDaMrAz. All testing was done on his side. Thanks for cooperation!

Requirements for this topic
To replicate our demo from here, you basically need two things:
- TuyaMCU sensor device that will send data
- a HTTP server with a PHP script that will receive data
No Home Assistant is needed.

Sending measurements from TuyaMCU

According to OBK docs:
https://github.com/openshwprojects/OpenBK7231T_App/blob/main/docs/commands.md
There is a SendGET command, but we need to know when to use it.
TuyaMCU reports measurements with a delay.
So we need to setup a change handler for measurement channel:

addEventHandler OnChannelChange 1 SendGet http://192.168.0.75/log.php?t=$CH1

The following script will run SendGet with channel 1 value, which in this particular case is used for temperature value.
For the sake of an example, I can also show you how to send a GET once the device connects to WiFi. It is important to wait for the WiFi connection first, see script belowq:

waitFor WiFiState 4
SendGet http://192.168.0.75/log.php?t=HEEELLLO

Here is full script (modified script from here)

startDriver TuyaMCU
startDriver tmSensor

// may be needed, depends on device, some also use 9600
tuyaMCU_setBaudRate 115200

// dpID 1 is tempererature div 10
setChannelType 1 temperature_div10
linkTuyaMCUOutputToChannel 1 val 1
// dpID 2 is % humidity
setChannelType 2 Humidity
linkTuyaMCUOutputToChannel 2 val 2
// dpID 3 is battery state - low(0), mid(1) and high(2)
linkTuyaMCUOutputToChannel 3 enum 3
setChannelType 3 ReadOnlyLowMidHigh
setChannelLabel 3 Battery

// on tempererature change
addEventHandler OnChannelChange 1 SendGet http://192.168.0.75/log.php?t=$CH1


//
// setup dpCache - temperature interval
//
// Show textfield for that
setChannelType 5 TextField
// setup display name
setChannelLabel 5 Temperature Interval
// Make value persistant (stored between reboots), 
// start value -1 means "remember last"
SetStartValue 5 -1
// set default value if not set
if $CH5==0 then "setChannel 5 1"
// link dpID 17 to channel 5, the type is val, extra '1' means that its dpCache variable
linkTuyaMCUOutputToChannel 17 val 5 1

setChannelType 6 TextField
setChannelLabel 6 Humidity Interval
SetStartValue 6 -1
if $CH6==0 then "setChannel 6 1"
linkTuyaMCUOutputToChannel 18 val 6 1



waitFor WiFiState 4
SendGet http://192.168.0.75/log.php?t=HEEELLLO


HTTP server side
HTTP server should be reachable from the network of your device. On your HTTP server, setup just a simple PHP file that prints received GET argument to file along with the current timestamp. You can also insert it to the MySQL database, but that's not the scope of this tutorial. Here is a sample, simplest script:
PHP script snippet for logging data from the TuyaMCU sensor.
You can test the script just by accessing it's URL in your web browser:
Screenshot of a webpage showing a message about data appended to a file.


Now let's run our setup for some time. Here are sample results:
Screenshot of a log file showing timestamps and measurement results.
Everything seems to be working!

Adding second measurement
Everything seems to be working, but the device in question is able to measure both temperature and humidity. So let's add another change handler to send humidity data as well:

startDriver TuyaMCU
startDriver tmSensor

// may be needed, depends on device, some also use 9600
tuyaMCU_setBaudRate 115200

// dpID 1 is tempererature div 10
setChannelType 1 temperature_div10
linkTuyaMCUOutputToChannel 1 val 1
// dpID 2 is % humidity
setChannelType 2 Humidity
linkTuyaMCUOutputToChannel 2 val 2
// dpID 3 is battery state - low(0), mid(1) and high(2)
linkTuyaMCUOutputToChannel 3 enum 3
setChannelType 3 ReadOnlyLowMidHigh
setChannelLabel 3 Battery

// on tempererature change
addEventHandler OnChannelChange 1 SendGet http://192.168.0.75/log.php?t=$CH1
addEventHandler OnChannelChange 2 SendGet http://192.168.0.75/log.php?h=$CH2


//
// setup dpCache - temperature interval
//
// Show textfield for that
setChannelType 5 TextField
// setup display name
setChannelLabel 5 Temperature Interval
// Make value persistant (stored between reboots), 
// start value -1 means "remember last"
SetStartValue 5 -1
// set default value if not set
if $CH5==0 then "setChannel 5 1"
// link dpID 17 to channel 5, the type is val, extra '1' means that its dpCache variable
linkTuyaMCUOutputToChannel 17 val 5 1

setChannelType 6 TextField
setChannelLabel 6 Humidity Interval
SetStartValue 6 -1
if $CH6==0 then "setChannel 6 1"
linkTuyaMCUOutputToChannel 18 val 6 1



waitFor WiFiState 4
SendGet http://192.168.0.75/log.php?t=HEEELLLO

PHP script also needs to be updates:
PHP code for logging temperature and humidity measurements
Now it looks like this:
Screenshot showing temperature and humidity measurements sent by TuyaMCU.
Here are results collected over time:

Timestamp: 2023-10-12 19:40:13 | t: HEEELLLO
Timestamp: 2023-10-12 19:40:18 | t: 279
Timestamp: 2023-10-12 19:41:22 | t: HEEELLLO
Timestamp: 2023-10-12 19:41:27 | t: 312
Timestamp: 2023-10-12 19:41:27 | h: 40
Timestamp: 2023-10-12 19:42:31 | t: HEEELLLO
Timestamp: 2023-10-12 19:42:36 | h: 37
Timestamp: 2023-10-12 19:43:40 | t: HEEELLLO
Timestamp: 2023-10-12 19:43:45 | h: 35
Timestamp: 2023-10-12 19:44:49 | t: HEEELLLO
Timestamp: 2023-10-12 19:44:55 | t: 349
Timestamp: 2023-10-12 19:45:59 | t: HEEELLLO
Timestamp: 2023-10-12 19:46:03 | h: 34
Timestamp: 2023-10-12 19:47:08 | t: HEEELLLO
Timestamp: 2023-10-12 19:47:13 | t: 357
Timestamp: 2023-10-12 19:48:17 | t: HEEELLLO
Timestamp: 2023-10-12 19:48:22 | t: 362
Timestamp: 2023-10-12 19:49:26 | t: HEEELLLO
Timestamp: 2023-10-12 19:49:31 | t: 364
Timestamp: 2023-10-12 19:50:35 | t: HEEELLLO
Timestamp: 2023-10-12 19:50:40 | t: 362
Timestamp: 2023-10-12 19:51:44 | t: HEEELLLO
Timestamp: 2023-10-12 19:51:49 | t: 359
Timestamp: 2023-10-12 19:51:50 | h: 33
Timestamp: 2023-10-12 19:52:53 | t: HEEELLLO
Timestamp: 2023-10-12 19:52:58 | t: 357
Timestamp: 2023-10-12 19:54:03 | t: HEEELLLO
Timestamp: 2023-10-12 19:54:08 | h: 33
Timestamp: 2023-10-12 19:55:12 | t: HEEELLLO
Timestamp: 2023-10-12 19:55:17 | t: 359
Timestamp: 2023-10-12 19:55:17 | h: 33
Timestamp: 2023-10-12 19:56:21 | t: HEEELLLO
Timestamp: 2023-10-12 19:56:26 | t: 359
Timestamp: 2023-10-12 19:57:30 | t: HEEELLLO
Timestamp: 2023-10-12 19:57:35 | h: 33
Timestamp: 2023-10-12 19:58:39 | t: HEEELLLO
Timestamp: 2023-10-12 19:58:44 | h: 32
Timestamp: 2023-10-12 19:59:48 | t: HEEELLLO
Timestamp: 2023-10-12 19:59:53 | h: 32
Timestamp: 2023-10-12 20:00:58 | t: HEEELLLO
Timestamp: 2023-10-12 20:01:03 | h: 32
Timestamp: 2023-10-12 20:02:07 | t: HEEELLLO
Timestamp: 2023-10-12 20:02:12 | t: 362
Timestamp: 2023-10-12 20:03:16 | t: HEEELLLO
Timestamp: 2023-10-12 20:03:21 | t: 360
Timestamp: 2023-10-12 20:03:21 | h: 33
Timestamp: 2023-10-12 20:04:25 | t: HEEELLLO
Timestamp: 2023-10-12 20:04:30 | h: 32
Timestamp: 2023-10-12 20:05:34 | t: HEEELLLO
Timestamp: 2023-10-12 20:05:39 | t: 363
Timestamp: 2023-10-12 20:06:43 | t: HEEELLLO
Timestamp: 2023-10-12 20:06:48 | t: 363
Timestamp: 2023-10-12 20:07:53 | t: HEEELLLO
Timestamp: 2023-10-12 20:07:58 | t: 363
Timestamp: 2023-10-12 20:09:02 | t: HEEELLLO
Timestamp: 2023-10-12 20:09:07 | h: 33
Timestamp: 2023-10-12 20:10:11 | t: HEEELLLO
Timestamp: 2023-10-12 20:10:16 | t: 312
Timestamp: 2023-10-12 20:11:20 | t: HEEELLLO
Timestamp: 2023-10-12 20:11:25 | t: 285
Timestamp: 2023-10-12 20:12:29 | t: HEEELLLO
Timestamp: 2023-10-12 20:12:34 | t: 268
Timestamp: 2023-10-12 20:13:39 | t: HEEELLLO
Timestamp: 2023-10-12 20:13:44 | t: 257
Timestamp: 2023-10-12 20:13:44 | h: 48
Timestamp: 2023-10-12 20:14:48 | t: HEEELLLO
Timestamp: 2023-10-12 20:14:53 | h: 50
Timestamp: 2023-10-12 20:15:57 | t: HEEELLLO
Timestamp: 2023-10-12 20:16:02 | h: 52
Timestamp: 2023-10-12 20:17:06 | t: HEEELLLO
Timestamp: 2023-10-12 20:17:11 | t: 242
Timestamp: 2023-10-12 20:18:16 | t: HEEELLLO
Timestamp: 2023-10-12 20:18:21 | t: 239
Timestamp: 2023-10-12 20:18:21 | h: 53
Timestamp: 2023-10-12 20:19:25 | t: HEEELLLO
Timestamp: 2023-10-12 20:19:30 | t: 237
Timestamp: 2023-10-12 20:20:34 | t: HEEELLLO
Timestamp: 2023-10-12 20:20:39 | t: 235
Timestamp: 2023-10-12 20:21:43 | t: HEEELLLO
Timestamp: 2023-10-12 20:21:48 | t: 234
Timestamp: 2023-10-12 20:22:53 | t: HEEELLLO
Timestamp: 2023-10-12 20:22:58 | t: 234
Timestamp: 2023-10-12 20:22:58 | h: 55
Timestamp: 2023-10-12 20:24:02 | t: HEEELLLO
Timestamp: 2023-10-12 20:24:07 | t: 233
Timestamp: 2023-10-12 20:25:11 | t: HEEELLLO
Timestamp: 2023-10-12 20:25:16 | t: 232
Timestamp: 2023-10-12 20:26:21 | t: HEEELLLO
Timestamp: 2023-10-12 20:26:25 | t: 232
Timestamp: 2023-10-12 20:27:30 | t: HEEELLLO
Timestamp: 2023-10-12 20:27:35 | t: 231
Timestamp: 2023-10-12 20:28:39 | t: HEEELLLO
Timestamp: 2023-10-12 20:28:44 | t: 230
Timestamp: 2023-10-12 20:28:44 | h: 55
Timestamp: 2023-10-12 20:29:48 | t: HEEELLLO
Timestamp: 2023-10-12 20:29:53 | t: 230
Timestamp: 2023-10-12 20:30:58 | t: HEEELLLO
Timestamp: 2023-10-12 20:31:03 | t: 231
Timestamp: 2023-10-12 20:32:07 | t: HEEELLLO
Timestamp: 2023-10-12 20:32:12 | t: 230
Timestamp: 2023-10-12 20:33:16 | t: HEEELLLO
Timestamp: 2023-10-12 20:33:21 | t: 229
Timestamp: 2023-10-12 20:34:25 | t: HEEELLLO
Timestamp: 2023-10-12 20:34:30 | t: 229
Timestamp: 2023-10-12 20:35:35 | t: HEEELLLO
Timestamp: 2023-10-12 20:35:40 | t: 229
Timestamp: 2023-10-12 20:36:44 | t: HEEELLLO
Timestamp: 2023-10-12 20:36:49 | t: 229
Timestamp: 2023-10-12 20:37:53 | t: HEEELLLO
Timestamp: 2023-10-12 20:37:58 | t: 229
Timestamp: 2023-10-12 20:39:03 | t: HEEELLLO
Timestamp: 2023-10-12 20:39:08 | h: 56
Timestamp: 2023-10-12 20:40:12 | t: HEEELLLO
Timestamp: 2023-10-12 20:40:17 | t: 229
Timestamp: 2023-10-12 20:41:21 | t: HEEELLLO
Timestamp: 2023-10-12 20:41:26 | t: 229
Timestamp: 2023-10-12 20:42:30 | t: HEEELLLO
Timestamp: 2023-10-12 20:42:36 | t: 229
Timestamp: 2023-10-12 20:43:40 | t: HEEELLLO
Timestamp: 2023-10-12 20:43:45 | t: 229
Timestamp: 2023-10-12 20:44:49 | t: HEEELLLO
Timestamp: 2023-10-12 20:44:54 | t: 229
Timestamp: 2023-10-12 20:45:58 | t: HEEELLLO
Timestamp: 2023-10-12 20:46:03 | t: 231
Timestamp: 2023-10-12 20:47:08 | t: HEEELLLO
Timestamp: 2023-10-12 20:47:13 | h: 55
Timestamp: 2023-10-12 20:48:17 | t: HEEELLLO
Timestamp: 2023-10-12 20:48:22 | t: 232
Timestamp: 2023-10-12 20:49:26 | t: HEEELLLO
Timestamp: 2023-10-12 20:49:31 | t: 234
Timestamp: 2023-10-12 20:50:35 | t: HEEELLLO
Timestamp: 2023-10-12 20:50:40 | t: 233
Timestamp: 2023-10-12 20:51:45 | t: HEEELLLO
Timestamp: 2023-10-12 20:51:50 | t: 234
Timestamp: 2023-10-12 20:51:50 | h: 55
Timestamp: 2023-10-12 20:52:54 | t: HEEELLLO
Timestamp: 2023-10-12 20:52:59 | h: 55
Timestamp: 2023-10-12 20:52:59 | t: 234

Some things to note:
- TuyaMCU sends temperature as an integer, you need to divide it by 10 to get correct result in this case
- TuyaMCU seems to report only data when there is a change, so not always all measurements are sent
You can also report the battery state in the same way.


Summary

This way you can report data directly to HTTP server and then process it in PHP (or any other) script any way you like. All required files are available on Github:
https://github.com/openshwprojects/BK7231-TuyaMCU-PHP-logger/tree/main
Soon I will publish another tutorial on the topic, this time maybe with MySQL or with chart creation, so stay tuned!

About Author
p.kaczmarek2
p.kaczmarek2 wrote 14238 posts with rating 12142 , helped 647 times. Been with us since 2014 year.

Comments

Tommy82 13 Oct 2023 18:26

And why not using the POST method? Posting this explicitly as parameters has the downside that it can unnecessarily litter the http server log. [Read more]

p.kaczmarek2 13 Oct 2023 19:13

Basically, there is nothing preventing you from using POST. In OpenBeken there is a SendPost function for this. You can also create JSON in its body, quote escaping is supported. It just so happened... [Read more]

krzbor 14 Oct 2023 00:04

It seems to me that it is more convenient to use MQTT. In the topic Link I presented the combination of MQTT and PHP (both automation and reading by web server). [Read more]

p.kaczmarek2 14 Oct 2023 08:35

@krzbor can your solution be fired on free/budget HTTP/PHP hosting? There used to be a lot of such even free services with one subdomain like mojasub dot hosting dot pl In the module you are using I see:... [Read more]

krzbor 14 Oct 2023 14:21

There should be no problem stream_socket_client is in PHP a connection opening - in other words a low-level access that is used by any higher layer. If there is no certificate then a connection is opened... [Read more]

sq3evp 19 Oct 2023 10:53

Do I understand correctly that, in general, any sensor not necessarily Tuya can so transmit data to the HTTP server? Does it have to be implemented something specific (some dedicated library) or anything,... [Read more]

Tommy82 19 Oct 2023 11:26

@sq3evp Everything from which you are able to generate a request (request) to the http server will work, that is, in the case of the GET method is the analogy of clicking on a link with the appropriate... [Read more]

p.kaczmarek2 19 Oct 2023 11:46

Any Tuya IoT device and any other IoT device, as long as it is supported by the batch used OpenBeken and will have this batch uploaded to it according to the materials on our channel Elektroda.com... [Read more]

sq3evp 19 Oct 2023 12:29

Other sensors via bluetooth will probably need gateways? Anybody got to Xiaomi Mijia thermometer 2 Bluetooth? Will it be possible to read data without a gateway from Xiaomi? [Read more]

krzbor 19 Oct 2023 17:45

I once posted something like this: Link But now I would choose Zigbee. [Read more]

FAQ

TL;DR: Sample log shows 57 temperature lines in 20 min (~1 every 21 s) and “Nothing prevents you from using POST” [Elektroda, p.kaczmarek2, #20768717; #20769358].

Why it matters: You can store battery-sensor data without Home Assistant or Tuya cloud.

Quick Facts

• SendGET & SendPost are available in OpenBeken ≥ 1.17 [Elektroda, p.kaczmarek2, post #20769358] • TuyaMCU temperature (DP 1) needs ÷10 scaling; DP 2 = humidity % [Elektroda, 20768717] • Battery enum: 0 low, 1 mid, 2 high [Elektroda, 20768717] • Typical shared PHP hosting still supports stream_socket_client() [Elektroda, krzbor, post #20770175] • Public MQTT brokers listen on 8883 (TLS) and 1883 (plain) [EMQX, 2023]

How do I trigger an HTTP GET when the temperature changes?

  1. Flash the sensor with OpenBeken.
  2. Map DP 1 to Channel 1 and run startDriver TuyaMCU.
  3. Add a handler: addEventHandler OnChannelChange 1 SendGet http://IP/log.php?t=$CH1 The script fires only when the DP value changes, limiting traffic [Elektroda, p.kaczmarek2, post #20768717]

What scaling do I apply to raw TuyaMCU values?

Temperature arrives as an integer divided by 10 (e.g., 279 → 27.9 °C). Humidity arrives as a direct percentage. Scale in your PHP or database layer [Elektroda, 20768717]

Where can I host the PHP logger?

Any server that runs PHP 5.6 + will work. The script writes to a text file, so no database is required. Shared hosting or XAMPP on Windows both succeed because they allow basic file I/O and outbound connections [Elektroda, p.kaczmarek2, post #20776318]

Do I need Home Assistant or an MQTT broker for this setup?

No. The device sends data directly to your HTTP endpoint, so neither Home Assistant nor MQTT is mandatory [Elektroda, p.kaczmarek2, post #20768717]

Is MQTT a better choice for battery devices?

MQTT decouples sensors and web pages; both connect to a broker asynchronously. It scales well, but you need a broker instance and possibly port forwarding, which free hosts rarely allow [Elektroda, krzbor, post #20770175]

Will the logger run on older PHP versions?

Yes. The sample uses fopen() and fwrite(), functions present since PHP 4. The script runs on legacy servers without changes [Elektroda, p.kaczmarek2, post #20776318]

Can non-Tuya hardware send data this way?

Any board supported by OpenBeken—including custom DHT11 sensors, ADC inputs, or push-buttons—can call SendGet/SendPost, so you are not limited to Tuya products [Elektroda, p.kaczmarek2, post #20776318]

Do Bluetooth thermometers like Xiaomi Mijia 2 need a gateway?

Yes. Bluetooth LE devices broadcast locally; you need a BLE-to-Wi-Fi gateway or a host with BLE radio (e.g., a Raspberry Pi) to capture packets before forwarding via HTTP/MQTT [Elektroda, sq3evp & krzbor, #20776393; #20776858].

How do I keep the server private?

Run the web server on your LAN and reference it by internal IP (e.g., 192.168.x.x). No port-forwarding means no internet exposure [Elektroda, Tommy82, post #20776280]

What happens if Wi-Fi is not up when the device boots?

Scripts that call SendGet before Wi-Fi is ready will fail silently. Use waitFor WiFiState 4 to delay the transmission until association completes [Elektroda, 20768717]

How much network traffic does each reading add?

A minimal GET with headers is ~150 bytes. At one reading every 20 s that is ~648 KB/day, negligible for typical home Wi-Fi [HTTP/1.1 Spec]. An 802.11n frame of this size draws ~120 µJ, a minor battery hit [Espressif, 2021].

Edge case: what if temperature never changes?

TuyaMCU only pushes on change, so no events fire. Add a periodic timer or use dpCache to force transmissions at set intervals [Elektroda, 20768717]
Generated by the language model.
%}