Maidesite Standing Desk with ESPHome

Hey, thanks for the update!
I changed my setup according to your image, now everything works!
After some experimentation, I simplified the whole thing a bit. I tested it both with and without the resistors, and it seems to be just fine without them, this is what it looks like now:

RJ12 COLOR ESP32 PIN
PIN 1 white
PIN 2 brown GND
PIN 3 green RX (GPIO3)
PIN 4 yellow 5V
PIN 5 purple TX (GPIO1)
PIN 6 red

(using the numbering like in our previous pictures, colours might be different depending on your cable used)

Turns out the RJ12 port supplies enough power for the ESP32-S3-Zero that I’m using, making the whole thing even cleaner.
Here’s a photo after soldering:

And here’s the yaml once again, configured for my model of ESP32, without the deskenable and presence features.

deskcontrol.yaml
esphome:
  name: deskcontrol
  friendly_name: DeskControl
  includes:
    - desk.h
  on_boot:
    priority: 800
    then:
      - uart.write: [0xf1, 0xf1, 0x07,0x00,0x07,0x7e,0xf1, 0xf1, 0x08,0x00,0x08,0x7e,0xf1, 0xf1, 0x09,0x00,0x09,0x7e,0xf1, 0xf1, 0x0c,0x00,0x0c,0x7e,0xf1, 0xf1, 0x0e,0x00,0x0e,0x7e]

esp32:
  board: esp32-s3-devkitc-1
  framework:
    type: arduino

# Enable logging
logger:

# Enable Home Assistant API
api:


ota:
  platform: esphome
  password: !secret ota_pass

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_pass

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Deskcontrol Fallback Hotspot"
    password: "fopfxEuvlxy3"

captive_portal:


uart:
  - id: desk_uart
    tx_pin: TX  
    rx_pin: RX
    baud_rate: 9600
    debug:
      direction: BOTH
      after:
        bytes: 9
      sequence:
        - lambda: UARTDebug::log_int(direction, bytes, ',');

custom_component:
- lambda: |-
    auto my_custom = new MyCustomComponent(id(desk_uart));
    return {my_custom};


sensor:
  - platform: template
    name: "Desk M1 Height"
    id: "deskm1"
    filters:
    - lambda: !lambda |-
        if (x <1 ) return {};
        return x/10;
  - platform: template
    name: "Desk M2 Height"
    id: "deskm2"
    filters:
    - lambda: !lambda |-
        if (x <1 ) return {};
        return x/10;
  - platform: template
    name: "Desk M3 Height"
    id: "deskm3"
    filters:
    - lambda: !lambda |-
        if (x <1 ) return {};
        return x/10;
  - platform: template
    name: "Desk M4 Height"
    id: "deskm4"
    filters:
    - lambda: !lambda |-
        if (x <1 ) return {};
        return x/10;


button:
  - platform: template
    name: Desk UP
    id: my_deskup
    on_press:
      - logger.log: UP Pressed
      - uart.write: [0xf1, 0xf1, 0x01,0x00,0x01,0x7e]
  - platform: template
    name: Desk DOWN
    id: my_deskdown
    on_press:
      - logger.log: DOWN Pressed
      - uart.write: [0xf1, 0xf1, 0x02,0x00,0x02,0x7e]      
  - platform: template
    name: Desk SIT
    id: my_desksit
    on_press:
      - logger.log: SIT Pressed
      - uart.write: [0xf1, 0xf1, 0x05,0x00,0x05,0x7e]
  - platform: template
    name: Desk STAND
    id: my_deskstand
    on_press:
      - logger.log: STAND Pressed
      - uart.write: [0xf1, 0xf1, 0x06,0x00,0x06,0x7e]  
  - platform: template
    name: Desk FULLUP
    id: my_deskfullup
    on_press:
      - logger.log: FULLUP Pressed
      - uart.write: [0xf1, 0xf1, 0x28,0x00,0x28,0x7e]
  - platform: template
    name: Desk test
    id: my_desktest
    on_press:
      - logger.log: TEST Pressed
      - uart.write: [0xf1, 0xf1, 0x07,0x00,0x07,0x7e,0xf1, 0xf1, 0x08,0x00,0x08,0x7e,0xf1, 0xf1, 0x09,0x00,0x09,0x7e,0xf1, 0xf1, 0x0c,0x00,0x0c,0x7e,0xf1, 0xf1, 0x0e,0x00,0x0e,0x7e]


