alistair23 / AutoMower-BLE

This is an unofficial reverse engineered Husqvarna Automower Connect BLE library. This allows connecting and controlling an Automower without any accounts, cloud or network connection.
GNU General Public License v3.0
78 stars 21 forks source link

Thank you! #1

Closed AlessandroTischer closed 5 months ago

AlessandroTischer commented 8 months ago

Thanks for your work. I'm not sure if this can help, since it's more about the uart communication rather than the Bluetooth one, but I founded some resources some time ago, and they might be handy.

https://community.home-assistant.io/t/esphome-for-husqvarna-gardena/481903/1

alistair23 commented 8 months ago

Thanks for sharing that!

From a quick look at https://gitlab.com/nbrgmn/wall-e-esp8266-automower/-/blob/develop/Robomower_V0.8.pdf?ref_type=heads it does look like it might be helpful in decoding the requests/responses. Which is the main thing left to do here to support more features/commands

AlessandroTischer commented 8 months ago

Thanks for sharing that!

From a quick look at https://gitlab.com/nbrgmn/wall-e-esp8266-automower/-/blob/develop/Robomower_V0.8.pdf?ref_type=heads it does look like it might be helpful in decoding the requests/responses. Which is the main thing left to do here to support more features/commands

I'm glad it can be useful. Just one question: would you think that your work can work with esphome Bluetooth proxies? I think that would be a key element in order to be able to reach the mower across the whole garden

alistair23 commented 8 months ago

Just one question: would you think that your work can work with esphome Bluetooth proxies? I think that would be a key element in order to be able to reach the mower across the whole garden

That's the plan!

I've started to put together a HA component for the mower. I'm now waiting on a longer Ethernet cable to arrive so I can setup a ESPHome Bluetooth proxy near the mower

alistair23 commented 7 months ago

PR submitted for initial support upstream: https://github.com/home-assistant/core/pull/108326

AlessandroTischer commented 7 months ago

PR submitted for initial support upstream: https://github.com/home-assistant/core/pull/108326

Thank you!! While waiting for the PR to be accepted, do you think I can try it out? How can I import it?

alistair23 commented 7 months ago

You can test it.

If you apply this diff (custom components require a version)

diff --git a/homeassistant/components/husqvarna_automower_ble/manifest.json b/homeassistant/components/husqvarna_automower_ble/manifest.json
index cb3ee2a502..bd7db5f1f1 100644
--- a/homeassistant/components/husqvarna_automower_ble/manifest.json
+++ b/homeassistant/components/husqvarna_automower_ble/manifest.json
@@ -12,5 +12,6 @@
   "dependencies": ["bluetooth_adapters"],
   "documentation": "https://www.home-assistant.io/integrations/???",
   "iot_class": "local_polling",
-  "requirements": ["automower-ble==0.1.14"]
+  "requirements": ["automower-ble==0.1.14"],
+  "version": "0.1.0"
 }

Then just rsync the entire homeassistant/components/husqvarna_automower_ble directory from the PR to /root/homeassistant/custom_components/ on your HA instance

You will also want to enable debug logging by adding this to your homeassistant/configuration.yaml file

logger:
  # default: debug
  logs:
    custom_components.husqvarna_automower_ble: debug
    custom_components.husqvarna_automower_ble.config_flow: debug
    automower_ble.mower: debug

Then just reboot. Let me know how it goes, I have only tested it on a 305

AlessandroTischer commented 7 months ago

You can test it.

Then just reboot. Let me know how it goes, I have only tested it on a 305

Ok, i installed the integration and I can get up to the configuration wizard. There I can see a blank textbox with no hints. I tried inserting the Bluetooth address but it gives me an unknown error.

In the log I get this:

Logger: aiohttp.server
Source: /usr/local/lib/python3.11/site-packages/aiohttp/web_protocol.py:421
First occurred: 12:15:26 (3 occurrences)
Last logged: 12:16:36

Error handling request
Traceback (most recent call last):
  File "/usr/local/lib/python3.11/site-packages/aiohttp/web_protocol.py", line 452, in _handle_request
    resp = await request_handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/aiohttp/web_app.py", line 543, in _handle
    resp = await handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/aiohttp/web_middlewares.py", line 114, in impl
    return await handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/security_filter.py", line 85, in security_filter_middleware
    return await handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/forwarded.py", line 100, in forwarded_middleware
    return await handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/request_context.py", line 28, in request_context_middleware
    return await handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/ban.py", line 80, in ban_middleware
    return await handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/auth.py", line 233, in auth_middleware
    return await handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/headers.py", line 31, in headers_middleware
    response = await handler(request)
               ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/view.py", line 149, in handle
    result = await handler(request, **request.match_info)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/decorators.py", line 63, in with_admin
    return await func(self, request, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/config/config_entries.py", line 177, in post
    return await super().post(request, flow_id)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/data_validator.py", line 72, in wrapper
    result = await method(view, request, data, *args, **kwargs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/helpers/data_entry_flow.py", line 110, in post
    result = await self._flow_mgr.async_configure(flow_id, data)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/data_entry_flow.py", line 320, in async_configure
    result = await self._async_handle_step(
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/data_entry_flow.py", line 416, in _async_handle_step
    result: FlowResult = await getattr(flow, method)(user_input)
                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/config/custom_components/husqvarna_automower_ble/config_flow.py", line 87, in async_step_user
    return await self.async_step_confirm()
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/config/custom_components/husqvarna_automower_ble/config_flow.py", line 55, in async_step_confirm
    (manufacture, device_type, model) = await Mower(
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: cannot unpack non-iterable bool object
alistair23 commented 7 months ago

You need to insert the Bluetooth address in the box. I think I still need to provide strings which is why it's empty.

Did you enable logging in the config? There should be more details then that

AlessandroTischer commented 7 months ago

You need to insert the Bluetooth address in the box. I think I still need to provide strings which is why it's empty.

Yes, I imagined that could have been the problem, but it's a minor thing.

Did you enable logging in the config? There should be more details then that

Yes, I enabled it. I tried it again and found that missed an error:

This error originated from a custom integration.

Logger: automower_ble.mower
Source: custom_components/husqvarna_automower_ble/config_flow.py:55
Integration: Husqvarna Automower BLE
First occurred: 21:44:59 (6 occurrences)
Last logged: 22:08:11

could not find device with address '00:81:F9:68:E3:60'

Now I'm wandering: is the Bluetooth proxy via esphome supposed to work already? I took it for granted and tried it with the mower near an esp I already have in the garden (the server is in the basement...).

alistair23 commented 7 months ago

I have had a range of issues with the ESPHome BLE proxy and BLE devices in the past. So this is what I have for the node in the backyard

esp32_ble_tracker:
  scan_parameters:
    interval: 1100ms
    window: 1100ms
    active: true
    continuous: true

bluetooth_proxy:
  active: true
  cache_services: true

ble_client:
  - mac_address: D8:B6:73:40:07:37
    id:  automower_305

button:
  - platform: restart
    name: "ESP restart"
  - platform: template
    name: "ESP start Scan"
    on_press:
      - esp32_ble_tracker.start_scan:

Then the device page in HA has a "ESP start Scan" button. I usually click that to force a connection to the mower first, before loading the integration.

It's the same thing I have to do for the official HA Gardena integration as well. I see the device connect in the ESPHome logs. You can check there to see if a connection is being made.

Obviously make sure the mower is in range :)

AlessandroTischer commented 7 months ago

I have had a range of issues with the ESPHome BLE proxy and BLE devices in the past. So this is what I have for the node in the backyard

I'm now using your config, with the correct Bluetooth address

Then the device page in HA has a "ESP start Scan" button. I usually click that to force a connection to the mower first, before loading the integration.

You can check there to see if a connection is being made.

[13:10:42][D][button:010]: 'ESP start Scan' Pressed.
[13:10:42][D][esp32_ble_tracker:266]: Starting scan...
[13:10:42][D][esp32_ble_tracker:661]: Found device 00:81:F9:68:E3:60 RSSI=-63
[13:10:42][D][esp32_ble_tracker:682]:   Address Type: PUBLIC
[13:10:42][D][esp32_ble_tracker:684]:   Name: '315'

Obviously make sure the mower is in range :)

Now it takes a bit longer, but still results in an error:

This error originated from a custom integration.

Logger: homeassistant
Source: custom_components/husqvarna_automower_ble/config_flow.py:55
Integration: Husqvarna Automower BLE
First occurred: 13:00:43 (1 occurrences)
Last logged: 13:00:43

Error doing job: Task exception was never retrieved
Traceback (most recent call last):
  File "/usr/local/lib/python3.11/site-packages/aioesphomeapi/client.py", line 568, in bluetooth_device_connect
    await connect_future
TimeoutError

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/usr/local/lib/python3.11/site-packages/bleak_esphome/backend/client.py", line 77, in _async_wrap_bluetooth_operation
    return await func(self, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/bleak_esphome/backend/client.py", line 297, in connect
    await self._client.bluetooth_device_connect(
  File "/usr/local/lib/python3.11/site-packages/aioesphomeapi/client.py", line 588, in bluetooth_device_connect
    raise TimeoutAPIError(
aioesphomeapi.core.TimeoutAPIError: Timeout waiting for connect response while connecting to 00:81:F9:68:E3:60 after 10.0s, disconnect timed out: True,  after 20.0s

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/config_entries.py", line 888, in async_init
    flow, result = await task
                   ^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/config_entries.py", line 916, in _async_init
    result = await self._async_handle_step(flow, flow.init_step, data)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/data_entry_flow.py", line 416, in _async_handle_step
    result: FlowResult = await getattr(flow, method)(user_input)
                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/config/custom_components/husqvarna_automower_ble/config_flow.py", line 42, in async_step_bluetooth
    return await self.async_step_confirm()
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/config/custom_components/husqvarna_automower_ble/config_flow.py", line 55, in async_step_confirm
    (manufacture, device_type, model) = await Mower(
                                        ^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/automower_ble/mower.py", line 159, in probe_gatts
    await client.connect()
  File "/usr/local/lib/python3.11/site-packages/habluetooth/wrappers.py", line 295, in connect
    connected = await super().connect(**kwargs)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/bleak/__init__.py", line 605, in connect
    return await self._backend.connect(**kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/bleak_esphome/backend/client.py", line 79, in _async_wrap_bluetooth_operation
    raise asyncio.TimeoutError(str(err)) from err
TimeoutError: Timeout waiting for connect response while connecting to 00:81:F9:68:E3:60 after 10.0s, disconnect timed out: True,  after 20.0s
alistair23 commented 7 months ago

[13:10:42][D][button:010]: 'ESP start Scan' Pressed. [13:10:42][D][esp32_ble_tracker:266]: Starting scan... [13:10:42][D][esp32_ble_tracker:661]: Found device 00:81:F9:68:E3:60 RSSI=-63 [13:10:42][D][esp32_ble_tracker:682]: Address Type: PUBLIC

You need to get a connection here. You should get something in the log saying it connected. I suspect the issue is that the mower isn't in pairing mode. I have updated the documentation here: https://github.com/home-assistant/home-assistant.io/pull/30921

Basically make sure the mower is in pairing mode before doing this. For the 305 I need to power cycle the mower and trigger a connection in the first 3 minutes after startup.

Also, try moving the node closer. The timeout while connecting is weird and coming directly from the HA Bluetooth stack. You should be able to connect to the mower even without my integration.

Thanks for testing! You have helped me update the documentation already :)

AlessandroTischer commented 7 months ago

Hi! Sorry for the delay.

I think I'm getting closer, but I'm still having issues connecting.

This is the log from the ESPHome Node:

[15:05:31][D][esp32_ble_tracker:661]: Found device 00:81:F9:68:E3:60 RSSI=-42
[15:05:31][D][esp32_ble_tracker:682]:   Address Type: PUBLIC
[15:05:31][D][esp32_ble_tracker:684]:   Name: '315'
[15:05:31][W][bluetooth_proxy:268]: [0] [00:81:F9:68:E3:60] Connection request ignored, device is disconnecting
[15:05:35][D][esp-idf:000]: W (366880) BT_APPL: gattc_conn_cb: if=3 st=0 id=3 rsn=0x8

[15:05:35][D][esp-idf:000]: W (366883) BT_APPL: gattc_conn_cb: if=4 st=0 id=4 rsn=0x8

[15:05:35][D][esp-idf:000]: W (366887) BT_APPL: gattc_conn_cb: if=5 st=0 id=5 rsn=0x8

[15:05:35][D][esp-idf:000]: W (366888) BT_APPL: gattc_conn_cb: if=6 st=0 id=6 rsn=0x8

[15:05:35][D][esp-idf:000]: W (366890) BT_HCI: hcif disc complete: hdl 0x0, rsn 0x8

[15:05:35][D][esp32_ble_client:053]: [3] [00:81:F9:68:E3:60] Found device
[15:05:35][D][esp32_ble_tracker:215]: Pausing scan to make connection...
[15:05:35][D][esp32_ble_tracker:303]: End of scan.
[15:05:35][I][esp32_ble_client:069]: [3] [00:81:F9:68:E3:60] 0x00 Attempting BLE connection
[15:05:36][I][esp32_ble_client:201]: [3] [00:81:F9:68:E3:60] Connected

-------> Here I try to connect with the integration config flow submit button

[15:06:09][I][bluetooth_proxy:282]: [0] [00:81:F9:68:E3:60] Connecting v3 without cache
[15:06:09][I][esp32_ble_client:069]: [0] [00:81:F9:68:E3:60] 0x00 Attempting BLE connection
[15:06:09][D][esp-idf:000]: W (400891) BT_GATT: gatt_connect wrong state 4

[15:06:09][I][esp32_ble_client:201]: [0] [00:81:F9:68:E3:60] Connected
[15:06:10][W][bluetooth_proxy.connection:076]: [0] [00:81:F9:68:E3:60] Error reading char/descriptor at handle 0x E, status=5
[15:06:10][I][esp32_ble_client:086]: [0] [00:81:F9:68:E3:60] Disconnecting.

This is the log from HomeAssistant:

1:

This error originated from a custom integration.

Logger: homeassistant
Source: custom_components/husqvarna_automower_ble/config_flow.py:55
Integration: husqvarna_automower_ble
First occurred: 15:05:35 (1 occurrences)
Last logged: 15:05:35

Error doing job: Task exception was never retrieved
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/config_entries.py", line 888, in async_init
    flow, result = await task
                   ^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/config_entries.py", line 916, in _async_init
    result = await self._async_handle_step(flow, flow.init_step, data)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/data_entry_flow.py", line 416, in _async_handle_step
    result: FlowResult = await getattr(flow, method)(user_input)
                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/config/custom_components/husqvarna_automower_ble/config_flow.py", line 42, in async_step_bluetooth
    return await self.async_step_confirm()
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/config/custom_components/husqvarna_automower_ble/config_flow.py", line 55, in async_step_confirm
    (manufacture, device_type, model) = await Mower(
                                        ^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/automower_ble/mower.py", line 189, in probe_gatts
    await client.connect()
  File "/usr/local/lib/python3.11/site-packages/habluetooth/wrappers.py", line 295, in connect
    connected = await super().connect(**kwargs)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/bleak/__init__.py", line 605, in connect
    return await self._backend.connect(**kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/bleak_esphome/backend/client.py", line 77, in _async_wrap_bluetooth_operation
    return await func(self, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/bleak_esphome/backend/client.py", line 327, in connect
    await connected_future
bleak.exc.BleakError: Error ESP_GATT_CONN_TIMEOUT while connecting: Connection failed due to timeout

2:

This error originated from a custom integration.

Logger: automower_ble.mower
Source: custom_components/husqvarna_automower_ble/config_flow.py:55
Integration: husqvarna_automower_ble
First occurred: 15:06:10 (1 occurrences)
Last logged: 15:06:10

[Characteristic] 98bd0003-0b0e-421a-84e5-ddbf75dc6de4 (Handle: 14): Unknown (read,notify), Error: Bluetooth GATT Error address=00:81:F9:68:E3:60 handle=14 error=5 description=Insufficient authentication

Basically make sure the mower is in pairing mode before doing this. For the 305 I need to power cycle the mower and trigger a connection in the first 3 minutes after startup.

I'm not sure how the 305 connects, but my 315 has a connection menu where I can start the pairing, but I found that your 3 mins method seems to work better for this: when the mower has been turned on for a long time, even if I go to the pairing menu, the esphome node can't find the mower. Instead, during the mower startup, it is discoverable (I see the same behaviour using nRF connect app on my android phone). With the husqvarna app, instead, the mower can be connected only when in pairing mode (from its menu), and I can connect to it using the 4 digits pin.

Do you have any idea?

I hope this information will be somewhat useful for the project

alistair23 commented 7 months ago

bleak.exc.BleakError: Error ESP_GATT_CONN_TIMEOUT while connecting: Connection failed due to timeout

This is coming from the ESP device. I don't think there is much I can do here. How far away are the two devices? You can try moving them closer together to see if that works.

[Characteristic] 98bd0003-0b0e-421a-84e5-ddbf75dc6de4 (Handle: 14): Unknown (read,notify), Error: Bluetooth GATT Error address=00:81:F9:68:E3:60 handle=14 error=5 description=Insufficient authentication

This one is a good error!

That Insufficient authentication in the Characteristic means that the two devices are not paired. They are connected (so within range) but not paired.

I'm not sure how the 305 connects, but my 315 has a connection menu where I can start the pairing, but I found that your 3 mins method seems to work better for this

The 305 has the same setting. For me that menu option does nothing. The official app can not pair with the mower using that menu option. The only thing that works for me is the full reboot and then connect in the first 3 minutes. Even the official app with an Android phone held next to the mower took a few tries. So it might take a few goes.

Try pulling the latest changes. I have been working to try and improve the connection reliability as I test more with my mower.

Then just keep rebooting the mower and reload the integration until the husqvarna_automower_ble logs prints the Characteristics without any Insufficient authentication errors. Then the mower is paired. You only need to pair it once per BLE proxy, so don't stress about it being a bit of a pain

AlessandroTischer commented 7 months ago

bleak.exc.BleakError: Error ESP_GATT_CONN_TIMEOUT while connecting: Connection failed due to timeout

This is coming from the ESP device. I don't think there is much I can do here. How far away are the two devices? You can try moving them closer together to see if that works.

They are at less than a meter away from each other, I think this is not the problem

[Characteristic] 98bd0003-0b0e-421a-84e5-ddbf75dc6de4 (Handle: 14): Unknown (read,notify), Error: Bluetooth GATT Error address=00:81:F9:68:E3:60 handle=14 error=5 description=Insufficient authentication

This one is a good error!

That Insufficient authentication in the Characteristic means that the two devices are not paired. They are connected (so within range) but not paired.

I'm not sure how the 305 connects, but my 315 has a connection menu where I can start the pairing, but I found that your 3 mins method seems to work better for this

The 305 has the same setting. For me that menu option does nothing. The official app can not pair with the mower using that menu option. The only thing that works for me is the full reboot and then connect in the first 3 minutes. Even the official app with an Android phone held next to the mower took a few tries. So it might take a few goes.

Try pulling the latest changes. I have been working to try and improve the connection reliability as I test more with my mower.

I tried, since I saw some commits, but I'm not sure how to do so. I downloaded the folder from your homeassistant/core fork, but I'm not sure it's the latest (commit name is still initial commit)

Then just keep rebooting the mower and reload the integration until the husqvarna_automower_ble logs prints the Characteristics without any Insufficient authentication errors. Then the mower is paired. You only need to pair it once per BLE proxy, so don't stress about it being a bit of a pain

I will try, but I did so already a few times without success...

AlessandroTischer commented 7 months ago

I downloaded latest commit. Now I can finally finish the config flow and the integration entity is created... But it instantly shows "failed to setup". I already tried the setup at least 10 times.

I see that now, as soon as the esp node connects to the mower, the bt logo appears on the mower display and doesn't disappear.

Now the home assistant log reports:

1.

This error originated from a custom integration.

Logger: automower_ble.mower
Source: custom_components/husqvarna_automower_ble/config_flow.py:55
Integration: Husqvarna Automower BLE
First occurred: 16:52:21 (5 occurrences)
Last logged: 16:52:55

could not find device with address '00:81:F9:68:E3:60'
[Characteristic] 98bd0003-0b0e-421a-84e5-ddbf75dc6de4 (Handle: 14): Unknown (read,notify), Error: Bluetooth GATT Error address=00:81:F9:68:E3:60 handle=14 error=15 description=Insufficient encryption

2.

Logger: homeassistant.config_entries
Source: config_entries.py:406
First occurred: 16:53:02 (1 occurrences)
Last logged: 16:53:02

Error setting up entry Husqvarna Automower  for husqvarna_automower_ble
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/config_entries.py", line 406, in async_setup
    result = await component.async_setup_entry(hass, self)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/config/custom_components/husqvarna_automower_ble/__init__.py", line 52, in async_setup_entry
    model = await mower.get_model()
            ^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/automower_ble/mower.py", line 264, in get_model
    return self.response.decode_response_device_type(response)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/automower_ble/response.py", line 78, in decode_response_device_type
    return MowerModels[(data[19], data[20])]
           ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^
KeyError: (12, 0)

I also tried to move the security level on the mower from medium to low, but it doesn't help. Now I'm wondering: is it correct that I never have to insert my mower pin while configuring the integration? I don't see any way to remove it from the mower, and I'm not sure how the connection can be handled without it.

alistair23 commented 7 months ago

I see that now, as soon as the esp node connects to the mower, the bt logo appears on the mower display and doesn't disappear.

Now the home assistant log reports:

This error originated from a custom integration.

Logger: automower_ble.mower
Source: custom_components/husqvarna_automower_ble/config_flow.py:55
Integration: Husqvarna Automower BLE
First occurred: 16:52:21 (5 occurrences)
Last logged: 16:52:55

could not find device with address '00:81:F9:68:E3:60'
[Characteristic] 98bd0003-0b0e-421a-84e5-ddbf75dc6de4 (Handle: 14): Unknown (read,notify), Error: Bluetooth GATT Error address=00:81:F9:68:E3:60 handle=14 error=15 description=Insufficient encryption

This means it is connected but not paired. You need to make sure the mower is in pair mode then reload the integration.

I think you are missing some logs. You can SSH to the HA instance and run this? It will provide more logs and in an easier format

cat ./config/home-assistant.log | grep mow
alistair23 commented 7 months ago

I also tried to move the security level on the mower from medium to low, but it doesn't help. Now I'm wondering: is it correct that I never have to insert my mower pin while configuring the integration? I don't see any way to remove it from the mower, and I'm not sure how the connection can be handled without it.

Good question. I have decoded sending the PIN, the Python library supports providing it. But I have never needed to actually use it. You might need to the PIN to change some advanced settings (which we don't support). Currently everything works for me without using the PIN. My mower is set to low security.

If we find out we need the PIN I can look at adding support for that

AlessandroTischer commented 7 months ago
cat ./config/home-assistant.log | grep mow

mower_log.txt

alistair23 commented 7 months ago

Great! That is really helpful.

The mower is connected and paired. The Insufficient authentication error is from earlier.

You can communicate with the mower as well, so it's mostly working. The issue is the mower model lookup in the Python code. It's using the wrong values. It worked for the 305 by coincidence. I have pushed a fix, if you update to the latest from my PR it should work for you

AlessandroTischer commented 7 months ago

Great! That is really helpful.

I'm happy to help as much as I can!

I have pushed a fix, if you update to the latest from my PR it should work for you

I can finally confirm the integration setup works! Tomorrow I'll try to test it (it's 1am here, but I still wanted to try to connect). For now, I can only say a massive thank you!

BTW, Just out of curiosity: do you think that it would be feasible to add some kind of ble beacon functionality to track the mower position in the garden in the future?

alistair23 commented 7 months ago

Awesome! I'm glad it's working. This has helped narrow down a few bugs, so hopefully it helps this get merged

I don't think it would be feasible to track the mower position via BLE. Looking at some existing features in HA like iBeacon we could probably detect a rough distance. But that isn't super useful.

It would probably be easier to attach a GNSS device to the mower and use that instead

AlessandroTischer commented 7 months ago

Awesome! I'm glad it's working. This has helped narrow down a few bugs, so hopefully it helps this get merged

About this: why don't you create a custom component with HACS requirements in the meanwhile? It's quite straightforward and it would help for having more testers I think.

I don't think it would be feasible to track the mower position via BLE. Looking at some existing features in HA like iBeacon we could probably detect a rough distance. But that isn't super useful.

You're right

It would probably be easier to attach a GNSS device to the mower and use that instead

It would be nice to find some way to keep an esp and/or the gnss powered/charged on board of the mower itself, I need to look inside and see if I find some 3v or 5v pins

alistair23 commented 7 months ago

I really don't want to be maintaining an out of tree component. I have a few currently installed and I'm trying to get rid of them.

I would like to get this upstream so that it can benefit the most number of users and be included in the HA infrastructure. I must admit I didn't realise that it would take so long just to get a response though.

There are power pins somewhere :P The question is how easy are they to get to and then can you setup something in a secure and waterproof way.

A little solar/battery node might be easier. Although I now have the mower house setup, so that probably won't work too well for me

alistair23 commented 7 months ago

Have you had a chance to test this a bit more?

AlessandroTischer commented 7 months ago

Have you had a chance to test this a bit more?

Unfortunately not, I'm having some issues with the loop wire that is broken in multiple points (I hope the station is ok... Last spring I had to replace the board on the station since it fried during the winter). Now I have very little time, but I'll try to repair it ASAP. Then, I'll test it as much as I can.

alistair23 commented 7 months ago

Aw no! I'm sorry to hear that

No rush, I was just checking in

AlessandroTischer commented 6 months ago

Aw no! I'm sorry to hear that

Unfortunately the board was actually fried. I just replaced it.

After the setup with the new loop signal, the mower loses all its connections, and now I can't get it to connect to HA again... Tomorrow I could send you the logs again, if it's something useful. I also updated the integration to your latest commit.

alistair23 commented 6 months ago

Urgh! That's a pain. If you send the logs I can investigate. Sometimes it does take a few tries to get a connection though

AlessandroTischer commented 6 months ago

husqvarna_logs.txt

I managed to connect to the mower. Battery level seems ok and changes correctly when it's mowing or charging. Mower status is instead locked on "docked", even if the mower is in the middle of the garden. It also does not respond to any command from the integration. Moreover, if the server or the esp bt_proxy node reboot for any reason, it seems to disconnect and never connect to the mower again unless I pair it manually again.

alistair23 commented 6 months ago

Great!

Looking at your log I never see the mower send a "Mowing" activity. So the mower might not be connected when that happens.

The connection is pretty unreliable. That seems to be an issue with Home Assistant. I have the same issue with other BLE devices. I'm not sure there is much I can do in the integration to improve that unfortunately. I have tried testing a few different approaches, and they don't seem to help too a lot.

I can see you starting the mower in the logs. It looks like it works, but there is a strange exception in the Python code. I'll add more debug logs, so if it happens again hopefully we can see what's going on.

AlessandroTischer commented 6 months ago

Great!

Looking at your log I never see the mower send a "Mowing" activity. So the mower might not be connected when that happens.

The connection is pretty unreliable. That seems to be an issue with Home Assistant. I have the same issue with other BLE devices. I'm not sure there is much I can do in the integration to improve that unfortunately. I have tried testing a few different approaches, and they don't seem to help too a lot.

I can see you starting the mower in the logs. It looks like it works, but there is a strange exception in the Python code. I'll add more debug logs, so if it happens again hopefully we can see what's going on.

Hi! Sorry for the late reply, but I really didn't have any chance to look at the mower integration. Did you have the time to update the project to get more debug instead?

alistair23 commented 6 months ago

No worries. I have been slowly tweaking and updating things. The BLE connection is now as reliable as my other BLE connections. I'm still trying to improve it though

AlessandroTischer commented 6 months ago

No worries. I have been slowly tweaking and updating things.

I pulled latest commit, but I still have problems connecting to the mower. I attach latest logs.

mowerlogs.txt

alistair23 commented 6 months ago

Do you mind opening the log, finding the line

File "/usr/local/lib/python3.12/site-packages/automower_ble/mower.py", line 259, in probe_gatts

and including the lines around it. Something is failing in the decode and I can't see what

alistair23 commented 6 months ago

Ah, I see in the log it is Insufficient encryption. So you aren't paired

AlessandroTischer commented 6 months ago

Ah, I see in the log it is Insufficient encryption.

Do you still need the logs you asked before?

So you aren't paired

Is there anything I can do about it?

alistair23 commented 6 months ago

You need to put the mower into pair mode and then try again

GitWally commented 5 months ago

You can test it.

If you apply this diff (custom components require a version)

diff --git a/homeassistant/components/husqvarna_automower_ble/manifest.json b/homeassistant/components/husqvarna_automower_ble/manifest.json
index cb3ee2a502..bd7db5f1f1 100644
--- a/homeassistant/components/husqvarna_automower_ble/manifest.json
+++ b/homeassistant/components/husqvarna_automower_ble/manifest.json
@@ -12,5 +12,6 @@
   "dependencies": ["bluetooth_adapters"],
   "documentation": "https://www.home-assistant.io/integrations/???",
   "iot_class": "local_polling",
-  "requirements": ["automower-ble==0.1.14"]
+  "requirements": ["automower-ble==0.1.14"],
+  "version": "0.1.0"
 }

Then just rsync the entire homeassistant/components/husqvarna_automower_ble directory from the PR to /root/homeassistant/custom_components/ on your HA instance

You will also want to enable debug logging by adding this to your homeassistant/configuration.yaml file

logger:
  # default: debug
  logs:
    custom_components.husqvarna_automower_ble: debug
    custom_components.husqvarna_automower_ble.config_flow: debug
    automower_ble.mower: debug

Then just reboot. Let me know how it goes, I have only tested it on a 305

Hello I have a 305 and would like to test your integration with my HA Supervised (which has a BT antenna connected), if you think this could be helpful, while waiting for the merge to be approved.

I understood I have to download files to my HA instance. After reboot I think a configuration should be made: BT address, user, password ... am I right? Will there be a UI or should I write something in configuration.yaml? Or should I execute commands from terminal? Thanks

alistair23 commented 5 months ago

Once you have installed the component you can just add it like any other integration. You will need to specify the BLE address of the mower when setting up the integration

GitWally commented 5 months ago

Once you have installed the component you can just add it like any other integration. You will need to specify the BLE address of the mower when setting up the integration

Hello, may be I am new at this type of installation, but when I try to add https://github.com/alistair23/AutoMower-BLE as Custom component I get the following error: "<Integration alistair23/AutoMower-BLE> Repository structure for main is not compliant"

immagine

So I did:

  1. git clone to /usr/share/hassio/homeassistant/custom_components/AutoMower-BLE
  2. set logger options in configuration.yaml
  3. restart

But still can't see the new integration: searching for BLE ble or automower gave no result (except the official Husquarna Automower)

I came to the conclusion I should take files from another folder: may be the following one?

https://github.com/alistair23/homeassistant-core/tree/alistair/husqvarna_automower_ble/homeassistant/components/husqvarna_automower_ble?

I copied all 6 files from homeassistant/components/husqvarna_automower_ble

  1. https://github.com/alistair23/homeassistant-core/blob/alistair/husqvarna_automower_ble/homeassistant/components/husqvarna_automower_ble/__init__.py
  2. https://github.com/alistair23/homeassistant-core/blob/alistair/husqvarna_automower_ble/homeassistant/components/husqvarna_automower_ble/config_flow.py
  3. https://github.com/alistair23/homeassistant-core/blob/alistair/husqvarna_automower_ble/homeassistant/components/husqvarna_automower_ble/const.py
  4. https://github.com/alistair23/homeassistant-core/blob/alistair/husqvarna_automower_ble/homeassistant/components/husqvarna_automower_ble/coordinator.py)
  5. https://github.com/alistair23/homeassistant-core/blob/alistair/husqvarna_automower_ble/homeassistant/components/husqvarna_automower_ble/lawn_mower.py
  6. https://github.com/alistair23/homeassistant-core/blob/alistair/husqvarna_automower_ble/homeassistant/components/husqvarna_automower_ble/manifest.json

and rebooted (the whole system, not just HA)

Anyhow still no new integration dealing with "hus" or "automow" or "ble" found. What am I missing?

Thanks

alistair23 commented 5 months ago

Then just rsync the entire homeassistant/components/husqvarna_automower_ble directory from the PR to /root/homeassistant/custom_components/ on your HA instance

GitWally commented 5 months ago

Then just rsync the entire homeassistant/components/husqvarna_automower_ble directory from the PR to /root/homeassistant/custom_components/ on your HA instance

I'm not able to rsync from github just that folder ... stuck with permissions. I will wait for the merge to be accepted. Thanks

AlessandroTischer commented 5 months ago

Then just rsync the entire homeassistant/components/husqvarna_automower_ble directory from the PR to /root/homeassistant/custom_components/ on your HA instance

I'm not able to rsync from github just that folder ... stuck with permissions. I will wait for the merge to be accepted. Thanks

It's just like 6 files, you can create them manually and copy/paste them. I find this way faster than the other options

GitWally commented 5 months ago

Then just rsync the entire homeassistant/components/husqvarna_automower_ble directory from the PR to /root/homeassistant/custom_components/ on your HA instance

I'm not able to rsync from github just that folder ... stuck with permissions. I will wait for the merge to be accepted. Thanks

It's just like 6 files, you can create them manually and copy/paste them. I find this way faster than the other options

Hello Alessandro, thanks for your contribution: I think we did more or less the same. For the sake of completeness, I have downloaded and moved files as "root"

And this is the content of my homeassistant/custom_components/husqvarna_automower_ble folder

immagine

The thing is, I cannot find the new integration:

immagine

You said:

Ok, i installed the integration and I can get up to the configuration wizard. There I can see a blank textbox with no hints. I tried inserting the Bluetooth address but it gives me an unknown error.

Where did you started the integration wizard? How did you find it? Thanks

alistair23 commented 5 months ago

What does cat ./config/home-assistant.log | grep mow say?

Did you add the version field to the manifest?

GitWally commented 5 months ago

Hello @alistair23 sorry for the delay, but I'm in the opposite part of the world ;-)

What does cat ./config/home-assistant.log | grep mow say?

/usr/share/hassio/homeassistant$ cat home-assistant.log | grep mow 2024-03-22 21:58:47.753 WARNING (SyncWorker_1) [homeassistant.loader] We found a custom integration husqvarna_automower_ble which has not been tested by Home Assistant. This component might cause stability problems, be sure to disable it if you experience issues with Home Assistant 2024-03-22 21:58:47.753 ERROR (SyncWorker_1) [homeassistant.loader] The custom integration 'husqvarna_automower_ble' does not have a version key in the manifest file and was blocked from loading. See https://developers.home-assistant.io/blog/2021/01/29/custom-integration-changes#versions for more details

Did you add the version field to the manifest?

No, sorry, this is the first time I try to add a not-yet-release integration and I didn't know. This is manifest.json I have:

{ "domain": "husqvarna_automower_ble", "name": "Husqvarna Automower BLE", "bluetooth": [ { "service_uuid": "98bd0001-0b0e-421a-84e5-ddbf75dc6de4", "connectable": true } ], "codeowners": ["@alistair23"], "config_flow": true, "dependencies": ["bluetooth_adapters"], "documentation": "https://www.home-assistant.io/integrations/???", "iot_class": "local_polling", "requirements": ["automower-ble==0.1.32"] }

documentation says:

The version of the integration is required for custom integrations. The version needs to be a valid version recognized by AwesomeVersion like CalVer or SemVer.

So, as you suggested here i added

"version": "0.1.0"

so these are last lines of manifest.json now:

"iot_class": "local_polling", "requirements": ["automower-ble==0.1.32"] "version": "0.1.0" }

Now I can find the integration!!! Many thanks!

immagine

Let's go!

GitWally commented 5 months ago

Hello, I put the 305 in pairing mode and tried to pair 3 (or more) times. I'm using the MAC address found in known_devices.yaml identified as "305" by the name. But I came across the following unknown error:

immagine

in home-assistant.log I found:


2024-03-23 08:21:01.715 INFO (MainThread) [automower_ble.mower] connecting to device...
  File "/config/custom_components/husqvarna_automower_ble/config_flow.py", line 105, in async_step_user
  File "/config/custom_components/husqvarna_automower_ble/config_flow.py", line 69, in async_step_confirm
  File "/usr/local/lib/python3.12/site-packages/automower_ble/mower.py", line 217, in probe_gatts

Is there any helpful log I could provide to investigate?

I'm using a ZEXMTE 5.3 BT antenna, not an ESP, to connect to 305. Thanks

GitWally commented 5 months ago

Hi guys, looking at the logs, to see if there is something I could do, I noticed the last line of home-assistant.log is referring to python3.12

  File "/config/custom_components/husqvarna_automower_ble/config_flow.py", line 105, in async_step_user
  File "/config/custom_components/husqvarna_automower_ble/config_flow.py", line 69, in async_step_confirm
  File "/usr/local/lib/python3.12/site-packages/automower_ble/mower.py", line 217, in probe_gatts

The fact is I don't have such a dir, because I have just python 3.9 (default version for Debian 11):

immagine

I assumed an upgrade to Python 3.12 is required, so I installed Py 3.12 alongside 3.9. Now the home-assistant.log says something different ...

2024-03-23 08:47:14.053 INFO (MainThread) [automower_ble.mower] connecting to device...
  File "/config/custom_components/husqvarna_automower_ble/config_flow.py", line 105, in async_step_user
  File "/config/custom_components/husqvarna_automower_ble/config_flow.py", line 69, in async_step_confirm
  File "/usr/local/lib/python3.12/site-packages/automower_ble/mower.py", line 217, in probe_gatts
2024-03-23 08:48:59.502 INFO (MainThread) [automower_ble.mower] connecting to device...
2024-03-23 08:49:46.559 INFO (MainThread) [automower_ble.mower] connecting to device...
2024-03-23 18:20:05.178 INFO (MainThread) [automower_ble.mower] connecting to device...
2024-03-23 18:20:40.836 INFO (MainThread) [automower_ble.mower] connecting to device...
2024-03-23 18:21:15.797 INFO (MainThread) [automower_ble.mower] connecting to device...

Last 3 lines are the attempts I've done after Py upgrade.

Since in previous messages there was this reference

File "/usr/local/lib/python3.12/site-packages/automower_ble/mower.py", line 259, in probe_gatts

I tried to see the content of such a dir: there is not a "automower_ble" folder yet.

What should I try now?

Thanks

alistair23 commented 5 months ago

Can you open the log, find line 217, in probe_gatts and then provide all of the lines around it?

The grep for mower doesn't always show the Python exception information unfortunately