LEGO DUPLO train control with esphome

I feel honored to share my first project here with the community!

A year ago I bought a Lego Duplo train set for my son. I was disappointed that it had to be operated with a smartphone or tablet.
So I made a Bluetooth controller that can control the train with a ESP32 .
Now I thought it would be fun to set up the train as a decoration for Christmas and operate it using a home assistant.

Electronics:
ESP32 (ESP-WROOM-32)
TP4056 Type-C
2x 13300 cells

The 13300 cells i recycled from old vapes(there are all over here on the streets…).
I cleaned them and tested if there were still useable.

With Esphome I wrote a code that makes it possible for me to send Bluetooth commands to the train using buttons.

esphome:
  name: Duplo_Train_Control
  platform: ESP32
  board: esp-wrover-kit

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: ''********''

ota:
  password: "************"

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

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Duplo_Train_Control"
    password: "gPYZ2uE4eb8W"

# Configure Bluetooth
esp32_ble_tracker:

# Configure BLE Client
ble_client:
  - mac_address: "a0:6c:65:55:26:2c" 
    id: Duplo_Train_Control

captive_portal:

button:
  - platform: template
    name: "Speed 1"
    on_press:
      - logger.log: "Switch toggled"
      - ble_client.ble_write:
          id: my_ble_client
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          # List of bytes to write.
          value: [0x0a, 0x00, 0x41, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01]
      - ble_client.ble_write:
          id: my_ble_client
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          # A lambda returning an std::vector<uint8_t>.
          value: !lambda |-
              return {0x08, 0x00, 0x81, 0x00, 0x01, 0x51, 0x00, 0x1e};

  - platform: template
    name: "Speed 2"
    on_press:
      - logger.log: "Switch toggled"
      - ble_client.ble_write:
          id: my_ble_client
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          # List of bytes to write.
          value: [0x0a, 0x00, 0x41, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01]
      - ble_client.ble_write:
          id: my_ble_client
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          # A lambda returning an std::vector<uint8_t>.
          value: !lambda |-
              return {0x08, 0x00, 0x81, 0x00, 0x01, 0x51, 0x00, 0x32};
            
  - platform: template
    name: "Speed 3"
    on_press:
      - logger.log: "Switch toggled"
      - ble_client.ble_write:
          id: my_ble_client
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          # List of bytes to write.
          value: [0x0a, 0x00, 0x41, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01]
      - ble_client.ble_write:
          id: my_ble_client
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          # A lambda returning an std::vector<uint8_t>.
          value: !lambda |-
              return {0x08, 0x00, 0x81, 0x00, 0x01, 0x51, 0x00, 0x64};
             
  - platform: template
    name: "Stop"
    on_press:
      - logger.log: "Switch toggled"
      - ble_client.ble_write:
          id: my_ble_client
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          # List of bytes to write.
          value: [0x0a, 0x00, 0x41, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01]
      - ble_client.ble_write:
          id: my_ble_client
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          # A lambda returning an std::vector<uint8_t>.
          value: !lambda |-
              return {0x08, 0x00, 0x81, 0x00, 0x01, 0x51, 0x00, 0x00};
            
  - platform: template
    name: "Backward 1"
    on_press:
      - logger.log: "Switch toggled"
      - ble_client.ble_write:
          id: my_ble_client
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          # List of bytes to write.
          value: [0x0a, 0x00, 0x41, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01]
      - ble_client.ble_write:
          id: my_ble_client
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          # A lambda returning an std::vector<uint8_t>.
          value: !lambda |-
              return {0x08, 0x00, 0x81, 0x00, 0x01, 0x51, 0x00, 0xce};
          
  - platform: template
    name: "Backward 2"
    on_press:
      - logger.log: "Switch toggled"
      - ble_client.ble_write:
          id: my_ble_client
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          # List of bytes to write.
          value: [0x0a, 0x00, 0x41, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01]
      - ble_client.ble_write:
          id: my_ble_client
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          # A lambda returning an std::vector<uint8_t>.
          value: !lambda |-
              return {0x08, 0x00, 0x81, 0x00, 0x01, 0x51, 0x00, 0xce};
      
  - platform: template
    name: "horn"
    on_press:
      - logger.log: "Switch toggled"
      - ble_client.ble_write:
          id: my_ble_client
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          # List of bytes to write.
          value: [0x0a, 0x00, 0x41, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01]
      - ble_client.ble_write:
          id: my_ble_client
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          # A lambda returning an std::vector<uint8_t>.
          value: !lambda |-
              return {0x08, 0x00, 0x81, 0x01, 0x11, 0x51, 0x01, 0x09};
  - platform: template
    name: "fill water"
    on_press:
      - logger.log: "Switch toggled"
      - ble_client.ble_write:
          id: my_ble_client
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          # List of bytes to write.
          value: [0x0a, 0x00, 0x41, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01]
      - ble_client.ble_write:
          id: my_ble_client
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          # A lambda returning an std::vector<uint8_t>.
          value: !lambda |-
              return {0x08, 0x00, 0x81, 0x01, 0x11, 0x51, 0x01, 0x07};
  - platform: template
    name: "light"
    on_press:
      - logger.log: "Switch toggled"
      - ble_client.ble_write:
          id: my_ble_client
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          # List of bytes to write.
          value: [0x0a, 0x00, 0x41, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01]
      - ble_client.ble_write:
          id: my_ble_client
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          # A lambda returning an std::vector<uint8_t>.
          value: !lambda |-
              return {0x08, 0x00, 0x81, 0x11, 0x11, 0x51, 0x00, 0x0a};

