Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Switchbot Curtain 3, crashes when started with --fetch-device-info #232

Open
NiekD opened this issue May 8, 2024 · 6 comments
Open

Switchbot Curtain 3, crashes when started with --fetch-device-info #232

NiekD opened this issue May 8, 2024 · 6 comments
Labels
bug Something isn't working

Comments

@NiekD
Copy link

NiekD commented May 8, 2024

I am using a couple of Switchbot Curtain 3 devices and I would like to get battery- and position information. Unfortunately switchbot-mqtt (latest version) crashes immediately on the first attempt to do so.

Although I don't understand much of the Switchbot API yet, I noticed that the protocols for Curtain 2 and Curtain 3 are different, especially with respect to the device info. I guess that this is the reason for the crashes.
If switchbot-mqtt is started without --fetch-device-info, it works well with my Curtain 3 devices.

@fphammerle, Is it possible to add support for Curtain 3 device info?

@fphammerle fphammerle added the bug Something isn't working label May 8, 2024
@fphammerle
Copy link
Owner

Does the log contain any information before switchbot-mqtt crashes?

@NiekD
Copy link
Author

NiekD commented Jul 2, 2024

@fphammerle, sorry that it took so long for me to respond. This is the traceback of the crash that occurs when switcbot-mqtt is run with --fetch-device-info and a command is sent (CLOSE in this case). Apparently _switchbot_device_data is not properly being created with a Switchbot Curtain3. Possibly because there is a difference between the protocols of Curtain2 and Curtain3 with respect to the device info?

Traceback:

Successfully sent command to Switchbot (MAC: fc:85:6b:9b:77:03)
switchbot curtain fc:85:6b:9b:77:03 closing
Traceback (most recent call last):
File "/root/.local/bin/switchbot-mqtt", line 10, in
sys.exit(_main())
File "/root/.local/lib/python3.7/site-packages/switchbot_mqtt/_cli.py", line 169, in _main
or bool(os.environ.get("FETCH_DEVICE_INFO")),
File "/root/.local/lib/python3.7/site-packages/switchbot_mqtt/init.py", line 105, in _run
mqtt_client.loop_forever()
File "/usr/local/lib/python3.7/dist-packages/paho/mqtt/client.py", line 1756, in loop_forever
rc = self._loop(timeout)
File "/usr/local/lib/python3.7/dist-packages/paho/mqtt/client.py", line 1164, in _loop
rc = self.loop_read()
File "/usr/local/lib/python3.7/dist-packages/paho/mqtt/client.py", line 1556, in loop_read
rc = self._packet_read()
File "/usr/local/lib/python3.7/dist-packages/paho/mqtt/client.py", line 2439, in _packet_read
rc = self._packet_handle()
File "/usr/local/lib/python3.7/dist-packages/paho/mqtt/client.py", line 3033, in _packet_handle
return self._handle_publish()
File "/usr/local/lib/python3.7/dist-packages/paho/mqtt/client.py", line 3327, in _handle_publish
self._handle_on_message(message)
File "/usr/local/lib/python3.7/dist-packages/paho/mqtt/client.py", line 3556, in _handle_on_message
callback(self, self._userdata, message)
File "/root/.local/lib/python3.7/site-packages/switchbot_mqtt/_actors/base.py", line 239, in _mqtt_command_callback
mqtt_topic_prefix=userdata.mqtt_topic_prefix,
File "/root/.local/lib/python3.7/site-packages/switchbot_mqtt/_actors/init.py", line 249, in execute_command
report_position=report_position,
File "/root/.local/lib/python3.7/site-packages/switchbot_mqtt/_actors/init.py", line 184, in _update_and_report_device_info
super()._update_and_report_device_info(mqtt_client, mqtt_topic_prefix)
File "/root/.local/lib/python3.7/site-packages/switchbot_mqtt/_actors/base.py", line 151, in _update_and_report_device_info
mqtt_client=mqtt_client, mqtt_topic_prefix=mqtt_topic_prefix
File "/root/.local/lib/python3.7/site-packages/switchbot_mqtt/_actors/base.py", line 142, in _report_battery_level
payload=str(self._get_device().get_battery_percent()).encode(),
File "/root/.local/lib/python3.7/site-packages/switchbot/init.py", line 308, in get_battery_percent
return self._switchbot_device_data["data"]["battery"]
KeyError: 'data'

