My findings getting this desk working with ESPHome
For anyone interested, my test code so far is here GitHub - shades66/Maidesite-standing-desk: My experimentations with connecting a Maidesite PRO 2 standing desk controller to HomeAssist
I was following another great thread on here around how to integrate with HA/ESPHome by tapping into the control & serial lines between the controller & handset but when I received my standing desk it looks like Maidesite changed the design so instead of a separate control box & handset everything is now contained within the handset itself. While I suspect a lot of what others have found would be do-able on this new handset it could easily void any warranties/guarantees pretty quickly I decided to see what could be done via the RJ12 socket which this machine does have. It has no mention Jiecang anywhere on the hardware/instructions I started playing with some information found off that thread and pretty quickly got the basics working. The hardest part was trying to get information to make the desk move to a specific position but eventually found someone had created a spreadsheet with a ton of useful information which suggests the controller is probably made by Jiecang or based on their design so is possibly usable by other brands that have an RJ12 connector.
So far working is
- Button to trigger any of the 4 presets
- Button to move UP/DOWN
- Slider to move direct to a height
- Get current settings for height & presets
Todo
- Tidy up code (remove test stuff)
- Make it retrieve the current height automatically (you need to press the test button at the start)
- Add buttons to create presets based on current height
- Look into automations to automatically lower after alarms/no-one at desk
hope it is of use to someone else with this desk.
Great work @Shades66.
I am planing to automate my Maidesite Desk, just waiting for the RJ12 cable to arrive.
By any chance could you add a photo / pic with the esp wiring. The devider for the TX connection is confusing me a bit.
Thanks a lot.
Edit: The cable arrived, but the colors are different. I think I have managed to work out the connections.
I have set up the eps32. Now when I trigger the TEST button, the desk control pannel lights up and the following is printed to the console. The rest of the sensors are unavailable.
It seem I’ve got some data send to the desk, but looks like nothing is getting from the desk to the ESP32.
[21:49:35][D][uart_debug:176]: >>> 241,241,7,0,7,126,241,241,8
[21:49:35][D][uart_debug:176]: >>> 0,8,126,241,241,9,0,9,126
[21:49:35][D][uart_debug:176]: >>> 241,241,12,0,12,126,241,241,14
[21:49:35][W][component:204]: Component api took a long time for an operation (0.05 s).
[21:49:35][W][component:205]: Components should block for at most 20-30ms.
[21:49:35][D][uart_debug:176]: >>> 0,14,12
Edit 2:
Got there at the end. Works well. Can’t wait to automate my daily standing routine
Thanks again for your work!!!
Hey, sorry I didn’t see anyone had responded to this, Glad to hear you got it working
I’ll add an image of the wiring to make it easier to identify the correct colours at some point over the weekend
anyone else wanting to know the circuit diagram I used the circuit from this page (just the resistors part into the ESP’s RX pin) Arduino Uno serial communication with ESP32 using voltage divider - #2 by groundFungus - Project Guidance - Arduino Forum
Nice work, i’ve got my cable and begin my work these days… thanks for your effort! Will tell you, if i was successful
Hi Mark,
I’m a bit lost as unfortunately not as technical as I once was… do you have a photo of your wiring etc please if possible linked to the ESP 32?
Do I flash desk.h onto the board and load dskcontrol.yaml into my configuration on Home Assistant?
Thanks
Richard
Hi guys!
I’m following the GitHub project to integrate my Maidesite desk as well.
Code on the ESP seems to be OK but I’m stuck at the very same first edit of @tomino
[21:18:05][D][button:010]: 'Desk test' Pressed.
[21:18:05][D][main:495]: TEST Pressed
[21:18:05][D][uart_debug:176]: >>> 241,241,7,0,7,126,241,241,8
[21:18:05][D][uart_debug:176]: >>> 0,8,126,241,241,9,0,9,126
[21:18:05][D][uart_debug:176]: >>> 241,241,12,0,12,126,241,241,14
[21:18:05][D][uart_debug:176]: >>> 0,14,126
No infos from the desk and as far as I can tell no other button are functioning. Any clues are welcome. What did I do wrong?
Hoping to read from you, as I revived this aging topic…
My bad!…
I was missing the home assistant’s entity to enable desk movement.
All’s up&running! Big up for the awesome work.
Hey, how did you manage to make it work in the end?
I got to the point where I can send the signals to the desk and make it move up/down, but I’m not getting any data from the desk back (current height, M1-4 heights). Do you happen to have a photo of your setup?
Hey, my problem was with the connections to uart. I had them mixed up.
Hi. I’m about to dive into your solution.
Has there been any progress on the remaining todo list?
I have a hard time to get it running.
I have a nodemcu esp-c3-32s-kit a151, the 5V from the RJ Connector is enough to power it. (Still tried the USB power to make sure)
But I had trouble finding the correct TX and RX pins for the esphome config. Turns out, I could not use the uart0 pins (U0RX U0TX). Instead I had to use others.
Receiving data now works, I get the memory profiles and the current height.
Sending data does not work, except the “Desk test” to trigger re-receiving the data.
But all commands dont do anything. Changed to different pins made no difference.
I also redid the whole connection, first I had a really long cable. Also I can beep it through with my multimeter. So I find it a bit strange that receiving works, but sending (that’s just a plain connection) does not.
Any ideas?
Added: my working wiring (maybe you need 5V and GND from USB - esp32-c3-devkitm-1 got enough power over RJ14, esp32dev (wroom rev1) did not)
From top to bottom:
purple GND
green TX
blue 5V
white RX
I have a RJ14, that works too(same connector, but only 4 pins in use)
My bad!…
I was missing the home assistant’s entity to enable desk movement.
I finally found out what was the problem. This. I didn’t understood what HobbitBen ment. It took me very long to figure it out myself.
Also the documentation is very unclear about this “feature”.
I also expected, that when I manually turn on that switch, it should stay on.
For anyone else that stumbles over this problem:
There is a home assistant entitiy binary_sensor.presence
that is imported into ESPhome, and it only works if that is “on”.
- So either update the ESPhome config to reflect that binary sensor name, if you have any presence detection. (under t
ext_sensor:
) - Or create a dummy
binary_sensor.presence
that is always on. - Or disable the check in the ESPhome config:
switch:
- platform: template
name: "Desk Enable"
...
return true;
} else {
return true; # <--- instead of false
}
...
Can someone maybe post a picture of the final set up.
I have a MAIDeSITe T2 Pro desk which I understand is the same as what @Shades66 has.
My understanding is that to get the control of the desk to HomeAssistant one needs a ESP board connected via RJ12 to the second (free) port to the motor controller (see picture at the bottom) and a usb power cable to provide power to the ESP.
Then deskcontrol.yaml
and desk.h
are used with ESPHome and that should be all.
Am I wrong?
I suspect that this project will work for the Maidesite desks on the RJ12 port.
I’ve tested it and it works well on my Desky Desk.
The RJ12 dongle is also easier to make than the RJ45 dongle.
Probably you can even get a basic solution with yaml only like this:
Yaml only solution
# You probably won't need the stuff under platformio_options: and framework: , I'm just using a weird board.
esphome:
name: "jiecang-desk-controller-rj12-c3"
friendly_name: Desk Controller RJ12 C3
comment: Desk Controller for Jiecang Controllers via RJ12 port
platformio_options:
board_build.flash_mode: dio
on_boot:
priority: 0
then:
- button.press: cmdFetchHeightValue # Request height on boot.
esp32:
board: esp32-c3-devkitm-1
framework:
type: esp-idf
sdkconfig_options:
CONFIG_BT_BLE_42_FEATURES_SUPPORTED: y
CONFIG_BT_BLE_50_FEATURES_SUPPORTED: y
CONFIG_ESP_TASK_WDT_TIMEOUT_S: "10"
variant: ESP32C3 # lolin c3 pico pinout | https://arduino-projekte.info/wp-content/uploads/2023/01/Wemos-Lolin-C3-Pico-Pinout.webp
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
manual_ip:
static_ip: 192.168.1.XXX # I like to set static IPs.
gateway: 192.168.1.1
subnet: 255.255.255.0
api:
ota:
logger:
level: VERBOSE # Required for uart debug messages.
uart:
tx_pin: GPIO21
rx_pin: GPIO20
baud_rate: 9600
debug:
direction: BOTH
dummy_receiver: true
after:
delimiter: [0x7E]
# timeout: 5ms
sequence:
# Use mulcmu's method for reading uart without a custome component: https://community.home-assistant.io/t/how-to-uart-read-without-custom-component/491950?u=mahko_mahko
- lambda: |-
UARTDebug::log_int(direction, bytes, ','); // Log the message as int. Good for height message checks.
UARTDebug::log_hex(direction, bytes, ','); // Log the message in hex. Good for checking against protocol documentation.
ESP_LOGD("custom", "Bytes size: %d", bytes.size()); // Logs how many bytes in the message, useful for protocol and message identification.
if (direction == UART_DIRECTION_RX)
{
if (bytes.size() == 9) // Only parse messages with 9 bytes.
{
// Do some validation that it is a height message by checking some bytes.
if (bytes[0] == 0xF2 && bytes[1] == 0xF2 && bytes[2] == 0x01 && bytes[8] == 0x7E)
{
int height = (bytes[4] * 256) + bytes[5];
id(desk_height).publish_state(height);
}
}
}
sensor:
- platform: template
name: "Desk Height"
id: desk_height
update_interval: never
- platform: uptime
icon: mdi:sort-clock-descending
name: Uptime
id: uptime_sensor
update_interval: 5s
accuracy_decimals: 0
unit_of_measurement: s
number:
- platform: template
name: "Go To Height cm"
id: go_to_height_value
optimistic: true
min_value: 80.0
max_value: 250.0
step: 0.1
button:
- platform: uart
id: "cmdStop"
name: "Stop"
data: [0xF1, 0xF1, 0x2B, 0x00, 0x2B, 0x7E]
# Memory Presets
- platform: uart
id: "cmdGotoMemory1"
name: "Go To Memory 1"
data: [0xF1, 0xF1, 0x05, 0x00, 0x05, 0x7E]
- platform: uart
id: "cmdGotoMemory2"
name: "Go To Memory 2"
data: [0xF1, 0xF1, 0x06, 0x00, 0x06, 0x7E]
- platform: uart
id: "cmdGotoMemory3"
name: "Go To Memory 3"
data: [0xF1, 0xF1, 0x27, 0x00, 0x27, 0x7E]
- platform: template
name: "Go to specific height X"
on_press:
then:
- uart.write:
data: !lambda |-
float height_cm = id(go_to_height_value).state;
int height_mm = static_cast<int>(height_cm * 10); // Convert cm to mm
std::vector<uint8_t> bArr(8);
bArr[0] = 0xF1;
bArr[1] = 0xF1;
bArr[2] = 0x1B;
bArr[3] = 0x02;
bArr[4] = static_cast<uint8_t>(height_mm / 256);
bArr[5] = static_cast<uint8_t>(height_mm % 256);
bArr[6] = static_cast<uint8_t>((bArr[2] + bArr[3] + bArr[4] + bArr[5]) % 256); // Calculate checksum
bArr[7] = 0x7E;
return bArr;
- platform: uart
id: "cmdDown"
name: "Nudge Down"
data: [0xF1, 0xF1, 0x02, 0x00, 0x02, 0x7E]
- platform: uart
id: "cmdUp"
name: "Nudge Up"
data: [0xF1, 0xF1, 0x01, 0x00, 0x01, 0x7E]
- platform: uart
id: "cmdMemory1"
name: "Set Memory 1"
data: [0xF1, 0xF1, 0x03, 0x00, 0x03, 0x7E]
- platform: uart
id: "cmdMemory2"
name: "Set Memory 2"
data: [0xF1, 0xF1, 0x04, 0x00, 0x04, 0x7E]
- platform: uart
id: "cmdMemory3"
name: "Set Memory 3"
data: [0xF1, 0xF1, 0x25, 0x00, 0x25, 0x7E]
- platform: uart
id: "cmdFetchHeightValue"
name: "Fetch Height Value"
data: [0xF1, 0xF1, 0x07, 0x00, 0x07, 0x7E]
# If you need anything more than the above you should probably move across to another method / project.
# - platform: uart
# id: "cmdFetchAllTime"
# name: "Fetch All Time"
# data: [0xF1, 0xF1, 0xAA, 0x00, 0xAA, 0x7E]
# - platform: uart
# id: "cmdFetchHeightRange"
# name: "Fetch Height Range"
# data: [0xF1, 0xF1, 0x0C, 0x00, 0x0C, 0x7E]
# - platform: uart
# id: "cmdFetchHeightValue"
# name: "Fetch Height Value"
# data: [0xF1, 0xF1, 0x07, 0x00, 0x07, 0x7E]
# - platform: uart
# id: "cmdFetchHighestLowestLimit"
# name: "Fetch Highest Lowest Limit"
# data: [0xF1, 0xF1, 0x20, 0x00, 0x20, 0x7E]
# - platform: uart
# id: "cmdFetchStandTime"
# name: "Fetch Stand Time"
# data: [0xF1, 0xF1, 0xA6, 0x01, 0xA7, 0x7E]
# - platform: uart
# id: "cmdPatch"
# name: "Patch"
# data: [0xF1, 0xF1, 0xA0, 0x00, 0xA0, 0x7E]
I have tried creating this manual with my Maidesite T2 Pro Plus desk, but I can’t raise or lower it from Home Assistant, although I can read the data.
Has anyone managed to do it with this desk?
Thank you very much for everything.
Hi @tomino,
Great job getting your desk automation to work! I’m also working on automating my Maidesite Desk with an ESP32, but I’m having trouble getting it to communicate properly with the desk.
Could you share more details on how you managed to fix the issue with the desk not sending data back to the ESP32? Did you have to change anything in the wiring, code, or configuration?
Any advice would be greatly appreciated. Thanks for your help!
Hey, I have the same desk, but have the opposite problem.
I can move the desk up and down, but can’t read any of the data.
Maybe we can both help each other out here.
Here’s how I have it connected, but changing the height from Home Assistant works with just connecting to pin 2 and 5 of the RJ12 to GND and TX of the ESP32. (I’m using an ESP32-S3-Zero)
EDIT: I messed up the resistors in the image, the 1K should be 5K and the 5K should be 10K, that’s how I have it at the moment, but it’s not working.
Here’s my yaml: esphome: name: deskcontrol friendly_name: DeskControl includes: - - Pastebin.com
Note that I removed the deskenable switch, as I don’t have a need to disable or enable the desk controls based on presence. I suspect that maybe this is holding you back.
(also, ignore the tx_pin and rx_pin in the yaml, it works the same with leaving it at TX and RX, I was just testing other pins on the ESP)
Could you show me how you have yours wired up, maybe that’ll help me fix my problem too.
Good afternoon!
Thank you so much for your response. Thanks to your guidance, I can now say that I have it configured and working perfectly.
I’m sharing the wiring diagram I used to connect the pins, along with the YAML configuration I implemented. It’s important to note that I used an ESP32 WROOM, which corresponds to an ESP32Dev in ESPHome. Therefore, you’ll need to adjust the board model and pin configuration if you’re using a different ESP device.
If you need any additional information about how I connected it or anything else, feel free to let me know, and I’ll gladly help however I can.
Thank you very much for everything, and best regards!
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: esp32dev
framework:
type: arduino
# Enable logging
logger:
# Enable Home Assistant API
api:
ota:
platform: esphome
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Deskcontrol Fallback Hotspot"
password: !secret ap_password2
captive_portal:
uart:
- id: desk_uart
tx_pin: 17
rx_pin: 16
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;
text_sensor:
- platform: homeassistant
id: movement_status
entity_id: binary_sensor.presence
switch:
- platform: template
name: "Desk Enable"
id: deskenable
lambda: |-
if (id(movement_status).state == "on") {
return true;
} else {
return true;
}
turn_on_action:
- logger.log: Desk Enabled
on_turn_on:
- logger.log: Desk Enabled
on_turn_off:
- logger.log: Desk Disabled
- delay: 100s
- if:
condition:
text_sensor.state:
id: movement_status
state: "off"
then:
- logger.log: Reset Desk to lowest setting.
- uart.write: [0xf1, 0xf1, 0x05,0x00,0x05,0x7e]
button:
- platform: template
name: Desk UP
id: my_deskup
on_press:
if:
condition:
# Same syntax for is_off
switch.is_on: deskenable
then:
- logger.log: UP Pressed
- uart.write: [0xf1, 0xf1, 0x01,0x00,0x01,0x7e]
- platform: template
name: Desk Down
id: my_deskdown
on_press:
if:
condition:
# Same syntax for is_off
switch.is_on: deskenable
then:
- logger.log: DOWN Pressed
- uart.write: [0xf1, 0xf1, 0x02,0x00,0x02,0x7e]
- platform: template
name: Desk Sit
id: my_desksit
on_press:
if:
condition:
# Same syntax for is_off
switch.is_on: deskenable
then:
- logger.log: SIT Pressed
- uart.write: [0xf1, 0xf1, 0x05,0x00,0x05,0x7e]
- platform: template
name: Desk Stand
id: my_deskstamd
on_press:
if:
condition:
# Same syntax for is_off
switch.is_on: deskenable
then:
- logger.log: STAND Pressed
- uart.write: [0xf1, 0xf1, 0x06,0x00,0x06,0x7e]
- platform: template
name: Desk FULLUP
id: my_deskfullup
on_press:
if:
condition:
# Same syntax for is_off
switch.is_on: deskenable
then:
- logger.log: FULLUP Pressed
- uart.write: [0xf1, 0xf1, 0x28,0x00,0x28,0x7e]
- platform: template
name: Desk test
id: my_desktest
on_press:
then:
- 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:
if:
condition:
# Same syntax for is_off
switch.is_on: deskenable
then:
- 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};