Schreibtisch smart machen von Flexispot / Sanodesk mit Loctek Motion Steuerung per ESPHome + ESP8266

Schreibtisch smart machen von Flexispot / Sanodesk mit Loctek Motion Steuerung per ESPHome + ESP8266

In diesem Video zeige ich dir, wie ich meinen Schreibtisch von Flexispot smart gemacht habe. Der Schreibtisch benötigt dazu eine Steuerung von Loctek Motion. Umgesetzt habe ich das Projekt mit einem ESP8266 und ESPHome. Anschließend ist die Steuerung über Home Assistant als auch per Sprachsteuerung mit Alexa und Google möglich!

In diesem Video zeige ich dir, wie du einen Itron Everblu Cyble Wasserzähler auslesen kannst. Technisch basiert die Lösung auf einem Arduino Sketch der mittels ESP32 und einem CC1101 die Daten ausliest. Im Weiteren zeige ich am Ende des Videos wie du die Daten mittels InfluxDB und Grafana Visualisieren kannst.

4 „Gefällt mir“

einfach nur geil Udo. Danke für die Idee
Sam Elliott Hello GIF by GritTV

1 „Gefällt mir“

Ohne jetzt Werbung für Sanodesk machen zu wollen, muss ich sagen, dass die Qualität der Schreibtische überzeugt. Seit nun 3 Jahren fahre ich den Schreibtisch mehrmals am Tag hoch und runter ohne irgendwelche Probleme. Und da an meinem Schreibtisch auch das Youtube Setup befestigt ist, ist da etwas Gewicht drauf.

Aber z.B. per Sprachsteuerung den Schreibtisch fahren ist schon praktisch :wink:

2 „Gefällt mir“

Wenn ich nicht überall nur fest verschraubte Arbeitsplatten hätte, würde ich auch schon länger mit so was liebäugeln. Aber ausser dem Esstisch wird’s hier wohl vorerst keine losen Tische geben. Bekomm meine ESPs aber auch so weiterhin ganz gut verteilt glaub ich :wink:

2 „Gefällt mir“

Hallöchen zusammen,

seit dem Update auf ESP Home 2025.2. bekomme ich fogende Fehlermeldung.

INFO ESPHome 2025.2.0
INFO Reading configuration /config/esphome/flexispot.yaml...
Failed config

sensor.custom: [source /config/esphome/flexispot.yaml:52]
  
  The "custom" component has been removed. Consider conversion to an external component.
  https://esphome.io/guides/contributing#a-note-about-custom-components.
  platform: custom
  lambda: |-
    auto desk_height_sensor = new DeskHeightSensor(id(desk_uart));
    App.register_component(desk_height_sensor);
    return {desk_height_sensor}
  sensors: 
    id: desk_height
    name: Desk Height
    unit_of_measurement: cm
    accuracy_decimals: 1
    icon: mdi:counter

wie lässt sich das ganze jetzt abändern?

Liebe Gruß und ein schönes Wochenende.

Würde das alles auch mit einem Raspberry Pi gehen?
Aber so das man die LAN Buchse direkt nutzt und per Kabel nur noch einsteckt?
Hab hier noch 2 Pi 4 rumliegen, wäre damit einfach.

Oder geht so etwas mit einem ESP32 mit LAN Anschluss?
Falls der Anschluss so um konfiguriert werden kann.

Hi,
nein mit einen Raspi wird es nicht funktionieren.
Der ESP32 brauch auch keinen Lanaschluss, schau dir das Projekt genau an. :wink: hier wird nur ein Datenkabel (RJ45) benutzt um den Tisch zu steuern.

Dachte ich mir schon, hätte ja sein können das es über eine Firmware,… irgend eine Option gibt.

Sieh es doch positiv. Du brauchst lediglich einen günstigen ESP32.

1 „Gefällt mir“

ein esp32 kostet dich 3,50€ und ein altes RJ45 kabel hat jeder daheim.

So würde dann der Code aussehen.

substitutions:
  device_name: Tisch Daniel
  name: "tisch-daniel"
  min_height: "71" # cm
  max_height: "110" # cm
  ap_fallback_password: "hier kannst du irgendwas reinschreiben"
  tx_pin: GPIO21 # TXD 2
  rx_pin: GPIO20 # RXD 2
  screen_pin: GPIO6
  encryption_key: "hier kannst du irgendwas reinschreiben"

external_components:
  source: github://iMicknl/LoctekMotion_IoT
  components: [ loctekmotion_desk_height ]

esp32:
  board: esp32-c3-devkitm-1
  framework:
    type: arduino

esphome:
  name: ${name}
  friendly_name: ${device_name}
  comment: Used to control your ${device_name} standing desk via Home Assistant.

  # Wake Desk by sending the "M" command
  # This will pull the current height after boot
  on_boot:
    priority: -10
    then:
      - button.press: button_m


# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: ${encryption_key}

ota:
  platform: esphome

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

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: ${device_name} Fallback Hotspot
    password: ${ap_fallback_password}

bluetooth_proxy:
  active: true

uart:
  - id: desk_uart
    baud_rate: 9600
    tx_pin: ${tx_pin}
    rx_pin: ${rx_pin}
    # debug:

sensor:
  - platform: wifi_signal
    name: "WiFi Signal"
    update_interval: 60s

  - platform: uptime
    name: Uptime

  - platform: loctekmotion_desk_height
    id: "desk_height"
    name: Tisch Höhe
    on_value_range:
    - below: ${min_height}
      then:
        - switch.turn_off: switch_down
    - above: ${max_height}
      then:
        - switch.turn_off: switch_up
    on_value:
      then:
        - cover.template.publish:
            id: desk_cover
            position: !lambda |-
                // The sensor outputs values from min_height (cm) to max_height (cm)
                // We need to translate this to 0 - 1 scale.
                float position = (float(x) - float(${min_height})) / (float(${max_height}) - float(${min_height}));
                return position;
        - component.update: set_desk_height

switch:
  - platform: gpio
    name: "Virtual Screen" # PIN20
    pin:
      number: ${screen_pin}
      mode: OUTPUT
    restore_mode: ALWAYS_ON
    entity_category: "config"
    internal: true

  - platform: uart
    name: "Hoch"
    id: switch_up
    icon: mdi:arrow-up-bold
    data: [0x9b, 0x06, 0x02, 0x01, 0x00, 0xfc, 0xa0, 0x9d]
    uart_id: desk_uart
    send_every: 108ms
    internal: true

  - platform: uart
    name: "Runter"
    id: switch_down
    icon: mdi:arrow-down-bold
    data: [0x9b, 0x06, 0x02, 0x02, 0x00, 0x0c, 0xa0, 0x9d]
    uart_id: desk_uart
    send_every: 108ms
    internal: true

button:
  - platform: template
    name: "Preset 1"
    icon: mdi:numeric-1-box
    on_press:
      - uart.write:
          id: desk_uart
          data: [0x9b, 0x06, 0x02, 0x04, 0x00, 0xac, 0xa3, 0x9d]

  - platform: template
    name: "PC aus"
    icon: mdi:numeric-2-box
    on_press:
      - uart.write:
          id: desk_uart
          data: [0x9b, 0x06, 0x02, 0x08, 0x00, 0xac, 0xa6, 0x9d]

  - platform: template
    name: "Sitzen" # Preset 3 on some control panels
    icon: mdi:chair-rolling
    on_press:
      - uart.write:
          id: desk_uart
          data: [0x9b, 0x06, 0x02, 0x00, 0x01, 0xac, 0x60, 0x9d]

  - platform: template
    name: "Stehen" # Preset 4 on some control panels
    icon: mdi:human-handsup
    on_press:
      - uart.write:
          id: desk_uart
          data: [0x9b, 0x06, 0x02, 0x10, 0x00, 0xac, 0xac, 0x9d]

  - platform: template
    name: "Memory"
    id: button_m
    icon: mdi:alpha-m-box
    entity_category: "config"
    on_press:
      - uart.write:
          id: desk_uart
          data: [0x9b, 0x06, 0x02, 0x20, 0x00, 0xac, 0xb8, 0x9d]

  - platform: template
    name: "Wake Screen"
    id: button_wake_screen
    icon: mdi:gesture-tap-button
    entity_category: "config"
    on_press:
      - uart.write:
          id: desk_uart
          data: [0x9b, 0x06, 0x02, 0x00, 0x00, 0x6c, 0xa1, 0x9d]

  - platform: restart
    name: "Restart"
    entity_category: "config"

cover:
  - platform: template
    id: "desk_cover"
    icon: mdi:desk # or mdi:human-male-height-variant
    name: "Tisch"
    device_class: blind # makes it easier to integrate with Google/Alexa
    has_position: true
    position_action:
      - if:
          condition:
            - lambda: !lambda |-
                return pos > id(desk_cover).position;
          then:
            - cover.open: desk_cover
            - wait_until:
                lambda: |-
                  return id(desk_cover).position  >= pos;
            - cover.stop: desk_cover
          else:
            - cover.close: desk_cover
            - wait_until:
                lambda: |-
                  return id(desk_cover).position <= pos;
            - cover.stop: desk_cover
    stop_action:
      - switch.turn_off: switch_up
      - switch.turn_off: switch_down
    open_action:
      - switch.turn_off: switch_down
      - switch.turn_on: switch_up
    close_action:
      - switch.turn_off: switch_up
      - switch.turn_on: switch_down
    optimistic: false

number:
  - platform: template
    name: "Tisch Höhe"
    id: set_desk_height
    min_value: ${min_height}
    max_value: ${max_height}
    icon: "mdi:counter"
    unit_of_measurement: "cm"
    device_class: "distance"
    step: 0.1
    lambda: !lambda |-
      return id(desk_height).state;
    set_action:
      - if:
          condition:
            - lambda: !lambda |-
                return x > id(desk_height).state;
          then:
            - cover.open: desk_cover
            - wait_until:
                lambda: |-
                  return id(desk_height).state  >= x;
            - cover.stop: desk_cover
          else:
            - cover.close: desk_cover
            - wait_until:
                lambda: |-
                  return id(desk_height).state <= x;
            - cover.stop: desk_cover