diff --git a/ch-13/1-modelling-space/computer/display_arena_from_robot.py b/ch-13/1-modelling-space/computer/display_arena_from_robot.py index 0236def..9b7a6eb 100644 --- a/ch-13/1-modelling-space/computer/display_arena_from_robot.py +++ b/ch-13/1-modelling-space/computer/display_arena_from_robot.py @@ -7,15 +7,14 @@ from robot_ble_connection import BleConnection class RobotDisplay: - def __init__(self, ble_connection: BleConnection): + def __init__(self): self.fig, self.ax = plt.subplots() - self.ble_connection = ble_connection + self.ble_connection = BleConnection(self.handle_data, self.connected) + self.arena = None self.display_closed = False # handle closed event self.fig.canvas.mpl_connect("close_event", self.handle_close) - ble_connection.receive_handler = self.handle_data - ble_connection.connected_handler = self.connected self.line = "" def handle_close(self, _): @@ -49,20 +48,16 @@ class RobotDisplay: print(f"Sending request for arena: {request}") self.ble_connection.send_uart_data(request) + async def main(self): + plt.ion() -async def main(): - - plt.ion() + asyncio.create_task(self.ble_connection.connect()) + while not self.display_closed: + plt.pause(0.05) + plt.draw() + await asyncio.sleep(0.01) + + plt.show() - ble_connection = BleConnection() - robot_display = RobotDisplay(ble_connection) - asyncio.create_task(ble_connection.connect()) - while not robot_display.display_closed: - plt.pause(0.05) - plt.draw() - await asyncio.sleep(0.01) - - plt.show() - - -asyncio.run(main()) +robot_display = RobotDisplay() +asyncio.run(robot_display.main()) diff --git a/ch-13/1-modelling-space/computer/find_devices.py b/ch-13/1-modelling-space/computer/find_devices.py index ab7f96d..829f62c 100644 --- a/ch-13/1-modelling-space/computer/find_devices.py +++ b/ch-13/1-modelling-space/computer/find_devices.py @@ -1,8 +1,13 @@ import asyncio -from robot_ble_connection import BleConnection +import bleak async def run(): - ble_connection = BleConnection() - await ble_connection.connect() + ble_uuid = "6E400001-B5A3-F393-E0A9-E50E24DCCA9E" + ble_name = "Adafruit Bluefruit LE" + devices = await bleak.BleakScanner.discover(service_uuids=[ble_uuid]) + print(f"Found {len(devices)} devices") + print([device.name for device in devices]) + ble_device_info = [device for device in devices if device.name==ble_name][0] + print("Found robot {}...".format(ble_device_info.name)) asyncio.run(run()) diff --git a/ch-13/1-modelling-space/computer/poetry.lock b/ch-13/1-modelling-space/computer/poetry.lock index 9d90003..1a2c130 100644 --- a/ch-13/1-modelling-space/computer/poetry.lock +++ b/ch-13/1-modelling-space/computer/poetry.lock @@ -6,6 +6,28 @@ category = "main" optional = false python-versions = ">=3.6" +[[package]] +name = "black" +version = "22.10.0" +description = "The uncompromising code formatter." +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +click = ">=8.0.0" +mypy-extensions = ">=0.4.3" +pathspec = ">=0.9.0" +platformdirs = ">=2" +tomli = {version = ">=1.1.0", markers = "python_full_version < \"3.11.0a7\""} +typing-extensions = {version = ">=3.10.0.0", markers = "python_version < \"3.10\""} + +[package.extras] +colorama = ["colorama (>=0.4.3)"] +d = ["aiohttp (>=3.7.4)"] +jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] +uvloop = ["uvloop (>=0.15.2)"] + [[package]] name = "bleak" version = "0.19.0" @@ -30,6 +52,25 @@ category = "main" optional = false python-versions = "*" +[[package]] +name = "click" +version = "8.1.3" +description = "Composable command line interface toolkit" +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +colorama = {version = "*", markers = "platform_system == \"Windows\""} + +[[package]] +name = "colorama" +version = "0.4.6" +description = "Cross-platform colored terminal text." +category = "dev" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" + [[package]] name = "contourpy" version = "1.0.6" @@ -117,6 +158,14 @@ pyparsing = ">=2.2.1" python-dateutil = ">=2.7" setuptools_scm = ">=7" +[[package]] +name = "mypy-extensions" +version = "0.4.3" +description = "Experimental type system extensions for programs checked with the mypy typechecker." +category = "dev" +optional = false +python-versions = "*" + [[package]] name = "numpy" version = "1.23.4" @@ -136,6 +185,14 @@ python-versions = ">=3.6" [package.dependencies] pyparsing = ">=2.0.2,<3.0.5 || >3.0.5" +[[package]] +name = "pathspec" +version = "0.10.1" +description = "Utility library for gitignore style pattern matching of file paths." +category = "dev" +optional = false +python-versions = ">=3.7" + [[package]] name = "Pillow" version = "9.3.0" @@ -148,6 +205,18 @@ python-versions = ">=3.7" docs = ["furo", "olefile", "sphinx (>=2.4)", "sphinx-copybutton", "sphinx-issues (>=3.0.1)", "sphinx-removed-in", "sphinxext-opengraph"] tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout"] +[[package]] +name = "platformdirs" +version = "2.5.2" +description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.extras] +docs = ["furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx (>=4)", "sphinx-autodoc-typehints (>=1.12)"] +test = ["appdirs (==1.4.4)", "pytest (>=6)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)"] + [[package]] name = "pyobjc-core" version = "8.5.1" @@ -270,13 +339,36 @@ python-versions = ">=3.7" [metadata] lock-version = "1.1" python-versions = "^3.9" -content-hash = "727473570c922b0886d57e696aae6126808af34ee62e8a011dbddb4da4991b9d" +content-hash = "4ec6eb3464cbb49afad347e67bdf7c353d7ea4030fd8ed4257098a5df334eb99" [metadata.files] async-timeout = [ {file = "async-timeout-4.0.2.tar.gz", hash = "sha256:2163e1640ddb52b7a8c80d0a67a08587e5d245cc9c553a74a847056bc2976b15"}, {file = "async_timeout-4.0.2-py3-none-any.whl", hash = "sha256:8ca1e4fcf50d07413d66d1a5e416e42cfdf5851c981d679a09851a6853383b3c"}, ] +black = [ + {file = "black-22.10.0-1fixedarch-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:5cc42ca67989e9c3cf859e84c2bf014f6633db63d1cbdf8fdb666dcd9e77e3fa"}, + {file = "black-22.10.0-1fixedarch-cp311-cp311-macosx_11_0_x86_64.whl", hash = "sha256:5d8f74030e67087b219b032aa33a919fae8806d49c867846bfacde57f43972ef"}, + {file = "black-22.10.0-1fixedarch-cp37-cp37m-macosx_10_16_x86_64.whl", hash = "sha256:197df8509263b0b8614e1df1756b1dd41be6738eed2ba9e9769f3880c2b9d7b6"}, + {file = "black-22.10.0-1fixedarch-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:2644b5d63633702bc2c5f3754b1b475378fbbfb481f62319388235d0cd104c2d"}, + {file = "black-22.10.0-1fixedarch-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:e41a86c6c650bcecc6633ee3180d80a025db041a8e2398dcc059b3afa8382cd4"}, + {file = "black-22.10.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2039230db3c6c639bd84efe3292ec7b06e9214a2992cd9beb293d639c6402edb"}, + {file = "black-22.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14ff67aec0a47c424bc99b71005202045dc09270da44a27848d534600ac64fc7"}, + {file = "black-22.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:819dc789f4498ecc91438a7de64427c73b45035e2e3680c92e18795a839ebb66"}, + {file = "black-22.10.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5b9b29da4f564ba8787c119f37d174f2b69cdfdf9015b7d8c5c16121ddc054ae"}, + {file = "black-22.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8b49776299fece66bffaafe357d929ca9451450f5466e997a7285ab0fe28e3b"}, + {file = "black-22.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:21199526696b8f09c3997e2b4db8d0b108d801a348414264d2eb8eb2532e540d"}, + {file = "black-22.10.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1e464456d24e23d11fced2bc8c47ef66d471f845c7b7a42f3bd77bf3d1789650"}, + {file = "black-22.10.0-cp37-cp37m-win_amd64.whl", hash = "sha256:9311e99228ae10023300ecac05be5a296f60d2fd10fff31cf5c1fa4ca4b1988d"}, + {file = "black-22.10.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:fba8a281e570adafb79f7755ac8721b6cf1bbf691186a287e990c7929c7692ff"}, + {file = "black-22.10.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:915ace4ff03fdfff953962fa672d44be269deb2eaf88499a0f8805221bc68c87"}, + {file = "black-22.10.0-cp38-cp38-win_amd64.whl", hash = "sha256:444ebfb4e441254e87bad00c661fe32df9969b2bf224373a448d8aca2132b395"}, + {file = "black-22.10.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:974308c58d057a651d182208a484ce80a26dac0caef2895836a92dd6ebd725e0"}, + {file = "black-22.10.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72ef3925f30e12a184889aac03d77d031056860ccae8a1e519f6cbb742736383"}, + {file = "black-22.10.0-cp39-cp39-win_amd64.whl", hash = "sha256:432247333090c8c5366e69627ccb363bc58514ae3e63f7fc75c54b1ea80fa7de"}, + {file = "black-22.10.0-py3-none-any.whl", hash = "sha256:c957b2b4ea88587b46cf49d1dc17681c1e672864fd7af32fc1e9664d572b3458"}, + {file = "black-22.10.0.tar.gz", hash = "sha256:f513588da599943e0cde4e32cc9879e825d58720d6557062d1098c5ad80080e1"}, +] bleak = [ {file = "bleak-0.19.0-py3-none-any.whl", hash = "sha256:ccdba0d17dcceb1326e4e46600b37e9019cd52ce01948e2a3dbd6c94d1e4de01"}, {file = "bleak-0.19.0.tar.gz", hash = "sha256:cce5200ca9bac7daaa74dd009c867c8c2b161a124e234c74307462e86caf50e6"}, @@ -294,6 +386,14 @@ bleak-winrt = [ {file = "bleak_winrt-1.2.0-cp39-cp39-win32.whl", hash = "sha256:dd740047a08925bde54bec357391fcee595d7b8ca0c74c87170a5cbc3f97aa0a"}, {file = "bleak_winrt-1.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:63130c11acfe75c504a79c01f9919e87f009f5e742bfc7b7a5c2a9c72bf591a7"}, ] +click = [ + {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"}, + {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"}, +] +colorama = [ + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, +] contourpy = [ {file = "contourpy-1.0.6-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:613c665529899b5d9fade7e5d1760111a0b011231277a0d36c49f0d3d6914bd6"}, {file = "contourpy-1.0.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:78ced51807ccb2f45d4ea73aca339756d75d021069604c2fccd05390dc3c28eb"}, @@ -516,6 +616,10 @@ matplotlib = [ {file = "matplotlib-3.6.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:5f97141e05baf160c3ec125f06ceb2a44c9bb62f42fcb8ee1c05313c73e99432"}, {file = "matplotlib-3.6.1.tar.gz", hash = "sha256:e2d1b7225666f7e1bcc94c0bc9c587a82e3e8691da4757e357e5c2515222ee37"}, ] +mypy-extensions = [ + {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, + {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, +] numpy = [ {file = "numpy-1.23.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:95d79ada05005f6f4f337d3bb9de8a7774f259341c70bc88047a1f7b96a4bcb2"}, {file = "numpy-1.23.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:926db372bc4ac1edf81cfb6c59e2a881606b409ddc0d0920b988174b2e2a767f"}, @@ -550,6 +654,10 @@ packaging = [ {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"}, {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"}, ] +pathspec = [ + {file = "pathspec-0.10.1-py3-none-any.whl", hash = "sha256:46846318467efc4556ccfd27816e004270a9eeeeb4d062ce5e6fc7a87c573f93"}, + {file = "pathspec-0.10.1.tar.gz", hash = "sha256:7ace6161b621d31e7902eb6b5ae148d12cfd23f4a249b9ffb6b9fee12084323d"}, +] Pillow = [ {file = "Pillow-9.3.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:0b7257127d646ff8676ec8a15520013a698d1fdc48bc2a79ba4e53df792526f2"}, {file = "Pillow-9.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b90f7616ea170e92820775ed47e136208e04c967271c9ef615b6fbd08d9af0e3"}, @@ -611,6 +719,10 @@ Pillow = [ {file = "Pillow-9.3.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:073adb2ae23431d3b9bcbcff3fe698b62ed47211d0716b067385538a1b0f28b8"}, {file = "Pillow-9.3.0.tar.gz", hash = "sha256:c935a22a557a560108d780f9a0fc426dd7459940dc54faa49d83249c8d3e760f"}, ] +platformdirs = [ + {file = "platformdirs-2.5.2-py3-none-any.whl", hash = "sha256:027d8e83a2d7de06bbac4e5ef7e023c02b863d7ea5d079477e722bb41ab25788"}, + {file = "platformdirs-2.5.2.tar.gz", hash = "sha256:58c8abb07dcb441e6ee4b11d8df0ac856038f944ab98b7be6b27b2a3c7feef19"}, +] pyobjc-core = [ {file = "pyobjc-core-8.5.1.tar.gz", hash = "sha256:f8592a12de076c27006700c4a46164478564fa33d7da41e7cbdd0a3bf9ddbccf"}, {file = "pyobjc_core-8.5.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:b62dcf987cc511188fc2aa5b4d3b9fd895361ea4984380463497ce4b0752ddf4"}, diff --git a/ch-13/1-modelling-space/computer/pyproject.toml b/ch-13/1-modelling-space/computer/pyproject.toml index f829dbc..e5ac640 100644 --- a/ch-13/1-modelling-space/computer/pyproject.toml +++ b/ch-13/1-modelling-space/computer/pyproject.toml @@ -13,6 +13,9 @@ numpy = "1.23.4" bleak = "0.19.0" +[tool.poetry.group.dev.dependencies] +black = "^22.10.0" + [build-system] requires = ["poetry-core"] build-backend = "poetry.core.masonry.api" diff --git a/ch-13/1-modelling-space/computer/robot_ble_connection.py b/ch-13/1-modelling-space/computer/robot_ble_connection.py index 0fbb72d..61674b4 100644 --- a/ch-13/1-modelling-space/computer/robot_ble_connection.py +++ b/ch-13/1-modelling-space/computer/robot_ble_connection.py @@ -11,30 +11,25 @@ class BleConnection: adafruit_tx_uuid = "6E400002-B5A3-F393-E0A9-E50E24DCCA9E" ble_name = "Adafruit Bluefruit LE" - def __init__(self, receive_handler: typing.Callable[[bytes], None] = None, - connected_handler: typing.Callable[[], None] = None): + def __init__(self, receive_handler: typing.Callable[[bytes], None], + connected_handler: typing.Callable[[], None]): self.ble_client : bleak.BleakClient = None - # receive_handler(bytes) -> None self.receive_handler = receive_handler - # connected_handler() -> None self.connected_handler = connected_handler def _uart_handler(self, _, data: bytes): - # hmm - not receiving the whole message, only parts of it... - if self.receive_handler: - self.receive_handler(data) + self.receive_handler(data) async def connect(self): print("Scanning for devices...") devices = await bleak.BleakScanner.discover(service_uuids=[self.ble_uuid]) - print("Found {} devices".format(len(devices))) - print([device.name for device in devices]) + print(f"Found {len(devices)} devices") + print([device.name for device in devices]) ble_device_info = [device for device in devices if device.name==self.ble_name][0] print("Connecting to {}...".format(ble_device_info.name)) async with bleak.BleakClient(ble_device_info.address) as ble_client: self.ble_client = ble_client - if self.connected_handler: - self.connected_handler() + self.connected_handler() print("Connected to {}".format(ble_device_info.name)) asyncio.create_task( self.ble_client.start_notify(self.adafruit_rx_uuid, self._uart_handler) diff --git a/ch-13/arena.FCStd b/ch-13/arena.FCStd index 7a7dc18..912fda8 100644 Binary files a/ch-13/arena.FCStd and b/ch-13/arena.FCStd differ