Finally i made a control card:

type: vertical-stack
cards:
  - type: vertical-stack
    cards:
      - type: custom:mushroom-title-card
        title: Trein contoller
        alignment: center
      - type: horizontal-stack
        cards:
          - show_name: true
            show_icon: true
            type: button
            tap_action:
              action: toggle
            entity: button.speed_1
            name: Versnelling 1
            icon: mdi:chevron-right
          - show_name: true
            show_icon: true
            type: button
            tap_action:
              action: toggle
            icon: mdi:chevron-double-right
            entity: button.speed_2
            name: Versnelling 2
          - show_name: true
            show_icon: true
            type: button
            tap_action:
              action: toggle
            entity: button.speed_3
            icon: mdi:transfer-right
            name: Versnelling 3
      - type: horizontal-stack
        cards:
          - show_name: true
            show_icon: true
            type: button
            tap_action:
              action: toggle
            entity: button.stop
            icon: mdi:stop
          - show_name: true
            show_icon: true
            type: button
            tap_action:
              action: toggle
            entity: button.backward_1
            icon: mdi:chevron-left
            name: Terug 1
          - show_name: true
            show_icon: true
            type: button
            tap_action:
              action: toggle
            entity: button.backward_2
            icon: mdi:chevron-double-left
            name: Terug 2
      - type: horizontal-stack
        cards:
          - show_name: true
            show_icon: true
            type: button
            tap_action:
              action: toggle
            entity: button.horn
            icon: mdi:bugle
            name: Toeter
          - show_name: true
            show_icon: true
            type: button
            tap_action:
              action: toggle
            entity: button.fill_water
            name: Water vullen
            icon: mdi:water-pump
          - show_name: true
            show_icon: true
            type: button
            tap_action:
              action: toggle
            entity: button.light
            name: Licht
            icon: mdi:car-parking-lights

The title’s are in dutch so need to be changed to the preferred language.

I would like to hear if if you guys liked this project and love to hear the comments.!

10 Likes

I also made a design for the housing of the ESP32. To my surprise, the inside of a standard Duplo block has exactly the right dimensions for the ESP.

Link STL for 3d print:
https://makerworld.com/en/models/675692

3 Likes

Cool idea! Please share some videos on this when you can :slight_smile:

1 Like

Here is a test video:

15 Likes

That’s really cool! I can imagine kid me finding this absolutely incredible to play with.
Also, that enclosure is so charming as well :slight_smile:

1 Like

This is great, I’d completely forgotten that I also wanted to do this!

I’ve extended your code a bit, to cover some additional colours:

esphome:
  name: esphome-web-8be058
  friendly_name: Duplo Train

esp32:
  board: esp32dev
  framework:
    type: arduino

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: "xxxxxxx="

ota:

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

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Esphome-Web-8Be058"
    password: "xxxxxxx"

esp32_ble_tracker:

ble_client:
  - mac_address: "60:98:66:9A:B3:07"
    id: Duplo_Train_Control
    on_connect:
      then:
        - lambda: |-
            ESP_LOGD("ble_client_lambda", "Connected to Train");
    on_disconnect:
      then:
        - lambda: |-
            ESP_LOGD("ble_client_lambda", "Disconnected from Train");

switch:
  - platform: ble_client
    ble_client_id: Duplo_Train_Control
    name: Train

