wifwucite / esphome-ble-controller

Bluetooth Low Energy (BLE) controller for ESPHome
MIT License
114 stars 24 forks source link

Secure connection between two esphome devices #21

Open PRosenb opened 1 year ago

PRosenb commented 1 year ago

Hi, Is it possible to connect two esphome devices without displays using an encrypted BLE connection? I tried different variations of security configurations with esp32_ble_controller and ble_client but didn't manage to get it to work. I'm thinking on the last example in the readme with security switched on.

archef2000 commented 1 year ago

You first need to flash the server with the code below and then look for the BLE MAC and enter it in the client substitutions -> mac_light then flash the client look at both log outputs and open HA and call the passkey service with the pin from the log output of the server of the web server if you don't have it setup in HA use your browser's dev tool and set the pin via the slider on the client (it is going to fail) now you see a POST request in the network tab choose edit and resend and now enter the right pin (there is a newly generated pin for each try) server:


web_server:
  port: 80

external_components:
  - source: github://wifwucite/esphome-ble-controller

substitutions:
  light_virtual_switch_uuid: 32f40d3a-d24d-11ed-afa1-0242ac120002
  light_control_service_uuid: 2dc01d40-d24d-11ed-afa1-0242ac120002
  light_virtual_switch_id: light_virtual_switch

text_sensor:
  - platform: template
    name: "PAIRING PIN"
    id: ble_pin

switch:
  - platform: template
    id: ${light_virtual_switch_id}
    name: "Template Switch"
    optimistic: true
    turn_on_action:
      - logger.log: "Switch ON"
    turn_off_action:
      - logger.log: "Switch OFF"

esp32_ble_controller:
  security_mode: secure
  on_show_pass_key:
    - logger.log:
        format: "pass key is %s"
        args: 'pass_key.c_str()'
    - lambda: id(ble_pin).publish_state(pass_key);
  maintenance: false
  services:
    - service: ${light_control_service_uuid}
      characteristics:
        - characteristic: ${light_virtual_switch_uuid}
          exposes: ${light_virtual_switch_id}
  on_connected:
    - logger.log: "Connected."
  on_disconnected:
    - logger.log: "Disconnected."

client:


web_server:
  port: 80

api:
  encryption:
    key: "***"
  services:
    - service: passkey_reply
      variables:
        passkey: int
      then:
        - logger.log: "Authenticating with passkey"
        - ble_client.passkey_reply:
            id: ble_itag
            passkey: !lambda return passkey;

esp32_ble:
  io_capability: keyboard_display

web_server:
  port: 80

number:
  - platform: template
    name: "BLE Passkey"
    id: ble_passkey
    step: 1
    min_value: 000000
    max_value: 999999
    optimistic: True
    on_value:
      then:
        - ble_client.passkey_reply:
            id: ble_itag
            passkey: !lambda "return (int)id(ble_passkey).state;"

esp32_ble_tracker:

ble_client:
  - mac_address: EC:62:60:9C:9E:9A
    id: ble_itag
    on_passkey_request:
      logger.log: "Waiting on passkey"
    on_connect:
      then:
        - lambda: |-
            ESP_LOGD("ble_client_lambda", "Connected to BLE device");
    on_disconnect:
      then:
        - lambda: |-
            ESP_LOGD("ble_client_lambda", "Disconnected from BLE device");

substitutions:
  # You have to put your server's BLE address here, see server's startup log
  mac_light: "***"
  switch_button_id: button0
  light_virtual_switch_uuid: 32f40d3a-d24d-11ed-afa1-0242ac120002
  light_control_service_uuid: 2dc01d40-d24d-11ed-afa1-0242ac120002

switch:
  - platform: factory_reset
    name: Restart with Factory Default Settings
  - platform: template
    id: ${switch_button_id}
    name: ${switch_button_id}
    icon: "mdi:gesture-tap-button"
    optimistic: true
    turn_on_action:
      then:
        - logger.log: "Toggling the light using BLE"
        - ble_client.ble_write:
            id: ble_itag
            service_uuid: ${light_control_service_uuid}
            characteristic_uuid: ${light_virtual_switch_uuid}
            value: 1
    turn_off_action:
      then:
        - logger.log: "Toggling the light using BLE"
        - ble_client.ble_write:
            id: ble_itag
            service_uuid: ${light_control_service_uuid}
            characteristic_uuid: ${light_virtual_switch_uuid}
            value: 0
wifwucite commented 1 year ago

Sorry for the late answer. I am currently away from my computer. Did the suggestion above work? Another thing is to use security mode „bond“ for the first connect. After the devices know it each you could change it to „secure“. Unfortunately I cannot test it right now.

PRosenb commented 1 year ago

Many thanks for your replies @archef2000 and @wifwucite. I was hoping there would be an easier way. I'll try the idea above and let you know.

PRosenb commented 1 year ago

I tried to get it working with a minimal configuration as follows. It requires a browser and an MQTT client.

Watch the debug topic of the server to see the passkey and then do the POST request as @archef2000 describes above.

Client:

# ..
web_server:
  port: 80
esp32_ble:
  io_capability: keyboard_display
number:
  - platform: template
    name: "BLE Passkey"
    id: ble_passkey
    step: 1
    min_value: 000000
    max_value: 999999
    optimistic: True
    on_value:
      then:
        - ble_client.passkey_reply:
            id: ble_itag
            passkey: !lambda "return (int)id(ble_passkey).state;"
ble_client:
  - mac_address: "xx:xx:xx:xx:xx:xx"
    id: ble_itag
# ...

Server:

# ...
mqtt:
  broker: 192.168.x.x
esp32_ble_controller:
  security_mode: secure
  on_show_pass_key:
    - logger.log:
        format: "pass key is %s"
        args: 'pass_key.c_str()'
# ...

It would be great to have such a complete example e.g. on the readme or a separate page. What do you think @wifwucite?

archef2000 commented 1 year ago

For what do you need the mqtt client?

PRosenb commented 1 year ago

To see the passkey in the debug topic. I'm using MQTT anyway and didn't configure the webserver on the server. But good point, only using the webserver/browser would be a simpler flow.

archef2000 commented 1 year ago

Is the config working?

PRosenb commented 1 year ago

Yes @archef2000, it works like that and I have it in use since then.