logo elektroda
logo elektroda
X
logo elektroda

[BK7231N/CB2S] Ceiling Fan Controller with Dimmer and RF Remote

totallylost 1461 2
ADVERTISEMENT
  • Universal Smart Ceiling Fan Remote Control and Dimmer Light Switch
    Functions: 3-Speed Ceiling Fan Remote, Off-timer, Dimming
    buy: amazon.com

    Universal smart ceiling fan remote control and light dimmer with wiring.Universal Smart Ceiling Fan Remote Control and Dimmer, model RE-028W. Ceiling fan remote control kit box with certification logos.



    Quick Start:
    -desolder, flash, reinstall
    -No pins need configured, OpenBeken takes care of the TuyaTX/RX automagically.
    -Place the 'autoexec.bat' on the device file-system and reboot.
    -Grab the 'HA MQTT yaml' near the bottom of this post.



    Manufacturer: San Sheng (Zhongshan), but it is branded [or unbranded] under various names.
    Model: RE-028W
    Chipset: CB2S
    Module Firmware: V2.1.6
    MCU Firmware: V1.0.0
    Replacement: ESP8685-WROOM-03-H4
    Notes: The unit connects electrically to load and neutral without a ground.


    Primary distributors:
    ParrotUncle (Subsidiary of Eileen Grays Network Technology)
    Model: GA030
    FEKOTS
    Model: SS-T28

    Potential FCC-ID: 2AX7R-RE021


    About the board
    The unit ships with a Beken BK7231N on a CB2S:
    On the front of the chip, only CEN pin was soldered to the board.
    On the back of the chip, all pins were soldered to the board.
    However, the only important pins seem to be Tuya_Rx and Tuya_Tx.

    ESP8685-WROOM-03 is a direct drop-in replacement just with different pin names.
    CB2S : CEN || 3v3 | GND | RX1 | TX1 | P24 | P26
    ESP-x : _EN || 3V3 | GND | RX_ | TX_ | IO5 | IO4


    Open smart ceiling fan remote control with internal components exposed. PCB with electronic components, including a CB2S module and two large capacitors. Close-up of a circuit board with electronic components. Close-up of a circuit board with electronic components and capacitors. Circuit board of a ceiling fan remote control showing capacitors and components. Electronic module for ceiling fan control.

    Printed circuit board inside a device casing with protruding wires.
    Printed circuit board with various electronic components and wires.
    View of the circuit board of a ceiling fan remote module.



    Tuya Cloud Controls and Device Info:
    Prior to flashing the device, I tried to gather as much information I could regarding the stock functionality.

    Below are the features available in the Tuya Cloud app and Version Info provided.
    App screen for controlling a ceiling fan and light dimmer remotely. Device update screen with no updates available

    In the Tuya Dev Project, below are the Tuya JSON and Standard Instruction Set:
    JSON EDITOR
    [
      {
        "code": "switch_led",
        "value": true
      },
      {
        "code": "bright_value",
        "value": 100
      },
      {
        "code": "temp_value",
        "value": 1
      },
      {
        "code": "fan_switch",
        "value": false
      },
      {
        "code": "fan_speed",
        "value": 1
      },
      {
        "code": "fan_direction",
        "value": "forward"
      },
      {
        "code": "fan_countdown_set",
        "value": "cancel"
      }
    ]


    STANDARD INSTRUCTION SET
    Code	Type	Values
    switch_led	Boolean	
    "{true,false}"
    bright_value	Integer	
    {
      "unit": "",
      "min": 1,
      "max": 100,
      "scale": 0,
      "step": 1
    }
    temp_value	Integer	
    {
      "unit": "",
      "min": 1,
      "max": 3,
      "scale": 0,
      "step": 1
    }
    fan_switch	Boolean	
    "{true,false}"
    fan_speed	Integer	
    {
      "unit": "",
      "min": 1,
      "max": 3,
      "scale": 0,
      "step": 1
    }
    fan_direction	Enum	
    {
      "range": [
        "forward",
        "reverse"
      ]
    }
    fan_countdown_set	Enum	
    {
      "range": [
        "cancel",
        "1h",
        "2h",
        "4h",
        "8h"
      ]
    }


    Home Assistant Debug Info for Tuya Cloud Integration
    {
      "home_assistant": {
    [...]
      },
      "integration_manifest": {
        "domain": "tuya",
        "name": "Tuya",
        "codeowners": [
          "@Tuya",
          "@zlinoliver",
          "@frenck"
        ],
        "config_flow": true,
        "dependencies": [
          "ffmpeg"
        ],
        "dhcp": [
          {
            "macaddress": "REDACTED*"
          }
          }
        ],
        "documentation": "https://www.home-assistant.io/integrations/tuya",
        "integration_type": "hub",
        "iot_class": "cloud_push",
        "loggers": [
          "tuya_iot"
        ],
        "requirements": [
          "tuya-iot-py-sdk==0.6.6"
        ],
        "is_built_in": true
      },
      "data": {
        "endpoint": "https://openapi.tuyaus.com",
        "auth_type": 0,
        "country_code": "1",
        "app_type": "smartlife",
        "mqtt_connected": null,
        "disabled_by": null,
        "disabled_polling": false,
        "name": "Ceiling Fan",
        "model": "AC 02",
        "category": "fsd",
        "product_id": "puj7wgpctcgpn70b",
        "product_name": "Ceiling Fan",
        "online": true,
        "sub": false,
        "time_zone": "-05:00",
        "active_time": "2023-11-16T00:51:32+00:00",
        "create_time": "2023-11-15T04:02:47+00:00",
        "update_time": "2023-11-16T00:51:32+00:00",
        "function": {
          "switch_led": {
            "type": "Boolean",
            "value": {}
          },
          "bright_value": {
            "type": "Integer",
            "value": {
              "unit": "",
              "min": 1,
              "max": 100,
              "scale": 0,
              "step": 1
            }
          },
          "temp_value": {
            "type": "Integer",
            "value": {
              "unit": "",
              "min": 1,
              "max": 3,
              "scale": 0,
              "step": 1
            }
          },
          "fan_switch": {
            "type": "Boolean",
            "value": {}
          },
          "fan_speed": {
            "type": "Integer",
            "value": {
              "unit": "",
              "min": 1,
              "max": 3,
              "scale": 0,
              "step": 1
            }
          },
          "fan_direction": {
            "type": "Enum",
            "value": {
              "range": [
                "forward",
                "reverse"
              ]
            }
          },
          "fan_countdown_set": {
            "type": "Enum",
            "value": {
              "range": [
                "cancel",
                "1h",
                "2h",
                "4h",
                "8h"
              ]
            }
          }
        },
        "status_range": {
          "switch_led": {
            "type": "Boolean",
            "value": {}
          },
          "bright_value": {
            "type": "Integer",
            "value": {
              "unit": "",
              "min": 1,
              "max": 100,
              "scale": 0,
              "step": 1
            }
          },
          "temp_value": {
            "type": "Integer",
            "value": {
              "unit": "",
              "min": 1,
              "max": 3,
              "scale": 0,
              "step": 1
            }
          },
          "fan_switch": {
            "type": "Boolean",
            "value": {}
          },
          "fan_speed": {
            "type": "Integer",
            "value": {
              "unit": "",
              "min": 1,
              "max": 3,
              "scale": 0,
              "step": 1
            }
          },
          "fan_direction": {
            "type": "Enum",
            "value": {
              "range": [
                "forward",
                "reverse"
              ]
            }
          },
          "fan_countdown_set": {
            "type": "Enum",
            "value": {
              "range": [
                "cancel",
                "1h",
                "2h",
                "4h",
                "8h"
              ]
            }
          }
        },
        "status": {
          "switch_led": true,
          "bright_value": 100,
          "temp_value": 1,
          "fan_switch": false,
          "fan_speed": 1,
          "fan_direction": "forward",
          "fan_countdown_set": "cancel"
        },
        "home_assistant": {
          "name": "Ceiling Fan",
          "name_by_user": null,
          "disabled": false,
          "disabled_by": null,
          "entities": [
            {
              "disabled": false,
              "disabled_by": null,
              "entity_category": null,
              "device_class": null,
              "original_device_class": null,
              "icon": null,
              "original_icon": null,
              "unit_of_measurement": null,
              "state": {
                "entity_id": "fan.ceiling_fan",
                "state": "off",
                "attributes": {
                  "preset_modes": [],
                  "direction": "forward",
                  "percentage": 1,
                  "percentage_step": 1.0,
                  "preset_mode": null,
                  "friendly_name": "Ceiling Fan",
                  "supported_features": 5
                },
                "last_changed": "2023-11-16T01:54:03.463633+00:00",
                "last_updated": "2023-11-16T01:54:03.463633+00:00"
              }
            },
            {
              "disabled": false,
              "disabled_by": null,
              "entity_category": null,
              "device_class": null,
              "original_device_class": null,
              "icon": null,
              "original_icon": null,
              "unit_of_measurement": null,
              "state": {
                "entity_id": "light.ceiling_fan",
                "state": "on",
                "attributes": {
                  "min_color_temp_kelvin": 2000,
                  "max_color_temp_kelvin": 6535,
                  "min_mireds": 153,
                  "max_mireds": 500,
                  "supported_color_modes": [
                    "brightness",
                    "color_temp"
                  ],
                  "color_mode": "color_temp",
                  "brightness": 255,
                  "color_temp_kelvin": 2000,
                  "color_temp": 500,
                  "hs_color": [
                    30.601,
                    94.547
                  ],
                  "rgb_color": [
                    255,
                    136,
                    13
                  ],
                  "xy_color": [
                    0.599,
                    0.382
                  ],
                  "friendly_name": "Ceiling Fan",
                  "supported_features": 0
                },
                "last_changed": "2023-11-16T01:54:03.464796+00:00",
                "last_updated": "2023-11-16T01:54:03.464796+00:00"
              }
            }
          ]
        }
      }
    }


    Tuya Data Points for DpId assignment
    {"20":"Lamp ON/OFF","22":"Brightness","23":"Color Temperature","60":"Fan ON/OFF","62":"Wind Speed Level","63":"Direction Fan","101":"Fan Countdown Set"}


    Flashing and Configuring
    Once I acquired all of the data I believed to be available, I desoldered the CB2S from the unit and flashed it using bk7231flasher_1.1.2.
    Controller module mounted on a breadboard with wires and a USB programmer.
    Getting the module into flash mode was easy; simply tap the CEN pin to ground while bk-flasher is first attempting to read the bus.


    Reading the output for the Template/GPIO config had me concerned.
    Device configuration with Tuya Config Quick Viewer

    Dumping the config from ltchiptool yielded similar concerns.
    Screenshot of ltchiptool showing a list of warnings during YAML generation.


    I proceeded with the flash.
    Screenshot of the BK7231N Easy UART Flasher tool with operational log of a flashing process on a processor. Screenshot of BK7231 Easy UART Flasher tool during device flashing.

    Once complete, I soldered the chip back into the unit and reassembled everything. For testing, I hooked it up to mains power and used alligator clips to attach a lamp for testing.
    I connected to the OpenBeken WebApp at 192.168.4.1 on its default broadcasting SSID and reconfigured it to connect to my IoT network.

    I thought GPIO5 / GPIO4 were going to be my magic pins with GPIO20 / GPIO21 (RX / TX) for TuyaMCU comms.
    This is when the fun started.
    Spoiler:
    I was unable to determine the proper pin configuration and tried to hook it up to my Oscilloscope. POP! The unit doesn't have a ground and fried the CB2S. I had a backup, but wanted to keep it mint until I figured things out and knew I could get it working.
    I swapped the cooked CB2S for the ESP8685 I had available and loaded up the full Tasmota firmware.
    Fun fact, the ESP8685-WROOM-03-H4 is not nearly as simple to flash. GPIO8 [EN?] needs pulled to 3V3 while GPIO9 needs pulled to GND and it's only available as a pad on the back of the board.
    I continued to play with Tasmota settings, but had no success. Discussion on the forum lead me to take a leap and try once more to OBK my untouched unit and hope I could get it working.

    It turns out that OpenBeken communicated with the TuyaMCU out of the box without needing to configure any pins. The rest of the pins do nothing and all of the configuration is Channel based using the autoexec.bat.

    After much debugging and button-presses on the RF remote, I was able to develop the below autoexec.bat

    autoexec.bat should contain the below content and be uploaded to the file-system of the OpenBeken flashed device.
    startDriver TuyaMCU
    
    //setChannelType [ChannelIndex][TypeString]
    //linkTuyaMCUOutputToChannel [dpId][varType][channelID][bDPCache-Optional]
    
    //{"TuyaReceived":{"Data":"55AA03070005140100010125","Cmnd":7,"CmndData":"1401000101","DpType1Id20":1,"20":{"DpId":20,"DpIdType":1,"DpIdData":"01"}}}
    //Map DpID20 to channel1, type1 (Boolean) - Lamp On/Off
    setChannelType 1 Toggle
    linkTuyaMCUOutputToChannel 20 1 1
    
    //{"TuyaReceived":{"Data":"55AA03070008160200040000006491","Cmnd":7,"CmndData":"1602000400000064","DpType2Id22":100,"22":{"DpId":22,"DpIdType":2,"DpIdData":"00000064"}}}
    //Map DpID22 to channel2, type2 (Integer) - bright_value - {1-100,step1}
    setChannelType 2 Dimmer
    linkTuyaMCUOutputToChannel 22 2 2
    
    //{"TuyaReceived":{"Data":"55AA0307000817020004000000012F","Cmnd":7,"CmndData":"1702000400000001","DpType2Id23":1,"23":{"DpId":23,"DpIdType":2,"DpIdData":"00000001"}}}
    //Map DpID23 to channel3, type2 (Integer) - [color] temp_value - {1-3,step1}
    //Note: This feature is not on the remote, but shows up in Tuya Cloud and I cannot find appropriate bulbs to test. If used, field should be: LowMidHigh
    setChannelType 3 ReadOnly
    linkTuyaMCUOutputToChannel 23 2 3
    
    //{"TuyaReceived":{"Data":"55AA030700053C010001004C","Cmnd":7,"CmndData":"3C01000100","DpType1Id60":0,"60":{"DpId":60,"DpIdType":1,"DpIdData":"00"}}}
    //Map DpID20 to channel4, type1 (Boolean) - Fan On/Off (On=1)
    setChannelType 4 Toggle
    linkTuyaMCUOutputToChannel 60 1 4
    
    //{"TuyaReceived":{"Data":"55AA030700083E0200040000000358","Cmnd":7,"CmndData":"3E02000400000003","DpType2Id62":3,"62":{"DpId":62,"DpIdType":2,"DpIdData":"00000003"}}}
    //Map DpID20 to channel5, type2 (Integer) - Fan Speed - {Off,Low,Med,High} (0,1,2,3)
    setChannelType 5 OffLowMidHigh
    linkTuyaMCUOutputToChannel 62 2 5
    
    
    //{"TuyaReceived":{"Data":"55AA030700053F0400010052","Cmnd":7,"CmndData":"3F04000100","DpType4Id63":0,"63":{"DpId":63,"DpIdType":4,"DpIdData":"00"}}}
    //Map DpID63 to channel6, type4 (Enum) - fan_direction - {"range": ["forward","reverse"]}
    //Note: This model does not include wiring for the fan-reverse function. However, the solder-pad is labeled on the board and the toggle displays in Tuya Cloud. Feature Untested.
    setChannelType 6 ReadOnly
    linkTuyaMCUOutputToChannel 63 4 6
    
    //{"TuyaReceived":{"Data":"55AA03070005650400010078","Cmnd":7,"CmndData":"6504000100","DpType4Id101":0,"101":{"DpId":101,"DpIdType":4,"DpIdData":"00"}}}
    //Map DpID101 to channel7, type4 (Enum) - fan_countdown_set - {"range": ["cancel","1h","2h","4h","8h"]} (0,1,2,3,4)
    setChannelType 7 LowestLowMidHighHighest
    linkTuyaMCUOutputToChannel 101 4 7
    
    
    //enable powersave mode
    //seems to be default enabled
    startDriver SSDP
    PowerSave 1


    This should provide all the necessary functionality with a few things to note:
    -temp_value DpId23 is marked ReadOnly. Either I don't have any bulbs that use this feature or the feature doesn't work. LowMidHigh should enable the feature.
    -fan_direction DpId63 is also marked ReadOnly. The unit has a solder point and the feature shows up in Tuya Cloud, however it was not mentioned in the product description nor manual and the wiring is not included with the device It's probably also risky to potentially flip and reverse it while the fan is running. I assume bad things would happen.
    -I was unable to figure out how to rename the function labels on the OpenBeken WebApp for better usability (such as the timer selection is listed as fan speed). If someone knows how, I'll update the script.
    Control panel screen for a smart ceiling fan remote control.


    Home Assistant
    So far, I only have a minimally viable HA integration and was only able to read the Timer setting. If anyone more experienced can create a better UI and get the timer configurable, that would be great!
    I also need to figure out how to get MQTT to push more often. I found an edge-case where sometimes when power-cycled and HA's MQTT cache is cleared the fan speed will be set to 0 and Toggling Fan On/Off in UI won't cause any spinning action.

    In the OpenBeken WebApp, navigate to Config > Configure MQTT and enter your Home Assistant MQTT information.

    HA MQTT yaml
    
    light:    
        name: "Bedroom Fan Light"
        unique_id: "re028w.bedroom_fan_light"
        state_topic: "re028w/cfan_br/1/get"
        command_topic: "re028w/cfan_br/1/set"
        payload_on: "1"
        payload_off: "0"
        brightness_state_topic: "re028w/cfan_br/2/get"
        brightness_command_topic: "re028w/cfan_br/2/set"
        brightness_scale: 100
        color_temp_state_topic: "re028w/cfan_br/3/get"
        color_temp_command_topic: "re028w/cfan_br/3/set"
        color_temp_value_template: >-
          {% if value == '1' %}
          Warm
          {% elif value == '2' %}
          Neutral
          {% elif value == '3' %}
          Cool
          {% else %}
          Invalid
          {% endif %}
        availability_topic: "re028w/cfan_br/connected"
        payload_available: "online"
        payload_not_available: "offline"
        qos: 1
        retain: true
        device:
            configuration_url: http://192.168.4.1/cfg
            manufacturer: Parrot Uncle
            model: RE-028W
            name: Bedroom Fan Light
            identifiers: [ 're028w.bedroom_fan_light' ]
    
    fan:
        name: "Bedroom Fan"
        unique_id: "re028w.bedroom_fan"
        state_topic: "re028w/cfan_br/4/get"
        command_topic: "re028w/cfan_br/4/set"
        payload_on: '1'
        payload_off: '0'
        preset_modes:
          - 'Low'
          - 'Med'
          - 'Hi'
        preset_mode_state_topic: "re028w/cfan_br/5/get"
        preset_mode_value_template: >
          {% if value_json.FanSpeed == '1' %}
            Low
          {% elif value_json.FanSpeed == '2' %}
            Med
          {% elif value_json.FanSpeed == '3' %}
            Hi
          {% else %}
            Off
          {% endif %}
        preset_mode_command_topic: "re028w/cfan_br/5/set"
        preset_mode_command_template: >
          {% if value == 'Low' %}
            1
          {% elif value == 'Med' %}
            2
          {% elif value == 'Hi' %}
            3
          {% else %}
            Invalid
          {% endif %}
        direction_state_topic: "re028w/cfan_br/6/get"
        direction_value_template: >
          {% if value == '1' %}
          Reverse
          {% else %}
          Forward
          {% endif %}
        direction_command_topic: "re028w/cfan_br/6/set"
        direction_command_template: >
          {% if value_json.FanSpeed == '1' %}
            Reverse
          {% else %}
            Forward
          {% endif %}
        availability_topic: "re028w/cfan_br/connected"
        payload_available: "online"
        payload_not_available: "offline"
        qos: 1
        retain: true
        device:
            configuration_url: http://192.168.4.1/cfg
            manufacturer: Parrot Uncle
            model: RE-028W
            name: Bedroom Fan
            identifiers: [ 're028w.bedroom_fan' ]
    
    sensor:
        name: "Bedroom Fan Timer"
        unique_id: "re028w.bedroom_fan_timer"
        icon: mdi:fan-clock
        state_topic: "re028w/cfan_br/7/get"
        value_template: >
          {% if value == '1' %}
          1Hr
          {% elif value == '2' %}
          2Hr
          {% elif value == '3' %}
          4Hr
          {% elif value == '4' %}
          8Hr
          {% else %}
          Disabled
          {% endif %}
        availability_topic: "re028w/cfan_br/connected"
        payload_available: "online"
        payload_not_available: "offline"
        qos: 1
        device:
            configuration_url: http://192.168.4.1/cfg
            manufacturer: Parrot Uncle
            model: RE-028W
            name: Bedroom Fan Timer
            identifiers: [ 're028w.bedroom_fan_timer' ]
    





    Firmware Dump and JSON attached
    
    {
      "vendor": "Parrot Uncle",
      "bDetailed": "1",
      "name": "Universal Smart Ceiling Fan Remote Control and Dimmer Light Switch",
      "model": "RE-028W",
      "chip": "BK7231N",
      "board": "CB2S",
      "flags": "1024",
      "keywords": [
        "Eileen Grays",
        "Parrot Uncle",
    	"ParrotUncle",
    	"RE-028W",
    	"GA030",
    	"San Sheng",
    	"2AX7R-RE021"
    	"FEKOTS",
        "SS-T28",
    	"Fan",
    	"Dimmer"
      ],
      "pins": {},
      "command": "",
      "image": "https://obrazki.elektroda.pl/4797170800_1702090627_thumb.jpg",
      "wiki": "https://www.elektroda.com/rtvforum/viewtopic.php?p=20853026"
    }
    




    I hope my efforts help others who encounter this device. If anyone comes up with improvements, I'll gladly accept them. I would also like to Tasmota-fy the config for use on my ESP module.

    Cool? Ranking DIY
    About Author
    totallylost
    Level 2  
    Offline 
    totallylost wrote 6 posts with rating 1. Been with us since 2023 year.
  • ADVERTISEMENT
  • #2 20853081
    p.kaczmarek2
    Moderator Smart Home
    That's a very informative guide, let's start with this point:
    totallylost wrote:

    I also need to figure out how to get MQTT to push more often.

    According to our docks, here:
    https://github.com/openshwprojects/OpenBK7231T_App/blob/main/docs/commands.md
    You can use mqtt_broadcastInterval in autoexec.bat to set the broadcast interval of MQTT data. Make sure you also enable it in the flags first.
    Helpful post? Buy me a coffee.
  • #3 20853884
    totallylost
    Level 2  

    Thanks. I added it to my working config and will need to decide if I should keep it.
    It turns out this 'edge-case' was an issue of my own creation. I was thinking that deleting items in MQTT Explorer just deleted them from the HA MQTT cache, but just noticed that it actually publishes payloads of '0' to the device as well. If I don't delete them [while troubleshooting], I should never encounter a state where fan speed = 0.
ADVERTISEMENT