button:
  - platform: template
    name: "Speed 1"
    icon: mdi:play
    on_press:
      - logger.log: "Switch toggled"
      - ble_client.ble_write:
          id: Duplo_Train_Control
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          value: [0x0a, 0x00, 0x41, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01]
      - ble_client.ble_write:
          id: Duplo_Train_Control
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          value: [0x08, 0x00, 0x81, 0x00, 0x01, 0x51, 0x00, 0x1e]

  - platform: template
    name: "Speed 2"
    icon: mdi:step-forward
    on_press:
      - logger.log: "Switch toggled"
      - ble_client.ble_write:
          id: Duplo_Train_Control
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          value: [0x0a, 0x00, 0x41, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01]
      - ble_client.ble_write:
          id: Duplo_Train_Control
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          value: [0x08, 0x00, 0x81, 0x00, 0x01, 0x51, 0x00, 0x32]

  - platform: template
    name: "Speed 3"
    icon: mdi:step-forward-2
    on_press:
      - logger.log: "Switch toggled"
      - ble_client.ble_write:
          id: Duplo_Train_Control
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          value: [0x0a, 0x00, 0x41, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01]
      - ble_client.ble_write:
          id: Duplo_Train_Control
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          value: [0x08, 0x00, 0x81, 0x00, 0x01, 0x51, 0x00, 0x64]

  - platform: template
    name: "Stop"
    on_press:
      - logger.log: "Switch toggled"
      - ble_client.ble_write:
          id: Duplo_Train_Control
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          value: [0x0a, 0x00, 0x41, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01]
      - ble_client.ble_write:
          id: Duplo_Train_Control
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          value: [0x08, 0x00, 0x81, 0x00, 0x01, 0x51, 0x00, 0x00]

  - platform: template
    name: "Backward 1"
    icon: mdi:step-backward
    on_press:
      - logger.log: "Switch toggled"
      - ble_client.ble_write:
          id: Duplo_Train_Control
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          value: [0x0a, 0x00, 0x41, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01]
      - ble_client.ble_write:
          id: Duplo_Train_Control
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          value: [0x08, 0x00, 0x81, 0x00, 0x01, 0x51, 0x00, 0xce]

  - platform: template
    name: "Backward 2"
    icon: mdi:step-backward-2
    on_press:
      - logger.log: "Switch toggled"
      - ble_client.ble_write:
          id: Duplo_Train_Control
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          value: [0x0a, 0x00, 0x41, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01]
      - ble_client.ble_write:
          id: Duplo_Train_Control
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          value: [0x08, 0x00, 0x81, 0x00, 0x01, 0x51, 0x00, 0xce]

  - name: "Sound: Brake"
    icon: mdi:stop
    platform: template
    on_press:
      - logger.log: "Switch toggled"
      - ble_client.ble_write:
          id: Duplo_Train_Control
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          value: [0x0a, 0x00, 0x41, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01]
      - ble_client.ble_write:
          id: Duplo_Train_Control
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          value: [0x08, 0x00, 0x81, 0x01, 0x11, 0x51, 0x01, 0x03]

  - name: "Sound: depart"
    platform: template
    on_press:
      - logger.log: "Switch toggled"
      - ble_client.ble_write:
          id: Duplo_Train_Control
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          value: [0x0a, 0x00, 0x41, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01]
      - ble_client.ble_write:
          id: Duplo_Train_Control
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          value: [0x08, 0x00, 0x81, 0x01, 0x11, 0x51, 0x01, 0x05]

  - name: "Sound: fill water"
    icon: mdi:water
    platform: template
    on_press:
      - logger.log: "Switch toggled"
      - ble_client.ble_write:
          id: Duplo_Train_Control
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          value: [0x0a, 0x00, 0x41, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01]
      - ble_client.ble_write:
          id: Duplo_Train_Control
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          value: [0x08, 0x00, 0x81, 0x01, 0x11, 0x51, 0x01, 0x07]

  - name: "Sound: horn"
    icon: mdi:bugle
    platform: template
    on_press:
      - logger.log: "Switch toggled"
      - ble_client.ble_write:
          id: Duplo_Train_Control
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          value: [0x0a, 0x00, 0x41, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01]
      - ble_client.ble_write:
          id: Duplo_Train_Control
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          value: [0x08, 0x00, 0x81, 0x01, 0x11, 0x51, 0x01, 0x09]

  - name: "Sound: steam"
    icon: mdi:kettle-steam
    platform: template
    on_press:
      - logger.log: "Switch toggled"
      - ble_client.ble_write:
          id: Duplo_Train_Control
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          value: [0x0a, 0x00, 0x41, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01]
      - ble_client.ble_write:
          id: Duplo_Train_Control
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          value: [0x08, 0x00, 0x81, 0x01, 0x11, 0x51, 0x01, 0x0A]

  - name: "Light: Off"
    platform: template
    on_press:
      - logger.log: "Switch toggled"
      - ble_client.ble_write:
          id: Duplo_Train_Control
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          value: [0x0a, 0x00, 0x41, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01]
      - ble_client.ble_write:
          id: Duplo_Train_Control
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          value: [0x08, 0x00, 0x81, 0x11, 0x11, 0x51, 0x00, 0x00]

  - name: "Light: Pink"
    platform: template
    on_press:
      - logger.log: "Switch toggled"
      - ble_client.ble_write:
          id: Duplo_Train_Control
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          value: [0x0a, 0x00, 0x41, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01]
      - ble_client.ble_write:
          id: Duplo_Train_Control
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          value: [0x08, 0x00, 0x81, 0x11, 0x11, 0x51, 0x00, 0x01]

  - name: "Light: Purple"
    platform: template
    on_press:
      - logger.log: "Switch toggled"
      - ble_client.ble_write:
          id: Duplo_Train_Control
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          value: [0x0a, 0x00, 0x41, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01]
      - ble_client.ble_write:
          id: Duplo_Train_Control
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          value: [0x08, 0x00, 0x81, 0x11, 0x11, 0x51, 0x00, 0x02]

  - name: "Light: Blue"
    platform: template
    on_press:
      - logger.log: "Switch toggled"
      - ble_client.ble_write:
          id: Duplo_Train_Control
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          value: [0x0a, 0x00, 0x41, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01]
      - ble_client.ble_write:
          id: Duplo_Train_Control
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          value: [0x08, 0x00, 0x81, 0x11, 0x11, 0x51, 0x00, 0x03]

  - name: "Light: Light Blue"
    platform: template
    on_press:
      - logger.log: "Switch toggled"
      - ble_client.ble_write:
          id: Duplo_Train_Control
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          value: [0x0a, 0x00, 0x41, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01]
      - ble_client.ble_write:
          id: Duplo_Train_Control
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          value: [0x08, 0x00, 0x81, 0x11, 0x11, 0x51, 0x00, 0x04]

  - name: "Light: Cyan"
    platform: template
    on_press:
      - logger.log: "Switch toggled"
      - ble_client.ble_write:
          id: Duplo_Train_Control
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          value: [0x0a, 0x00, 0x41, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01]
      - ble_client.ble_write:
          id: Duplo_Train_Control
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          value: [0x08, 0x00, 0x81, 0x11, 0x11, 0x51, 0x00, 0x05]

  - name: "Light: Green"
    platform: template
    on_press:
      - logger.log: "Switch toggled"
      - ble_client.ble_write:
          id: Duplo_Train_Control
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          value: [0x0a, 0x00, 0x41, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01]
      - ble_client.ble_write:
          id: Duplo_Train_Control
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          value: [0x08, 0x00, 0x81, 0x11, 0x11, 0x51, 0x00, 0x06]

  - name: "Light: Yellow"
    platform: template
    on_press:
      - logger.log: "Switch toggled"
      - ble_client.ble_write:
          id: Duplo_Train_Control
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          value: [0x0a, 0x00, 0x41, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01]
      - ble_client.ble_write:
          id: Duplo_Train_Control
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          value: [0x08, 0x00, 0x81, 0x11, 0x11, 0x51, 0x00, 0x07]

  - name: "Light: Orange"
    platform: template
    on_press:
      - logger.log: "Switch toggled"
      - ble_client.ble_write:
          id: Duplo_Train_Control
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          value: [0x0a, 0x00, 0x41, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01]
      - ble_client.ble_write:
          id: Duplo_Train_Control
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          value: [0x08, 0x00, 0x81, 0x11, 0x11, 0x51, 0x00, 0x08]

  - name: "Light: Red"
    platform: template
    on_press:
      - logger.log: "Switch toggled"
      - ble_client.ble_write:
          id: Duplo_Train_Control
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          value: [0x0a, 0x00, 0x41, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01]
      - ble_client.ble_write:
          id: Duplo_Train_Control
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          value: [0x08, 0x00, 0x81, 0x11, 0x11, 0x51, 0x00, 0x09]

  - name: "Light: White"
    platform: template
    on_press:
      - logger.log: "Switch toggled"
      - ble_client.ble_write:
          id: Duplo_Train_Control
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          value: [0x0a, 0x00, 0x41, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01]
      - ble_client.ble_write:
          id: Duplo_Train_Control
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          value: [0x08, 0x00, 0x81, 0x11, 0x11, 0x51, 0x00, 0x0A]

