0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Mac から BLE REPL で MicroPython を操作すると、

Posted at

動機

MicroPytohn をインストールした Raspberry Pi Pico W を Mac から BLE REPLしようとすると、幾つかのエラーに遭遇しました。
その時の対処法について残しておきます。

ESP32他 の MicroPython でも同様と思われる。

環境 Mac
macOS        14.7.5
Python       3.11.11
upydev       0.4.3
upydevice    0.3.8
packaging    24.2
環境 Raspberry Pi Pico W
MicroPython v1.24.1 on 2024-11-29; Raspberry Pi Pico W with RP2040

BLE REPLするための準備として、

  1. ここの 次の3つのファイルをRaspberry Pi Pico Wに配置しておく
    ble_advertising.py, ble_uart_peripheral.py, ble_uart_repl.py
     

  2. Raspberry Pi Pico Wにて、import ble_uart_repl; ble_uart_repl.start()を実行しておく
    main.pyに書いておけば(リ)ブート時に自動起動される)
     

  3. Mac に upydevをインストールしておく
    pip install upydevを実行)

エラー 1

BLEデバイスの検索にてエラー
% upydev scan -bl
Traceback (most recent call last):
  File "/opt/homebrew/bin/upydev", line 19, in <module>
    from packaging import version
ModuleNotFoundError: No module named 'packaging'

対処法

インストール済みででしたが、アンインストールして再インストールした。
pip install packaging -U ライブラリの最新化で対処できたと思われる)

% pip install packaging

Requirement already satisfied: packaging in /opt/homebrew/lib/python3.11/site-packages (24.0)



% pip uninstall packaging