number:
  - platform: template
    name: "Desk Height Control"
    id: "deskSlider"
    step: 1
    min_value: 677
    max_value: 1241
    mode: slider
    set_action:
      - uart.write: !lambda |-
          int a= (int(x) & 0xff);
          int b= ((int(x) >> 8) & 0xff);
          int c= (a+b+0x80+0x02) & 0xff;
          return {0xf1, 0xf1, 0x80, 2, b,a,c,0x7e,0xf1, 0xf1, 0x1b, 0x00, 0x1b,0x7e};

Hope this can help others with a Maidesite T2 Pro Plus, too.

Has anyone else got this working with a Maidesite S1 Pro desk? I’ve tried it, but all I’m able to do is produce an undocumented error code on the desk’s control panel.

Thanks @lukas-berger i did the same as you and works perfectly.
My Desk is a Maidesite TH2 Plus Art

This is what I did in case it helps anyone.

Used the same files unchanged as Lukas above, other than changing the name of the device.

Some of my pins were a different colour

RJ12 COLOR ESP32 PIN
PIN 1 white
PIN 2 Brown GND
PIN 3 Red RX GPIO3
PIN 4 Green 5V
PIN5 Yellow TX GPIO1
PIN6 Blue

One thing I got stumped on was where to upload the desk.h file, turns out it’s to home assistant’s /config/esphome folder after you’ve setup the esp32. Then overwrite the yaml file with the contents from deskcontrol.yaml

Bought these:
RJ12 cable

ESP32-S3 Zero/Mini

The RJ12 on the desk powers it, no need to use the USB-C.

1 Like

Following on from my post yesterday I’ve actually changed the GPIO3 pin to be GPIO4 because 3 was throwing up a warning in the logs and I don’t like warnings.
So in my pic the red wire has moved down one pin.

Just needed to update the RX line in the yaml file to be:
rx_pin: GPIO4

I also added the missing M3 button and renamed the buttons to match closer the memory preset sensors so Desk M1 etc

Updated yaml:

esphome:
 name: office-desk-controller
 friendly_name: Office Desk Controller
 includes:
   - include/desk.h
 on_boot:
   priority: 800
   then:
     - uart.write: [0xf1, 0xf1, 0x07,0x00,0x07,0x7e,0xf1, 0xf1, 0x08,0x00,0x08,0x7e,0xf1, 0xf1, 0x09,0x00,0x09,0x7e,0xf1, 0xf1, 0x0c,0x00,0x0c,0x7e,0xf1, 0xf1, 0x0e,0x00,0x0e,0x7e]

esp32:
 board: esp32-s3-devkitc-1
 framework:
   type: arduino

# Enable logging
logger:

# Enable Home Assistant API
api:
 encryption:
   key: "your key here"

ota:
 - platform: esphome
   password: "your password here"

wifi:
 ssid: !secret wifi_ssid
 password: !secret wifi_password

 # Enable fallback hotspot (captive portal) in case wifi connection fails
 ap:
   ssid: "Office-Desk-Controller"
   password: "zNu29TwKlkI7"

captive_portal:


uart:
 - id: desk_uart
   tx_pin: TX  
   rx_pin: GPIO4
   baud_rate: 9600
   debug:
     direction: BOTH
     after:
       bytes: 9
     sequence:
       - lambda: UARTDebug::log_int(direction, bytes, ',');

custom_component:
- lambda: |-
   auto my_custom = new MyCustomComponent(id(desk_uart));
   return {my_custom};


sensor:
 - platform: template
   name: "Desk M1 Height"
   id: "deskm1"
   filters:
   - lambda: !lambda |-
       if (x <1 ) return {};
       return x/10;
 - platform: template
   name: "Desk M2 Height"
   id: "deskm2"
   filters:
   - lambda: !lambda |-
       if (x <1 ) return {};
       return x/10;
 - platform: template
   name: "Desk M3 Height"
   id: "deskm3"
   filters:
   - lambda: !lambda |-
       if (x <1 ) return {};
       return x/10;
 - platform: template
   name: "Desk M4 Height"
   id: "deskm4"
   filters:
   - lambda: !lambda |-
       if (x <1 ) return {};
       return x/10;