There are some other things which I’d like to do to this:

  • Deduplicate the code, e.g. the colour options above are all the same except for the last character of the value. I haven’t yet read the esphome docs, but I’d assume that this is possible with setting a var and inserting that in
  • Reading sensors from the train - battery would be handy, and I also want to read the colour sensor (the one which changes when it drives over the coloured bits on the track)
  • Set up the RGB light option on the train, so that I can use a Home Assistant / esphome RGB light rather than being limited to preset options
1 Like

Nice,
I already wanted to add the multi colours too the code and had the same idea for the color sensor.
I want to use the sensor to give extra information to home assistant so that the train can stop at a station.

1 Like

There probably comes a point where extending this with lots of repetitive yml in esphome gets silly.

I’m not 100% about what is the right way to do this, I can see 2 options:

I’m leaning towards the 2nd option

1 Like

Improved the configuration to make use scripts:

script:
  - id: prepare_ble
    then:
      - ble_client.ble_write:
          id: Duplo_Train_Control
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          value: [0x0a, 0x00, 0x41, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01]
  
  - id: switch_speed
    parameters:
      value: char
    then:
      - script.execute:
          id: prepare_ble
      - ble_client.ble_write:
          id: Duplo_Train_Control
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          value: !lambda |-
            std::vector<unsigned char> v = {0x08, 0x00, 0x81, 0x00, 0x01, 0x51, 0x00};
            v.push_back(value);
            return v;

  - id: make_sound
    parameters:
      value: char
    then:
      - script.execute:
          id: prepare_ble
      - ble_client.ble_write:
          id: Duplo_Train_Control
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          value: !lambda |-
            std::vector<unsigned char> v = {0x08, 0x00, 0x81, 0x01, 0x11, 0x51, 0x01};
            v.push_back(value);
            return v;

  - id: lights
    parameters:
      value: char
    then:
      - script.execute:
          id: prepare_ble
      - ble_client.ble_write:
          id: Duplo_Train_Control
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          value: !lambda |-
            std::vector<unsigned char> v = {0x08, 0x00, 0x81, 0x11, 0x11, 0x51, 0x00};
            v.push_back(value);
            return v;

button:
  - platform: template
    name: "Speed 1"
    icon: mdi:play
    on_press:
      - script.execute:
          id: switch_speed
          value: 0x1e

  - platform: template
    name: "Speed 2"
    icon: mdi:step-forward
    on_press:
      - script.execute:
          id: switch_speed
          value: 0x32

  - platform: template
    name: "Speed 3"
    icon: mdi:step-forward-2
    on_press:
      - script.execute:
          id: switch_speed
          value: 0x64

  - platform: template
    name: "Stop"
    icon: mdi:stop
    on_press:
      - script.execute:
          id: switch_speed
          value: 0x00

  - platform: template
    name: "Backward"
    icon: mdi:step-backward
    on_press:
      - script.execute:
          id: switch_speed
          value: 0xce

  - name: "Sound: Brake"
    icon: mdi:stop
    platform: template
    on_press:
      - script.execute:
          id: make_sound
          value: 0x03

  - name: "Sound: depart"
    platform: template
    on_press:
      - script.execute:
          id: make_sound
          value: 0x05

  - name: "Sound: fill water"
    icon: mdi:water
    platform: template
    on_press:
      - script.execute:
          id: make_sound
          value: 0x07

  - name: "Sound: horn"
    icon: mdi:bugle
    platform: template
    on_press:
      - script.execute:
          id: make_sound
          value: 0x09

  - name: "Sound: steam"
    icon: mdi:kettle-steam
    platform: template
    on_press:
      - script.execute:
          id: make_sound
          value: 0x0A

  - name: "Light: Off"
    platform: template
    on_press:
      - script.execute:
          id: lights
          value: 0x00

  - name: "Light: Pink"
    platform: template
    on_press:
      - script.execute:
          id: lights
          value: 0x01

  - name: "Light: Purple"
    platform: template
    on_press:
      - script.execute:
          id: lights
          value: 0x02

  - name: "Light: Blue"
    platform: template
    on_press:
      - script.execute:
          id: lights
          value: 0x03

  - name: "Light: Light Blue"
    platform: template
    on_press:
      - script.execute:
          id: lights
          value: 0x04

  - name: "Light: Cyan"
    platform: template
    on_press:
      - script.execute:
          id: lights
          value: 0x05

  - name: "Light: Green"
    platform: template
    on_press:
      - script.execute:
          id: lights
          value: 0x06

  - name: "Light: Yellow"
    platform: template
    on_press:
      - script.execute:
          id: lights
          value: 0x07

  - name: "Light: Orange"
    platform: template
    on_press:
      - script.execute:
          id: lights
          value: 0x08

  - name: "Light: Red"
    platform: template
    on_press:
      - script.execute:
          id: lights
          value: 0x09

  - name: "Light: White"
    platform: template
    on_press:
      - script.execute:
          id: lights
          value: 0x0A
3 Likes

Thanks for sharing your code. My kids just got the train and now I’m able to controll it via Home Assistant. That’s aweseom!

I would like to add a remote control, so that the kids can control the train without needing my phone.

1 Like

Hi! Many thanks for sharing this. I am also building a remote with buttons. I have noticed something: when the train is used with this method, the bricks for horn, stop, etc are not working, the train is passing by them also pushing is not working. Perhaps when the train is connected to bluetooth, the reading of the bricks or movements is made on the remote device (for example the phone app)? Has someone figure this out? Thank you!

1 Like

bricknil lists that the train has color and speed sensors which would react to the bricks and pushes, but I was so far unable to make ESPHome react to them

1 Like

@vrutkovs I would assume that it’s possible to do this in esphome with the ble client sensor, although this would mean that you effectively are polling the train every x seconds to get the reading from the sensors. Not sure what effect this would have on battery life.

1 Like

Hello. I’ve been looking at building an integration for this purpose over the last few weeks before stumbling into this thread. The main issue I have is bluetooth disconnects (possibly due to my instance being a Raspberry Pi 3). I’m finding when this happens I have to put my train back into pairing mode before it will reconnect, and even then it sometimes doesn’t reconnect. What is this behaviour like with the ESP home? Does it reconnect fine?

I love this little project!
I used the fan component to control the train speed. This makes is possible to control forward and backward speed with a single entity. It’s not perfect, but it works. Could probably use similar outputs to create a RGB Light entity.

globals:
  - id: direction
    type: int
    initial_value: "1"

output:     
  - platform: template
    id: output_speed
    type: float
    write_action:
      - script.execute:
          id: switch_speed
          value: !lambda return (int)(state*100) * id(direction);

  - platform: template
    id: output_direction
    type: binary
    write_action:
      - lambda: |-
          if (state) {
            id(direction) = -1;
          } else {
            id(direction) = 1;
          }

fan:
  - platform: speed
    id: train_speed
    output: output_speed
    direction_output: output_direction
    name: None
    icon: mdi:train
    speed_count: 100
3 Likes

Do you think you could post your full yaml for the train with the other controls? (obviously, omitting your private data.)
Thanks!

Sorry for the delay. Here is my full yaml. I think the lambda in the speed-output component could be tuned a bit. My train doesn’t start until 30%.

The API have RGB color mode for the light (section 3.27.21: LEGO Wireless Protocol 3.0.00 Doc v3.0.00 r17 documentation) so it shouldn’t be too hard to implement as RGB Light in ESPHome

esphome:
  name: "duplo-train"
  friendly_name: Duplo Train
  comment: Bluetooth Proxy - Duplo Train
  # Disable BLE connection at boot
  on_boot:
    priority: 200
    then:
      - switch.turn_off: connected

esp32:
  board: esp32dev
  framework:
    type: esp-idf

wifi:
  ssid: !secret iot_ssid
  password: !secret iot_password
  domain: !secret iot_domain
  ap:
    ssid: !secret fallback_ssid
    password: !secret fallback_password
    
logger:
  
api:
  encryption:
    key: !secret api_key
ota:

esp32_ble_tracker:
  scan_parameters:
    interval: 1100ms
    window: 1100ms
    active: True

ble_client:
  - mac_address: "C4:64:E3:26:6E:D0"
    id: Duplo_Train_Control
    on_connect:
      then:
        - lambda: |-
            ESP_LOGD("ble_client_lambda", "Connected to Train");
    on_disconnect:
      then:
        - lambda: |-
            ESP_LOGD("ble_client_lambda", "Disconnected from Train");

script:
  - id: prepare_ble
    then:
      - ble_client.ble_write:
          id: Duplo_Train_Control
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          value: [0x0a, 0x00, 0x41, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01]
  
  - id: switch_speed
    parameters:
      value: char
    then:
      - script.execute:
          id: prepare_ble
      - ble_client.ble_write:
          id: Duplo_Train_Control
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          value: !lambda |-
            std::vector<unsigned char> v = {0x08, 0x00, 0x81, 0x00, 0x01, 0x51, 0x00};
            v.push_back(value);
            return v;
      - lambda: |-
          ESP_LOGD("switch_speed", "Speed - int: %i, hex: %x", value, value);

  - id: make_sound
    parameters:
      value: char
    then:
      - script.execute:
          id: prepare_ble
      - ble_client.ble_write:
          id: Duplo_Train_Control
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          value: !lambda |-
            std::vector<unsigned char> v = {0x08, 0x00, 0x81, 0x01, 0x11, 0x51, 0x01};
            v.push_back(value);
            return v;

  - id: lights
    parameters:
      value: char
    then:
      - script.execute:
          id: prepare_ble
      - ble_client.ble_write:
          id: Duplo_Train_Control
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          value: !lambda |-
            std::vector<unsigned char> v = {0x08, 0x00, 0x81, 0x11, 0x11, 0x51, 0x00};
            v.push_back(value);
            return v;

output:
  - platform: template
    id: output_speed
    type: float
    write_action:
      - script.execute:
          id: switch_speed
          value: !lambda return (int)((state*100)) * (id(direction));

  - platform: template
    id: output_direction
    type: binary
    write_action:
      - lambda: |-
          if (state) {
            id(direction) = -1;
          } else {
            id(direction) = 1;
          }

globals:
  - id: direction
    type: int
    initial_value: "1"

fan:
  - platform: speed
    id: train_speed
    output: output_speed
    direction_output: output_direction
    name: None
    icon: mdi:train
    speed_count: 100

switch:
  - platform: ble_client
    ble_client_id: Duplo_Train_Control
    name: Connected
    id: connected
    restore_mode: ALWAYS_OFF

button:
  - platform: safe_mode
    name: Safe Mode Boot
    entity_category: diagnostic
  - platform: restart
    name: Restart
    entity_category: diagnostic

  - platform: template
    name: "Stop"
    id: stop
    icon: mdi:stop
    on_press:
      - script.execute:
          id: switch_speed
          value: 0x00

  - name: "Sound: Brake"
    icon: mdi:stop
    platform: template
    on_press:
      - script.execute:
          id: make_sound
          value: 0x03

  - name: "Sound: Depart"
    platform: template
    on_press:
      - script.execute:
          id: make_sound
          value: 0x05

  - name: "Sound: Fill water"
    icon: mdi:water
    platform: template
    on_press:
      - script.execute:
          id: make_sound
          value: 0x07

  - name: "Sound: Horn"
    icon: mdi:bugle
    platform: template
    on_press:
      - script.execute:
          id: make_sound
          value: 0x09

  - name: "Sound: Steam"
    icon: mdi:kettle-steam
    platform: template
    on_press:
      - script.execute:
          id: make_sound
          value: 0x0A

  - name: "Light: Off"
    platform: template
    on_press:
      - script.execute:
          id: lights
          value: 0x00

  - name: "Light: Pink"
    platform: template
    on_press:
      - script.execute:
          id: lights
          value: 0x01

  - name: "Light: Purple"
    platform: template
    on_press:
      - script.execute:
          id: lights
          value: 0x02

  - name: "Light: Blue"
    platform: template
    on_press:
      - script.execute:
          id: lights
          value: 0x03

  - name: "Light: Light Blue"
    platform: template
    on_press:
      - script.execute:
          id: lights
          value: 0x04

  - name: "Light: Cyan"
    platform: template
    on_press:
      - script.execute:
          id: lights
          value: 0x05

  - name: "Light: Green"
    platform: template
    on_press:
      - script.execute:
          id: lights
          value: 0x06

  - name: "Light: Yellow"
    platform: template
    on_press:
      - script.execute:
          id: lights
          value: 0x07

  - name: "Light: Orange"
    platform: template
    on_press:
      - script.execute:
          id: lights
          value: 0x08

  - name: "Light: Red"
    platform: template
    on_press:
      - script.execute:
          id: lights
          value: 0x09

  - name: "Light: White"
    platform: template
    on_press:
      - script.execute:
          id: lights
          value: 0x0A
2 Likes

I have absolutely no idea how to achieve this … I was thinking to try with rgb senors, but by guesing :frowning: .

Thanks for putting that up!

This is my approach to mimic non connected controller behavior, while connected to BT. Train will react to action bricks as well as pushes and stops.
I use the vision sensor in “COLOR” mode which returns one of the predefined colors. “RGB” mode may drain battery faster due to more frequent changes and more frequent BLE transmission.
Speed sensor returns the raw value converted to integer, but I haven’t yet implement ed any interpolation to make sure it is somewhere between -100 and 100.
Now at least we can redefine or even extend behavior for action bricks. The good thing that the sensor in “COLOR” mode supports more colors than the 5 original action bricks.

Enjoy.

substitutions:
  service_uuid: '00001623-1212-efde-1623-785feabcd123'
  characteristic_uuid: '00001624-1212-efde-1623-785feabcd123'

esphome:
  name: duplo-steam-train
  friendly_name: Duplo Steam Train
  includes:
    - duplo.h

esp32:
  board: esp32dev
  framework:
    type: arduino

logger:

api:
  encryption:
    key: !secret enc_key
ota:
  password: !secret ota_pwd

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

globals:
   - id: motor_on
     type: bool
     restore_value: no
     initial_value: 'false'
   - id: white_on
     type: bool
     restore_value: no
     initial_value: 'false'

esp32_ble_tracker:

ble_client:
  - mac_address: "6C:B2:FD:83:AA:31"
    id: train_hub
    on_connect:
      then:
        - lambda: |-
            ESP_LOGD("train", "Connected to Train");
        - delay: 1s
        # activate vision sensor in COLOR mode
        - script.execute:
            id: activate_single
            port: !lambda "return VISION_SENSOR_PORT_ID;"
            mode: !lambda "return VISION_SENSOR_MODE_COLOR;"
        # activate speed sensor in SPEED mode
        - script.execute:
            id: activate_single
            port: !lambda "return SPEED_SENSOR_PORT_ID;"
            mode: !lambda "return SPEED_SENSOR_MODE_SPEED;"
    on_disconnect:
      then:
        - lambda: |-
            ESP_LOGD("train", "Disconnected from Train");

sensor:
  - platform: ble_client
    type: characteristic
    id: ble_sensor
    ble_client_id: train_hub
    service_uuid: ${service_uuid}
    characteristic_uuid: ${characteristic_uuid}
    lambda: |-
      ESP_LOGD("train", "Sensor raw bytes: [{%d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d}]", x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], x[8], x[9], x[10], x[11], x[12]);
      
      switch(x[3]) {
        case VISION_SENSOR_PORT_ID:
          {
            int color = x[4];
            if (x[4] == 1 || x[4] == 5) {
              color = color + 1;
            }
            if (color == 255) {
              color = 11;
            }
            id(hub_color).publish_state((float)color);
            break;
          }
        case SPEED_SENSOR_PORT_ID:
          {
            int16_t speed = x[4] | (int16_t)(x[5] << 8);
            id(hub_speed).publish_state((float)speed);
            break;
          }
      }
      return 0;
    notify: true

  - platform: template
    id: hub_color
    filters:
      - debounce: 0.2s
    on_value:
      then:
        - lambda: |-
            int value = (int)x;
            id(hub_color_text).publish_state(COLORS[value]);
            switch (value) {
              case RED:
                id(brake).press();
                id(stop).press();
                break;
              case BLUE:
                id(brake).press();
                id(stop).press();
                id(fill_water).press();
                delay(4000);
                id(speed_2).press();
                break;
              case YELLOW:
                id(horn).press();
                break;
              case GREEN:
                id(brake).press();
                if (id(hub_speed).state < 0) {
                  id(stop).press();
                  id(speed_2).press();
                } else {
                  id(stop).press();
                  id(backward).press();
                }
                break;
              case WHITE:
                if (id(white_on)) {
                  id(light_off).press();
                  id(white_on) = false;
                } else {
                  id(light_white).press();
                  id(white_on) = true;
                }
                break;
            }

  - platform: template
    id: hub_speed
    name: Speed
    on_value:
      then:
        - lambda: |-
            if (!id(motor_on)) {
              if (x > 10) {
                id(speed_2).press();
                id(motor_on) = true;
                return;
              }
              if (x < -10) {
                id(backward).press();
                id(motor_on) = true;
                return;
              }
            }
            if (x == 0.0) {
              id(motor_on) = false;
            }

text_sensor:
  - platform: template
    id: hub_color_text
    name: Color

switch:
  - platform: ble_client
    ble_client_id: train_hub
    name: Train

script:
  # activate updates for given port and given mode
  - id: activate_single
    parameters:
      port: char
      mode: char
    then:
      - ble_client.ble_write:
          id: train_hub
          service_uuid: ${service_uuid}
          characteristic_uuid: ${characteristic_uuid}
          value: !lambda |-
            std::vector<unsigned char> result { 0x0a, 0x00, 0x41, port, mode, 0x01, 0x00, 0x00, 0x00, 0x01 };
            return result;
  - id: prepare_ble
    then:
      - ble_client.ble_write:
          id: train_hub
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          value: [0x0a, 0x00, 0x41, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01]
  
  - id: switch_speed
    parameters:
      value: char
    then:
      - script.execute:
          id: prepare_ble
      - ble_client.ble_write:
          id: train_hub
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          value: !lambda |-
            std::vector<unsigned char> v = {0x08, 0x00, 0x81, 0x00, 0x01, 0x51, 0x00};
            v.push_back(value);
            return v;

  - id: make_sound
    parameters:
      value: char
    then:
      - script.execute:
          id: prepare_ble
      - ble_client.ble_write:
          id: train_hub
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          value: !lambda |-
            std::vector<unsigned char> v = {0x08, 0x00, 0x81, 0x01, 0x11, 0x51, 0x01};
            v.push_back(value);
            return v;

  - id: lights
    parameters:
      value: char
    then:
      - script.execute:
          id: prepare_ble
      - ble_client.ble_write:
          id: train_hub
          service_uuid: 00001623-1212-efde-1623-785feabcd123
          characteristic_uuid: 00001624-1212-efde-1623-785feabcd123
          value: !lambda |-
            std::vector<unsigned char> v = {0x08, 0x00, 0x81, 0x11, 0x11, 0x51, 0x00};
            v.push_back(value);
            return v;

button:
  - platform: template
    name: "Speed 1"
    id: speed_1
    icon: mdi:play
    on_press:
      - script.execute:
          id: switch_speed
          value: 0x1e

  - platform: template
    name: "Speed 2"
    id: speed_2
    icon: mdi:step-forward
    on_press:
      - script.execute:
          id: switch_speed
          value: 0x32

  - platform: template
    name: "Speed 3"
    id: speed_3
    icon: mdi:step-forward-2
    on_press:
      - script.execute:
          id: switch_speed
          value: 0x64

  - platform: template
    name: "Stop"
    id: stop
    icon: mdi:stop
    on_press:
      - script.execute:
          id: switch_speed
          value: 0x00

  - platform: template
    name: "Backward"
    id: backward
    icon: mdi:step-backward
    on_press:
      - script.execute:
          id: switch_speed
          value: 0xce

  - platform: template
    name: "Sound: Brake"
    id: brake
    icon: mdi:stop
    on_press:
      - script.execute:
          id: make_sound
          value: 0x03

  - platform: template
    name: "Sound: depart"
    id: depart
    on_press:
      - script.execute:
          id: make_sound
          value: 0x05

  - platform: template
    name: "Sound: fill water"
    id:  fill_water
    icon: mdi:water
    on_press:
      - script.execute:
          id: make_sound
          value: 0x07

  - platform: template
    name: "Sound: horn"
    id: horn
    icon: mdi:bugle
    on_press:
      - script.execute:
          id: make_sound
          value: 0x09

  - platform: template
    name: "Sound: steam"
    id: steam
    icon: mdi:kettle-steam
    on_press:
      - script.execute:
          id: make_sound
          value: 0x0A

  - name: "Light: Off"
    platform: template
    on_press:
      - script.execute:
          id: lights
          value: 0x00

  - name: "Light: Pink"
    platform: template
    on_press:
      - script.execute:
          id: lights
          value: 0x01

  - name: "Light: Purple"
    platform: template
    on_press:
      - script.execute:
          id: lights
          value: 0x02

  - name: "Light: Blue"
    platform: template
    on_press:
      - script.execute:
          id: lights
          value: 0x03

  - name: "Light: Light Blue"
    platform: template
    on_press:
      - script.execute:
          id: lights
          value: 0x04

  - name: "Light: Cyan"
    platform: template
    on_press:
      - script.execute:
          id: lights
          value: 0x05

  - name: "Light: Green"
    platform: template
    on_press:
      - script.execute:
          id: lights
          value: 0x06

  - name: "Light: Yellow"
    platform: template
    on_press:
      - script.execute:
          id: lights
          value: 0x07

  - name: "Light: Orange"
    platform: template
    on_press:
      - script.execute:
          id: lights
          value: 0x08

  - name: "Light: Red"
    platform: template
    on_press:
      - script.execute:
          id: lights
          value: 0x09

  - name: "Light: White"
    platform: template
    on_press:
      - script.execute:
          id: lights
          value: 0x0A

duplo.h

static const char VISION_SENSOR_PORT_ID = 0x12;
static const char VISION_SENSOR_MODE_COLOR = 0x00;
static const char VISION_SENSOR_MODE_CTAG = 0x01;
static const char VISION_SENSOR_MODE_REFLECTIVITY = 0x02;
static const char VISION_SENSOR_MODE_RGB = 0x03;

static const int BLACK = 0;
static const int PINK = 1;
static const int PURPLE = 2;
static const int BLUE = 3;
static const int LIGHTBLUE = 4;
static const int CYAN = 5;
static const int GREEN = 6;
static const int YELLOW = 7;
static const int ORANGE = 8;
static const int RED = 9;
static const int WHITE = 10;
static const int NONE = 255;
static const char *COLORS[12] = {"black", "pink", "purple", "blue", "lightblue", "cyan", "green", "yellow", "orange", "red", "white", "none"};

static const char SPEED_SENSOR_PORT_ID = 0x13;
static const char SPEED_SENSOR_MODE_SPEED = 0x00;
static const char SPEED_SENSOR_MODE_COUNT = 0x01;

static const char VOLTAGE_SENSOR_PORT_ID = 0x14;
5 Likes