Found existing installation: packaging 24.0
Uninstalling packaging-24.0:
  Would remove:
    /opt/homebrew/lib/python3.11/site-packages/packaging-24.0.dist-info/*
Proceed (Y/n)? y
  Successfully uninstalled packaging-24.0


  
% pip install packaging  

Collecting packaging
  Downloading packaging-24.2-py3-none-any.whl.metadata (3.2 kB)
Downloading packaging-24.2-py3-none-any.whl (65 kB)
Installing collected packages: packaging
Successfully installed packaging-24.2

エラー 2

BLEデバイスの検索にて再びエラー
% upydev scan -bl        
Bluetooth Low Energy scan:
Scanning...
BleDevice/s found: 3
┏━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃        NAME         ┃                   UUID                   ┃    RSSI    ┃                 Services                 ┃
┣━━━━━━━━━━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╋━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
┃      mpy-repl       ┃   856C4A83-B2D3-339F-8CE2-xxxxxxxxxxxx   ┃    -56     ┃                                          ┃
┣━━━━━━━━━━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╋━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
Traceback (most recent call last):
  File "/opt/homebrew/bin/upydev", line 1034, in <module>
    handle_action(args)
  File "/opt/homebrew/bin/upydev", line 499, in handle_action
    debugging_action(args, unknown_args, command_line=' '.join(sys.argv[1:]),
  File "/opt/homebrew/lib/python3.11/site-packages/upydev/debugging.py", line 1045, in debugging_action
    print('┃{0:^20} ┃ {1:^40} ┃ {2:^10} ┃ {3:^40} ┃'.format(dev.name, dev.address,
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: unsupported format string passed to NoneType.__format__

対処法

上記エラーログにあるdebugging.pyのソースコードを修正した。
(1行追加)

debugging.py#1045(フルパスはエラーログを参照)
+                   if dev.name is None: dev.name = '(None)'
                    print('┃{0:^20} ┃ {1:^40} ┃ {2:^10} ┃ {3:^40} ┃'.format(dev.name, dev.address,
                                                                            int(dev.rssi), ','.join(services)))

これで無事に検索できるようになった。

% upydev scan -bl
Bluetooth Low Energy scan:
Scanning...
BleDevice/s found: 2
┏━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃        NAME         ┃                   UUID                   ┃    RSSI    ┃                 Services                 ┃
┣━━━━━━━━━━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╋━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
┃       (None)        ┃   4256B44A-5C48-2353-4E15-xxxxxxxxxxxx   ┃    -60     ┃                                          ┃
┣━━━━━━━━━━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╋━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
┃      mpy-repl       ┃   856C4A83-B2D3-339F-8CE2-xxxxxxxxxxxx   ┃    -62     ┃                                          ┃
┗━━━━━━━━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┻━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛

エラー 3

BLEデバイスに接続時にエラー
% blerepl -t 856C4A83-B2D3-339F-8CE2-xxxxxxxxxxxx                    
Traceback (most recent call last):
  File "/opt/homebrew/bin/blerepl", line 63, in <module>
    dev.connect(show_servs=args.v, debug=args.v)
  File "/opt/homebrew/lib/python3.11/site-packages/upydevice/bledevice.py", line 1320, in connect
    return self.as_connect(**kargs).result()
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/lib/python3.11/site-packages/unsync/unsync.py", line 144, in result
    return self.concurrent_future.result(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/Cellar/python@3.11/3.11.11/Frameworks/Python.framework/Versions/3.11/lib/python3.11/concurrent/futures/_base.py", line 456, in result
    return self.__get_result()
           ^^^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/Cellar/python@3.11/3.11.11/Frameworks/Python.framework/Versions/3.11/lib/python3.11/concurrent/futures/_base.py", line 401, in __get_result
    raise self._exception
  File "/opt/homebrew/lib/python3.11/site-packages/upydevice/bledevice.py", line 1309, in as_connect
    if hasattr(self.ble_client._peripheral, 'name'):
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'BleakClient' object has no attribute '_peripheral'

対処法

上記エラーログにあるbledevice.pyのソースコードを修正した。
(2行変更、2行追加)

bledevice.py#1305(フルパスはエラーログを参照)
    async def as_connect(self, n_tries=5, show_servs=True, debug=False):
        await self.connect_client(n_tries=n_tries, debug=debug)
        if self.connected:
            self.get_services(log=show_servs)
-           if hasattr(self.ble_client._peripheral, 'name'):
+           if hasattr(self.ble_client, '_peripheral') and hasattr(self.ble_client._peripheral, 'name'):
                if callable(self.ble_client._peripheral.name):
                    self.name = self.ble_client._peripheral.name()
-           else:
+           elif hasattr(self.ble_client, '_device_info') and hasattr(self.ble_client._device_info, 'get'):
                self.name = self.ble_client._device_info.get('Name')
+           else:
+               self.name = '(None)'
            if self.name in _WASPDEVS:
                self.len_buffer = 20
        else:
            raise DeviceNotFound('BleDevice @ {} is not reachable'.format(self.UUID))

これで無事に接続できるようになった。

% blerepl -t 856C4A83-B2D3-339F-8CE2-xxxxxxxxxxxx 
BleREPL connected

MicroPython v1.24.1 on 2024-11-29; Raspberry Pi Pico W with RP2040
Type "help()" for more information.

- CTRL-k to see keybindings or -h to see help
- CTRL-s to toggle shell/repl mode
- CTRL-x or "exit" to exit
rp2@e66138528394892c:~ $ (Ctrl+S)
>>> import sys
>>> sys.version
'3.4.0; MicroPython v1.24.1 on 2024-11-29'
>>> (Ctrl+X)
>>> closing...
>>>
logout
Connection to (None) closed.
% 

しかし、

これで BLE REPL できるようになったが、まだ次のエラーが出る。

エラー 4

BLEデバイスの検索にてエラー
% upydev scan -bl
Bluetooth Low Energy scan:
Scanning...
BleDevice/s found: 1
┏━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃        NAME         ┃                   UUID                   ┃    RSSI    ┃                 Services                 ┃
┣━━━━━━━━━━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╋━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
/opt/homebrew/lib/python3.11/site-packages/upydev/debugging.py:1036: FutureWarning: BLEDevice.metadata is deprecated and will be removed in a future version of Bleak, use AdvertisementData instead
  if hasattr(dev, 'metadata'):
/opt/homebrew/lib/python3.11/site-packages/upydev/debugging.py:1037: FutureWarning: BLEDevice.metadata is deprecated and will be removed in a future version of Bleak, use AdvertisementData instead
  if isinstance(dev.metadata, dict):
/opt/homebrew/lib/python3.11/site-packages/upydev/debugging.py:1038: FutureWarning: BLEDevice.metadata is deprecated and will be removed in a future version of Bleak, use AdvertisementData instead
  if 'uuids' in dev.metadata.keys():
/opt/homebrew/lib/python3.11/site-packages/upydev/debugging.py:1041: FutureWarning: BLEDevice.metadata is deprecated and will be removed in a future version of Bleak, use AdvertisementData instead
  for serv in dev.metadata['uuids']]
/opt/homebrew/lib/python3.11/site-packages/upydev/debugging.py:1048: FutureWarning: BLEDevice.rssi is deprecated and will be removed in a future version of Bleak, use AdvertisementData.rssi instead
  int(dev.rssi), ','.join(services)))

ググってみたが、有効な対処法が見つからず。
致命傷では無いので とりあえずスルー。

エラー 5

⭐️ REPLCtrl+D すると例外が発生する。

BLE REPL でエラー
% blerepl -t 856C4A83-B2D3-339F-8CE2-xxxxxxxxxxxx                
BleREPL connected

MicroPython v1.24.1 on 2024-11-29; Raspberry Pi Pico W with RP2040
Type "help()" for more information.

- CTRL-k to see keybindings or -h to see help
- CTRL-s to toggle shell/repl mode
- CTRL-x or "exit" to exit
rp2@e66138528394892c:~ $ (Ctrl+S)
>>> (Ctrl+D) ⭐️

Unhandled exception in event loop:
  File "/opt/homebrew/Cellar/python@3.11/3.11.11/Frameworks/Python.framework/Versions/3.11/lib/python3.11/asyncio/events.py", line 84, in _run
    self._context.run(self._callback, *self._args)
  File "/opt/homebrew/lib/python3.11/site-packages/prompt_toolkit/input/vt100.py", line 162, in callback_wrapper
    callback()
  File "/opt/homebrew/lib/python3.11/site-packages/prompt_toolkit/application/application.py", line 714, in read_from_input_in_context
    context.copy().run(read_from_input)
  File "/opt/homebrew/lib/python3.11/site-packages/prompt_toolkit/application/application.py", line 694, in read_from_input
    self.key_processor.process_keys()
  File "/opt/homebrew/lib/python3.11/site-packages/prompt_toolkit/key_binding/key_processor.py", line 273, in process_keys
    self._process_coroutine.send(key_press)
  File "/opt/homebrew/lib/python3.11/site-packages/prompt_toolkit/key_binding/key_processor.py", line 188, in _process
    self._call_handler(matches[-1], key_sequence=buffer[:])
  File "/opt/homebrew/lib/python3.11/site-packages/prompt_toolkit/key_binding/key_processor.py", line 323, in _call_handler
    handler.call(event)
  File "/opt/homebrew/lib/python3.11/site-packages/prompt_toolkit/key_binding/key_bindings.py", line 127, in call
    result = self.handler(event)
             ^^^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/lib/python3.11/site-packages/upydev/shell/keybindings.py", line 766, in paste_mode_exit
    dev.reset()
  File "/opt/homebrew/lib/python3.11/site-packages/upydevice/bledevice.py", line 1558, in reset
    return self.un_reset(**kargs).result()
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/lib/python3.11/site-packages/unsync/unsync.py", line 144, in result
    return self.concurrent_future.result(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/Cellar/python@3.11/3.11.11/Frameworks/Python.framework/Versions/3.11/lib/python3.11/concurrent/futures/_base.py", line 456, in result
    return self.__get_result()
           ^^^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/Cellar/python@3.11/3.11.11/Frameworks/Python.framework/Versions/3.11/lib/python3.11/concurrent/futures/_base.py", line 401, in __get_result
    raise self._exception
  File "/opt/homebrew/lib/python3.11/site-packages/upydevice/bledevice.py", line 1553, in un_reset
    await self.as_reset(**kargs)
  File "/opt/homebrew/lib/python3.11/site-packages/upydevice/bledevice.py", line 750, in as_reset
    await self.as_write_char(self.writeables['Nordic UART RX'],
  File "/opt/homebrew/lib/python3.11/site-packages/upydevice/bledevice.py", line 399, in as_write_char
    await self.ble_client.write_gatt_char(uuid, data)
  File "/opt/homebrew/lib/python3.11/site-packages/bleak/__init__.py", line 786, in write_gatt_char
    await self._backend.write_gatt_char(characteristic, data, response)
  File "/opt/homebrew/lib/python3.11/site-packages/bleak/backends/corebluetooth/client.py", line 326, in write_gatt_char
    await self._delegate.write_characteristic(
  File "/opt/homebrew/lib/python3.11/site-packages/bleak/backends/corebluetooth/PeripheralDelegate.py", line 196, in write_characteristic
    await future

Exception disconnected
Press ENTER to continue...

同時に、Raspberry Pi Pico W は リセット(ソフトブート)される。

Raspberry Pi Pico W
>>>
MPY: soft reboot
Unhandled exception in IRQ callback handler
Traceback (most recent call last):
  File "/lib/ble_uart_peripheral.py", line 66, in _irq
  File "/lib/ble_uart_peripheral.py", line 94, in _advertise
OSError: [Errno 19] ENODEV
MicroPython v1.24.1 on 2024-11-29; Raspberry Pi Pico W with RP2040
Type "help()" for more information.
>>> 

原因は、
REPL で Ctrl+D すると ソフトブートされる。これは正しい動作
⇨ ブートにより、BLE通信が切断される
⇨ Mac側のblereplコマンドで例外が発生

REPL でCtrl+Dしなければ問題ない。

以上

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?