@fphammerle
Copy link
Owner

Could you try upgrading the pySwitchbot library and check if the issue persists?

@NiekD
Copy link
Author

NiekD commented Jul 6, 2024

I was running switchbot-mqtt version 3.3.1 with pySwitchbot version 0.12.0. and was unable to ugrade pySwitchbot to a newer version. It appears that upgrading to a higher version of pySwitchbot (using pip install) is only possible with switchbot-mqtt version 4.0.0a0. I did a quick check with Rasperry Pi Os Bullseye, Python 3.9.2. and switchbot-mqtt 4.4.0a0 and got pySwitchbot 0.40.1.

I know4.0.0a0 is a pre-release, and you may be interested in my findings:

It is working well when used in a normal way (including the device info).

I see one (reproducible) crash that occurs when OPEN/CLOSE commands are being sent quickly after one another:

  File "/usr/local/lib/python3.9/dist-packages/switchbot/devices/curtain.py", line 99, in get_basic_info
    _position = max(min(_data[6], 100), 0)
IndexError: bytearray index out of range

@fphammerle
Copy link
Owner

Thanks for your report! Great to hear that switchbot-mqtt version 4.0.0a0 worked.

Unfortunately, I am unable to investigate the "IndexError: bytearray index out of range" error as I do not own a switchbot curtain device. Might alrighty be fixed in a newer version of pySwitchbot.

@NiekD
Copy link
Author

NiekD commented Jul 10, 2024

I ran into another issue, that hopefully can be solved without having a curtain device at hand.

The issue is, that when the bluetooth signal is disturbed, the switchbot devices tend to disconnect sometimes. If that happens, apparently the bleak_retry_connector tries to reestablish the connection several times. When all attempts fail, it gives up and raises an error.