button:
 - platform: template
   name: Desk UP
   id: my_deskup
   on_press:
     - logger.log: UP Pressed
     - uart.write: [0xf1, 0xf1, 0x01,0x00,0x01,0x7e]
 - platform: template
   name: Desk DOWN
   id: my_deskdown
   on_press:
     - logger.log: DOWN Pressed
     - uart.write: [0xf1, 0xf1, 0x02,0x00,0x02,0x7e]      
 - platform: template
   name: Desk M1
   id: my_desk_m1
   on_press:
     - logger.log: M1 Pressed
     - uart.write: [0xf1, 0xf1, 0x05,0x00,0x05,0x7e]
 - platform: template
   name: Desk M2
   id: my_desk_m2
   on_press:
     - logger.log: M2 Pressed
     - uart.write: [0xf1, 0xf1, 0x06,0x00,0x06,0x7e]  
 - platform: template 
   name: Desk M3
   id: my_desk_m3
   on_press: 
     - logger.log: M3 Pressed 
     - uart.write: [0xF1, 0xF1, 0x27, 0x00, 0x27, 0x7E]
 - platform: template
   name: Desk M4
   id: my_desk_m4
   on_press:
     - logger.log: M4 Pressed
     - uart.write: [0xf1, 0xf1, 0x28,0x00,0x28,0x7e]
 - platform: template
   name: Desk Test
   id: my_desktest
   on_press:
     - logger.log: TEST Pressed
     - uart.write: [0xf1, 0xf1, 0x07,0x00,0x07,0x7e,0xf1, 0xf1, 0x08,0x00,0x08,0x7e,0xf1, 0xf1, 0x09,0x00,0x09,0x7e,0xf1, 0xf1, 0x0c,0x00,0x0c,0x7e,0xf1, 0xf1, 0x0e,0x00,0x0e,0x7e]


number:
 - platform: template
   name: "Desk Height Control"
   id: "deskSlider"
   step: 1
   min_value: 677
   max_value: 1241
   mode: slider
   set_action:
     - uart.write: !lambda |-
         int a= (int(x) & 0xff);
         int b= ((int(x) >> 8) & 0xff);
         int c= (a+b+0x80+0x02) & 0xff;
         return {0xf1, 0xf1, 0x80, 2, b,a,c,0x7e,0xf1, 0xf1, 0x1b, 0x00, 0x1b,0x7e};
1 Like

Hi Lukas,
this looks really promising and I am already impressed and motivated to also make my “MAIDeSITe T2 Pro Plus” being smart.
I just try to flash my ESP32 S3 Zero and running in a compiling error while downloading the install-file within the ESPHome Builder (renamed script to Schreibtisch-Control) (used your code for my yaml and just adopted wifi credentials but have not updated HA OS to 14.2 or HA Core to 2025.1.2):

INFO ESPHome 2024.12.4
INFO Reading configuration /config/esphome/schreibtisch-control.yaml...
INFO Generating C++ source...
INFO Compiling app...
Processing schreibtisch-control (board: esp32dev; framework: arduino; platform: platformio/[email protected])
--------------------------------------------------------------------------------
HARDWARE: ESP32 240MHz, 320KB RAM, 4MB Flash
 - toolchain-xtensa-esp32 @ 8.4.0+2021r2-patch5
Dependency Graph
|-- AsyncTCP-esphome @ 2.1.4
|-- WiFi @ 2.0.0
|-- FS @ 2.0.0
|-- Update @ 2.0.0
|-- ESPAsyncWebServer-esphome @ 3.2.2
|-- DNSServer @ 2.0.0
|-- ESPmDNS @ 2.0.0
|-- noise-c @ 0.1.6
Compiling .pioenvs/schreibtisch-control/src/main.cpp.o
Compiling .pioenvs/schreibtisch-control/libc58/ESPAsyncWebServer-esphome/WebHandlers.cpp.o
Compiling .pioenvs/schreibtisch-control/libc58/ESPAsyncWebServer-esphome/WebRequest.cpp.o
Compiling .pioenvs/schreibtisch-control/libc58/ESPAsyncWebServer-esphome/WebResponses.cpp.o
/config/esphome/schreibtisch-control.yaml: In lambda function:
/config/esphome/schreibtisch-control.yaml:47:28: error: expected type-specifier before 'MyCustomComponent'
     auto my_custom = new MyCustomComponent(id(desk_uart));
                            ^~~~~~~~~~~~~~~~~
/config/esphome/schreibtisch-control.yaml:48:24: error: could not convert '{my_custom}' from '<brace-enclosed initializer list>' to 'std::vector<esphome::Component*>'
     return {my_custom};
                        ^
/config/esphome/schreibtisch-control.yaml: In lambda function:
/config/esphome/schreibtisch-control.yaml:131:80: warning: narrowing conversion of 'b' from 'int' to 'unsigned char' inside { } [-Wnarrowing]
           return {0xf1, 0xf1, 0x80, 2, b,a,c,0x7e,0xf1, 0xf1, 0x1b, 0x00, 0x1b,0x7e};
                                                                                ^
