Thanks for the reply. After browsing that list, it appears to be the JCB35NH2: Control Box JCB35NH2 - JIECANG
I’m only basing that off of the fact it has the same ports, looks to be the same size and is also 400w.
Thanks for the reply. After browsing that list, it appears to be the JCB35NH2: Control Box JCB35NH2 - JIECANG
I’m only basing that off of the fact it has the same ports, looks to be the same size and is also 400w.
So there’s a decent chance it should work with this project. You just need to keep an eye out for the “secondary or alternative protocol” mentioned in this thread (which is not yet supported).
Just wanted to report back my findings. I got the desk working with Option #1 in the original post! I changed the units to inches and also changed my limits to match. Still tweaking with it slightly but it moves up and down and reports height in Home Assistant!
Thanks again for the help!
Glad to hear. Thanks for reporting back!
Looks like a neat build.
Thanks! I had one last question. I’m actually using the “Desk Is Moving” state to control a zigbee plug that energizes/de-energizes an electromagnet that is mounted to my desk that attaches to a steel plate I mounted to my wall. Well, the zigbee plug is too slow to turn on/off with the “Desk Is Moving” state.
Do you think I could use an output on the D1 Mini that fires when that “Desk Is Moving” state is true?
Edit: disregard, I figured out how to add the output. Had to just play with it some more I’m still fairly new to esphome in general. Super excited for this!
You’ve got me curious about this!
Would you mind sharing the use case?
Yeah definitely. So, I am a big proponent of having a rigid benchtop and desktop, so I typically just bolt my desks to the wall with a big L bracket. Well, you obviously can’t do that with a standing desk, so I bought a piece of 6" x 30" steel and mounted it to the wall behind my desk and bought an electromagnet from amazon that is meant to hold doors shut. I printed a mount to hold the magnet to the desk and it has like a 350lb rating.
I’m currently using a zigbee plug with a 12v power supply plugged into it to control the electromagnet. Ideally, I’d like to control this zigbee plug with the “desk is moving” bit in home assistant, however there is too much delay between when I press the down button, and the zigbee plug turns off. It’s only like a second or two, but that’s enough to bind up the desk and cause the magnet to keep holding.
This is where my question came in. I plan on controlling the magnet with an output from the D1 to a relay that allows the 12v to go to the magnet instead. I think this will give a much more instant response than waiting for the zigbee plug. The magnet takes like 1-2 seconds to energize, however it de-energizes very quickly, allowing the desk to move.
Here are some pictures to get a better idea, and this is the electromagnet that I am using (I took it out of its case since that just added bulk).
Ah I see. So it is an anti-wobble device?
Yep. Albeit, maybe a little over-engineered or overkill, but that’s kind of why we’re all here, right? haha
You might get a laugh out of one of my lockdown projects then. It was a bit of failure in the end but was fun to build.
Oh my goodness, this is amazing! Yeah, not going to mention “overkill” again, I now know I’m in the right place haha.
Hello @jcastro. Do you have the big fully controller with display or only the small one?
Could you maybe DM me your ESPHome config? I cant get the logging working.
Also my display isnt working anymore on the fully controller when my passthrough is connected. @Mahko_Mahko do you maybe have an idea about this?
Controller and ESP32
The first one is my used controller. This is my used ESP32
Config
esphome:
name: standing-desk
friendly_name: Standing Desk
on_boot:
priority: -100.0
then:
#Request a desk height update after boot.
- delay: 5s
- switch.turn_on: wake_desk_and_get_height
esp32:
board: esp32dev
framework:
type: arduino
# Enable logging
logger:
level: VERY_VERBOSE
# Enable Home Assistant API
api:
encryption:
key: "lBXwa0ZuqNLMwW4rHZC0PhX7yCSeXnKencdECSKA1wY="
ota:
password: "359fa6d122acb1d2dabc5366276edc66"
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Standing-Desk Fallback Hotspot"
password: "gi4UyEI3xG5D"
captive_portal:
external_components:
#Fetch ssieb's custom component# https://github.com/ssieb/custom_components/tree/master/components/desky
- source:
type: git
url: https://github.com/ssieb/custom_components
components: [ desky ]
uart:
- id: desk_uart
baud_rate: 9600
rx_pin: 1
##You can uncomment the debug section below to see UART messages.
debug:
direction: BOTH
dummy_receiver: true
after:
bytes: 9
sequence:
- lambda: UARTDebug::log_int(direction, bytes, ',');
desky:
id: my_desky
####################################################################################
##Uncomment this block to use Ssieb's move_to componet function.
# up:
# number: 4 #D2
# inverted: true
# down:
# number: 5 #D1
# inverted: true
# stopping_distance: 15 # optional distance from target to turn off moving, default 15
####################################################################################
height: # Sensor publishing the current height
name: Desky Height
id: desky_height
accuracy_decimals: 1
unit_of_measurement: cm
#any other sensor options
filters:
- delta: 0.05 #Only send values to HA if they change
- throttle: 200ms #Limit values sent to Ha to 5 per sec.
- multiply: 0.1 #convert from mm to cm
on_value:
then:
#If the value changes, then the desk is moving
- binary_sensor.template.publish:
id: desky_is_moving
state: ON
- delay: 300ms
#Assume it's stopped moving if no height changes after a short time.
- binary_sensor.template.publish:
id: desky_is_moving
state: Off
binary_sensor:
- platform: template
id: desky_is_moving
name: "Desky Is Moving"
filters:
- delayed_off: 400ms
#If the desk isn't moving for a bit we better turn off attempts at movement. It's like poor man's collision detection?
on_release:
then:
- button.press: desky_stop_desk
button:
#Stop movement
- platform: template
name: Stop Desk
id: desky_stop_desk
on_press:
then:
- switch.turn_off: raise_desk
- switch.turn_off: lower_desk
#Move to function
- platform: template
name: Go To Desky Height x
id: go_to_desky_preset_height_x
on_press:
then:
##Option 1: Uncomment to use Ssieb's move_to componet functions
# - lambda: id(my_desky).move_to(id(desky_target_height).state*10);
##Option 2: Uncomment to use Mahko's lambda alternative
#Check if we need to move desk up or down from current position
if:
condition:
#Current height is more than target height, then move desk down
lambda: |-
return id(desky_target_height).state < id(desky_height).state;
then:
- switch.turn_on: lower_desk
- wait_until:
#Run until the difference between current and target state is < stopping distance
condition:
lambda: return abs((id(desky_height).state - (id(desky_target_height).state)))<(id(stopping_distance_cm).state);
- switch.turn_off: lower_desk
else:
#Current height is less than target height, move desk up
- switch.turn_on: raise_desk
- wait_until:
condition:
lambda: return abs((id(desky_height).state - (id(desky_target_height).state)))<(id(stopping_distance_cm).state);
#Run until the difference between current and target state is <0.3cm
- switch.turn_off: raise_desk
number:
#Target Height ("Move desk to height x").
#You should probably limit the range you can move the desk to to within the limits you've set via the control panel, perhaps offset a little within the range.
#Sending commands higher/lower than this may cause error messages and require desk reset (or worse).
- platform: template
id: desky_target_height
name: "Desky Target Height"
optimistic: true
unit_of_measurement: cm
min_value: 80
max_value: 130.0
step: 0.1
#Offset correction - Adjust until you get the best accuracy.
#The desk keeps moving for a little while after the up/down pins are released and we try to account for this.
#1.5cm was about right on mine
- platform: template
name: "Desky Stopping Distance cm"
id: stopping_distance_cm
unit_of_measurement: cm
optimistic: true
min_value: 0
max_value: 2
step: 0.1
restore_value: true
initial_value: 1.5
###############################################
#Define some preset heights.
###############################################
#You can freely define as many adjustable presets as you like.
#These are all seperate/independant of what you've set via the control panel (we can't retrieve them currently).
#Standing Height #1 - Set a standing height.
- platform: template
id: desky_standing_height_1
name: "Desky Standing Height 1"
optimistic: true
unit_of_measurement: cm
#Limit the range
min_value: 120
max_value: 130
step: 0.1
restore_value: true
initial_value: 124
#Sitting Height #1 - Set a sitting height. This is independant of what you've set via the control panel.
- platform: template
id: desky_sitting_height_1
name: "Desky Sitting Height 1"
optimistic: true
unit_of_measurement: cm
#Limit the range
min_value: 79.7
max_value: 82
step: 0.1
restore_value: true
initial_value: 79.9
switch:
#wake up ther desk and request it sends its height
- platform: gpio
id: wake_desk_and_get_height
name: "Request Desk Height"
pin:
number: GPIO18
inverted: true
on_turn_on:
- delay: 100ms
- switch.turn_off: wake_desk_and_get_height
#Raise the desk
- platform: gpio
id: raise_desk
name: "Raise Desk"
pin:
number: GPIO21
# mode: INPUT_PULLUP
inverted: true
interlock: lower_desk
on_turn_on:
#Auto off after 15s just in case
- delay: 15s
- switch.turn_off: raise_desk
#Lower the desk
- platform: gpio
id: lower_desk
name: "Lower Desk"
pin:
number: GPIO22
# mode: INPUT_PULLUP
inverted: true
interlock: raise_desk
on_turn_on:
#Auto off after 15s just in case
- delay: 15s
- switch.turn_off: lower_desk
Logs so far - Cant’t get uart logs
[15:03:52][V][mdns:117]: Services:
[15:03:52][V][mdns:119]: - _esphomelib, _tcp, 6053
[15:03:52][V][mdns:121]: TXT: friendly_name = Standing Desk
[15:03:52][V][mdns:121]: TXT: version = 2024.4.2
[15:03:52][V][mdns:121]: TXT: mac = 409151ab9734
[15:03:52][V][mdns:121]: TXT: platform = ESP32
[15:03:52][V][mdns:121]: TXT: board = esp32dev
[15:03:52][V][mdns:121]: TXT: api_encryption = Noise_NNpsk0_25519_ChaChaPoly_SHA256
[15:03:52][VV][scheduler:226]: Running interval 'update' with interval=60000 last_execution=768395 (now=828396)
[15:03:54][VV][scheduler:226]: Running interval '' with interval=60000 last_execution=772092 (now=832092)
[15:03:54][VV][scheduler:226]: Running interval 'update' with interval=60000 last_execution=772340 (now=832345)
[15:03:55][VV][api.service:602]: on_ping_request: PingRequest {}
[15:03:55][VV][api.service:043]: send_ping_response: PingResponse {}
[15:04:26][VV][api.service:690]: on_switch_command_request: SwitchCommandRequest {
key: 529781321
state: YES
}
[15:04:26][D][switch:012]: 'Raise Desk' Turning ON.
[15:04:26][D][switch:055]: 'Raise Desk': Sending state ON
[15:04:27][VV][scheduler:032]: set_timeout(name='', timeout=15000)
[15:04:27][VV][api.service:156]: send_switch_state_response: SwitchStateResponse {
key: 529781321
state: YES
}
[15:04:27][VV][api.service:690]: on_switch_command_request: SwitchCommandRequest {
key: 529781321
state: NO
}
[15:04:27][D][switch:016]: 'Raise Desk' Turning OFF.
[15:04:27][D][switch:055]: 'Raise Desk': Sending state OFF
[15:04:27][VV][api.service:156]: send_switch_state_response: SwitchStateResponse {
key: 529781321
state: NO
}
[15:04:31][VV][api.service:690]: on_switch_command_request: SwitchCommandRequest {
key: 2153922382
state: YES
}
[15:04:31][D][switch:012]: 'Request Desk Height' Turning ON.
[15:04:31][D][switch:055]: 'Request Desk Height': Sending state ON
[15:04:31][VV][scheduler:032]: set_timeout(name='', timeout=100)
[15:04:31][VV][api.service:156]: send_switch_state_response: SwitchStateResponse {
key: 2153922382
state: YES
}
[15:04:31][VV][scheduler:226]: Running timeout '' with interval=100 last_execution=869049 (now=869154)
[15:04:31][D][switch:016]: 'Request Desk Height' Turning OFF.
[15:04:31][D][switch:055]: 'Request Desk Height': Sending state OFF
[15:04:31][VV][api.service:156]: send_switch_state_response: SwitchStateResponse {
key: 2153922382
state: NO
}
[15:04:37][VV][scheduler:226]: Running interval 'update' with interval=60000 last_execution=814817 (now=874818)
[15:04:38][VV][scheduler:226]: Running interval 'update' with interval=60000 last_execution=816082 (now=876090)
[15:04:41][VV][scheduler:226]: Running timeout '' with interval=15000 last_execution=864543 (now=879544)
[15:04:41][D][switch:016]: 'Raise Desk' Turning OFF.
HA Details
Up and down is working.
One last thing i noticed:
The desk usually is showing the height in inch not cm or mm when the display is working.
I also opend my controller board and checked my RJ45 layout. It matched the config from #Option 1
UPDATE:
I had to solder the TX pin of the controller to GPIO17 instead of GPIO3. No I’m getting the uart logs. I still facing the same issue as @jcastro. When looking at my logs the 5th and the 6th byte caltulate my desk height. Therefore i still cant see the height in HA. I managed to switch from inch to cm in the controllers settings.
@Mahko_Mahko @ssieb do you have any further tips how to get the height to work?
LOGS:
[20:43:51][D][switch:012]: 'Request Desk Height' Turning ON.
[20:43:51][D][switch:055]: 'Request Desk Height': Sending state ON
[20:43:51][VV][scheduler:032]: set_timeout(name='', timeout=100)
[20:43:51][VV][api.service:156]: send_switch_state_response: SwitchStateResponse {
key: 2153922382
state: YES
}
[20:43:51][D][uart_debug:176]: <<< 242,242,1,3,2,232,15,253,126
[20:43:51][VV][scheduler:226]: Running timeout '' with interval=100 last_execution=12504 (now=12610)
[20:43:51][D][switch:016]: 'Request Desk Height' Turning OFF.
[20:43:51][D][switch:055]: 'Request Desk Height': Sending state OFF
[20:43:51][VV][api.service:156]: send_switch_state_response: SwitchStateResponse {
key: 2153922382
state: NO
}
[20:43:51][D][uart_debug:176]: <<< 242,242,1,3,2,232,15,253,126
[20:43:52][D][uart_debug:176]: <<< 242,242,1,3,2,232,15,253,126
[20:43:52][D][uart_debug:176]: <<< 242,242,1,3,2,232,15,253,126
[20:43:52][D][uart_debug:176]: <<< 242,242,1,3,2,232,15,253,126
[20:43:52][D][uart_debug:176]: <<< 242,242,1,3,2,232,15,253,126
[20:43:52][D][uart_debug:176]: <<< 242,242,1,3,2,232,15,253,126
[20:43:53][D][uart_debug:176]: <<< 242,242,1,3,2,232,15,253,126
[20:43:53][D][uart_debug:176]: <<< 242,242,1,3,2,232,15,253,126
[20:43:53][D][uart_debug:176]: <<< 242,242,1,3,2,232,15,253,126
[20:43:53][D][uart_debug:176]: <<< 242,242,1,3,2,232,15,253,126
[20:43:53][D][uart_debug:176]: <<< 242,242,1,3,2,232,15,253,126
[20:43:54][D][uart_debug:176]: <<< 242,242,1,3,2,232,15,253,126
CONFIG:
uart:
- id: desk_uart
baud_rate: 9600
rx_pin: GPIO17
##You can uncomment the debug section below to see UART messages.
debug:
dummy_receiver: true
after:
bytes: 9
sequence:
- lambda: UARTDebug::log_int(direction, bytes, ',');
hi! I removed it completely a long time ago because it was never implemented, as a function to control the desk, so I gave up
Interesting. So you’re the second person in addition to @jcastro who has a desk that uses a slightly different protocol.
The feature request for supporting that has been open for some time.
What I’d encourage you both to do is make a comment on the issue to help flag to @ssieb that there is still demand for the enhancement.
You could also take a look at the Upsy Desky project and try to figure out if your protocol is already supported.
If you are willing to tinker in cpp I suspect it would be relatively small adjustments to this code section to just read bytes in two different positions.
Thanks for your response. I will make a comment tomorrow. I also will check the c++ config. Maybe I can figure it out by myself. Not really into c++ but we’ll see.
ssieb is active on the development of support for this alternative protocol now (beta has been released), so if you still have some interest and the hardware, more testers would be helpful.
I can confirm @ssieb work. I tried his solution with my Fully Jarvis Desk.
Everything works like a charm. @jcastro you could also try it now. Should also work with your desk.
How to update the repository:
Clean the Build folder of your ESP32 and reinstall the yaml file. This way the repository should update. You also could change your config in the following way and reinstall:
external_components:
#Fetch ssieb's custom component# https://github.com/ssieb/custom_components/tree/master/components/desky
- source:
type: git
url: https://github.com/ssieb/custom_components
components: [ desky ]
refresh: 0s
Thanks again to the nice work of @ssieb and @Mahko_Mahko.
@hraschan would you mind sharing your whole config? I don’t have mine anymore. I’m using ESP8266 so I will just change the pin numbers. Thanks
Please keep in mind that i also configured my 4 memory buttons. As i remember you got the small controller. Therefor you don’t need them. Also make sure your uart config is right. I also changed that. Because I needed a different pin there as well.
esphome:
name: standing-desk
friendly_name: Standing Desk
on_boot:
priority: -100.0
then:
#Request a desk height update after boot.
- delay: 5s
- switch.turn_on: wake_desk_and_get_height
esp32:
board: esp32dev
framework:
type: arduino
# Enable logging
logger:
level: VERY_VERBOSE
# baud_rate: 0 #disable logging over uart
# Enable Home Assistant API
api:
encryption:
key: "lBXwa0ZuqNLMwW4rHZC0PhX7yCSeXnKencdECSKA1wY="
ota:
password: "359fa6d122acb1d2dabc5366276edc66"
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
external_components:
#Fetch ssieb's custom component# https://github.com/ssieb/custom_components/tree/master/components/desky
- source:
type: git
url: https://github.com/ssieb/custom_components
components: [ desky ]
uart:
- id: desk_uart
baud_rate: 9600
rx_pin: GPIO17
##You can uncomment the debug section below to see UART messages.
debug:
dummy_receiver: true
after:
bytes: 9
sequence:
- lambda: UARTDebug::log_int(direction, bytes, ',');
desky:
id: my_desky
####################################################################################
##Uncomment this block to use Ssieb's move_to componet function.
# up:
# number: 4 #D2
# inverted: true
# down:
# number: 5 #D1
# inverted: true
# stopping_distance: 15 # optional distance from target to turn off moving, default 15
####################################################################################
height: # Sensor publishing the current height
name: Desky Height
id: desky_height
accuracy_decimals: 1
unit_of_measurement: cm
#any other sensor options
filters:
- delta: 0.05 #Only send values to HA if they change
- throttle: 200ms #Limit values sent to Ha to 5 per sec.
- multiply: 0.1 #convert from mm to cm
on_value:
then:
#If the value changes, then the desk is moving
- binary_sensor.template.publish:
id: desky_is_moving
state: ON
- delay: 300ms
#Assume it's stopped moving if no height changes after a short time.
- binary_sensor.template.publish:
id: desky_is_moving
state: Off
binary_sensor:
- platform: template
id: desky_is_moving
name: "Desky Is Moving"
filters:
- delayed_off: 400ms
#If the desk isn't moving for a bit we better turn off attempts at movement. It's like poor man's collision detection?
on_release:
then:
- button.press: desky_stop_desk
substitutions:
#Use your own ESP pin values
desky_request_height_pin: GPIO18 #Request desk height | white wire
desky_purple_pin: GPIO16 #purple wire
desky_down_pin: GPIO22 #Move desk down | yellow wire
desky_up_pin: GPIO21 #Move desk up | green wire
output:
- platform: gpio
pin: ${desky_up_pin}
id: up_green_wire
inverted: true
- platform: gpio
pin: ${desky_down_pin}
id: down_yellow_wire
inverted: true
- platform: gpio
pin: ${desky_purple_pin}
id: purple_wire
inverted: true
switch:
#wake up ther desk and request it sends its height
- platform: gpio
id: wake_desk_and_get_height
name: "Request Desk Height"
pin:
number: ${desky_request_height_pin}
inverted: true
on_turn_on:
- delay: 100ms
- switch.turn_off: wake_desk_and_get_height
#Raise the desk
- platform: output
output: up_green_wire
id: raise_desk
name: "Raise Desk"
on_turn_on:
#Auto off after 15s just in case
- delay: 15s
- switch.turn_off: raise_desk
#Lower the desk
- platform: output
output: down_yellow_wire
id: lower_desk
name: "Lower Desk"
on_turn_on:
#Auto off after 15s just in case
- delay: 15s
- switch.turn_off: lower_desk
button:
# Combination Buttons
- platform: template
name: "Memory 1"
id: button_1
on_press:
then:
- output.turn_on: up_green_wire
- output.turn_on: down_yellow_wire
- delay: 300ms
- output.turn_off: down_yellow_wire
- output.turn_off: up_green_wire
- platform: output
output: purple_wire
name: "Memory 2"
id: button_2
duration: 300ms
- platform: template
name: "Memory 3"
id: button_3
on_press:
then:
- output.turn_on: purple_wire
- output.turn_on: down_yellow_wire
- delay: 300ms
- output.turn_off: down_yellow_wire
- output.turn_off: purple_wire
- platform: template
name: "Memory 4"
id: button_4
on_press:
then:
- output.turn_on: purple_wire
- output.turn_on: up_green_wire
- delay: 300ms
- output.turn_off: up_green_wire
- output.turn_off: purple_wire
#Stop movement
- platform: template
name: Stop Desk
id: desky_stop_desk
on_press:
then:
- switch.turn_off: raise_desk
- switch.turn_off: lower_desk