WoCtn3 (F3:3A:35:29:20:92): Device unexpectedly disconnected; RSSI: -63
WoCtn3 (F3:3A:35:29:20:92): Device unexpectedly disconnected; RSSI: -63
WoCtn3 (F3:3A:35:29:20:92): Device unexpectedly disconnected; RSSI: -63
WoCtn3 (F3:3A:35:29:20:92): Device unexpectedly disconnected; RSSI: -63
WoCtn3 (F3:3A:35:29:20:92): Device unexpectedly disconnected; RSSI: -63
WoCtn3 (F3:3A:35:29:20:92): communication failed; Stopping trying; RSSI: -63
Traceback (most recent call last):
  File "/usr/local/lib/python3.9/dist-packages/bleak_retry_connector/__init__.py", line 343, in establish_connection
    await client.connect(
  File "/usr/local/lib/python3.9/dist-packages/bleak/__init__.py", line 605, in connect
    return await self._backend.connect(**kwargs)
  File "/usr/local/lib/python3.9/dist-packages/bleak/backends/bluezdbus/client.py", line 249, in connect
    assert_reply(reply)
  File "/usr/local/lib/python3.9/dist-packages/bleak/backends/bluezdbus/utils.py", line 22, in assert_reply
    raise BleakDBusError(reply.error_name, reply.body)
bleak.exc.BleakDBusError: [org.bluez.Error.Failed] Software caused connection abort

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

Traceback (most recent call last):
  File "/usr/local/lib/python3.9/dist-packages/switchbot/devices/device.py", line 180, in _send_command
    return await self._send_command_locked(key, command)
  File "/usr/local/lib/python3.9/dist-packages/switchbot/devices/device.py", line 414, in _send_command_locked
    await self._ensure_connected()
  File "/usr/local/lib/python3.9/dist-packages/switchbot/devices/device.py", line 274, in _ensure_connected
    client: BleakClientWithServiceCache = await establish_connection(
  File "/usr/local/lib/python3.9/dist-packages/bleak_retry_connector/__init__.py", line 420, in establish_connection
    _raise_if_needed(name, device.address, exc)
  File "/usr/local/lib/python3.9/dist-packages/bleak_retry_connector/__init__.py", line 319, in _raise_if_needed
    raise BleakConnectionError(msg) from exc
bleak_retry_connector.BleakConnectionError: WoCtn3 (F3:3A:35:29:20:92) - F3:3A:35:29:20:92: Failed to connect: [org.bluez.Error.Failed] Software caused connection abort
Traceback (most recent call last):
  File "/usr/local/lib/python3.9/dist-packages/bleak_retry_connector/__init__.py", line 343, in establish_connection
    await client.connect(
  File "/usr/local/lib/python3.9/dist-packages/bleak/__init__.py", line 605, in connect
    return await self._backend.connect(**kwargs)
  File "/usr/local/lib/python3.9/dist-packages/bleak/backends/bluezdbus/client.py", line 249, in connect
    assert_reply(reply)
  File "/usr/local/lib/python3.9/dist-packages/bleak/backends/bluezdbus/utils.py", line 22, in assert_reply
    raise BleakDBusError(reply.error_name, reply.body)
bleak.exc.BleakDBusError: [org.bluez.Error.Failed] Software caused connection abort

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

Traceback (most recent call last):
  File "/usr/local/bin/switchbot-mqtt", line 8, in <module>
    sys.exit(_main())
  File "/usr/local/lib/python3.9/dist-packages/switchbot_mqtt/_cli.py", line 142, in _main
    asyncio.run(
  File "/usr/lib/python3.9/asyncio/runners.py", line 44, in run
    return loop.run_until_complete(main)
  File "/usr/lib/python3.9/asyncio/base_events.py", line 642, in run_until_complete
    return future.result()
  File "/usr/local/lib/python3.9/dist-packages/switchbot_mqtt/__init__.py", line 128, in _run
    await _listen(
  File "/usr/local/lib/python3.9/dist-packages/switchbot_mqtt/__init__.py", line 55, in _listen
    await callback(
  File "/usr/local/lib/python3.9/dist-packages/switchbot_mqtt/_actors/base.py", line 178, in _mqtt_update_device_info_callback
    await actor._update_and_report_device_info(
  File "/usr/local/lib/python3.9/dist-packages/switchbot_mqtt/_actors/__init__.py", line 193, in _update_and_report_device_info
    await super()._update_and_report_device_info(mqtt_client, mqtt_topic_prefix)
  File "/usr/local/lib/python3.9/dist-packages/switchbot_mqtt/_actors/base.py", line 105, in _update_and_report_device_info
    self._basic_device_info = await self._get_device().get_basic_info()
  File "/usr/local/lib/python3.9/dist-packages/switchbot/devices/curtain.py", line 96, in get_basic_info
    if not (_data := await self._get_basic_info()):
  File "/usr/local/lib/python3.9/dist-packages/switchbot/devices/device.py", line 529, in _get_basic_info
    _data = await self._send_command(
  File "/usr/local/lib/python3.9/dist-packages/switchbot/devices/device.py", line 180, in _send_command
    return await self._send_command_locked(key, command)
  File "/usr/local/lib/python3.9/dist-packages/switchbot/devices/device.py", line 414, in _send_command_locked
    await self._ensure_connected()
  File "/usr/local/lib/python3.9/dist-packages/switchbot/devices/device.py", line 274, in _ensure_connected
    client: BleakClientWithServiceCache = await establish_connection(
  File "/usr/local/lib/python3.9/dist-packages/bleak_retry_connector/__init__.py", line 420, in establish_connection
    _raise_if_needed(name, device.address, exc)
  File "/usr/local/lib/python3.9/dist-packages/bleak_retry_connector/__init__.py", line 319, in _raise_if_needed
    raise BleakConnectionError(msg) from exc
bleak_retry_connector.BleakConnectionError: WoCtn3 (F3:3A:35:29:20:92) - F3:3A:35:29:20:92: Failed to connect: [org.bluez.Error.Failed] Software caused connection abort

This error is not handled by switchbot-mqtt, so the program crashes.

Bluetooth connection failures can and will occur every now and then and imho switchbot-mqtt should keep running then. As it is now, I need to start switchbot-mqtt several times per day, because of these crashes, which is a nuisance, especally when I am not at home.

I asume that the type of switchbot device is not relevant for this issue, and as said, I hope this is something that can be solved, without having a curtain device.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants