logo elektroda
logo elektroda
X
logo elektroda

Seeking Template for [BK7231N] Tuya 8-in-1 Air Quality Monitor PV28-CW After OpenBeken Flash

markiespark 9495 30
Best answers

How can I identify the Tuya MCU datapoints and safely determine whether my flashed BK7231N PV28-CW air quality monitor uses a MCU without opening the device?

Start the TuyaMCU driver in OpenBeken and query the MCU state; if the device has a baud key (your UART extraction showed 9600) and you receive dpIDs with types/values, it is acting like a TuyaMCU device [#20966444] [#20967673] [#20969759] Use `tuyaMcu_sendQueryState` and watch the values while comparing them to the readings on the device screen to figure out which dpID is CO2, PM2.5, temperature, humidity, battery, etc. [#20969759] [#20971249] If you hit the `packet too large` error, update OBK first; after that the query output became readable and revealed many datapoints [#20967797] [#20969610] Once identified, map each dpID to a channel in `autoexec.bat` with `setChannelLabel`, `setChannelType`, and `linkTuyaMCUOutputToChannel`, which is the recommended way to make the values visible and usable in Home Assistant [#20974509] [#21004234] For custom devices, the maintainers also suggest the scriptable OBK page, but simple channel mapping is enough for this sensor [#20971404]
Generated by the language model.
ADVERTISEMENT
  • #31 21371022
    markiespark
    Level 5  
    Posts: 12
    Help: 1
    Rate: 1
    >>21361285 Ok, this has helped a lot. After much testing I've ruled out dp 5,6,7 and 104 using TextFields. All is accounted for apart from 107 which is valid but still unknown. I set it to 1 but it sets itself back to 0. Also I set the alarm off and repeated that test - no different. So yes it could possibly be a calibration setting as mentioned before. Here's a revised autoexec, based on the JSON:

    // Tuya PV28-CW 8-in-1 Air Quality Sensor autoexec.bat
    
    // Clear previous autoexec settings
    clearIO
    
    // clear flags
    // flags 0
    
    // set flag 46
    SetFlag 46 1
    
    // Start TuyaMCU driver at Baud 9600
    startDriver TuyaMCU
    tuyaMCU_setBaudRate 9600
    
    // If not using MQTT comment out waitFor MQTTState 1 or
    // If using MQTT comment out tuyaMcu_defWiFiState 4
    
    waitFor MQTTState 1
    // tuyaMcu_defWiFiState 4
    
    // Force update from TuyaMCU every 10 sec
    addRepeatingEvent 10 -1 tuyaMcu_sendQueryState
    
    // Mappings [dpID] [varType] [tgChannel]
    
    // CO2 (ppm) - Dp 2 - Ch 1
    setChannelLabel 1 "CO2 (ppm)"
    setChannelType 1 ReadOnly
    linkTuyaMCUOutputToChannel 2 val 1
    
    // PM2.5 (ug/m3) - Dp 20 -Ch 2
    setChannelLabel 2 "PM2.5 (ug/m3)"
    setChannelType 2 ReadOnly
    linkTuyaMCUOutputToChannel 20 val 2
    
    // PM1.0 (ug/m3 - Dp 102 - Ch 3
    setChannelLabel 3 "PM1.0 (ug/m3)"
    setChannelType 3 ReadOnly
    linkTuyaMCUOutputToChannel 102 val 3
    
    // PM10 (ug/m3) - Dp 101 - Ch 4
    setChannelLabel 4 "PM10 (ug/m3)"
    setChannelType 4 ReadOnly
    linkTuyaMCUOutputToChannel 101 val 4
    
    // HCHO (ug/m3) - Dp 22 - Ch 5
    setChannelLabel 5 "HCHO Formaldehyde (ug/m3)"
    setChannelType 5 ReadOnly
    linkTuyaMCUOutputToChannel 22 val 5
    
    // TVOC (ug/m3) - Dp 21 - Ch 6
    setChannelLabel 6 "TVOC (ug/m3)"
    setChannelType 6 ReadOnly
    linkTuyaMCUOutputToChannel 21 val 6
    
    // Temperature - Dp 18 - Ch 7
    setChannelType 7 Temperature
    setChannelLabel 7 "Temperature"
    linkTuyaMCUOutputToChannel  18 val 7
    
    // Humidity ID19 (%) - Dp 19 - Ch 8
    setChannelLabel 8 "Humidity"
    setChannelType 8 Humidity
    linkTuyaMCUOutputToChannel 19 val 8
    
    // Humidity Current ID103 (%) - Dp 103 - Ch 9
    setChannelLabel 9 "Humidity Current"
    setChannelType 9 Humidity
    linkTuyaMCUOutputToChannel 103 val 9
    
    // Battery Level (%) - Dp 15 - Ch 10
    setChannelLabel 10 "Battery Level"
    setChannelType 10 BatteryLevelPercent
    linkTuyaMCUOutputToChannel 15 val 10
    
    // Brightness Level Detected - Dp 17 - Ch 11
    setChannelLabel 11 "Brightness Level Detected (0-100)"
    setChannelType 11 ReadOnly
    linkTuyaMCUOutputToChannel 17 val 11
    
    // CO2 Alarm State - Dp 1 - Ch 12
    setChannelLabel 12 "CO2 Alarm State (1 Normal, 0 Alarm)"
    setChannelType 12 ReadOnly
    linkTuyaMCUOutputToChannel 1 enum 12
    
    // Battery State - Dp 14 - Ch 13
    setChannelLabel 13 "Battery State (1 Charging, 0 Discharging)"
    setChannelType 13 ReadOnly
    linkTuyaMCUOutputToChannel 14 enum 13
    
    // PM2.5 Alarm State - Dp 106 - Ch 14
    setChannelLabel 14 "PM2.5 Alarm State (1 Normal, 0 Alarm)"
    setChannelType 14 ReadOnly
    linkTuyaMCUOutputToChannel 106 enum 14
    
    // CO2 Alarm Threshold - Dp 26 - Ch 15
    setChannelLabel 15 "CO2 Alarm Threshold (400-5000 ppm - Default: 1500)"
    setChannelType 15 TextField
    linkTuyaMCUOutputToChannel 26 val 15
    
    // PM2.5 Alarm Threshold - Dp 105 - Ch 20
    setChannelLabel 20 "PM2.5 Alarm Threshold (0-1000 - Default: 75)"
    setChannelType 20 TextField
    linkTuyaMCUOutputToChannel 105 val 20
    
    // Temperature Unit Display - Dp 31 - Ch 16
    setChannelLabel 16 "Temperature Unit (0=Celsius, 1=Fahrenheit)"
    setChannelType 16 Toggle
    linkTuyaMCUOutputToChannel 31 enum 16
    
    // Check Time Unknown - stays set - Dp 107 - Ch 17
    setChannelLabel 17 "Check Time? Unknown."
    setChannelType 17 TextField
    linkTuyaMCUOutputToChannel 107 bool 17
    
    // Display Sleep - Dp 108 - Ch 18
    setChannelLabel 18 "Display Sleep (0=Off, 1=On)"
    setChannelType 18 Toggle
    linkTuyaMCUOutputToChannel 108 bool 18
    
    // Display Sleep Time - Dp 109 - Ch 19
    setChannelLabel 19 "Display Sleep Time (1-3600 sec - Default: 30)"
    setChannelType 19 TextField
    linkTuyaMCUOutputToChannel 109 val 19
    
    // Alarm Setting - Dp 13 - Ch 21
    setChannelLabel 21 "Alarm Setting"
    setChannelType 21 Toggle
    linkTuyaMCUOutputToChannel 13 bool 21


    I've also found a workaround for the save crashes (autoexec only) by keeping web tabs open.
    One for the display interface where I can click Restart
    One from the Web Application - Filesystem tab
    One from the Web Application - Logs tab
    This way, when the save corrupts after a restart, I can tab over and save again, tab back and restart. This works 100%. It's just unfortunate that most times it means 2x saves, occasionally 3, sometimes 4 just to get it to load right. Not good for flash wear but it is what it is.
    After much experimentation, looking through the commands, and ChatGPT getting it wrong, I've given up on decimalisation in the autoexec. Looks like it can only de done in HTML, which if it wasn't guaranteed to crash the device I'd love to try and work on again. So instead of trying to copy the nice display on the web inferface, I'll see if I can get the values from MQTT into Home Assistant and then modify them.

    Thanks everyone for your help with this. With just dp107 left we're almost there.
    Helpful post? Buy me a coffee.
  • ADVERTISEMENT

Topic summary

✨ The discussion centers on flashing the Tuya PV28-CW 8-in-1 Air Quality Monitor, which uses the BK7231N chip, with OpenBeken firmware after initial flashing via Tuya Cloudcutter. The device requires USB power due to a short battery life. Initial challenges included lack of a dedicated OpenBeken template and handling TuyaMCU communication, including baud rate settings and command queries. Users identified and mapped TuyaMCU datapoint IDs (dpIDs) corresponding to sensor readings such as CO2, PM2.5, PM1.0, PM10, HCHO, TVOC, temperature, humidity, battery level, and screen wake timeout. The dpIDs were linked to OpenBeken channels with appropriate labels and read-only types. Issues with data scaling (e.g., _div10) and autoexec.bat file corruption were noted. The community shared JSON configurations extracted from Tuya firmware, aiding in understanding dpID functions and enabling more complete autoexec.bat scripts. Calibration and alarm dpIDs were discussed, with some remaining unknown or unconfirmed. Guidance on flashing hardware, including removing the Tuya module or cutting TX/RX lines, was provided. The device supports MQTT integration, and custom web interfaces can be created using OpenBeken’s scripting capabilities. Overall, a near-complete OpenBeken configuration for the PV28-CW was developed, enabling sensor data acquisition and MQTT publishing, with ongoing refinement of calibration and alarm features.
Generated by the language model.

FAQ

TL;DR: With 21 dpIDs identified and "You are correctly receiving dpIDs," this FAQ helps OpenBeken users turn a flashed BK7231N PV28-CW into a usable TuyaMCU air-quality monitor with working channel maps, autoexec startup, MQTT export, and safer wire-flash guidance. [#20969759]

Why it matters: This thread turns a risky no-template flash into a practical, reusable setup for CO2, PM, VOC, HCHO, temperature, humidity, battery, alarms, and display controls.

Approach Best use What the thread confirms Main limitation
Tuya Cloudcutter flash Fast first flash OpenBeken was flashed by selecting Tuya Generic and a PM2.5 device profile The user reported it felt easy to brick during retries
OpenBeken custom page Full on-device dashboard Recommended as the preferred route for custom TuyaMCU devices Harder for beginners to build and keep stable
Home Assistant via MQTT Easiest practical display Suggested as a simpler alternative to custom UI Decimal scaling still needed outside stock web UI
Wire flash Recovery when cloud paths are patched Confirmed possible after opening the unit and isolating MCU serial lines Display adhesive is strong and access is awkward

Key insight: The PV28-CW is usable after OpenBeken because the real work is not the flash itself; it is identifying TuyaMCU dpIDs and making them persistent with autoexec.bat. Once those dpIDs are mapped, the monitor can publish nearly all major readings reliably.

Quick Facts

  • The most complete mapping lists 21 dpIDs, including CO2, PM1.0, PM2.5, PM10, TVOC, HCHO, temperature, humidity, battery, alarms, screen sleep, and thresholds. [#21361285]
  • The MCU serial link runs at 9600 bps, and the published autoexec examples set tuyaMCU_setBaudRate 9600 before channel mapping. [#21371022]
  • The battery is only 350 mAh and lasts about 1 hour unplugged, so this monitor is effectively a USB-powered device with brief bridge power. [#21177255]
  • Sensor and setting ranges recovered from Tuya definitions include CO2 0-5000 ppm, PM2.5 0-1000 ug/m3, TVOC 0-9999 with scale 3, and screen sleep time 10-300 s. [#21361285]
  • The hardware teardown identifies an FMD Fremont Micro MCU, a PMS7003-clone PM sensor, and an NDIR CO2 sensor; the PM module fan must spin or response becomes very slow. [#21177255]

How do I create an OpenBeken autoexec.bat template for the Tuya PV28-CW 8-in-1 air quality monitor with a BK7231N chip?

Create autoexec.bat by starting TuyaMCU, setting baud to 9600, then mapping each discovered dpID to a channel. Use this order: clearIO, SetFlag 46 1, startDriver TuyaMCU, tuyaMCU_setBaudRate 9600, then linkTuyaMCUOutputToChannel lines for CO2, PM, VOC, HCHO, temperature, humidity, battery, and alarms. The thread’s later template also adds addRepeatingEvent 10 -1 tuyaMcu_sendQueryState so values refresh every 10 seconds after boot. [#21371022]

What is TuyaMCU, and how can I tell whether the PV28-CW air quality monitor uses it after flashing OpenBeken?

Yes, this PV28-CW uses TuyaMCU after flashing. "TuyaMCU is a secondary microcontroller system that handles sensors or device logic over UART, while the Wi-Fi chip relays commands and states; its key characteristic is dpID-based serial messaging such as heartbeat, product info, and state packets." You can confirm it by seeing heartbeats like 55 AA 03 00, product info, and repeated ParseState entries after startDriver TuyaMCU. The thread also notes two practical checks: sleep behavior and the presence of a baud key. [#20967673]

How can I safely identify whether a flashed Tuya air quality monitor has a separate MCU without opening the device and risking sensor damage?

Use the OpenBeken web interface and logs first. 1. Run startDriver TuyaMCU. 2. Raise log level and run tuyaMcu_sendQueryState. 3. Watch for heartbeat, product info, MCU config, and ParseState lines with dpIDs. This device showed product key data, heartbeat frames, and multiple sensor values without opening the case, which safely confirmed a separate MCU path. That method avoids touching the sensors until you know the UART layer is active. [#20967673]

Why does OpenBeken lose the TuyaMCU driver after reboot, and how do I make it start automatically with autoexec.bat?

OpenBeken loses the TuyaMCU driver after reboot because the command was started manually, not persisted. Put the startup commands in autoexec.bat so they run every boot: startDriver TuyaMCU and tuyaMCU_setBaudRate 9600. The thread also points to using startup automation tutorials and examples for commands that must survive restarts. In practice, that turns a temporary test session into a persistent configuration. [#20967797]

What does the OpenBeken command tuyaMcu_sendQueryState do, and how do I use it to discover dpIDs on a TuyaMCU device?

tuyaMcu_sendQueryState asks the MCU to send its current datapoints, which reveals dpIDs, types, and values. Use it after startDriver TuyaMCU, then compare the returned numbers with the device screen. On this monitor, that process exposed values like id 2 = 1122, id 18 = 23, and id 19 = 65, which later matched CO2, temperature, and humidity. Repeating the query while changing room conditions makes unknown dpIDs much easier to identify. [#20969759]

Which dpIDs have been identified for the Tuya PV28-CW 8-in-1 monitor, and what measurements do they correspond to in OpenBeken?

The identified dpIDs include 1 CO2 alarm, 2 CO2 ppm, 13 alarm enable, 14 battery state, 15 battery %, 17 light or screen brightness, 18 temperature °C, 19 humidity %, 20 PM2.5, 21 TVOC, 22 HCHO, 26 CO2 alarm threshold, 31 °C/°F, 101 PM10, 102 PM1.0, 103 duplicate humidity, 105 PM2.5 alarm threshold, 106 PM2.5 alarm, 107 unknown/check time, 108 display sleep, and 109 display sleep timer. That is the most complete mapping posted in the thread. [#21177255]

How do I map TuyaMCU dpIDs like CO2, PM2.5, PM10, HCHO, TVOC, temperature, humidity, and battery to OpenBeken channels?

Map each dpID to any free OpenBeken channel, then set a suitable channel type. For example: CO2 dpID 2, PM2.5 20, PM10 101, HCHO 22, TVOC 21, temperature 18, humidity 19, and battery 15. The safe pattern is setChannelLabel, setChannelType, then linkTuyaMCUOutputToChannel dpID type channel. Temperature can use Temperature, humidity can use Humidity, and battery can use BatteryLevelPercent, while most air metrics can stay ReadOnly. [#21004234]

Why are humidity readings reported on both dpID 19 and dpID 103 on the PV28-CW, and which one should I use?

Both dpID 19 and dpID 103 report humidity on this device, and the thread never found a functional difference. The Tuya product JSON labels 19 as Humidity and 103 as Humidity Current, but both use a 0-100 value range with scale 0. For a simple template, use dpID 19 and ignore 103 unless you want to log both during testing. That keeps the channel layout cleaner without losing the actual humidity reading. [#21361285]

How should I handle scaled values like TVOC and HCHO in OpenBeken when the Tuya definition shows scale 3 but the web UI and MQTT values are not decimalized correctly?

Treat TVOC and HCHO as raw integer values in OpenBeken, then scale them outside the default UI. The recovered Tuya definition shows scale: 3 for dpID 21 and dpID 22, meaning values such as 1 represent 0.001 in display terms. The thread reports that _div10 or _div1000 style attempts did not fix decimalization in the stock web UI or MQTT, so the practical workaround is Home Assistant templates or custom HTML. [#21358711]

What is the difference between OpenBeken channel numbers and Tuya dpIDs, and how should I choose channel assignments safely?

Tuya dpIDs identify the MCU datapoints, while OpenBeken channel numbers are only local slots for displaying or publishing values. You can map any dpID to any free channel, but the thread advises against matching dpID and channel number by habit because channels are limited. The safe rule is simple: choose unused channels, label them clearly, and mark sensor outputs as ReadOnly unless you intentionally want a writable control. [#20974509]

OpenBeken custom web page vs Home Assistant MQTT for the PV28-CW — which approach is better for displaying all air quality readings?

Home Assistant via MQTT is better for most users, while a custom OpenBeken page is better for advanced users. The thread explicitly says the preferred solution for such custom devices is the scriptable OpenBeken page, but it also says you can ignore the interface and forward everything to Home Assistant. In this case, the user found JavaScript pages attractive but harder to maintain, while MQTT offered a more practical path for scaling and dashboards. [#20971404]

How can I use the extracted Tuya product JSON to improve an OpenBeken template for the PV28-CW, especially for dpIDs 1, 14, 104, 107, 108, and 109?

Use the Tuya product JSON as the authoritative source for names, types, and ranges. It resolves dpID 1 as CO2 alarm enum, 14 as battery state enum, 104 as air-quality enum, 107 as Check Time bool, 108 as screen sleep bool, and 109 as screen sleep time with a 10-300 s range and 10 s steps. That lets you replace placeholder labels, choose enum, bool, or val correctly, and expose writable controls such as screen sleep and timer. [#21361285]

Why does saving autoexec.bat sometimes corrupt files or force AP recovery on this device, and what troubleshooting steps are available?

The thread shows repeated save corruption, but it does not prove a root cause. The reported symptoms are missing autoexec.bat sections after restart, repeated re-saves, and occasional AP recovery. The practical workaround was keeping three tabs open: the display page, the filesystem tab, and the logs tab, then re-saving and restarting until the file loaded correctly. The user also considered lfs_format, but no confirmed size or final fix was posted. This is the main failure case still unresolved in the thread. [#21371022]

What is Tuya Cloudcutter, and how was it used to flash OpenBeken onto the BK7231N-based PV28-CW air quality monitor?

Tuya Cloudcutter was used as the initial cloud-flashing method for this BK7231N PV28-CW. "Tuya Cloudcutter is a software flashing method that installs replacement firmware over Tuya’s onboarding path, without opening the device; its key characteristic is profile-based flashing, such as selecting a generic Tuya device and a matching product type." In this case, the user chose Tuya Generic and a PM2.5 profile, hit connection errors, retried, and eventually got OpenBeken installed and OTA updates working. [#20965286]

What's the safest way to open and wire-flash the Tuya PV28-CW if cloud flashing is patched, including handling the display adhesive and MCU serial lines?

Open it from the front and isolate the MCU serial path before wiring. 1. Lift the LCD bezel carefully; it is held by double-sided tape. 2. Remove the 4 screws underneath. 3. For flashing, remove the Tuya module or cut the TX/RX tracks, or unsolder the 100R series resistors to the MCU. The thread warns that the display adhesive is strong and can pull the backlight reflector sheet loose. It also confirms MCU communications run at 9600 bps after access. [#21177255]
Generated by the language model.
ADVERTISEMENT