/config/esphome/schreibtisch-control.yaml:131:80: warning: narrowing conversion of 'b' from 'int' to 'unsigned char' inside { } [-Wnarrowing]
/config/esphome/schreibtisch-control.yaml:131:80: warning: narrowing conversion of 'a' from 'int' to 'unsigned char' inside { } [-Wnarrowing]
/config/esphome/schreibtisch-control.yaml:131:80: warning: narrowing conversion of 'a' from 'int' to 'unsigned char' inside { } [-Wnarrowing]
/config/esphome/schreibtisch-control.yaml:131:80: warning: narrowing conversion of 'c' from 'int' to 'unsigned char' inside { } [-Wnarrowing]
/config/esphome/schreibtisch-control.yaml:131:80: warning: narrowing conversion of 'c' from 'int' to 'unsigned char' inside { } [-Wnarrowing]
*** [.pioenvs/schreibtisch-control/src/main.cpp.o] Error 1
========================== [FAILED] Took 6.00 seconds ==========================

Any ideas? Thank you for your efforts.

1 Like

I figured out what was wrong. I had a typo in the desk.h (I guess due to auto translation).
With a fresh copy of desk.h everything went smooth. :v:

1 Like

Thank you for this helpful explanation and discussion for building a small device to make the MaidSaite T2 Pro Plus Desk smart and visible/usable in Home Assistant.

Maybe this helps others also willing to automate their Desk:

Used items:
Needed steps for programming (~15min):
  1. Connect ESP32-device to PC and flash with ESPHome Builder with Home Assistant (3min)
  2. Flash ESP32 with provided yaml (see above; adjust to your convenenience) (~5min)
  3. Copy or write a new file “desk.h” to ~/esphome/include/ (i used this file from GitHub; 2min)
Needed steps for wiring (~30min):
  1. Cut jumper wires and RJ12 cable (1min)
  2. Separate all cable ends to be able to work on the individual ends (2min)
  3. Strip the isolations and twist all cables (8min)
  4. Put small shrinking tubes over the single wires and a bigger one over the wiring harness (7min)
  5. Twist the 6 cable-pairs (2 min)
  6. Solder the twisted ends for a proper cable connection (3min)
  7. Note the cable color-combination of the 6 connected wires if not identical on the used cables (1min)
  8. Slide the shrinking tubes over the soldered cable pairs and slide the big tube over all cables (2min)
  9. Shrink the tubes with hot airstream (I used a hairdryer not melt the tiny isolation - worked pretty good; 2min)
  10. Wire the ESP32 (see above) and put all into the box and connect to the desk (2min)

I’ve got everything working on my desk. If you are well prepared and having all you need at hand you should be able to make the desk tunable via Home Assistant within approx. 45-60min.
All used items cost below 15 Euros (if counting package prices you’ll might spending a bit more).

Considering improvements: Advancing this tool (maybe somebody has an idea):
  1. Fetching the current height in a separate entity. I am not sure, if this could be achived conveniently. My idea is, having an own entity/sensor showing the current height which gets updated every time the desk height had been changed.

→ EDIT: solved, see pictures below.

  1. Also the height unit could be switched: cm/ft, … but this could also be recalculated with helpers in Home Assistant and might to be part of the ESP itself.
see Pictures below

01: Complete device

2: Wired ESP32 (detail)

3: Closed Box (detail)

4: Finally: connected box @ MaideSite T2 Pro Plus (this is what this is about :slightly_smiling_face: )


I will rewire the box beyond the support and the table top to not cover the box with the metal guard covering the technic to avoid impacting signal strength. Therefore: consider cable length!

5: HA Device Details

→ EDIT:
Added “Desk Current Height” and icons:
Desk Current Height:

### Desk Current Height ###
# add to sensors-section: #
- platform: template
    name: "Desk Current Height"
    id: "desk_current_height"
    icon: "mdi:format-vertical-align-center"
    lambda: |-
      float desk_current_height = id(deskSlider).state / 10.0;
      return desk_current_height;
### /Desk Current Height ###

used following icons:

### ICONS (enter below respective "id:"-entry/see 'Desk Current Height' example)
* icon: "mdi:arrow-expand-vertical" ##(M 1-4)
* icon: "mdi:arrow-expand-up" ##(Desk UP)
* icon: "mdi:arrow-expand-down" ##(Desk DOWN)
* icon: "mdi:reload" ##(Desk Test)
* icon: "mdi:format-vertical-align-center" ##(Current Height)