diff --git a/README.md b/README.md index d90329d..9b59799 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ [![PyPI Releases][img_pypi]][url_pypi] [![Supported Python Versions][img_pyversions]][url_pyversions] -[img_version]: https://img.shields.io/static/v1.svg?label=SemVer&message=0.0.1&color=blue +[img_version]: https://img.shields.io/static/v1.svg?label=SemVer&message=0.4.0&color=blue [url_version]: https://pypi.org/project/pymammotion/ [img_pypi]: https://img.shields.io/badge/PyPI-wheels-green.svg diff --git a/poetry.lock b/poetry.lock index 2ed9f17..50f0bd7 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. [[package]] name = "aiohttp" @@ -242,12 +242,12 @@ requests = ">=2.21.0,<3.0.0" [[package]] name = "alibabacloud-tea-util" -version = "0.3.12" +version = "0.3.13" description = "The tea-util module of alibabaCloud Python SDK." optional = false python-versions = ">=3.6" files = [ - {file = "alibabacloud_tea_util-0.3.12.tar.gz", hash = "sha256:72a2f5a046e5b977ade4202eb4f65b3d70ad707a548e29aacd4a572c2d18d06b"}, + {file = "alibabacloud_tea_util-0.3.13.tar.gz", hash = "sha256:8cbdfd2a03fbbf622f901439fa08643898290dd40e1d928347f6346e43f63c90"}, ] [package.dependencies] @@ -331,13 +331,13 @@ aliyun-python-sdk-core = ">=2.11.5" [[package]] name = "astroid" -version = "3.2.2" +version = "3.2.4" description = "An abstract syntax tree for Python with inference support." optional = false python-versions = ">=3.8.0" files = [ - {file = "astroid-3.2.2-py3-none-any.whl", hash = "sha256:e8a0083b4bb28fcffb6207a3bfc9e5d0a68be951dd7e336d5dcf639c682388c0"}, - {file = "astroid-3.2.2.tar.gz", hash = "sha256:8ead48e31b92b2e217b6c9733a21afafe479d52d6e164dd25fb1a770c7c3cf94"}, + {file = "astroid-3.2.4-py3-none-any.whl", hash = "sha256:413658a61eeca6202a59231abb473f932038fbcbf1666587f66d482083413a25"}, + {file = "astroid-3.2.4.tar.gz", hash = "sha256:0e14202810b30da1b735827f78f5157be2bbd4a7a59b7707ca0bfc2fb4c0063a"}, ] [[package]] @@ -725,43 +725,38 @@ files = [ [[package]] name = "cryptography" -version = "42.0.8" +version = "43.0.0" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." optional = false python-versions = ">=3.7" files = [ - {file = "cryptography-42.0.8-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:81d8a521705787afe7a18d5bfb47ea9d9cc068206270aad0b96a725022e18d2e"}, - {file = "cryptography-42.0.8-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:961e61cefdcb06e0c6d7e3a1b22ebe8b996eb2bf50614e89384be54c48c6b63d"}, - {file = "cryptography-42.0.8-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e3ec3672626e1b9e55afd0df6d774ff0e953452886e06e0f1eb7eb0c832e8902"}, - {file = "cryptography-42.0.8-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e599b53fd95357d92304510fb7bda8523ed1f79ca98dce2f43c115950aa78801"}, - {file = "cryptography-42.0.8-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:5226d5d21ab681f432a9c1cf8b658c0cb02533eece706b155e5fbd8a0cdd3949"}, - {file = "cryptography-42.0.8-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:6b7c4f03ce01afd3b76cf69a5455caa9cfa3de8c8f493e0d3ab7d20611c8dae9"}, - {file = "cryptography-42.0.8-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:2346b911eb349ab547076f47f2e035fc8ff2c02380a7cbbf8d87114fa0f1c583"}, - {file = "cryptography-42.0.8-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:ad803773e9df0b92e0a817d22fd8a3675493f690b96130a5e24f1b8fabbea9c7"}, - {file = "cryptography-42.0.8-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:2f66d9cd9147ee495a8374a45ca445819f8929a3efcd2e3df6428e46c3cbb10b"}, - {file = "cryptography-42.0.8-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:d45b940883a03e19e944456a558b67a41160e367a719833c53de6911cabba2b7"}, - {file = "cryptography-42.0.8-cp37-abi3-win32.whl", hash = "sha256:a0c5b2b0585b6af82d7e385f55a8bc568abff8923af147ee3c07bd8b42cda8b2"}, - {file = "cryptography-42.0.8-cp37-abi3-win_amd64.whl", hash = "sha256:57080dee41209e556a9a4ce60d229244f7a66ef52750f813bfbe18959770cfba"}, - {file = "cryptography-42.0.8-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:dea567d1b0e8bc5764b9443858b673b734100c2871dc93163f58c46a97a83d28"}, - {file = "cryptography-42.0.8-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4783183f7cb757b73b2ae9aed6599b96338eb957233c58ca8f49a49cc32fd5e"}, - {file = "cryptography-42.0.8-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a0608251135d0e03111152e41f0cc2392d1e74e35703960d4190b2e0f4ca9c70"}, - {file = "cryptography-42.0.8-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:dc0fdf6787f37b1c6b08e6dfc892d9d068b5bdb671198c72072828b80bd5fe4c"}, - {file = "cryptography-42.0.8-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:9c0c1716c8447ee7dbf08d6db2e5c41c688544c61074b54fc4564196f55c25a7"}, - {file = "cryptography-42.0.8-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:fff12c88a672ab9c9c1cf7b0c80e3ad9e2ebd9d828d955c126be4fd3e5578c9e"}, - {file = "cryptography-42.0.8-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:cafb92b2bc622cd1aa6a1dce4b93307792633f4c5fe1f46c6b97cf67073ec961"}, - {file = "cryptography-42.0.8-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:31f721658a29331f895a5a54e7e82075554ccfb8b163a18719d342f5ffe5ecb1"}, - {file = "cryptography-42.0.8-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:b297f90c5723d04bcc8265fc2a0f86d4ea2e0f7ab4b6994459548d3a6b992a14"}, - {file = "cryptography-42.0.8-cp39-abi3-win32.whl", hash = "sha256:2f88d197e66c65be5e42cd72e5c18afbfae3f741742070e3019ac8f4ac57262c"}, - {file = "cryptography-42.0.8-cp39-abi3-win_amd64.whl", hash = "sha256:fa76fbb7596cc5839320000cdd5d0955313696d9511debab7ee7278fc8b5c84a"}, - {file = "cryptography-42.0.8-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:ba4f0a211697362e89ad822e667d8d340b4d8d55fae72cdd619389fb5912eefe"}, - {file = "cryptography-42.0.8-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:81884c4d096c272f00aeb1f11cf62ccd39763581645b0812e99a91505fa48e0c"}, - {file = "cryptography-42.0.8-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c9bb2ae11bfbab395bdd072985abde58ea9860ed84e59dbc0463a5d0159f5b71"}, - {file = "cryptography-42.0.8-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:7016f837e15b0a1c119d27ecd89b3515f01f90a8615ed5e9427e30d9cdbfed3d"}, - {file = "cryptography-42.0.8-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5a94eccb2a81a309806027e1670a358b99b8fe8bfe9f8d329f27d72c094dde8c"}, - {file = "cryptography-42.0.8-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:dec9b018df185f08483f294cae6ccac29e7a6e0678996587363dc352dc65c842"}, - {file = "cryptography-42.0.8-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:343728aac38decfdeecf55ecab3264b015be68fc2816ca800db649607aeee648"}, - {file = "cryptography-42.0.8-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:013629ae70b40af70c9a7a5db40abe5d9054e6f4380e50ce769947b73bf3caad"}, - {file = "cryptography-42.0.8.tar.gz", hash = "sha256:8d09d05439ce7baa8e9e95b07ec5b6c886f548deb7e0f69ef25f64b3bce842f2"}, + {file = "cryptography-43.0.0-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:64c3f16e2a4fc51c0d06af28441881f98c5d91009b8caaff40cf3548089e9c74"}, + {file = "cryptography-43.0.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3dcdedae5c7710b9f97ac6bba7e1052b95c7083c9d0e9df96e02a1932e777895"}, + {file = "cryptography-43.0.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d9a1eca329405219b605fac09ecfc09ac09e595d6def650a437523fcd08dd22"}, + {file = "cryptography-43.0.0-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:ea9e57f8ea880eeea38ab5abf9fbe39f923544d7884228ec67d666abd60f5a47"}, + {file = "cryptography-43.0.0-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:9a8d6802e0825767476f62aafed40532bd435e8a5f7d23bd8b4f5fd04cc80ecf"}, + {file = "cryptography-43.0.0-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:cc70b4b581f28d0a254d006f26949245e3657d40d8857066c2ae22a61222ef55"}, + {file = "cryptography-43.0.0-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:4a997df8c1c2aae1e1e5ac49c2e4f610ad037fc5a3aadc7b64e39dea42249431"}, + {file = "cryptography-43.0.0-cp37-abi3-win32.whl", hash = "sha256:6e2b11c55d260d03a8cf29ac9b5e0608d35f08077d8c087be96287f43af3ccdc"}, + {file = "cryptography-43.0.0-cp37-abi3-win_amd64.whl", hash = "sha256:31e44a986ceccec3d0498e16f3d27b2ee5fdf69ce2ab89b52eaad1d2f33d8778"}, + {file = "cryptography-43.0.0-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:7b3f5fe74a5ca32d4d0f302ffe6680fcc5c28f8ef0dc0ae8f40c0f3a1b4fca66"}, + {file = "cryptography-43.0.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac1955ce000cb29ab40def14fd1bbfa7af2017cca696ee696925615cafd0dce5"}, + {file = "cryptography-43.0.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:299d3da8e00b7e2b54bb02ef58d73cd5f55fb31f33ebbf33bd00d9aa6807df7e"}, + {file = "cryptography-43.0.0-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:ee0c405832ade84d4de74b9029bedb7b31200600fa524d218fc29bfa371e97f5"}, + {file = "cryptography-43.0.0-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:cb013933d4c127349b3948aa8aaf2f12c0353ad0eccd715ca789c8a0f671646f"}, + {file = "cryptography-43.0.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:fdcb265de28585de5b859ae13e3846a8e805268a823a12a4da2597f1f5afc9f0"}, + {file = "cryptography-43.0.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:2905ccf93a8a2a416f3ec01b1a7911c3fe4073ef35640e7ee5296754e30b762b"}, + {file = "cryptography-43.0.0-cp39-abi3-win32.whl", hash = "sha256:47ca71115e545954e6c1d207dd13461ab81f4eccfcb1345eac874828b5e3eaaf"}, + {file = "cryptography-43.0.0-cp39-abi3-win_amd64.whl", hash = "sha256:0663585d02f76929792470451a5ba64424acc3cd5227b03921dab0e2f27b1709"}, + {file = "cryptography-43.0.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:2c6d112bf61c5ef44042c253e4859b3cbbb50df2f78fa8fae6747a7814484a70"}, + {file = "cryptography-43.0.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:844b6d608374e7d08f4f6e6f9f7b951f9256db41421917dfb2d003dde4cd6b66"}, + {file = "cryptography-43.0.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:51956cf8730665e2bdf8ddb8da0056f699c1a5715648c1b0144670c1ba00b48f"}, + {file = "cryptography-43.0.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:aae4d918f6b180a8ab8bf6511a419473d107df4dbb4225c7b48c5c9602c38c7f"}, + {file = "cryptography-43.0.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:232ce02943a579095a339ac4b390fbbe97f5b5d5d107f8a08260ea2768be8cc2"}, + {file = "cryptography-43.0.0-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:5bcb8a5620008a8034d39bce21dc3e23735dfdb6a33a06974739bfa04f853947"}, + {file = "cryptography-43.0.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:08a24a7070b2b6804c1940ff0f910ff728932a9d0e80e7814234269f9d46d069"}, + {file = "cryptography-43.0.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:e9c5266c432a1e23738d178e51c2c7a5e2ddf790f248be939448c0ba2021f9d1"}, + {file = "cryptography-43.0.0.tar.gz", hash = "sha256:b88075ada2d51aa9f18283532c9f60e72170041bba88d7f37e49cbb10275299e"}, ] [package.dependencies] @@ -774,7 +769,7 @@ nox = ["nox"] pep8test = ["check-sdist", "click", "mypy", "ruff"] sdist = ["build"] ssh = ["bcrypt (>=3.1.5)"] -test = ["certifi", "pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-xdist"] +test = ["certifi", "cryptography-vectors (==43.0.0)", "pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-xdist"] test-randomorder = ["pytest-randomly"] [[package]] @@ -869,34 +864,34 @@ typing = ["typing-extensions (>=4.8)"] [[package]] name = "frida" -version = "16.4.2" +version = "16.4.5" description = "Dynamic instrumentation toolkit for developers, reverse-engineers, and security researchers" optional = false python-versions = ">=3.7" files = [ - {file = "frida-16.4.2-cp37-abi3-macosx_10_13_x86_64.whl", hash = "sha256:dce52c90de65a798213e06ee47b9cc4f0867beebc30dba57e18a2049e14ee48e"}, - {file = "frida-16.4.2-cp37-abi3-macosx_11_0_arm64.whl", hash = "sha256:5836e3c7aec8c343b6214ae0ba24a7f93b682d91d2f8f1081486d0e6e05b650d"}, - {file = "frida-16.4.2-cp37-abi3-manylinux1_i686.whl", hash = "sha256:cb8f7e3f5a59412bedec778f02b5c3ae97496e53208464136e9aa2259104c43b"}, - {file = "frida-16.4.2-cp37-abi3-manylinux1_x86_64.whl", hash = "sha256:4f23120df6699959ef841bb8857567b0448ca51ba6f379e7ea28192bc69be5fb"}, - {file = "frida-16.4.2-cp37-abi3-manylinux2014_aarch64.whl", hash = "sha256:ea5d725d5cb9ace25e6937188f0bf8e3cfb4f9808996b221fe935c2e3eaad0e1"}, - {file = "frida-16.4.2-cp37-abi3-manylinux2014_armv7l.whl", hash = "sha256:b89cbdc35fe8965df33c65a6cd2caeb79df995400cb2d6b71b355d44100c56eb"}, - {file = "frida-16.4.2-cp37-abi3-manylinux_2_17_aarch64.whl", hash = "sha256:a70df120e7489539028156dd4f205a62746408271f9cc3a9aa74732f7351f1c3"}, - {file = "frida-16.4.2-cp37-abi3-manylinux_2_17_armv7l.whl", hash = "sha256:5ee53c1aa8be45eabb63cac773b715e14556eda424f604fd475c8303b95fc4a5"}, - {file = "frida-16.4.2-cp37-abi3-manylinux_2_5_i686.whl", hash = "sha256:f8ab7df238a07d002d7a6e9a206e0218e4608367d8cf005997c5137e81892571"}, - {file = "frida-16.4.2-cp37-abi3-manylinux_2_5_x86_64.whl", hash = "sha256:706cf50fb558addd1bf1de905ce20675a1b67179b61e811a933e9f12628476dc"}, - {file = "frida-16.4.2-cp37-abi3-win32.whl", hash = "sha256:bf47aebd923efb12957c8b550b6519f5451d4bb3b2961541c2ed9cebefacb4f7"}, - {file = "frida-16.4.2-cp37-abi3-win_amd64.whl", hash = "sha256:d962ad9ccaa31fa88240918159660e761f820634337b340490192017b16d4eb4"}, - {file = "frida-16.4.2.tar.gz", hash = "sha256:b0807db6d0430053a70bc5abdf2a335f3c248d7cccb59cce49caeed30dc7f4b3"}, + {file = "frida-16.4.5-cp37-abi3-macosx_10_13_x86_64.whl", hash = "sha256:a4e1f6b47ad6b52d0e247525ebf87546e38ebfa05e0f7d1b698220cfd03e182b"}, + {file = "frida-16.4.5-cp37-abi3-macosx_11_0_arm64.whl", hash = "sha256:42c6ebf0493ed056b52b31b362051ff68f625a464d03d30f17f8dc4c76dc113e"}, + {file = "frida-16.4.5-cp37-abi3-manylinux1_i686.whl", hash = "sha256:0901ab8a79801cdca854af0de0b7245b3420c06ffd8183716cc5ea49a4ad1e75"}, + {file = "frida-16.4.5-cp37-abi3-manylinux1_x86_64.whl", hash = "sha256:358797178893e6bf4c4a58127533ed3913c1df0661236e3587f3a4e3bf157ddd"}, + {file = "frida-16.4.5-cp37-abi3-manylinux2014_aarch64.whl", hash = "sha256:7400a6bd04b61ed22f560fdfcf9fc4ec992c94e1363f85be35a5ef040314cf6d"}, + {file = "frida-16.4.5-cp37-abi3-manylinux2014_armv7l.whl", hash = "sha256:35ee47f4e1f8a297f644e2baf033de795535ffb769a7615047cb7c0e4a4ae6c4"}, + {file = "frida-16.4.5-cp37-abi3-manylinux_2_17_aarch64.whl", hash = "sha256:bd941f303e27b55edf6b79b939dd0701833e32fa883bd43be45211d8b9e37bb0"}, + {file = "frida-16.4.5-cp37-abi3-manylinux_2_17_armv7l.whl", hash = "sha256:cc68ff3d4fc018483b03b284cb25c71ce99673d693d56f5b54d1c907fe2d22eb"}, + {file = "frida-16.4.5-cp37-abi3-manylinux_2_5_i686.whl", hash = "sha256:a8fbd36bc0dd24b027c8798ccafd66a6ccfcd909a9a96be1059120faf68db4f1"}, + {file = "frida-16.4.5-cp37-abi3-manylinux_2_5_x86_64.whl", hash = "sha256:fc6fb74e0684f106144832328ca56248522c21c85de5ae8d66341a7800ce4fc1"}, + {file = "frida-16.4.5-cp37-abi3-win32.whl", hash = "sha256:6ac33bc77975365db9773e296fadd8aa926eb840f7a8f5ef7819251f62ae236f"}, + {file = "frida-16.4.5-cp37-abi3-win_amd64.whl", hash = "sha256:7bed852e38ca8975578d08f5bc0b8a2d784d412341223d5ff36525bed8e2b62d"}, + {file = "frida-16.4.5.tar.gz", hash = "sha256:d8240fa083b0f5bed71b913bad2d4950837f9076de2935f298e9a4a906bee29d"}, ] [[package]] name = "frida-tools" -version = "12.4.4" +version = "12.5.0" description = "Frida CLI tools" optional = false python-versions = "*" files = [ - {file = "frida-tools-12.4.4.tar.gz", hash = "sha256:683633dd9d9daaa3a2e6e4bb1c314846f5253ba26c3b72127dafabc6e1915f05"}, + {file = "frida-tools-12.5.0.tar.gz", hash = "sha256:be5a8137413e6e97f1f932e5899de180269e38474c44ffeb9807e49a3393ab20"}, ] [package.dependencies] @@ -993,119 +988,119 @@ files = [ [[package]] name = "grpcio" -version = "1.64.1" +version = "1.65.1" description = "HTTP/2-based RPC framework" optional = false python-versions = ">=3.8" files = [ - {file = "grpcio-1.64.1-cp310-cp310-linux_armv7l.whl", hash = "sha256:55697ecec192bc3f2f3cc13a295ab670f51de29884ca9ae6cd6247df55df2502"}, - {file = "grpcio-1.64.1-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:3b64ae304c175671efdaa7ec9ae2cc36996b681eb63ca39c464958396697daff"}, - {file = "grpcio-1.64.1-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:bac71b4b28bc9af61efcdc7630b166440bbfbaa80940c9a697271b5e1dabbc61"}, - {file = "grpcio-1.64.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6c024ffc22d6dc59000faf8ad781696d81e8e38f4078cb0f2630b4a3cf231a90"}, - {file = "grpcio-1.64.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e7cd5c1325f6808b8ae31657d281aadb2a51ac11ab081ae335f4f7fc44c1721d"}, - {file = "grpcio-1.64.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:0a2813093ddb27418a4c99f9b1c223fab0b053157176a64cc9db0f4557b69bd9"}, - {file = "grpcio-1.64.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:2981c7365a9353f9b5c864595c510c983251b1ab403e05b1ccc70a3d9541a73b"}, - {file = "grpcio-1.64.1-cp310-cp310-win32.whl", hash = "sha256:1262402af5a511c245c3ae918167eca57342c72320dffae5d9b51840c4b2f86d"}, - {file = "grpcio-1.64.1-cp310-cp310-win_amd64.whl", hash = "sha256:19264fc964576ddb065368cae953f8d0514ecc6cb3da8903766d9fb9d4554c33"}, - {file = "grpcio-1.64.1-cp311-cp311-linux_armv7l.whl", hash = "sha256:58b1041e7c870bb30ee41d3090cbd6f0851f30ae4eb68228955d973d3efa2e61"}, - {file = "grpcio-1.64.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:bbc5b1d78a7822b0a84c6f8917faa986c1a744e65d762ef6d8be9d75677af2ca"}, - {file = "grpcio-1.64.1-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:5841dd1f284bd1b3d8a6eca3a7f062b06f1eec09b184397e1d1d43447e89a7ae"}, - {file = "grpcio-1.64.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8caee47e970b92b3dd948371230fcceb80d3f2277b3bf7fbd7c0564e7d39068e"}, - {file = "grpcio-1.64.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:73819689c169417a4f978e562d24f2def2be75739c4bed1992435d007819da1b"}, - {file = "grpcio-1.64.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:6503b64c8b2dfad299749cad1b595c650c91e5b2c8a1b775380fcf8d2cbba1e9"}, - {file = "grpcio-1.64.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1de403fc1305fd96cfa75e83be3dee8538f2413a6b1685b8452301c7ba33c294"}, - {file = "grpcio-1.64.1-cp311-cp311-win32.whl", hash = "sha256:d4d29cc612e1332237877dfa7fe687157973aab1d63bd0f84cf06692f04c0367"}, - {file = "grpcio-1.64.1-cp311-cp311-win_amd64.whl", hash = "sha256:5e56462b05a6f860b72f0fa50dca06d5b26543a4e88d0396259a07dc30f4e5aa"}, - {file = "grpcio-1.64.1-cp312-cp312-linux_armv7l.whl", hash = "sha256:4657d24c8063e6095f850b68f2d1ba3b39f2b287a38242dcabc166453e950c59"}, - {file = "grpcio-1.64.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:62b4e6eb7bf901719fce0ca83e3ed474ae5022bb3827b0a501e056458c51c0a1"}, - {file = "grpcio-1.64.1-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:ee73a2f5ca4ba44fa33b4d7d2c71e2c8a9e9f78d53f6507ad68e7d2ad5f64a22"}, - {file = "grpcio-1.64.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:198908f9b22e2672a998870355e226a725aeab327ac4e6ff3a1399792ece4762"}, - {file = "grpcio-1.64.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:39b9d0acaa8d835a6566c640f48b50054f422d03e77e49716d4c4e8e279665a1"}, - {file = "grpcio-1.64.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:5e42634a989c3aa6049f132266faf6b949ec2a6f7d302dbb5c15395b77d757eb"}, - {file = "grpcio-1.64.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:b1a82e0b9b3022799c336e1fc0f6210adc019ae84efb7321d668129d28ee1efb"}, - {file = "grpcio-1.64.1-cp312-cp312-win32.whl", hash = "sha256:55260032b95c49bee69a423c2f5365baa9369d2f7d233e933564d8a47b893027"}, - {file = "grpcio-1.64.1-cp312-cp312-win_amd64.whl", hash = "sha256:c1a786ac592b47573a5bb7e35665c08064a5d77ab88a076eec11f8ae86b3e3f6"}, - {file = "grpcio-1.64.1-cp38-cp38-linux_armv7l.whl", hash = "sha256:a011ac6c03cfe162ff2b727bcb530567826cec85eb8d4ad2bfb4bd023287a52d"}, - {file = "grpcio-1.64.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:4d6dab6124225496010bd22690f2d9bd35c7cbb267b3f14e7a3eb05c911325d4"}, - {file = "grpcio-1.64.1-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:a5e771d0252e871ce194d0fdcafd13971f1aae0ddacc5f25615030d5df55c3a2"}, - {file = "grpcio-1.64.1-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2c3c1b90ab93fed424e454e93c0ed0b9d552bdf1b0929712b094f5ecfe7a23ad"}, - {file = "grpcio-1.64.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:20405cb8b13fd779135df23fabadc53b86522d0f1cba8cca0e87968587f50650"}, - {file = "grpcio-1.64.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:0cc79c982ccb2feec8aad0e8fb0d168bcbca85bc77b080d0d3c5f2f15c24ea8f"}, - {file = "grpcio-1.64.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:a3a035c37ce7565b8f4f35ff683a4db34d24e53dc487e47438e434eb3f701b2a"}, - {file = "grpcio-1.64.1-cp38-cp38-win32.whl", hash = "sha256:1257b76748612aca0f89beec7fa0615727fd6f2a1ad580a9638816a4b2eb18fd"}, - {file = "grpcio-1.64.1-cp38-cp38-win_amd64.whl", hash = "sha256:0a12ddb1678ebc6a84ec6b0487feac020ee2b1659cbe69b80f06dbffdb249122"}, - {file = "grpcio-1.64.1-cp39-cp39-linux_armv7l.whl", hash = "sha256:75dbbf415026d2862192fe1b28d71f209e2fd87079d98470db90bebe57b33179"}, - {file = "grpcio-1.64.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e3d9f8d1221baa0ced7ec7322a981e28deb23749c76eeeb3d33e18b72935ab62"}, - {file = "grpcio-1.64.1-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:5f8b75f64d5d324c565b263c67dbe4f0af595635bbdd93bb1a88189fc62ed2e5"}, - {file = "grpcio-1.64.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c84ad903d0d94311a2b7eea608da163dace97c5fe9412ea311e72c3684925602"}, - {file = "grpcio-1.64.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:940e3ec884520155f68a3b712d045e077d61c520a195d1a5932c531f11883489"}, - {file = "grpcio-1.64.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f10193c69fc9d3d726e83bbf0f3d316f1847c3071c8c93d8090cf5f326b14309"}, - {file = "grpcio-1.64.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ac15b6c2c80a4d1338b04d42a02d376a53395ddf0ec9ab157cbaf44191f3ffdd"}, - {file = "grpcio-1.64.1-cp39-cp39-win32.whl", hash = "sha256:03b43d0ccf99c557ec671c7dede64f023c7da9bb632ac65dbc57f166e4970040"}, - {file = "grpcio-1.64.1-cp39-cp39-win_amd64.whl", hash = "sha256:ed6091fa0adcc7e4ff944090cf203a52da35c37a130efa564ded02b7aff63bcd"}, - {file = "grpcio-1.64.1.tar.gz", hash = "sha256:8d51dd1c59d5fa0f34266b80a3805ec29a1f26425c2a54736133f6d87fc4968a"}, + {file = "grpcio-1.65.1-cp310-cp310-linux_armv7l.whl", hash = "sha256:3dc5f928815b8972fb83b78d8db5039559f39e004ec93ebac316403fe031a062"}, + {file = "grpcio-1.65.1-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:8333ca46053c35484c9f2f7e8d8ec98c1383a8675a449163cea31a2076d93de8"}, + {file = "grpcio-1.65.1-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:7af64838b6e615fff0ec711960ed9b6ee83086edfa8c32670eafb736f169d719"}, + {file = "grpcio-1.65.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dbb64b4166362d9326f7efbf75b1c72106c1aa87f13a8c8b56a1224fac152f5c"}, + {file = "grpcio-1.65.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8422dc13ad93ec8caa2612b5032a2b9cd6421c13ed87f54db4a3a2c93afaf77"}, + {file = "grpcio-1.65.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:4effc0562b6c65d4add6a873ca132e46ba5e5a46f07c93502c37a9ae7f043857"}, + {file = "grpcio-1.65.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a6c71575a2fedf259724981fd73a18906513d2f306169c46262a5bae956e6364"}, + {file = "grpcio-1.65.1-cp310-cp310-win32.whl", hash = "sha256:34966cf526ef0ea616e008d40d989463e3db157abb213b2f20c6ce0ae7928875"}, + {file = "grpcio-1.65.1-cp310-cp310-win_amd64.whl", hash = "sha256:ca931de5dd6d9eb94ff19a2c9434b23923bce6f767179fef04dfa991f282eaad"}, + {file = "grpcio-1.65.1-cp311-cp311-linux_armv7l.whl", hash = "sha256:bbb46330cc643ecf10bd9bd4ca8e7419a14b6b9dedd05f671c90fb2c813c6037"}, + {file = "grpcio-1.65.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:d827a6fb9215b961eb73459ad7977edb9e748b23e3407d21c845d1d8ef6597e5"}, + {file = "grpcio-1.65.1-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:6e71aed8835f8d9fbcb84babc93a9da95955d1685021cceb7089f4f1e717d719"}, + {file = "grpcio-1.65.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9a1c84560b3b2d34695c9ba53ab0264e2802721c530678a8f0a227951f453462"}, + {file = "grpcio-1.65.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:27adee2338d697e71143ed147fe286c05810965d5d30ec14dd09c22479bfe48a"}, + {file = "grpcio-1.65.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:f62652ddcadc75d0e7aa629e96bb61658f85a993e748333715b4ab667192e4e8"}, + {file = "grpcio-1.65.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:71a05fd814700dd9cb7d9a507f2f6a1ef85866733ccaf557eedacec32d65e4c2"}, + {file = "grpcio-1.65.1-cp311-cp311-win32.whl", hash = "sha256:b590f1ad056294dfaeac0b7e1b71d3d5ace638d8dd1f1147ce4bd13458783ba8"}, + {file = "grpcio-1.65.1-cp311-cp311-win_amd64.whl", hash = "sha256:12e9bdf3b5fd48e5fbe5b3da382ad8f97c08b47969f3cca81dd9b36b86ed39e2"}, + {file = "grpcio-1.65.1-cp312-cp312-linux_armv7l.whl", hash = "sha256:54cb822e177374b318b233e54b6856c692c24cdbd5a3ba5335f18a47396bac8f"}, + {file = "grpcio-1.65.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:aaf3c54419a28d45bd1681372029f40e5bfb58e5265e3882eaf21e4a5f81a119"}, + {file = "grpcio-1.65.1-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:557de35bdfbe8bafea0a003dbd0f4da6d89223ac6c4c7549d78e20f92ead95d9"}, + {file = "grpcio-1.65.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8bfd95ef3b097f0cc86ade54eafefa1c8ed623aa01a26fbbdcd1a3650494dd11"}, + {file = "grpcio-1.65.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e6a8f3d6c41e6b642870afe6cafbaf7b61c57317f9ec66d0efdaf19db992b90"}, + {file = "grpcio-1.65.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:1faaf7355ceed07ceaef0b9dcefa4c98daf1dd8840ed75c2de128c3f4a4d859d"}, + {file = "grpcio-1.65.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:60f1f38eed830488ad2a1b11579ef0f345ff16fffdad1d24d9fbc97ba31804ff"}, + {file = "grpcio-1.65.1-cp312-cp312-win32.whl", hash = "sha256:e75acfa52daf5ea0712e8aa82f0003bba964de7ae22c26d208cbd7bc08500177"}, + {file = "grpcio-1.65.1-cp312-cp312-win_amd64.whl", hash = "sha256:ff5a84907e51924973aa05ed8759210d8cdae7ffcf9e44fd17646cf4a902df59"}, + {file = "grpcio-1.65.1-cp38-cp38-linux_armv7l.whl", hash = "sha256:1fbd6331f18c3acd7e09d17fd840c096f56eaf0ef830fbd50af45ae9dc8dfd83"}, + {file = "grpcio-1.65.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:de5b6be29116e094c5ef9d9e4252e7eb143e3d5f6bd6d50a78075553ab4930b0"}, + {file = "grpcio-1.65.1-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:e4a3cdba62b2d6aeae6027ae65f350de6dc082b72e6215eccf82628e79efe9ba"}, + {file = "grpcio-1.65.1-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:941c4869aa229d88706b78187d60d66aca77fe5c32518b79e3c3e03fc26109a2"}, + {file = "grpcio-1.65.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f40cebe5edb518d78b8131e87cb83b3ee688984de38a232024b9b44e74ee53d3"}, + {file = "grpcio-1.65.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:2ca684ba331fb249d8a1ce88db5394e70dbcd96e58d8c4b7e0d7b141a453dce9"}, + {file = "grpcio-1.65.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8558f0083ddaf5de64a59c790bffd7568e353914c0c551eae2955f54ee4b857f"}, + {file = "grpcio-1.65.1-cp38-cp38-win32.whl", hash = "sha256:8d8143a3e3966f85dce6c5cc45387ec36552174ba5712c5dc6fcc0898fb324c0"}, + {file = "grpcio-1.65.1-cp38-cp38-win_amd64.whl", hash = "sha256:76e81a86424d6ca1ce7c16b15bdd6a964a42b40544bf796a48da241fdaf61153"}, + {file = "grpcio-1.65.1-cp39-cp39-linux_armv7l.whl", hash = "sha256:cb5175f45c980ff418998723ea1b3869cce3766d2ab4e4916fbd3cedbc9d0ed3"}, + {file = "grpcio-1.65.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:b12c1aa7b95abe73b3e04e052c8b362655b41c7798da69f1eaf8d186c7d204df"}, + {file = "grpcio-1.65.1-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:3019fb50128b21a5e018d89569ffaaaa361680e1346c2f261bb84a91082eb3d3"}, + {file = "grpcio-1.65.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7ae15275ed98ea267f64ee9ddedf8ecd5306a5b5bb87972a48bfe24af24153e8"}, + {file = "grpcio-1.65.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5f096ffb881f37e8d4f958b63c74bfc400c7cebd7a944b027357cd2fb8d91a57"}, + {file = "grpcio-1.65.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:2f56b5a68fdcf17a0a1d524bf177218c3c69b3947cb239ea222c6f1867c3ab68"}, + {file = "grpcio-1.65.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:941596d419b9736ab548aa0feb5bbba922f98872668847bf0720b42d1d227b9e"}, + {file = "grpcio-1.65.1-cp39-cp39-win32.whl", hash = "sha256:5fd7337a823b890215f07d429f4f193d24b80d62a5485cf88ee06648591a0c57"}, + {file = "grpcio-1.65.1-cp39-cp39-win_amd64.whl", hash = "sha256:1bceeec568372cbebf554eae1b436b06c2ff24cfaf04afade729fb9035408c6c"}, + {file = "grpcio-1.65.1.tar.gz", hash = "sha256:3c492301988cd720cd145d84e17318d45af342e29ef93141228f9cd73222368b"}, ] [package.extras] -protobuf = ["grpcio-tools (>=1.64.1)"] +protobuf = ["grpcio-tools (>=1.65.1)"] [[package]] name = "grpcio-tools" -version = "1.64.1" +version = "1.65.1" description = "Protobuf code generator for gRPC" optional = false python-versions = ">=3.8" files = [ - {file = "grpcio_tools-1.64.1-cp310-cp310-linux_armv7l.whl", hash = "sha256:6c8181318e3a21827c2f834fd0505040aa8f24fb568a154ff1c95c9802c0e3f5"}, - {file = "grpcio_tools-1.64.1-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:24340327f7fb85f7406910c9484f98dd9588bdf639578b9341920d67f64306a0"}, - {file = "grpcio_tools-1.64.1-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:646828eec31218e1314b04d7c62c78534d3478cae6348909b6a39ee880a757b2"}, - {file = "grpcio_tools-1.64.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1f467bd03d70de23e7d68d3465fd9bfd5167d15168a569edacee730b4ec105bf"}, - {file = "grpcio_tools-1.64.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a29163cbc6ecaf6f853711420ddab7e35f24d9ee014a5e35b0a6b31c328d1c63"}, - {file = "grpcio_tools-1.64.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:759982ba0f942995bf170386559679b9d9f3b00caf103f346f3c33b8703c3057"}, - {file = "grpcio_tools-1.64.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:1c0db41e812e1741b59844c71c8dfc8c3076eb4472b4c30165aefacf609c81bf"}, - {file = "grpcio_tools-1.64.1-cp310-cp310-win32.whl", hash = "sha256:a5208855046a338c5663ca39f59fb167e24514f1287c266db42fbf2057373aa0"}, - {file = "grpcio_tools-1.64.1-cp310-cp310-win_amd64.whl", hash = "sha256:a808aaa308e26fc5026b15008aec45bea8aa2f2662989cbaffa300601ac98fae"}, - {file = "grpcio_tools-1.64.1-cp311-cp311-linux_armv7l.whl", hash = "sha256:23e6c847647e338b6ed139c7d10ed783dbb37d8ce078ce9ab0a3f7e6a518ff4e"}, - {file = "grpcio_tools-1.64.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0a72a2d87529329117fca6493d948489f1963e3f645d27a785a27b54b05c38cb"}, - {file = "grpcio_tools-1.64.1-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:5532fbac9e1229d3290a512d4253bd311ed742d3b77d634ce7240e97b4af32ac"}, - {file = "grpcio_tools-1.64.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a75c8f13762dc323b38e8dc7186d80a61c0d1321062850e3056221a4db779a4"}, - {file = "grpcio_tools-1.64.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a653002b287accf79b0924bb1a76b33ea83774be57cef14e6ec383a965999ad5"}, - {file = "grpcio_tools-1.64.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:0d3572b62453342f4164cb245c434053c6991ee7bf883eb94f15e45f3121967b"}, - {file = "grpcio_tools-1.64.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e8ffaa1972e64d968a706c954f6614e718abd10068b107727028ffb9506503d2"}, - {file = "grpcio_tools-1.64.1-cp311-cp311-win32.whl", hash = "sha256:cf3fbad6312bb61f48eab8ae5d2b31dcb007653282d5901982e17111773104e1"}, - {file = "grpcio_tools-1.64.1-cp311-cp311-win_amd64.whl", hash = "sha256:fd4a596ec2b34c8a6b15c6581ef7ea91c9b85f68099004da656db79e5a2b7a8c"}, - {file = "grpcio_tools-1.64.1-cp312-cp312-linux_armv7l.whl", hash = "sha256:acf9a8bce188bb760c138327a89f64be8bbeb062634d151c77bbcd138d60bdc6"}, - {file = "grpcio_tools-1.64.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8c7d0633b1177fafaeb76e9b0c7b8b14221eb1086874a79925879b298843f8a0"}, - {file = "grpcio_tools-1.64.1-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:35efe38dd8cc5e05f44e67bcc2ae40f461862549b5d2590c1b644c5d4d93c390"}, - {file = "grpcio_tools-1.64.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e28cfaede2a243452252c94b72378f1d939b786689cb11d218fdae6a8421940f"}, - {file = "grpcio_tools-1.64.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6711f3e3fbfae9313e15f9abc47241d881772f3fb4e4d0257918bff24363139e"}, - {file = "grpcio_tools-1.64.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:be39db97d13f3bd0b2ff9bf8d0e68f590f4877cf2c4db201a2f9d4d39724e137"}, - {file = "grpcio_tools-1.64.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:22efb9a167da6fd051c76f1a00c4275b5d15e8b7842364c84dc4cc88def8fd4c"}, - {file = "grpcio_tools-1.64.1-cp312-cp312-win32.whl", hash = "sha256:d9a470f9e72bccc8994b025fa40cb1a7202db17a5f8e1869f4c2079ded869ac2"}, - {file = "grpcio_tools-1.64.1-cp312-cp312-win_amd64.whl", hash = "sha256:5ecfecf1da38fa9f0f95dd5f3314c04974be5af40264c520fbc1a9f4f5b1acca"}, - {file = "grpcio_tools-1.64.1-cp38-cp38-linux_armv7l.whl", hash = "sha256:9d3fd5f43503ac594872ad4deb80c08353a3d73c9304afe0226bcb077d5dacca"}, - {file = "grpcio_tools-1.64.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:c8cb5567cd5836b29d37ea12c8ccb753a19712ec459c4dbc05c084ca57b84b3b"}, - {file = "grpcio_tools-1.64.1-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:d0f42307f951851894a1ddcbed2e2403fdb0ac0920bbb4ec5c80a2959a1d328d"}, - {file = "grpcio_tools-1.64.1-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a078af44be25363f55cbedc33c560513f2b2928a0594c8069da0bc65917ef1a1"}, - {file = "grpcio_tools-1.64.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58eee15287eb54d1ba27d4e73fcd7e7a9f819e529a74dabc9cf3933fbe3bef07"}, - {file = "grpcio_tools-1.64.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:b740e136a12a992c3c75dafe12d96c65e9249daa71e6b75f17aac5459c64f165"}, - {file = "grpcio_tools-1.64.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:625cc1493d4672af90d23f9909bbc0c4041cfa9fa21f9228abe433f5ad9b356f"}, - {file = "grpcio_tools-1.64.1-cp38-cp38-win32.whl", hash = "sha256:85808e3c020d6e08975be00521ec8841885740ffd84a48375305fe7198d8b9e5"}, - {file = "grpcio_tools-1.64.1-cp38-cp38-win_amd64.whl", hash = "sha256:37664461c8da4777c78772f79914ddd59914a4c1dc0bdd11ba86b569477a9d25"}, - {file = "grpcio_tools-1.64.1-cp39-cp39-linux_armv7l.whl", hash = "sha256:ff9b631788573bfbecfe8cb647d484dfac9cfbad4a7bb640a9e5dcfb24a1b3c5"}, - {file = "grpcio_tools-1.64.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7e67903fba7b122cad7e41b1347c71f2d8e484f51f5c91cacc52249b4ab274bf"}, - {file = "grpcio_tools-1.64.1-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:6cef267289e3a1257ef79c399a4a244a2b508c4f8d28faf9b061983187b8c2ff"}, - {file = "grpcio_tools-1.64.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:23eef1138065edf360ed649381cf1d9c9123b3a8c003a4b28bf0c4a5b025087a"}, - {file = "grpcio_tools-1.64.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba0758d779bc2134219c9ee392d7d30a7ff7f788fd68bf4f56bb4a0213e5d2e4"}, - {file = "grpcio_tools-1.64.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:a8fb6a4438ef1ce619bd6695799b0a06c049a0be3e10ecf0b5fc5d72929a9f02"}, - {file = "grpcio_tools-1.64.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:3cc3036589e416cf8516802d3e6c37fd7de1b6c4defc292a1859848515c67ab5"}, - {file = "grpcio_tools-1.64.1-cp39-cp39-win32.whl", hash = "sha256:59db889e5f698e00ea65032d3fddbfdbec72b22b285a57c167fb7a48bce2ca27"}, - {file = "grpcio_tools-1.64.1-cp39-cp39-win_amd64.whl", hash = "sha256:984ed040f13efcede72c4dfb298274df3877573ca305f51f5cb24249463d6a77"}, - {file = "grpcio_tools-1.64.1.tar.gz", hash = "sha256:72b3550b91adb8354656ecf0f6d1d4611299044bae11fb1e7cc1d1bb66b8c1eb"}, + {file = "grpcio_tools-1.65.1-cp310-cp310-linux_armv7l.whl", hash = "sha256:16f2f49048c76a68a8171507c39652c8be9ed4e7408deb9877002813aea4c396"}, + {file = "grpcio_tools-1.65.1-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:6f75bf562057723818dff7bf4e05884c220653ead3db19effe5873ce88c7cfd2"}, + {file = "grpcio_tools-1.65.1-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:e859001e20d4199ac90979e11d0d0ecb83f6b0235b08f8bfae93c2bd1401795a"}, + {file = "grpcio_tools-1.65.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:257decc1782b9adca422a2625663529be64018c056d7346d8bbc7c9bf0fe3b80"}, + {file = "grpcio_tools-1.65.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac8cc2684bcde43296cf5a350b80b73713610f0789ff912c88f898ef065a0b6c"}, + {file = "grpcio_tools-1.65.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:b8ef108fceabb12ed29f750f2cb4827d7bad5033dc13596ad0de092f015f5123"}, + {file = "grpcio_tools-1.65.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:32fa16e64f4b1684ed634155af9b03fdeabdf641d484e53c453e592e0f574f03"}, + {file = "grpcio_tools-1.65.1-cp310-cp310-win32.whl", hash = "sha256:d4afb3e74c7a567eabda3c447421eb8fb5c6cbf19bb9292319056beff4ab49a1"}, + {file = "grpcio_tools-1.65.1-cp310-cp310-win_amd64.whl", hash = "sha256:edb4731b4ad068c3c48d52bbfa1404236cbcdd2524eb01a655e8adfadc2f0034"}, + {file = "grpcio_tools-1.65.1-cp311-cp311-linux_armv7l.whl", hash = "sha256:fabbc0698cf0c614059c3e103b06c74d07190e9c7518f457703e98617ed467c0"}, + {file = "grpcio_tools-1.65.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ee1353c741f8f2fcf4fcce8764d4570e2d7c3025cc4c918a0c6532c18b6cbac5"}, + {file = "grpcio_tools-1.65.1-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:f49acf17ae7b1a35b5e0e5907ed9b70c042b3e7ab8769ea9fd26f20b2b888743"}, + {file = "grpcio_tools-1.65.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c50895d383d41a379f9a235ce6d14c6639f36d43bf71c7148bf8a114a8f0936a"}, + {file = "grpcio_tools-1.65.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c394cf5b77eb71ff5c0ab857877f59dfee080cc95fb24d47e97d3965aaaf3c64"}, + {file = "grpcio_tools-1.65.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:e24819f8d11fc9e6bad1e13a1d7fddd6027ed2a1aad583f093cfe027852ff3f9"}, + {file = "grpcio_tools-1.65.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:2ec7e376f3f53e7ab90614d5a2404c19c7902750bcc5bed8219ab864f9bc1c4b"}, + {file = "grpcio_tools-1.65.1-cp311-cp311-win32.whl", hash = "sha256:9b6dbddca8e399ad96d263b786d0803acc67194cb80d01117691a9f239ac8dc9"}, + {file = "grpcio_tools-1.65.1-cp311-cp311-win_amd64.whl", hash = "sha256:3135888461888dcc7b358c17d60f32654cb36daf02bb805c84c0f8ab550743eb"}, + {file = "grpcio_tools-1.65.1-cp312-cp312-linux_armv7l.whl", hash = "sha256:b8fe0bd8e63a4dd84c022ccbb6057e9f3c338e036a1b95c2a6dbcc928c35b4f9"}, + {file = "grpcio_tools-1.65.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:bfb1a5e429756cdc9ce7183cca24a90bd7e68626379c83ea065bb30125d7aca4"}, + {file = "grpcio_tools-1.65.1-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:4dde0d90f96e29670c58a08aeeac61da49792f71602cb7421943be8918857a2a"}, + {file = "grpcio_tools-1.65.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a89203d864dd024c4a13032f2df792eb465c63c224f9b82460d53f0cf30a3d16"}, + {file = "grpcio_tools-1.65.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7813a67cb427847e1a88d4fd4cbabfd2ed272455bd78b4f417377361d3b8edbd"}, + {file = "grpcio_tools-1.65.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:33e4c602221f91c1d87c4574c496621f11826d4f8867f31f4c4c2ff1b144a777"}, + {file = "grpcio_tools-1.65.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:fd2fe61d40e7421dc64c90912e29c05f1c419dd7a90452c84a1b456e06bd8530"}, + {file = "grpcio_tools-1.65.1-cp312-cp312-win32.whl", hash = "sha256:013017df92d6165e1556a17c618cf22471ef131fb614b428683730968b54b46d"}, + {file = "grpcio_tools-1.65.1-cp312-cp312-win_amd64.whl", hash = "sha256:1ab64a9af7ce0aeb639a77423fa99de91863a0b8ce0e43fc50f57fc460a0d30e"}, + {file = "grpcio_tools-1.65.1-cp38-cp38-linux_armv7l.whl", hash = "sha256:a95fd13dc17b065a934f00a0b99078de7773d4743772312efc8e75521ab62f7b"}, + {file = "grpcio_tools-1.65.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e44c69c029614fc61da2701587299fe19e52031aa1fba2a69a02c2dd77f903fe"}, + {file = "grpcio_tools-1.65.1-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:196e12c18f0ebe5ac7f5446fc1daef8d9c69ba40a987a1f8379bfdf6c32e54af"}, + {file = "grpcio_tools-1.65.1-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:881ccc523a171235bb6b1d8e965c2f11e525b54eb1d66aeb8fea5a72f84d6e02"}, + {file = "grpcio_tools-1.65.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d5a12e0bd2a0f33af11e11d89f19cddea66568716b53b77f3f5dc605ceb32e0"}, + {file = "grpcio_tools-1.65.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:1d8671d82449206ef040756a14484b0c5189615a0aac5f4734ad3d023d07d4b1"}, + {file = "grpcio_tools-1.65.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:dc904f0de72eecbd024c111caa3e3165522349ff3c89361e4cbf06035c93061a"}, + {file = "grpcio_tools-1.65.1-cp38-cp38-win32.whl", hash = "sha256:b6e45377dbe50c7a737d81620841b8c3f3a1650c76cb56a87b5b0414d10f9987"}, + {file = "grpcio_tools-1.65.1-cp38-cp38-win_amd64.whl", hash = "sha256:5c9b4d95d2623b8b9435103305c3d375f8b4a266ee6fbbf29b5f4a57a8405047"}, + {file = "grpcio_tools-1.65.1-cp39-cp39-linux_armv7l.whl", hash = "sha256:4b0714458a6a3a1ed587271f3e7c301b735ccbdd7946071a1d85a6d0aabcb57a"}, + {file = "grpcio_tools-1.65.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:1ece34ebb677a869606200812653f274757844754f0b684e59d61244b194f002"}, + {file = "grpcio_tools-1.65.1-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:4887af67ff130174fa7fb420ee985d38659a7c960053639de28980003fe710eb"}, + {file = "grpcio_tools-1.65.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d99945dc53daa7987ae8c33227f96697ccc4d0a4a1ca6c366e28fcc9fc1c55fb"}, + {file = "grpcio_tools-1.65.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:68d14cbd135541366bbef18c1d463f5d560878629f1901cae03777dad87755d9"}, + {file = "grpcio_tools-1.65.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bc55edf7a0af0ad7384887845b6498fdb1a75d3633d11807f953cac531a34588"}, + {file = "grpcio_tools-1.65.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:074fce3b96a5c59ed526bdd07c04c6243c07b13278388837a0540840ae10bf5b"}, + {file = "grpcio_tools-1.65.1-cp39-cp39-win32.whl", hash = "sha256:004232fa8ef82298eeb01b391d708b3a89317910e2f7c623b566aea0448c8dcc"}, + {file = "grpcio_tools-1.65.1-cp39-cp39-win_amd64.whl", hash = "sha256:9cc6f342b8e8a2aa801d2d1640290a47563d8bb1a802671191dc3fc218747da3"}, + {file = "grpcio_tools-1.65.1.tar.gz", hash = "sha256:24cffe8bc90fb8237f0bcf240bd6c70304255fe27b69db32601499a043f871be"}, ] [package.dependencies] -grpcio = ">=1.64.1" +grpcio = ">=1.65.1" protobuf = ">=5.26.1,<6.0dev" setuptools = "*" @@ -1621,43 +1616,43 @@ files = [ [[package]] name = "mypy" -version = "1.10.1" +version = "1.11.0" description = "Optional static typing for Python" optional = false python-versions = ">=3.8" files = [ - {file = "mypy-1.10.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e36f229acfe250dc660790840916eb49726c928e8ce10fbdf90715090fe4ae02"}, - {file = "mypy-1.10.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:51a46974340baaa4145363b9e051812a2446cf583dfaeba124af966fa44593f7"}, - {file = "mypy-1.10.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:901c89c2d67bba57aaaca91ccdb659aa3a312de67f23b9dfb059727cce2e2e0a"}, - {file = "mypy-1.10.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0cd62192a4a32b77ceb31272d9e74d23cd88c8060c34d1d3622db3267679a5d9"}, - {file = "mypy-1.10.1-cp310-cp310-win_amd64.whl", hash = "sha256:a2cbc68cb9e943ac0814c13e2452d2046c2f2b23ff0278e26599224cf164e78d"}, - {file = "mypy-1.10.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:bd6f629b67bb43dc0d9211ee98b96d8dabc97b1ad38b9b25f5e4c4d7569a0c6a"}, - {file = "mypy-1.10.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a1bbb3a6f5ff319d2b9d40b4080d46cd639abe3516d5a62c070cf0114a457d84"}, - {file = "mypy-1.10.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8edd4e9bbbc9d7b79502eb9592cab808585516ae1bcc1446eb9122656c6066f"}, - {file = "mypy-1.10.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:6166a88b15f1759f94a46fa474c7b1b05d134b1b61fca627dd7335454cc9aa6b"}, - {file = "mypy-1.10.1-cp311-cp311-win_amd64.whl", hash = "sha256:5bb9cd11c01c8606a9d0b83ffa91d0b236a0e91bc4126d9ba9ce62906ada868e"}, - {file = "mypy-1.10.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d8681909f7b44d0b7b86e653ca152d6dff0eb5eb41694e163c6092124f8246d7"}, - {file = "mypy-1.10.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:378c03f53f10bbdd55ca94e46ec3ba255279706a6aacaecac52ad248f98205d3"}, - {file = "mypy-1.10.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6bacf8f3a3d7d849f40ca6caea5c055122efe70e81480c8328ad29c55c69e93e"}, - {file = "mypy-1.10.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:701b5f71413f1e9855566a34d6e9d12624e9e0a8818a5704d74d6b0402e66c04"}, - {file = "mypy-1.10.1-cp312-cp312-win_amd64.whl", hash = "sha256:3c4c2992f6ea46ff7fce0072642cfb62af7a2484efe69017ed8b095f7b39ef31"}, - {file = "mypy-1.10.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:604282c886497645ffb87b8f35a57ec773a4a2721161e709a4422c1636ddde5c"}, - {file = "mypy-1.10.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37fd87cab83f09842653f08de066ee68f1182b9b5282e4634cdb4b407266bade"}, - {file = "mypy-1.10.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8addf6313777dbb92e9564c5d32ec122bf2c6c39d683ea64de6a1fd98b90fe37"}, - {file = "mypy-1.10.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5cc3ca0a244eb9a5249c7c583ad9a7e881aa5d7b73c35652296ddcdb33b2b9c7"}, - {file = "mypy-1.10.1-cp38-cp38-win_amd64.whl", hash = "sha256:1b3a2ffce52cc4dbaeee4df762f20a2905aa171ef157b82192f2e2f368eec05d"}, - {file = "mypy-1.10.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:fe85ed6836165d52ae8b88f99527d3d1b2362e0cb90b005409b8bed90e9059b3"}, - {file = "mypy-1.10.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c2ae450d60d7d020d67ab440c6e3fae375809988119817214440033f26ddf7bf"}, - {file = "mypy-1.10.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6be84c06e6abd72f960ba9a71561c14137a583093ffcf9bbfaf5e613d63fa531"}, - {file = "mypy-1.10.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:2189ff1e39db399f08205e22a797383613ce1cb0cb3b13d8bcf0170e45b96cc3"}, - {file = "mypy-1.10.1-cp39-cp39-win_amd64.whl", hash = "sha256:97a131ee36ac37ce9581f4220311247ab6cba896b4395b9c87af0675a13a755f"}, - {file = "mypy-1.10.1-py3-none-any.whl", hash = "sha256:71d8ac0b906354ebda8ef1673e5fde785936ac1f29ff6987c7483cfbd5a4235a"}, - {file = "mypy-1.10.1.tar.gz", hash = "sha256:1f8f492d7db9e3593ef42d4f115f04e556130f2819ad33ab84551403e97dd4c0"}, + {file = "mypy-1.11.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a3824187c99b893f90c845bab405a585d1ced4ff55421fdf5c84cb7710995229"}, + {file = "mypy-1.11.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:96f8dbc2c85046c81bcddc246232d500ad729cb720da4e20fce3b542cab91287"}, + {file = "mypy-1.11.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1a5d8d8dd8613a3e2be3eae829ee891b6b2de6302f24766ff06cb2875f5be9c6"}, + {file = "mypy-1.11.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:72596a79bbfb195fd41405cffa18210af3811beb91ff946dbcb7368240eed6be"}, + {file = "mypy-1.11.0-cp310-cp310-win_amd64.whl", hash = "sha256:35ce88b8ed3a759634cb4eb646d002c4cef0a38f20565ee82b5023558eb90c00"}, + {file = "mypy-1.11.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:98790025861cb2c3db8c2f5ad10fc8c336ed2a55f4daf1b8b3f877826b6ff2eb"}, + {file = "mypy-1.11.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:25bcfa75b9b5a5f8d67147a54ea97ed63a653995a82798221cca2a315c0238c1"}, + {file = "mypy-1.11.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0bea2a0e71c2a375c9fa0ede3d98324214d67b3cbbfcbd55ac8f750f85a414e3"}, + {file = "mypy-1.11.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d2b3d36baac48e40e3064d2901f2fbd2a2d6880ec6ce6358825c85031d7c0d4d"}, + {file = "mypy-1.11.0-cp311-cp311-win_amd64.whl", hash = "sha256:d8e2e43977f0e09f149ea69fd0556623919f816764e26d74da0c8a7b48f3e18a"}, + {file = "mypy-1.11.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:1d44c1e44a8be986b54b09f15f2c1a66368eb43861b4e82573026e04c48a9e20"}, + {file = "mypy-1.11.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:cea3d0fb69637944dd321f41bc896e11d0fb0b0aa531d887a6da70f6e7473aba"}, + {file = "mypy-1.11.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a83ec98ae12d51c252be61521aa5731f5512231d0b738b4cb2498344f0b840cd"}, + {file = "mypy-1.11.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:c7b73a856522417beb78e0fb6d33ef89474e7a622db2653bc1285af36e2e3e3d"}, + {file = "mypy-1.11.0-cp312-cp312-win_amd64.whl", hash = "sha256:f2268d9fcd9686b61ab64f077be7ffbc6fbcdfb4103e5dd0cc5eaab53a8886c2"}, + {file = "mypy-1.11.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:940bfff7283c267ae6522ef926a7887305945f716a7704d3344d6d07f02df850"}, + {file = "mypy-1.11.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:14f9294528b5f5cf96c721f231c9f5b2733164e02c1c018ed1a0eff8a18005ac"}, + {file = "mypy-1.11.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d7b54c27783991399046837df5c7c9d325d921394757d09dbcbf96aee4649fe9"}, + {file = "mypy-1.11.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:65f190a6349dec29c8d1a1cd4aa71284177aee5949e0502e6379b42873eddbe7"}, + {file = "mypy-1.11.0-cp38-cp38-win_amd64.whl", hash = "sha256:dbe286303241fea8c2ea5466f6e0e6a046a135a7e7609167b07fd4e7baf151bf"}, + {file = "mypy-1.11.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:104e9c1620c2675420abd1f6c44bab7dd33cc85aea751c985006e83dcd001095"}, + {file = "mypy-1.11.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f006e955718ecd8d159cee9932b64fba8f86ee6f7728ca3ac66c3a54b0062abe"}, + {file = "mypy-1.11.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:becc9111ca572b04e7e77131bc708480cc88a911adf3d0239f974c034b78085c"}, + {file = "mypy-1.11.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6801319fe76c3f3a3833f2b5af7bd2c17bb93c00026a2a1b924e6762f5b19e13"}, + {file = "mypy-1.11.0-cp39-cp39-win_amd64.whl", hash = "sha256:c1a184c64521dc549324ec6ef7cbaa6b351912be9cb5edb803c2808a0d7e85ac"}, + {file = "mypy-1.11.0-py3-none-any.whl", hash = "sha256:56913ec8c7638b0091ef4da6fcc9136896914a9d60d54670a75880c3e5b99ace"}, + {file = "mypy-1.11.0.tar.gz", hash = "sha256:93743608c7348772fdc717af4aeee1997293a1ad04bc0ea6efa15bf65385c538"}, ] [package.dependencies] mypy-extensions = ">=1.0.0" -typing-extensions = ">=4.1.0" +typing-extensions = ">=4.6.0" [package.extras] dmypy = ["psutil (>=4.0)"] @@ -1972,17 +1967,17 @@ qt = ["QtPy (>=1.9.0)", "qt-thread-updater (>=0.0.1)"] [[package]] name = "pylint" -version = "3.2.5" +version = "3.2.6" description = "python code static checker" optional = false python-versions = ">=3.8.0" files = [ - {file = "pylint-3.2.5-py3-none-any.whl", hash = "sha256:32cd6c042b5004b8e857d727708720c54a676d1e22917cf1a2df9b4d4868abd6"}, - {file = "pylint-3.2.5.tar.gz", hash = "sha256:e9b7171e242dcc6ebd0aaa7540481d1a72860748a0a7816b8fe6cf6c80a6fe7e"}, + {file = "pylint-3.2.6-py3-none-any.whl", hash = "sha256:03c8e3baa1d9fb995b12c1dbe00aa6c4bcef210c2a2634374aedeb22fb4a8f8f"}, + {file = "pylint-3.2.6.tar.gz", hash = "sha256:a5d01678349454806cff6d886fb072294f56a58c4761278c97fb557d708e1eb3"}, ] [package.dependencies] -astroid = ">=3.2.2,<=3.3.0-dev0" +astroid = ">=3.2.4,<=3.3.0-dev0" colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} dill = {version = ">=0.3.7", markers = "python_version >= \"3.12\""} isort = ">=4.2.5,<5.13.0 || >5.13.0,<6" @@ -2070,6 +2065,45 @@ files = [ pyobjc-core = ">=10.3.1" pyobjc-framework-Cocoa = ">=10.3.1" +[[package]] +name = "pyproj" +version = "3.6.1" +description = "Python interface to PROJ (cartographic projections and coordinate transformations library)" +optional = false +python-versions = ">=3.9" +files = [ + {file = "pyproj-3.6.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ab7aa4d9ff3c3acf60d4b285ccec134167a948df02347585fdd934ebad8811b4"}, + {file = "pyproj-3.6.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4bc0472302919e59114aa140fd7213c2370d848a7249d09704f10f5b062031fe"}, + {file = "pyproj-3.6.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5279586013b8d6582e22b6f9e30c49796966770389a9d5b85e25a4223286cd3f"}, + {file = "pyproj-3.6.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80fafd1f3eb421694857f254a9bdbacd1eb22fc6c24ca74b136679f376f97d35"}, + {file = "pyproj-3.6.1-cp310-cp310-win32.whl", hash = "sha256:c41e80ddee130450dcb8829af7118f1ab69eaf8169c4bf0ee8d52b72f098dc2f"}, + {file = "pyproj-3.6.1-cp310-cp310-win_amd64.whl", hash = "sha256:db3aedd458e7f7f21d8176f0a1d924f1ae06d725228302b872885a1c34f3119e"}, + {file = "pyproj-3.6.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ebfbdbd0936e178091309f6cd4fcb4decd9eab12aa513cdd9add89efa3ec2882"}, + {file = "pyproj-3.6.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:447db19c7efad70ff161e5e46a54ab9cc2399acebb656b6ccf63e4bc4a04b97a"}, + {file = "pyproj-3.6.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e7e13c40183884ec7f94eb8e0f622f08f1d5716150b8d7a134de48c6110fee85"}, + {file = "pyproj-3.6.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:65ad699e0c830e2b8565afe42bd58cc972b47d829b2e0e48ad9638386d994915"}, + {file = "pyproj-3.6.1-cp311-cp311-win32.whl", hash = "sha256:8b8acc31fb8702c54625f4d5a2a6543557bec3c28a0ef638778b7ab1d1772132"}, + {file = "pyproj-3.6.1-cp311-cp311-win_amd64.whl", hash = "sha256:38a3361941eb72b82bd9a18f60c78b0df8408416f9340521df442cebfc4306e2"}, + {file = "pyproj-3.6.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:1e9fbaf920f0f9b4ee62aab832be3ae3968f33f24e2e3f7fbb8c6728ef1d9746"}, + {file = "pyproj-3.6.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6d227a865356f225591b6732430b1d1781e946893789a609bb34f59d09b8b0f8"}, + {file = "pyproj-3.6.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:83039e5ae04e5afc974f7d25ee0870a80a6bd6b7957c3aca5613ccbe0d3e72bf"}, + {file = "pyproj-3.6.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fffb059ba3bced6f6725961ba758649261d85ed6ce670d3e3b0a26e81cf1aa8d"}, + {file = "pyproj-3.6.1-cp312-cp312-win32.whl", hash = "sha256:2d6ff73cc6dbbce3766b6c0bce70ce070193105d8de17aa2470009463682a8eb"}, + {file = "pyproj-3.6.1-cp312-cp312-win_amd64.whl", hash = "sha256:7a27151ddad8e1439ba70c9b4b2b617b290c39395fa9ddb7411ebb0eb86d6fb0"}, + {file = "pyproj-3.6.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4ba1f9b03d04d8cab24d6375609070580a26ce76eaed54631f03bab00a9c737b"}, + {file = "pyproj-3.6.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:18faa54a3ca475bfe6255156f2f2874e9a1c8917b0004eee9f664b86ccc513d3"}, + {file = "pyproj-3.6.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fd43bd9a9b9239805f406fd82ba6b106bf4838d9ef37c167d3ed70383943ade1"}, + {file = "pyproj-3.6.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50100b2726a3ca946906cbaa789dd0749f213abf0cbb877e6de72ca7aa50e1ae"}, + {file = "pyproj-3.6.1-cp39-cp39-win32.whl", hash = "sha256:9274880263256f6292ff644ca92c46d96aa7e57a75c6df3f11d636ce845a1877"}, + {file = "pyproj-3.6.1-cp39-cp39-win_amd64.whl", hash = "sha256:36b64c2cb6ea1cc091f329c5bd34f9c01bb5da8c8e4492c709bda6a09f96808f"}, + {file = "pyproj-3.6.1-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:fd93c1a0c6c4aedc77c0fe275a9f2aba4d59b8acf88cebfc19fe3c430cfabf4f"}, + {file = "pyproj-3.6.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6420ea8e7d2a88cb148b124429fba8cd2e0fae700a2d96eab7083c0928a85110"}, + {file = "pyproj-3.6.1.tar.gz", hash = "sha256:44aa7c704c2b7d8fb3d483bbf75af6cb2350d30a63b144279a09b75fead501bf"}, +] + +[package.dependencies] +certifi = "*" + [[package]] name = "pysdl2" version = "0.9.16" @@ -2294,18 +2328,19 @@ jeepney = ">=0.6" [[package]] name = "setuptools" -version = "70.3.0" +version = "71.1.0" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "setuptools-70.3.0-py3-none-any.whl", hash = "sha256:fe384da74336c398e0d956d1cae0669bc02eed936cdb1d49b57de1990dc11ffc"}, - {file = "setuptools-70.3.0.tar.gz", hash = "sha256:f171bab1dfbc86b132997f26a119f6056a57950d058587841a0082e8830f9dc5"}, + {file = "setuptools-71.1.0-py3-none-any.whl", hash = "sha256:33874fdc59b3188304b2e7c80d9029097ea31627180896fb549c578ceb8a0855"}, + {file = "setuptools-71.1.0.tar.gz", hash = "sha256:032d42ee9fb536e33087fb66cac5f840eb9391ed05637b3f2a76a7c8fb477936"}, ] [package.extras] +core = ["importlib-metadata (>=6)", "importlib-resources (>=5.10.2)", "jaraco.text (>=3.7)", "more-itertools (>=8.8)", "ordered-set (>=3.1.1)", "packaging (>=24)", "platformdirs (>=2.6.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"] doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"] -test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "importlib-metadata", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test", "mypy (==1.10.0)", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy", "pytest-perf", "pytest-ruff (>=0.3.2)", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] +test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "importlib-metadata", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test", "mypy (==1.11.*)", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy", "pytest-perf", "pytest-ruff (<0.4)", "pytest-ruff (>=0.2.1)", "pytest-ruff (>=0.3.2)", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] [[package]] name = "six" @@ -2341,13 +2376,13 @@ files = [ [[package]] name = "tomlkit" -version = "0.12.5" +version = "0.13.0" description = "Style preserving TOML library" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "tomlkit-0.12.5-py3-none-any.whl", hash = "sha256:af914f5a9c59ed9d0762c7b64d3b5d5df007448eb9cd2edc8a46b1eafead172f"}, - {file = "tomlkit-0.12.5.tar.gz", hash = "sha256:eef34fba39834d4d6b73c9ba7f3e4d1c417a4e56f89a7e96e090dd0d24b8fb3c"}, + {file = "tomlkit-0.13.0-py3-none-any.whl", hash = "sha256:7075d3042d03b80f603482d69bf0c8f345c2b30e41699fd8883227f89972b264"}, + {file = "tomlkit-0.13.0.tar.gz", hash = "sha256:08ad192699734149f5b97b45f1f18dad7eb1b6d16bc72ad0c2335772650d7b72"}, ] [[package]] @@ -2802,5 +2837,5 @@ test = ["big-O", "importlib-resources", "jaraco.functools", "jaraco.itertools", [metadata] lock-version = "2.0" -python-versions = ">=3.12,<3.13" -content-hash = "1482869ccae06d9a6bedac2644c08fc5169214a9d73cf7f9a65c7e8cfb84b474" +python-versions = "~3.12.0" +content-hash = "9962c10a2ae8e45f7b476b3c033d3fe5a75843230de808f0ad417447261acec9" diff --git a/pymammotion/__init__.py b/pymammotion/__init__.py index 140c1e0..fb60bb8 100644 --- a/pymammotion/__init__.py +++ b/pymammotion/__init__.py @@ -14,7 +14,19 @@ # TODO make a working device that will work outside HA too. from pymammotion.mammotion.devices import MammotionBaseBLEDevice -from pymammotion.mqtt.mqtt import LubaMQTT, logger +from pymammotion.mqtt import MammotionMQTT + + + +__all__ = [ + 'LubaBLE', + 'LubaHTTP', + 'connect_http', + 'MammotionBaseBLEDevice', + 'MammotionMQTT' +] + +logger = logging.getLogger(__name__) # TODO provide interface to pick between mqtt/cloud/bluetooth @@ -28,7 +40,7 @@ CLIENT_ID = os.environ.get("CLIENT_ID") IOT_TOKEN = os.environ.get("IOT_TOKEN") REGION = os.environ.get("REGION") - luba = LubaMQTT( + luba = MammotionMQTT( iot_token=IOT_TOKEN, region_id=REGION, product_key=PRODUCT_KEY, diff --git a/pymammotion/aliyun/cloud_gateway.py b/pymammotion/aliyun/cloud_gateway.py index 9b3e54c..bc32676 100644 --- a/pymammotion/aliyun/cloud_gateway.py +++ b/pymammotion/aliyun/cloud_gateway.py @@ -121,9 +121,7 @@ def get_region(self, country_code: str, auth_code: str): ) # send request - response = client.do_request( - "/living/account/region/get", "https", "POST", None, body, RuntimeOptions() - ) + response = client.do_request("/living/account/region/get", "https", "POST", None, body, RuntimeOptions()) logger.debug(response.status_message) logger.debug(response.headers) logger.debug(response.status_code) @@ -182,9 +180,7 @@ def aep_handle(self): ) # send request - response = client.do_request( - "/app/aepauth/handle", "https", "POST", None, body, RuntimeOptions() - ) + response = client.do_request("/app/aepauth/handle", "https", "POST", None, body, RuntimeOptions()) logger.debug(response.status_message) logger.debug(response.headers) logger.debug(response.status_code) @@ -195,9 +191,7 @@ def aep_handle(self): response_body_dict = json.loads(response_body_str) if int(response_body_dict.get("code")) != 200: - raise Exception( - "Error in getting mqtt credentials: " + response_body_dict["msg"] - ) + raise Exception("Error in getting mqtt credentials: " + response_body_dict["msg"]) self._aep_response = AepResponse.from_dict(response_body_dict) @@ -250,14 +244,12 @@ async def connect(self): header = "".join(f"{k}:{dic[k]}\n" for k in keys).strip() headers["x-ca-signature-headers"] = sign_headers - string_to_sign = ( - "POST\n{}\n\n{}\n{}\n{}\n/api/prd/connect.json?request={}".format( - headers["accept"], - headers["content-type"], - headers["date"], - header, - json.dumps(_bodyParam, separators=(",", ":")), - ) + string_to_sign = "POST\n{}\n\n{}\n{}\n{}\n/api/prd/connect.json?request={}".format( + headers["accept"], + headers["content-type"], + headers["date"], + header, + json.dumps(_bodyParam, separators=(",", ":")), ) hash_val = hmac.new( @@ -339,9 +331,7 @@ async def login_by_oauth(self, country_code: str, auth_code: str): async with session.post( f"https://{region_url}/api/prd/loginbyoauth.json", headers=headers, - params={ - "loginByOauthRequest": json.dumps(_bodyParam, separators=(",", ":")) - }, + params={"loginByOauthRequest": json.dumps(_bodyParam, separators=(",", ":"))}, ) as resp: data = await resp.json() logger.debug(data) @@ -395,9 +385,7 @@ def session_by_auth_code(self): if int(response_body_dict.get("code")) != 200: raise Exception("Error in creating session: " + response_body_dict["msg"]) - self._session_by_authcode_response = SessionByAuthCodeResponse.from_dict( - response_body_dict - ) + self._session_by_authcode_response = SessionByAuthCodeResponse.from_dict(response_body_dict) return response.body @@ -472,9 +460,7 @@ def list_binding_by_account(self): ) # send request - response = client.do_request( - "/uc/listBindingByAccount", "https", "POST", None, body, RuntimeOptions() - ) + response = client.do_request("/uc/listBindingByAccount", "https", "POST", None, body, RuntimeOptions()) logger.debug(response.status_message) logger.debug(response.headers) logger.debug(response.status_code) @@ -489,9 +475,7 @@ def list_binding_by_account(self): if int(response_body_dict.get("code")) != 200: raise Exception("Error in creating session: " + response_body_dict["msg"]) - self._listing_dev_by_account_response = ListingDevByAccountResponse.from_dict( - response_body_dict - ) + self._listing_dev_by_account_response = ListingDevByAccountResponse.from_dict(response_body_dict) def send_cloud_command(self, iot_id: str, command: bytes) -> str: """Send a cloud command to the specified IoT device.""" @@ -526,9 +510,7 @@ def send_cloud_command(self, iot_id: str, command: bytes) -> str: ) # send request - response = client.do_request( - "/thing/service/invoke", "https", "POST", None, body, RuntimeOptions() - ) + response = client.do_request("/thing/service/invoke", "https", "POST", None, body, RuntimeOptions()) logger.debug(response.status_message) logger.debug(response.headers) logger.debug(response.status_code) diff --git a/pymammotion/aliyun/tmp_constant.py b/pymammotion/aliyun/tmp_constant.py index 6e6925e..589349c 100644 --- a/pymammotion/aliyun/tmp_constant.py +++ b/pymammotion/aliyun/tmp_constant.py @@ -143,9 +143,7 @@ class tmp_constant: URI_ALINK_SERVICE = "alink/service" # deprecated URI_AUTH = "/auth" # deprecated URI_AUTHEN_REGISTER = "/sys/{productKey}/{deviceName}/thing/authen/sub/register" - URI_AUTHEN_REGISTER_REPLY = ( - "/sys/{productKey}/{deviceName}/thing/authen/sub/register_reply" - ) + URI_AUTHEN_REGISTER_REPLY = "/sys/{productKey}/{deviceName}/thing/authen/sub/register_reply" URI_BLACKLIST_UPDATE_POST = "/thing/lan/blacklist/update" URI_BLACKLIST_UPDATE_REPLY_POST = "/thing/lan/blacklist/update_reply" URI_DEVICE = "/device/core/dev" @@ -165,9 +163,7 @@ class tmp_constant: URI_TOPIC_LOCALDEVICE_STATECHANGE = "group/localstatechange" URI_TOPIC_REPLY_POST = "_reply" URI_UPDATE_DEVICE_INFO = "/sys/{productKey}/{deviceName}/thing/deviceinfo/update" - URI_UPDATE_DEVICE_INFO_REPLY = ( - "/sys/{productKey}/{deviceName}/thing/deviceinfo/update_reply" - ) + URI_UPDATE_DEVICE_INFO_REPLY = "/sys/{productKey}/{deviceName}/thing/deviceinfo/update_reply" URI_USER = "/user" VALUE_SHA256 = "sha256" VERSION = "1.0" diff --git a/pymammotion/bluetooth/ble.py b/pymammotion/bluetooth/ble.py index 065cad2..a494d51 100644 --- a/pymammotion/bluetooth/ble.py +++ b/pymammotion/bluetooth/ble.py @@ -46,15 +46,11 @@ async def disconnect(self) -> bool: if self.client is not None: return await self.client.disconnect() - async def notification_handler( - self, _characteristic: BleakGATTCharacteristic, data: bytearray - ): + async def notification_handler(self, _characteristic: BleakGATTCharacteristic, data: bytearray): """Simple notification handler which prints the data received.""" await self._bleEvt.BleNotification(data) - def service_changed_handler( - self, characteristic: BleakGATTCharacteristic, data: bytearray - ): + def service_changed_handler(self, characteristic: BleakGATTCharacteristic, data: bytearray): """Simple notification handler which prints the data received.""" print(f"Response 2 {characteristic.description}: {data}") print(data.decode("utf-8")) @@ -63,12 +59,8 @@ def service_changed_handler( async def notifications(self): if self.client.is_connected: - await self.client.start_notify( - UUID_NOTIFICATION_CHARACTERISTIC, self.notification_handler - ) - await self.client.start_notify( - SERVICE_CHANGED_CHARACTERISTIC, self.service_changed_handler - ) + await self.client.start_notify(UUID_NOTIFICATION_CHARACTERISTIC, self.notification_handler) + await self.client.start_notify(SERVICE_CHANGED_CHARACTERISTIC, self.service_changed_handler) def getClient(self): return self.client diff --git a/pymammotion/bluetooth/ble_message.py b/pymammotion/bluetooth/ble_message.py index 7ee910b..1ebde2e 100644 --- a/pymammotion/bluetooth/ble_message.py +++ b/pymammotion/bluetooth/ble_message.py @@ -79,15 +79,11 @@ async def get_device_version_main(self): async def get_task(self): hash_map = {"pver": 1, "subCmd": 2, "result": 0} - await self.messageNavigation.post_custom_data( - self.get_json_string(bleOrderCmd.task, hash_map) - ) + await self.messageNavigation.post_custom_data(self.get_json_string(bleOrderCmd.task, hash_map)) async def send_ble_alive(self): hash_map = {"ctrl": 1} - await self.messageNavigation.post_custom_data( - self.get_json_string(bleOrderCmd.bleAlive, hash_map) - ) + await self.messageNavigation.post_custom_data(self.get_json_string(bleOrderCmd.bleAlive, hash_map)) def clearNotification(self): self.notification = None @@ -106,9 +102,7 @@ async def send_device_info(self): seqs=1, version=1, subtype=1, - net=dev_net_pb2.DevNet( - todev_ble_sync=1, todev_devinfo_req=dev_net_pb2.DrvDevInfoReq() - ), + net=dev_net_pb2.DevNet(todev_ble_sync=1, todev_devinfo_req=dev_net_pb2.DrvDevInfoReq()), ) byte_arr = luba_msg.SerializeToString() await self.post_custom_data_bytes(byte_arr) @@ -117,9 +111,7 @@ async def requestDeviceStatus(self): request = False type = self.messageNavigation.getTypeValue(0, 5) try: - request = await self.messageNavigation.post( - BleMessage.mEncrypted, BleMessage.mChecksum, False, type, None - ) + request = await self.messageNavigation.post(BleMessage.mEncrypted, BleMessage.mChecksum, False, type, None) # print(request) except Exception as err: # Log.w(TAG, "post requestDeviceStatus interrupted") @@ -133,9 +125,7 @@ async def requestDeviceVersion(self): request = False type = self.messageNavigation.getTypeValue(0, 7) try: - request = await self.messageNavigation.post( - BleMessage.mEncrypted, BleMessage.mChecksum, False, type, None - ) + request = await self.messageNavigation.post(BleMessage.mEncrypted, BleMessage.mChecksum, False, type, None) # print(request) except Exception as err: # Log.w(TAG, "post requestDeviceStatus interrupted") @@ -318,9 +308,7 @@ async def post_custom_data_bytes(self, data: bytes): return type_val = self.getTypeValue(1, 19) try: - suc = await self.post( - self.mEncrypted, self.mChecksum, self.mRequireAck, type_val, data - ) + suc = await self.post(self.mEncrypted, self.mChecksum, self.mRequireAck, type_val, data) # int status = suc ? 0 : BlufiCallback.CODE_WRITE_DATA_FAILED # onPostCustomDataResult(status, data) # print(suc) @@ -333,9 +321,7 @@ async def post_custom_data(self, data_str: str): return type_val = self.getTypeValue(1, 19) try: - suc = await self.post( - self.mEncrypted, self.mChecksum, self.mRequireAck, type_val, data - ) + suc = await self.post(self.mEncrypted, self.mChecksum, self.mRequireAck, type_val, data) # int status = suc ? 0 : BlufiCallback.CODE_WRITE_DATA_FAILED # onPostCustomDataResult(status, data) except Exception as err: @@ -352,17 +338,11 @@ async def post( if data is None: return await self.post_non_data(encrypt, checksum, require_ack, type_of) - return await self.post_contains_data( - encrypt, checksum, require_ack, type_of, data - ) + return await self.post_contains_data(encrypt, checksum, require_ack, type_of, data) - async def post_non_data( - self, encrypt: bool, checksum: bool, require_ack: bool, type_of: int - ) -> bool: + async def post_non_data(self, encrypt: bool, checksum: bool, require_ack: bool, type_of: int) -> bool: sequence = self.generateSendSequence() - postBytes = self.getPostBytes( - type_of, encrypt, checksum, require_ack, False, sequence, None - ) + postBytes = self.getPostBytes(type_of, encrypt, checksum, require_ack, False, sequence, None) posted = await self.gatt_write(postBytes) return posted and (not require_ack or self.receiveAck(sequence)) @@ -385,9 +365,7 @@ async def post_contains_data( for index, chunk in enumerate(chunks): frag = index != len(chunks) - 1 sequence = self.generateSendSequence() - postBytes = self.getPostBytes( - type_of, encrypt, checksum, require_ack, frag, sequence, chunk - ) + postBytes = self.getPostBytes(type_of, encrypt, checksum, require_ack, frag, sequence, chunk) # print("sequence") # print(sequence) posted = await self.gatt_write(postBytes) @@ -415,9 +393,7 @@ def getPostBytes( ) -> bytes: byteOS = BytesIO() dataLength = 0 if data == None else len(data) - frameCtrl = FrameCtrlData.getFrameCTRLValue( - encrypt, checksum, 0, require_ack, hasFrag - ) + frameCtrl = FrameCtrlData.getFrameCTRLValue(encrypt, checksum, 0, require_ack, hasFrag) byteOS.write(type.to_bytes(1, sys.byteorder)) byteOS.write(frameCtrl.to_bytes(1, sys.byteorder)) byteOS.write(sequence.to_bytes(1, sys.byteorder)) diff --git a/pymammotion/bluetooth/data/convert.py b/pymammotion/bluetooth/data/convert.py index 127c9d1..c25be18 100644 --- a/pymammotion/bluetooth/data/convert.py +++ b/pymammotion/bluetooth/data/convert.py @@ -19,9 +19,7 @@ def store_sys_data(sys): tard_state_data_list = sys.systemTardStateTunnel.tard_state_data longValue8 = tard_state_data_list[0] longValue9 = tard_state_data_list[1] - print( - "Device status report,deviceState:", longValue8, ",deviceName:", "Luba..." - ) + print("Device status report,deviceState:", longValue8, ",deviceName:", "Luba...") chargeStateTemp = longValue9 longValue10 = tard_state_data_list[6] longValue11 = tard_state_data_list[7] diff --git a/pymammotion/bluetooth/data/notifydata.py b/pymammotion/bluetooth/data/notifydata.py index b164376..1e11e53 100644 --- a/pymammotion/bluetooth/data/notifydata.py +++ b/pymammotion/bluetooth/data/notifydata.py @@ -59,5 +59,4 @@ def addData(self, bArr, i): # JADX INFO: Access modifiers changed from: package-private def getDataArray(self): """Generated source for method getDataArray""" - print("data Array") return self.mDataOS.getvalue() diff --git a/pymammotion/data/model/device.py b/pymammotion/data/model/device.py index 4d8d0b7..e2e556b 100644 --- a/pymammotion/data/model/device.py +++ b/pymammotion/data/model/device.py @@ -2,6 +2,8 @@ from dataclasses import dataclass +from pymammotion.data.model import HashList +from pymammotion.data.model.location import Location from pymammotion.proto.dev_net import DevNet from pymammotion.proto.luba_msg import LubaMsg from pymammotion.proto.luba_mul import SocMul @@ -9,19 +11,76 @@ from pymammotion.proto.mctrl_nav import MctlNav from pymammotion.proto.mctrl_ota import MctlOta from pymammotion.proto.mctrl_pept import MctlPept -from pymammotion.proto.mctrl_sys import MctlSys +from pymammotion.proto.mctrl_sys import MctlSys, SystemUpdateBufMsg @dataclass class MowingDevice: - """Wraps the betterproto dataclasses so we can bypass the groups for keeping all data.""" + """Wraps the betterproto dataclasses, so we can bypass the groups for keeping all data.""" device: LubaMsg + map: HashList + location: Location + + def __init__(self): + self.device = LubaMsg() + self.map = HashList(area={}, path={}, obstacle={}) + self.location = Location() + self.err_code_list = [] + self.err_code_list_time = [] @classmethod def from_raw(cls, raw: dict) -> "MowingDevice": """Take in raw data to hold in the betterproto dataclass.""" - return MowingDevice(device=LubaMsg(**raw)) + mowing_device = MowingDevice() + mowing_device.device = LubaMsg(**raw) + return mowing_device + + def update_raw(self, raw: dict) -> None: + """Update the raw LubaMsg data.""" + self.device = LubaMsg(**raw) + + def buffer(self, buffer_list: SystemUpdateBufMsg): + """Update the device based on which buffer we are reading from.""" + match buffer_list.update_buf_data[0]: + case 1: + # 4 speed + self.location.RTK.latitude = buffer_list.update_buf_data[5] + self.location.RTK.longitude = buffer_list.update_buf_data[6] + self.location.dock.latitude = buffer_list.update_buf_data[7] + self.location.dock.longitude = buffer_list.update_buf_data[8] + self.location.dock.rotation = buffer_list.update_buf_data[3] + 180 + case 2: + self.err_code_list.clear() + self.err_code_list_time.clear() + self.err_code_list.extend( + [ + buffer_list.update_buf_data[3], + buffer_list.update_buf_data[5], + buffer_list.update_buf_data[7], + buffer_list.update_buf_data[9], + buffer_list.update_buf_data[11], + buffer_list.update_buf_data[13], + buffer_list.update_buf_data[15], + buffer_list.update_buf_data[17], + buffer_list.update_buf_data[19], + buffer_list.update_buf_data[21], + ] + ) + self.err_code_list_time.extend( + [ + buffer_list.update_buf_data[4], + buffer_list.update_buf_data[6], + buffer_list.update_buf_data[8], + buffer_list.update_buf_data[10], + buffer_list.update_buf_data[12], + buffer_list.update_buf_data[14], + buffer_list.update_buf_data[16], + buffer_list.update_buf_data[18], + buffer_list.update_buf_data[20], + buffer_list.update_buf_data[22], + ] + ) @property def net(self): diff --git a/pymammotion/data/model/hash_list.py b/pymammotion/data/model/hash_list.py index 51170c2..2d7743a 100644 --- a/pymammotion/data/model/hash_list.py +++ b/pymammotion/data/model/hash_list.py @@ -1,17 +1,37 @@ -import typing +from dataclasses import dataclass +from pymammotion.proto.mctrl_nav import NavGetCommDataAck + +@dataclass +class FrameList: + total_frame: int + data: list[NavGetCommDataAck] + + +@dataclass class HashList: - def __init__(self): - self.pver: int = 0 - self.subCmd: int = 0 - self.totalFrame: int = 0 - self.currentFrame: int = 0 - self.dataHash: int = 0 - self.path: typing.List[int] = [] - - def __str__(self) -> str: - return ( - f"HashBean{{pver={self.pver}, subCmd={self.subCmd}, totalFrame={self.totalFrame}, " - + f"currentFrame={self.currentFrame}, dataHash={self.dataHash}, path={self.path}}}" - ) + """stores our map data. + [hashID, FrameList]. + """ + + area: dict # type 0 + path: dict # type 2 + obstacle: dict # type 1 + + def update(self, hash_data: NavGetCommDataAck): + """Update the map data.""" + if hash_data.type == 0: + if self.area.get(hash_data.hash) is None: + self.area[hash_data.hash] = FrameList(total_frame=hash_data.total_frame, data=[hash_data]) + self.area[hash_data.hash].data.append(hash_data) + + if hash_data.type == 1: + if self.obstacle.get(hash_data.hash) is None: + self.obstacle[hash_data.hash] = FrameList(total_frame=hash_data.total_frame, data=[hash_data]) + self.obstacle[hash_data.hash].data.append(hash_data) + + if hash_data.type == 2: + if self.path.get(hash_data.hash) is None: + self.path[hash_data.hash] = FrameList(total_frame=hash_data.total_frame, data=[hash_data]) + self.path[hash_data.hash].data.append(hash_data) diff --git a/pymammotion/data/model/location.py b/pymammotion/data/model/location.py new file mode 100644 index 0000000..a53fc1d --- /dev/null +++ b/pymammotion/data/model/location.py @@ -0,0 +1,40 @@ +"""Contains RTK models for robot location and RTK positions.""" + +from dataclasses import dataclass + + +@dataclass +class Point: + """Returns a lat long.""" + + latitude: float + longitude: float + + def __init__(self): + self.latitude = 0 + self.longitude = 0 + + +@dataclass +class Dock(Point): + """Stores robot dock position.""" + + rotation: int + + def __init__(self): + super().__init__() + self.rotation = 0 + + +@dataclass +class Location: + """Stores/retrieves RTK GPS data.""" + + device: Point + RTK: Point + dock: Dock + + def __init__(self): + self.device = Point() + self.RTK = Point() + self.dock = Dock() diff --git a/pymammotion/data/model/rapid_state.py b/pymammotion/data/model/rapid_state.py index 63c44a7..51ca219 100644 --- a/pymammotion/data/model/rapid_state.py +++ b/pymammotion/data/model/rapid_state.py @@ -26,11 +26,7 @@ class RapidState: @classmethod def from_raw(cls, raw: list[int]) -> "RapidState": return RapidState( - rtk_status=RTKStatus.FINE - if raw[0] == 4 - else RTKStatus.BAD - if raw[0] in (1, 5) - else RTKStatus.NONE, + rtk_status=RTKStatus.FINE if raw[0] == 4 else RTKStatus.BAD if raw[0] in (1, 5) else RTKStatus.NONE, pos_level=raw[1], satellites_total=raw[2], rtk_age=raw[3] / 10000, diff --git a/pymammotion/data/state_manager.py b/pymammotion/data/state_manager.py new file mode 100644 index 0000000..5abae6a --- /dev/null +++ b/pymammotion/data/state_manager.py @@ -0,0 +1,84 @@ +"""Manage state from notifications into MowingDevice.""" + +import betterproto + +from pymammotion.data.model.device import MowingDevice +from pymammotion.event.event import DataEvent +from pymammotion.proto.luba_msg import LubaMsg + + +class StateManager: + """Manage state.""" + + _device: MowingDevice + gethash_ack_callback: DataEvent + get_commondata_ack_callback: DataEvent + + def __init__(self, device: MowingDevice): + self._device = device + self.gethash_ack_callback = DataEvent() + self.get_commondata_ack_callback = DataEvent() + + def get_device(self) -> MowingDevice: + """Get device.""" + return self._device + + def set_device(self, device: MowingDevice): + """Set device.""" + self._device = device + + async def notification(self, message: LubaMsg): + """Handle protobuf notifications.""" + res = betterproto.which_one_of(message, "LubaSubMsg") + + match res[0]: + case "nav": + await self._update_nav_data(message) + case "sys": + self._update_sys_data(message) + case "driver": + self._update_driver_data(message) + case "net": + self._update_net_data(message) + case "mul": + self._update_mul_data(message) + case "ota": + self._update_ota_data(message) + + async def _update_nav_data(self, message): + """Update nav data.""" + nav_msg = betterproto.which_one_of(message.nav, "SubNavMsg") + match nav_msg[0]: + case "toapp_gethash_ack": + # call callback to handle this data + print(nav_msg[1]) + await self.gethash_ack_callback.data_event(nav_msg[1]) + case "toapp_get_commondata_ack": + # callback to additional method + print(nav_msg[1]) + self._device.map.update(nav_msg[1]) + await self.get_commondata_ack_callback.data_event(nav_msg[1]) + + def _update_sys_data(self, message): + """Update system.""" + sys_msg = betterproto.which_one_of(message.sys, "SubSysMsg") + match sys_msg[0]: + case "system_update_buf": + # call callback to handle this data + print(sys_msg[1]) + self._device.buffer(sys_msg[1]) + case "toapp_report_data": + # data for sensors + pass + + def _update_driver_data(self, message): + pass + + def _update_net_data(self, message): + pass + + def _update_mul_data(self, message): + pass + + def _update_ota_data(self, message): + pass diff --git a/pymammotion/event/event.py b/pymammotion/event/event.py index e235aa7..1ba0e38 100644 --- a/pymammotion/event/event.py +++ b/pymammotion/event/event.py @@ -14,9 +14,7 @@ def __isub__(self, handler): return self async def __call__(self, *args, **kwargs): - await asyncio.gather( - *[handler(*args, **kwargs) for handler in self.__eventhandlers] - ) + await asyncio.gather(*[handler(*args, **kwargs) for handler in self.__eventhandlers]) class MoveEvent: @@ -48,3 +46,20 @@ def AddSubscribersForBleNotificationEvent(self, objMethod): def RemoveSubscribersForBleNotificationEvent(self, objMethod): self.OnBleNotification -= objMethod + + +class DataEvent: + """Callbacks for data events.""" + + def __init__(self): + self.on_data_event = Event() + + async def data_event(self, data): + # This function will be executed when data is received. + await self.on_data_event(data) + + def add_subscribers(self, obj_method): + self.on_data_event += obj_method + + def remove_subscribers(self, obj_method): + self.on_data_event -= obj_method diff --git a/pymammotion/http/http.py b/pymammotion/http/http.py index 255a3d7..932cb15 100644 --- a/pymammotion/http/http.py +++ b/pymammotion/http/http.py @@ -51,9 +51,7 @@ def __init__(self, session: ClientSession, login: LoginResponseData): self._login = login @classmethod - async def login( - cls, session: ClientSession, username: str, password: str - ) -> Response[LoginResponseData]: + async def login(cls, session: ClientSession, username: str, password: str) -> Response[LoginResponseData]: async with session.post( "/user-server/v1/user/oauth/token", params=dict( @@ -69,9 +67,7 @@ async def login( # TODO catch errors from mismatch user / password # Assuming the data format matches the expected structure login_response_data = LoginResponseData.from_dict(data["data"]) - return Response( - data=login_response_data, code=data["code"], msg=data["msg"] - ) + return Response(data=login_response_data, code=data["code"], msg=data["msg"]) async def connect_http(username: str, password: str) -> LubaHTTP: diff --git a/pymammotion/mammotion/commands/mammotion_command.py b/pymammotion/mammotion/commands/mammotion_command.py index 8bd7ff4..534746e 100644 --- a/pymammotion/mammotion/commands/mammotion_command.py +++ b/pymammotion/mammotion/commands/mammotion_command.py @@ -6,9 +6,7 @@ from pymammotion.proto import dev_net_pb2, luba_msg_pb2 -class MammotionCommand( - MessageSystem, MessageNavigation, MessageNetwork, MessageOta, MessageVideo -): +class MammotionCommand(MessageSystem, MessageNavigation, MessageNetwork, MessageOta, MessageVideo): """MQTT commands for Luba.""" def __init__(self, device_name: str) -> None: diff --git a/pymammotion/mammotion/commands/messages/driver.py b/pymammotion/mammotion/commands/messages/driver.py index 7c472ac..34eb9b9 100644 --- a/pymammotion/mammotion/commands/messages/driver.py +++ b/pymammotion/mammotion/commands/messages/driver.py @@ -28,49 +28,35 @@ def send_order_msg_driver(driver): def set_blade_height(self, height: int): logger.debug(f"Send knife height height={height}") - build = mctrl_driver_pb2.MctlDriver( - todev_knife_height_set=mctrl_driver_pb2.DrvKnifeHeight(knifeHeight=height) - ) + build = mctrl_driver_pb2.MctlDriver(todev_knife_height_set=mctrl_driver_pb2.DrvKnifeHeight(knifeHeight=height)) logger.debug(f"Send command--Knife motor height setting height={height}") return self.send_order_msg_driver(build) def set_speed(self, speed: float): logger.debug(f"{self.get_device_name()} set speed, {speed}") - build = mctrl_driver_pb2.MctlDriver( - bidire_speed_read_set=mctrl_driver_pb2.DrvSrSpeed(speed=speed, rw=1) - ) + build = mctrl_driver_pb2.MctlDriver(bidire_speed_read_set=mctrl_driver_pb2.DrvSrSpeed(speed=speed, rw=1)) logger.debug(f"Send command--Speed setting speed={speed}") return self.send_order_msg_driver(build) def syn_nav_star_point_data(self, sat_system: int): build = mctrl_driver_pb2.MctlDriver( - rtk_sys_mask_query=mctrl_driver_pb2.rtk_sys_mask_query_t( - sat_system=sat_system - ) - ) - logger.debug( - f"Send command--Navigation satellite frequency point synchronization={sat_system}" + rtk_sys_mask_query=mctrl_driver_pb2.rtk_sys_mask_query_t(sat_system=sat_system) ) + logger.debug(f"Send command--Navigation satellite frequency point synchronization={sat_system}") return self.send_order_msg_driver(build) def set_nav_star_point(self, cmd_req: str): build = mctrl_driver_pb2.MctlDriver( - rtk_cfg_req=mctrl_driver_pb2.rtk_cfg_req_t( - cmd_req=cmd_req, cmd_length=len(cmd_req) - 1 - ) - ) - logger.debug( - f"Send command--Navigation satellite frequency point setting={cmd_req}" + rtk_cfg_req=mctrl_driver_pb2.rtk_cfg_req_t(cmd_req=cmd_req, cmd_length=len(cmd_req) - 1) ) + logger.debug(f"Send command--Navigation satellite frequency point setting={cmd_req}") logger.debug( f"Navigation satellite setting, Send command--Navigation satellite frequency point setting={cmd_req}" ) return self.send_order_msg_driver(build) def get_speed(self): - build = mctrl_driver_pb2.MctlDriver( - bidire_speed_read_set=mctrl_driver_pb2.DrvSrSpeed(rw=0) - ) + build = mctrl_driver_pb2.MctlDriver(bidire_speed_read_set=mctrl_driver_pb2.DrvSrSpeed(rw=0)) logger.debug("Send command--Get speed value") return self.send_order_msg_driver(build) diff --git a/pymammotion/mammotion/commands/messages/media.py b/pymammotion/mammotion/commands/messages/media.py index d7d97bf..51b52fb 100644 --- a/pymammotion/mammotion/commands/messages/media.py +++ b/pymammotion/mammotion/commands/messages/media.py @@ -4,6 +4,7 @@ class MessageMedia: + @staticmethod def send_order_msg_media(self, mul): luba_msg = luba_msg_pb2.LubaMsg( msgtype=luba_msg_pb2.MSG_CMD_TYPE_MUL, @@ -19,18 +20,12 @@ def send_order_msg_media(self, mul): return luba_msg.SerializeToString() def set_car_volume(self, volume: int): - return self.send_order_msg_media( - luba_mul_pb2.SocMul(set_audio=luba_mul_pb2.MulSetAudio(at_switch=volume)) - ) + return self.send_order_msg_media(luba_mul_pb2.SocMul(set_audio=luba_mul_pb2.MulSetAudio(at_switch=volume))) def set_car_voice_language(self, language_type: MUL_LANGUAGE | str | None): return self.send_order_msg_media( - luba_mul_pb2.SocMul( - set_audio=luba_mul_pb2.MulSetAudio(au_language=language_type) - ) + luba_mul_pb2.SocMul(set_audio=luba_mul_pb2.MulSetAudio(au_language=language_type)) ) def set_car_wiper(self, round_num: int): - return self.send_order_msg_media( - luba_mul_pb2.SocMul(set_wiper=luba_mul_pb2.MulSetWiper(round=round_num)) - ) + return self.send_order_msg_media(luba_mul_pb2.SocMul(set_wiper=luba_mul_pb2.MulSetWiper(round=round_num))) diff --git a/pymammotion/mammotion/commands/messages/navigation.py b/pymammotion/mammotion/commands/messages/navigation.py index e521f1e..c0c353f 100644 --- a/pymammotion/mammotion/commands/messages/navigation.py +++ b/pymammotion/mammotion/commands/messages/navigation.py @@ -1,5 +1,6 @@ # === sendOrderMsg_Nav === import logging +import time from abc import ABC from typing import List @@ -40,15 +41,14 @@ def send_order_msg_nav(build) -> bytes: version=1, subtype=1, nav=build, + timestamp=round(time.time() * 1000), ) return luba_msg.SerializeToString() def allpowerfull_rw_adapter_x3(self, id: int, context: int, rw: int) -> bytes: build = MctlNav(nav_sys_param_cmd=NavSysParamMsg(id=id, context=context, rw=rw)) - logger.debug( - f"Send command--9 general read and write command id={id}, context={context}, rw={rw}" - ) + logger.debug(f"Send command--9 general read and write command id={id}, context={context}, rw={rw}") return self.send_order_msg_nav(build) def along_border(self): @@ -83,9 +83,7 @@ def exit_dumping_status(self): def out_drop_dumping_add(self): build = MctlNav(todev_get_commondata=NavGetCommData(pver=1, action=15, type=12)) - logger.debug( - "Send command--Complete external grass collection point marking operation" - ) + logger.debug("Send command--Complete external grass collection point marking operation") return self.send_order_msg_nav(build) def recover_dumping(self): @@ -124,22 +122,14 @@ def save_task(self): return self.send_order_msg_nav(build) def set_edit_boundary(self, action: int): - build = MctlNav( - todev_get_commondata=NavGetCommData(pver=1, action=action, type=0) - ) + build = MctlNav(todev_get_commondata=NavGetCommData(pver=1, action=action, type=0)) logger.debug(f"Sending secondary editing command action={action}") return self.send_order_msg_nav(build) def set_data_synchronization(self, type: int): - logger.debug( - f"Sync data ==================== Sending ============ Restore command: {type}" - ) - build = MctlNav( - todev_get_commondata=NavGetCommData(pver=1, action=12, type=type) - ) - logger.debug( - "Sync data ==================== Sending ============ Restore command" - ) + logger.debug(f"Sync data ==================== Sending ============ Restore command: {type}") + build = MctlNav(todev_get_commondata=NavGetCommData(pver=1, action=12, type=type)) + logger.debug("Sync data ==================== Sending ============ Restore command") return self.send_order_msg_nav(build) def send_plan(self, plan_bean: Plan) -> bytes: @@ -223,30 +213,19 @@ def send_schedule(self, plan_bean: Plan) -> bytes: return self.send_order_msg_nav(MctlNav(todev_planjob_set=build)) def single_schedule(self, plan_id: str) -> bytes: - return self.send_order_msg_nav( - MctlNav(plan_task_execute=NavPlanTaskExecute(sub_cmd=1, id=plan_id)) - ) + return self.send_order_msg_nav(MctlNav(plan_task_execute=NavPlanTaskExecute(sub_cmd=1, id=plan_id))) - def read_plan(self, sub_cmd: int, plan_index: int) -> bytes: - build = MctlNav( - todev_planjob_set=NavPlanJobSet(sub_cmd=sub_cmd, plan_index=plan_index) - ) - logger.debug(f"Send read job plan command cmd={ - sub_cmd} PlanIndex = {plan_index}") + def read_plan(self, sub_cmd: int, plan_index: int = 0) -> bytes: + build = MctlNav(todev_planjob_set=NavPlanJobSet(sub_cmd=sub_cmd, plan_index=plan_index)) + logger.debug(f"Send read job plan command cmd={sub_cmd} PlanIndex = {plan_index}") return self.send_order_msg_nav(build) def delete_plan(self, sub_cmd: int, plan_id: str) -> bytes: - build = MctlNav( - todev_planjob_set=NavPlanJobSet(sub_cmd=sub_cmd, plan_id=plan_id) - ) - logger.debug( - f"Send command--Send delete job plan command cmd={sub_cmd} planId = {plan_id}" - ) + build = MctlNav(todev_planjob_set=NavPlanJobSet(sub_cmd=sub_cmd, plan_id=plan_id)) + logger.debug(f"Send command--Send delete job plan command cmd={sub_cmd} planId = {plan_id}") return self.send_order_msg_nav(build) - def set_plan_unable_time( - self, sub_cmd: int, device_id: str, unable_end_time: str, unable_start_time: str - ) -> bytes: + def set_plan_unable_time(self, sub_cmd: int, device_id: str, unable_end_time: str, unable_start_time: str) -> bytes: build = NavUnableTimeSet( sub_cmd=sub_cmd, device_id=device_id, @@ -265,16 +244,10 @@ def read_plan_unable_time(self, sub_cmd: int) -> bytes: return self.send_order_msg_nav(build2) def query_job_history(self) -> bytes: - return self.send_order_msg_nav( - MctlNav(todev_work_report_update_cmd=WorkReportUpdateCmd(sub_cmd=1)) - ) + return self.send_order_msg_nav(MctlNav(todev_work_report_update_cmd=WorkReportUpdateCmd(sub_cmd=1))) def request_job_history(self, num: int) -> bytes: - return self.send_order_msg_nav( - MctlNav( - todev_work_report_cmd=WorkReportCmdData(sub_cmd=1, get_info_num=num) - ) - ) + return self.send_order_msg_nav(MctlNav(todev_work_report_cmd=WorkReportCmdData(sub_cmd=1, get_info_num=num))) def leave_dock(self): build = MctlNav(todev_one_touch_leave_pile=1) @@ -283,45 +256,37 @@ def leave_dock(self): def get_all_boundary_hash_list(self, sub_cmd: int): build = MctlNav(todev_gethash=NavGetHashList(pver=1, sub_cmd=sub_cmd)) - logger.debug(f"Area loading=====================:Get area hash list++Bluetooth:{ - sub_cmd}") + logger.debug(f"Area loading=====================:Get area hash list++Bluetooth:{sub_cmd}") return self.send_order_msg_nav(build) def get_hash_response(self, total_frame: int, current_frame: int): build = MctlNav( - todev_gethash=NavGetHashList( - pver=1, sub_cmd=2, current_frame=current_frame, total_frame=total_frame - ) + todev_gethash=NavGetHashList(pver=1, sub_cmd=2, current_frame=current_frame, total_frame=total_frame) + ) + logger.debug( + f"Send command--208 Response hash list command totalFrame={total_frame},currentFrame={current_frame}" ) - logger.debug(f"Send command--208 Response hash list command totalFrame={ - total_frame},currentFrame={current_frame}") return self.send_order_msg_nav(build) def synchronize_hash_data(self, hash_num: int): - build = MctlNav( - todev_get_commondata=NavGetCommData( - pver=1, action=8, data_hash=hash_num, sub_cmd=1 - ) - ) + build = MctlNav(todev_get_commondata=NavGetCommData(pver=1, action=8, hash=hash_num, sub_cmd=1)) logger.debug(f"Send command--209,hash synchronize area data hash:{hash}") return self.send_order_msg_nav(build) def get_area_to_be_transferred(self): - build = MctlNav( - todev_get_commondata=NavGetCommData(pver=1, action=8, sub_cmd=1, type=3) - ) + build = MctlNav(todev_get_commondata=NavGetCommData(pver=1, action=8, sub_cmd=1, type=3)) logger.debug("Send command--Get transfer area before charging pile") return self.send_order_msg_nav(build) - def get_regional_data(self, regional_data_bean: RegionData): + def get_regional_data(self, regional_data: RegionData): build = MctlNav( todev_get_commondata=NavGetCommData( pver=1, - action=regional_data_bean.action, - type=regional_data_bean.type, - data_hash=regional_data_bean.hash, - total_frame=regional_data_bean.total_frame, - current_frame=regional_data_bean.current_frame, + action=regional_data.action, + type=regional_data.type, + hash=regional_data.hash, + total_frame=regional_data.total_frame, + current_frame=regional_data.current_frame, sub_cmd=2, ) ) @@ -334,43 +299,27 @@ def indoor_simulation(self, flag: int): return self.send_order_msg_nav(build) def send_tools_order(self, param_id: int, values: List[int]): - build = MctlNav( - simulation_cmd=SimulationCmdData( - sub_cmd=2, param_id=param_id, param_value=values - ) - ) + build = MctlNav(simulation_cmd=SimulationCmdData(sub_cmd=2, param_id=param_id, param_value=values)) logger.debug(f"Send command--Send tool command id={param_id},values={values}") return self.send_order_msg_nav(build) def end_draw_border(self, type: int): if type == -1: return - build = MctlNav( - todev_get_commondata=NavGetCommData(pver=1, action=1, type=type) - ) - logger.debug( - f"Send command--End drawing boundary, obstacle, channel command type={type}" - ) + build = MctlNav(todev_get_commondata=NavGetCommData(pver=1, action=1, type=type)) + logger.debug(f"Send command--End drawing boundary, obstacle, channel command type={type}") return self.send_order_msg_nav(build) def cancel_current_record(self): - build = MctlNav( - todev_get_commondata=NavGetCommData(pver=1, action=7, sub_cmd=0) - ) + build = MctlNav(todev_get_commondata=NavGetCommData(pver=1, action=7, sub_cmd=0)) logger.debug("Send command--Cancel current recording (boundary, obstacle)") return self.send_order_msg_nav(build) def delete_map_elements(self, type: int, hash_num: int): if type == -1: return - build = MctlNav( - todev_get_commondata=NavGetCommData( - pver=1, action=6, type=type, hash=hash_num - ) - ) - logger.debug( - f"Send command--Delete boundary or obstacle or channel command type={type},hash={hash}" - ) + build = MctlNav(todev_get_commondata=NavGetCommData(pver=1, action=6, type=type, hash=hash_num)) + logger.debug(f"Send command--Delete boundary or obstacle or channel command type={type},hash={hash}") return self.send_order_msg_nav(build) def delete_charge_point(self): @@ -390,9 +339,7 @@ def delete_all(self): logger.debug("Send command--Clear job data") return self.send_order_msg_nav(build) - def generate_route_information( - self, generate_route_information: GenerateRouteInformation - ): + def generate_route_information(self, generate_route_information: GenerateRouteInformation): logger.debug(f"Generate route data source:{generate_route_information}") build = NavReqCoverPath( pver=1, @@ -415,9 +362,7 @@ def generate_route_information( generate_route_information}") return self.send_order_msg_nav(MctlNav(bidire_reqconver_path=build)) - def modify_generate_route_information( - self, generate_route_information: GenerateRouteInformation - ): + def modify_generate_route_information(self, generate_route_information: GenerateRouteInformation): logger.debug(f"Generate route data source: {generate_route_information}") build = NavReqCoverPath( pver=1, @@ -442,9 +387,7 @@ def end_generate_route_information(self): build = NavReqCoverPath(pver=1, sub_cmd=9) logger.debug(f"{self.get_device_name()} Generate route ===== {build}") build2 = MctlNav(bidire_reqconver_path=build) - logger.debug( - "Send command -- End generating route information generate_route_information=" - ) + logger.debug("Send command -- End generating route information generate_route_information=") return self.send_order_msg_nav(build2) def query_generate_route_information(self): @@ -456,14 +399,8 @@ def query_generate_route_information(self): def get_line_info(self, current_hash: int) -> bytes: logger.debug(f"Sending==========Get route command: {current_hash}") - build = MctlNav( - todev_zigzag_ack=NavUploadZigZagResultAck( - pver=1, current_hash=current_hash, sub_cmd=0 - ) - ) - logger.debug( - f"Sending command--Get route data corresponding to hash={current_hash}" - ) + build = MctlNav(todev_zigzag_ack=NavUploadZigZagResultAck(pver=1, current_hash=current_hash, sub_cmd=0)) + logger.debug(f"Sending command--Get route data corresponding to hash={current_hash}") return self.send_order_msg_nav(build) def get_line_info_list(self, hash_list: List[int], transaction_id: int) -> bytes: @@ -473,9 +410,7 @@ def get_line_info_list(self, hash_list: List[int], transaction_id: int) -> bytes pver=1, hash_list=hash_list, transaction_id=transaction_id, sub_cmd=0 ) ) - logger.debug( - f"Sending command--Get route data corresponding to hash={hash_list}" - ) + logger.debug(f"Sending command--Get route data corresponding to hash={hash_list}") return self.send_order_msg_nav(build) def start_job(self) -> bytes: diff --git a/pymammotion/mammotion/commands/messages/network.py b/pymammotion/mammotion/commands/messages/network.py index 571600a..3a13e83 100644 --- a/pymammotion/mammotion/commands/messages/network.py +++ b/pymammotion/mammotion/commands/messages/network.py @@ -33,16 +33,12 @@ def get_device_base_info(self): return self.send_order_msg_net(net) def get_4g_module_info(self): - build = dev_net_pb2.DevNet( - todev_get_mnet_cfg_req=dev_net_pb2.DevNet().todev_get_mnet_cfg_req - ) + build = dev_net_pb2.DevNet(todev_get_mnet_cfg_req=dev_net_pb2.DevNet().todev_get_mnet_cfg_req) print("Send command -- Get device 4G network module information") return self.send_order_msg_net(build) def get_4g_info(self): - build = dev_net_pb2.DevNet( - todev_mnet_info_req=dev_net_pb2.DevNet().todev_mnet_info_req - ) + build = dev_net_pb2.DevNet(todev_mnet_info_req=dev_net_pb2.DevNet().todev_mnet_info_req) print("Send command -- Get device 4G network information") return self.send_order_msg_net(build) @@ -82,9 +78,7 @@ def set_device_log_upload( print( f"Send log====Feedback====Command======requestID:{request_id} operation:{operation} serverIp:{server_ip} type:{type}" ) - return self.send_order_msg_net( - dev_net_pb2.DevNet(todev_ble_sync=1, todev_uploadfile_req=build) - ) + return self.send_order_msg_net(dev_net_pb2.DevNet(todev_ble_sync=1, todev_uploadfile_req=build)) def set_device_socket_request( self, @@ -107,9 +101,7 @@ def set_device_socket_request( print( f"Send log====Feedback====Command======requestID:{request_id} operation:{operation} serverIp:{server_ip} type:{type}" ) - return self.send_order_msg_net( - dev_net_pb2.DevNet(todev_ble_sync=1, todev_uploadfile_req=build) - ) + return self.send_order_msg_net(dev_net_pb2.DevNet(todev_ble_sync=1, todev_uploadfile_req=build)) def get_device_log_info(self, biz_id: str, type: int, log_url: str) -> bytes: """Get device log info (bluetooth only).""" @@ -129,15 +121,11 @@ def get_device_log_info(self, biz_id: str, type: int, log_url: str) -> bytes: def cancel_log_update(self, biz_id: str): """Cancel log update (bluetooth only).""" return self.send_order_msg_net( - dev_net_pb2.DevNet( - todev_log_data_cancel=dev_net_pb2.DrvUploadFileCancel(bizId=biz_id) - ) + dev_net_pb2.DevNet(todev_log_data_cancel=dev_net_pb2.DrvUploadFileCancel(bizId=biz_id)) ) def get_device_network_info(self): - build = dev_net_pb2.DevNet( - todev_networkinfo_req=dev_net_pb2.GetNetworkInfoReq(req_ids=1) - ) + build = dev_net_pb2.DevNet(todev_networkinfo_req=dev_net_pb2.GetNetworkInfoReq(req_ids=1)) print("Send command - get device network information") return self.send_order_msg_net(build) @@ -159,13 +147,9 @@ def set_device_4g_enable_status(self, new_4g_status: bool): def set_device_wifi_enable_status(self, new_wifi_status: bool): build = dev_net_pb2.DevNet( todev_ble_sync=1, - todev_Wifi_Configuration=dev_net_pb2.DrvWifiSet( - configParam=4, wifi_enable=new_wifi_status - ), - ) - print( - f"szNetwork: Send command - set network (on/off status). newWifiStatus={new_wifi_status}" + todev_Wifi_Configuration=dev_net_pb2.DrvWifiSet(configParam=4, wifi_enable=new_wifi_status), ) + print(f"szNetwork: Send command - set network (on/off status). newWifiStatus={new_wifi_status}") return self.send_order_msg_net(build) def wifi_connectinfo_update(self, device_name: str, is_binary: bool): @@ -189,9 +173,7 @@ def wifi_connectinfo_update2(self): def get_record_wifi_list(self, is_binary: bool): print(f"getRecordWifiList().isBinary={is_binary}") if is_binary: - build = dev_net_pb2.DevNet( - todev_ble_sync=1, todev_WifiListUpload=dev_net_pb2.DrvWifiList() - ) + build = dev_net_pb2.DevNet(todev_ble_sync=1, todev_WifiListUpload=dev_net_pb2.DrvWifiList()) print("Send command - get memorized WiFi list upload command") return self.send_order_msg_net(build) self.get_record_wifi_list2() @@ -205,9 +187,7 @@ def close_clear_connect_current_wifi(self, ssid: str, status: int, is_binary: bo if is_binary: build = dev_net_pb2.DevNet( todev_ble_sync=1, - todev_Wifi_Configuration=dev_net_pb2.DrvWifiSet( - configParam=status, Confssid=ssid - ), + todev_Wifi_Configuration=dev_net_pb2.DrvWifiSet(configParam=status, Confssid=ssid), ) print( f"Send command - set network (disconnect, direct connect, forget, no operation reconnect) operation command (downlink ssid={ssid}, status={status})" diff --git a/pymammotion/mammotion/commands/messages/system.py b/pymammotion/mammotion/commands/messages/system.py index 4b8524b..e6e3554 100644 --- a/pymammotion/mammotion/commands/messages/system.py +++ b/pymammotion/mammotion/commands/messages/system.py @@ -1,5 +1,6 @@ # === sendOrderMsg_Sys === import datetime +from abc import ABC from typing import List from pymammotion.mammotion.commands.abstract_message import AbstractMessage @@ -9,7 +10,7 @@ from pymammotion.utility.device_type import DeviceType -class MessageSystem(AbstractMessage): +class MessageSystem(AbstractMessage, ABC): messageNavigation: MessageNavigation = MessageNavigation() def send_order_msg_sys(self, sys): @@ -37,9 +38,7 @@ async def set_blade_control(self, on_off: int): def get_device_product_model(self): return self.send_order_msg_sys( - mctrl_sys_pb2.MctlSys( - device_product_type_info=mctrl_sys_pb2.device_product_type_info_t() - ), + mctrl_sys_pb2.MctlSys(device_product_type_info=mctrl_sys_pb2.device_product_type_info_t()), 12, True, ) @@ -72,12 +71,8 @@ def read_and_set_sidelight(self, is_sidelight: bool, operate: int): is_sidelight}, operate:{operate}, timeCtrlLight:{build}") return self.send_order_msg_sys(build2) - def test_tool_order_to_sys( - self, sub_cmd: int, param_id: int, param_value: List[int] - ): - build = mctrl_sys_pb2.mCtrlSimulationCmdData( - sub_cmd=sub_cmd, param_id=param_id, param_value=param_value - ) + def test_tool_order_to_sys(self, sub_cmd: int, param_id: int, param_value: List[int]): + build = mctrl_sys_pb2.mCtrlSimulationCmdData(sub_cmd=sub_cmd, param_id=param_id, param_value=param_value) print(f"Send tool test command: subCmd={sub_cmd}, param_id:{ param_id}, param_value={param_value}") build2 = mctrl_sys_pb2.MctlSys(simulation_cmd=build) @@ -89,23 +84,15 @@ def read_and_set_rt_k_paring_code(self, op: int, cgf: str): print(f"Send read and write base station configuration quality op:{ op}, cgf:{cgf}") return self.send_order_msg_sys( - mctrl_sys_pb2.MctlSys( - todev_lora_cfg_req=mctrl_sys_pb2.LoraCfgReq(op=op, cfg=cgf) - ) + mctrl_sys_pb2.MctlSys(todev_lora_cfg_req=mctrl_sys_pb2.LoraCfgReq(op=op, cfg=cgf)) ) def allpowerfull_rw(self, id: int, context: int, rw: int): - if (id == 6 or id == 3 or id == 7) and DeviceType.is_luba_2( - self.get_device_name() - ): + if (id == 6 or id == 3 or id == 7) and DeviceType.is_luba_2(self.get_device_name()): self.messageNavigation.allpowerfull_rw_adapter_x3(id, context, rw) return - build = mctrl_sys_pb2.MctlSys( - bidire_comm_cmd=mctrl_sys_pb2.SysCommCmd(id=id, context=context, rw=rw) - ) - print( - f"Send command - 9 general read and write command id={id}, context={context}, rw={rw}" - ) + build = mctrl_sys_pb2.MctlSys(bidire_comm_cmd=mctrl_sys_pb2.SysCommCmd(id=id, context=context, rw=rw)) + print(f"Send command - 9 general read and write command id={id}, context={context}, rw={rw}") if id == 5: # This logic doesnt make snese, but its what they had so.. return self.send_order_msg_sys(build) @@ -218,7 +205,7 @@ def request_iot_sys( period: int, no_change_period: int, count: int, - ) -> None: + ) -> bytes: build = mctrl_sys_pb2.MctlSys( todev_report_cfg=mctrl_sys_pb2.report_info_cfg( act=rpt_act, @@ -233,9 +220,7 @@ def request_iot_sys( build.todev_report_cfg.act} {build}") return self.send_order_msg_sys(build) - def get_report_cfg( - self, timeout: int = 10000, period: int = 1000, no_change_period: int = 2000 - ): + def get_report_cfg(self, timeout: int = 10000, period: int = 1000, no_change_period: int = 2000): mctlsys = mctrl_sys_pb2.MctlSys( todev_report_cfg=mctrl_sys_pb2.report_info_cfg( timeout=timeout, diff --git a/pymammotion/mammotion/commands/messages/video.py b/pymammotion/mammotion/commands/messages/video.py index 5e6ccd7..807ccd3 100644 --- a/pymammotion/mammotion/commands/messages/video.py +++ b/pymammotion/mammotion/commands/messages/video.py @@ -21,7 +21,5 @@ def device_agora_join_channel_with_position(self, enter_state: int): if DeviceType.is_yuka(self.get_device_name()) else luba_mul_pb2.MUL_CAMERA_POSITION.LEFT ) - mctl_sys = luba_mul_pb2.SocMul( - set_video=luba_mul_pb2.MulSetVideo(position=position, vi_switch=enter_state) - ) + mctl_sys = luba_mul_pb2.SocMul(set_video=luba_mul_pb2.MulSetVideo(position=position, vi_switch=enter_state)) return self.send_order_msg_video(mctl_sys) diff --git a/pymammotion/mammotion/control/joystick.py b/pymammotion/mammotion/control/joystick.py index c8e1bb9..232dbec 100644 --- a/pymammotion/mammotion/control/joystick.py +++ b/pymammotion/mammotion/control/joystick.py @@ -31,9 +31,7 @@ def __init__(self, luba_ble: MammotionBaseBLEDevice): self._curr_time = timer() self.stopped = False - repeater = pyjoystick.HatRepeater( - first_repeat_timeout=0.2, repeat_timeout=0.03, check_timeout=0.01 - ) + repeater = pyjoystick.HatRepeater(first_repeat_timeout=0.2, repeat_timeout=0.03, check_timeout=0.01) self.mngr = pyjoystick.ThreadEventManager( event_loop=run_event_loop, @@ -43,9 +41,7 @@ def __init__(self, luba_ble: MammotionBaseBLEDevice): button_repeater=repeater, ) - self.worker = PeriodicThread( - 0.2, self.run_movement, name="luba-process_movements" - ) + self.worker = PeriodicThread(0.2, self.run_movement, name="luba-process_movements") self.worker.alive = self.mngr.alive # stop when this event stops self.worker.daemon = True @@ -64,11 +60,7 @@ def run_movement(self): self.linear_percent, self.angular_percent, ) - asyncio.run( - self._client.command( - "send_movement", linear_speed=linear_speed, angular_speed=angular_speed - ) - ) + asyncio.run(self._client.command("send_movement", linear_speed=linear_speed, angular_speed=angular_speed)) def print_add(self, joy): print("Added", joy) @@ -90,13 +82,9 @@ def get_percent(self, percent: float): return percent - 15.0 @staticmethod - def transform_both_speeds( - linear: float, angular: float, linear_percent: float, angular_percent: float - ): + def transform_both_speeds(linear: float, angular: float, linear_percent: float, angular_percent: float): transfrom3 = RockerControlUtil.getInstance().transfrom3(linear, linear_percent) - transform4 = RockerControlUtil.getInstance().transfrom3( - angular, angular_percent - ) + transform4 = RockerControlUtil.getInstance().transfrom3(angular, angular_percent) if transfrom3 is not None and len(transfrom3) > 0: linear_speed = transfrom3[0] * 10 @@ -121,20 +109,12 @@ def handle_key_received(self, key): # lower knife height if self._blade_height > 25: self._blade_height -= 5 - asyncio.run( - self._client.command( - "set_blade_height", height=self._blade_height - ) - ) + asyncio.run(self._client.command("set_blade_height", height=self._blade_height)) if key.number == 10: # raise knife height if self._blade_height < 60: self._blade_height += 5 - asyncio.run( - self._client.command( - "set_blade_height", height=self._blade_height - ) - ) + asyncio.run(self._client.command("set_blade_height", height=self._blade_height)) if key.keytype is Key.AXIS: # print(key, "-", key.keytype, "-", key.number, "-", key.value) @@ -163,16 +143,12 @@ def handle_key_received(self, key): # angular_speed==450 if key.value > 0: self.angular_speed = 0.0 - self.angular_percent = self.get_percent( - abs(key.value * 100) - ) + self.angular_percent = self.get_percent(abs(key.value * 100)) else: # angle=180.0 # linear_speed=0//angular_speed=-450 self.angular_speed = 180.0 - self.angular_percent = self.get_percent( - abs(key.value * 100) - ) + self.angular_percent = self.get_percent(abs(key.value * 100)) else: match key.number: diff --git a/pymammotion/mammotion/devices/mammotion.py b/pymammotion/mammotion/devices/mammotion.py index dde51a1..6031fce 100644 --- a/pymammotion/mammotion/devices/mammotion.py +++ b/pymammotion/mammotion/devices/mammotion.py @@ -24,11 +24,14 @@ ) from pymammotion.bluetooth import BleMessage +from pymammotion.data.model import RegionData from pymammotion.data.model.device import MowingDevice from pymammotion.data.mqtt.event import ThingEventMessage +from pymammotion.data.state_manager import StateManager from pymammotion.mammotion.commands.mammotion_command import MammotionCommand from pymammotion.mqtt import MammotionMQTT from pymammotion.proto.luba_msg import LubaMsg +from pymammotion.proto.mctrl_nav import NavGetCommDataAck, NavGetHashListAck class CharacteristicMissingError(Exception): @@ -82,6 +85,12 @@ def _handle_timeout(fut: asyncio.Future[None]) -> None: fut.set_exception(asyncio.TimeoutError) +async def _handle_retry(fut: asyncio.Future[None], func, command: bytes) -> None: + """Handle a retry.""" + if not fut.done(): + await func(command) + + class ConnectionPreference(Enum): """Enum for connection preference.""" @@ -118,13 +127,47 @@ def has_field(message: betterproto.Message) -> bool: class MammotionBaseDevice: """Base class for Mammotion devices.""" + _luba_msg: MowingDevice + _state_manager: StateManager + def __init__(self) -> None: """Initialize MammotionBaseDevice.""" self.loop = asyncio.get_event_loop() self._raw_data = LubaMsg().to_dict(casing=betterproto.Casing.SNAKE) - self._luba_msg = LubaMsg() + self._luba_msg = MowingDevice() + self._state_manager = StateManager(self._luba_msg) + + self._state_manager.gethash_ack_callback.add_subscribers(self.datahash_response) + self._state_manager.get_commondata_ack_callback.add_subscribers(self.commdata_response) self._notify_future: asyncio.Future[bytes] | None = None + async def datahash_response(self, hash_ack: NavGetHashListAck): + """Handle datahash responses.""" + for data_hash in hash_ack.data_couple: + result_hash = 0 + while data_hash != result_hash: + data = await self._send_command_with_args("synchronize_hash_data", hash_num=data_hash) + msg = LubaMsg().parse(data) + if betterproto.serialized_on_wire(msg.nav.toapp_get_commondata_ack): + result_hash = msg.nav.toapp_get_commondata_ack.hash + else: + await asyncio.sleep(0.5) + + async def commdata_response(self, common_data: NavGetCommDataAck): + """Handle common data responses.""" + # TODO check if the hash exists and whether or not to call get regional + total_frame = common_data.total_frame + current_frame = 1 + while current_frame <= total_frame: + region_data = RegionData() + region_data.hash = common_data.data_hash + region_data.action = common_data.action + region_data.type = common_data.type + region_data.total_frame = total_frame + region_data.current_frame = current_frame + await self._send_command_with_args("get_regional_data", regional_data=region_data) + current_frame += 1 + def _update_raw_data(self, data: bytes) -> None: """Update raw and model data from notifications.""" tmp_msg = LubaMsg().parse(data) @@ -143,7 +186,7 @@ def _update_raw_data(self, data: bytes) -> None: case "ota": self._update_ota_data(tmp_msg) - self._luba_msg = MowingDevice.from_raw(self._raw_data) + self._luba_msg.update_raw(self._raw_data) def _update_nav_data(self, tmp_msg): """Update navigation data.""" @@ -152,9 +195,7 @@ def _update_nav_data(self, tmp_msg): if isinstance(nav_sub_msg[1], int): nav[nav_sub_msg[0]] = nav_sub_msg[1] else: - nav[nav_sub_msg[0]] = nav_sub_msg[1].to_dict( - casing=betterproto.Casing.SNAKE - ) + nav[nav_sub_msg[0]] = nav_sub_msg[1].to_dict(casing=betterproto.Casing.SNAKE) self._raw_data["nav"] = nav def _update_sys_data(self, tmp_msg): @@ -178,9 +219,7 @@ def _update_net_data(self, tmp_msg): if isinstance(net_sub_msg[1], int): net[net_sub_msg[0]] = net_sub_msg[1] else: - net[net_sub_msg[0]] = net_sub_msg[1].to_dict( - casing=betterproto.Casing.SNAKE - ) + net[net_sub_msg[0]] = net_sub_msg[1].to_dict(casing=betterproto.Casing.SNAKE) self._raw_data["net"] = net def _update_mul_data(self, tmp_msg): @@ -215,12 +254,32 @@ async def _send_command(self, key: str, retry: int | None = None) -> bytes | Non async def _send_command_with_args(self, key: str, **kwargs: any) -> bytes | None: """Send command to device and read response.""" + @abstractmethod + async def _ble_sync(self): + """Send ble sync command every 3 seconds or sooner.""" + async def start_sync(self, retry: int): """Start synchronization with the device.""" await self._send_command("get_device_base_info", retry) await self._send_command("get_report_cfg", retry) + """RTK and dock location.""" + await self._send_command_with_args("allpowerfull_rw", id=5, rw=1, context=1) + """Error codes.""" + await self._send_command_with_args("allpowerfull_rw", id=5, rw=1, context=2) + await self._send_command_with_args("allpowerfull_rw", id=5, rw=1, context=3) + + async def start_map_sync(self): + """Start sync of map data.""" await self._send_command_with_args("read_plan", sub_cmd=2, plan_index=0) - await self._send_command_with_args("allpowerfull_rw", id=5, context=1, rw=1) + + await self._send_command_with_args("get_all_boundary_hash_list", sub_cmd=0) + + await self._send_command_with_args("get_hash_response", total_frame=1, current_frame=1) + + # sub_cmd 3 is job hashes?? + # sub_cmd 4 is dump location (yuka) + # jobs list + # hash_list_result = await self._send_command_with_args("get_all_boundary_hash_list", sub_cmd=3) async def command(self, key: str, **kwargs): """Send a command to the device.""" @@ -233,6 +292,9 @@ class MammotionBaseBLEDevice(MammotionBaseDevice): def __init__(self, device: BLEDevice, interface: int = 0, **kwargs: Any) -> None: """Initialize MammotionBaseBLEDevice.""" super().__init__() + self._pong_count = None + self._ble_sync_task = None + self._prev_notification = None self._interface = f"hci{interface}" self._device = device self._client: BleakClientWithServiceCache | None = None @@ -250,6 +312,24 @@ def update_device(self, device: BLEDevice) -> None: """Update the BLE device.""" self._device = device + async def _ble_sync(self): + command_bytes = self._commands.send_todev_ble_sync(2) + await self._message.post_custom_data_bytes(command_bytes) + + async def run_periodic_sync_task(self) -> None: + """Send ble sync to robot.""" + try: + await self._ble_sync() + finally: + self.schedule_ble_sync() + + def schedule_ble_sync(self): + """Periodically sync to keep connection alive.""" + if self._client.is_connected: + self._ble_sync_task = self.loop.call_later( + 130, lambda: asyncio.ensure_future(self.run_periodic_sync_task()) + ) + async def _send_command_with_args(self, key: str, **kwargs) -> bytes | None: """Send command to device and read response.""" if self._operation_lock.locked(): @@ -278,9 +358,7 @@ async def _send_command_with_args(self, key: str, **kwargs) -> bytes | None: exc_info=True, ) except BLEAK_RETRY_EXCEPTIONS: - _LOGGER.debug( - "%s: communication failed with:", self.name, exc_info=True - ) + _LOGGER.debug("%s: communication failed with:", self.name, exc_info=True) async def _send_command(self, key: str, retry: int | None = None) -> bytes | None: """Send command to device and read response.""" @@ -310,9 +388,7 @@ async def _send_command(self, key: str, retry: int | None = None) -> bytes | Non exc_info=True, ) except BLEAK_RETRY_EXCEPTIONS: - _LOGGER.debug( - "%s: communication failed with:", self.name, exc_info=True - ) + _LOGGER.debug("%s: communication failed with:", self.name, exc_info=True) @property def name(self) -> str: @@ -386,9 +462,7 @@ async def _ensure_connected(self): ) self._reset_disconnect_timer() await self._start_notify() - - command_bytes = self._commands.send_todev_ble_sync(2) - await self._message.post_custom_data_bytes(command_bytes) + self.schedule_ble_sync() async def _send_command_locked(self, key: str, command: bytes) -> bytes: """Send command to device and read response.""" @@ -409,15 +483,11 @@ async def _send_command_locked(self, key: str, command: bytes) -> bytes: raise except BLEAK_RETRY_EXCEPTIONS as ex: # Disconnect so we can reset state and try again - _LOGGER.debug( - "%s: RSSI: %s; Disconnecting due to error: %s", self.name, self.rssi, ex - ) + _LOGGER.debug("%s: RSSI: %s; Disconnecting due to error: %s", self.name, self.rssi, ex) await self._execute_forced_disconnect() raise - async def _notification_handler( - self, _sender: BleakGATTCharacteristic, data: bytearray - ) -> None: + async def _notification_handler(self, _sender: BleakGATTCharacteristic, data: bytearray) -> None: """Handle notification responses.""" _LOGGER.debug("%s: Received notification: %s", self.name, data) result = self._message.parseNotification(data) @@ -429,15 +499,18 @@ async def _notification_handler( return new_msg = LubaMsg().parse(data) if betterproto.serialized_on_wire(new_msg.net): - if new_msg.net.todev_ble_sync != 0 or has_field( - new_msg.net.toapp_wifi_iot_status - ): - # TODO occasionally respond with ble sync - return + if new_msg.net.todev_ble_sync != 0 or has_field(new_msg.net.toapp_wifi_iot_status): + self._pong_count += 1 + + if self._pong_count < 3: + return + # may or may not be correct, some work could be done here to correctly match responses if self._notify_future and not self._notify_future.done(): + self._pong_count = 0 self._notify_future.set_result(data) - return + + await self._state_manager.notification(new_msg) async def _start_notify(self) -> None: """Start notification.""" @@ -454,10 +527,14 @@ async def _execute_command_locked(self, key: str, command: bytes) -> bytes: _LOGGER.debug("%s: Sending command: %s", self.name, key) await self._message.post_custom_data_bytes(command) - timeout = 5 - timeout_handle = self.loop.call_at( - self.loop.time() + timeout, _handle_timeout, self._notify_future + retry_handle = self.loop.call_at( + self.loop.time() + 2, + lambda: asyncio.ensure_future( + _handle_retry(self._notify_future, self._message.post_custom_data_bytes, command) + ), ) + timeout = 5 + timeout_handle = self.loop.call_at(self.loop.time() + timeout, _handle_timeout, self._notify_future) timeout_expired = False try: notify_msg = await self._notify_future @@ -467,6 +544,7 @@ async def _execute_command_locked(self, key: str, command: bytes) -> bytes: finally: if not timeout_expired: timeout_handle.cancel() + retry_handle.cancel() self._notify_future = None _LOGGER.debug("%s: Notification received: %s", self.name, notify_msg.hex()) @@ -480,25 +558,23 @@ def _resolve_characteristics(self, services: BleakGATTServiceCollection) -> None """Resolve characteristics.""" self._read_char = services.get_characteristic(READ_CHAR_UUID) if not self._read_char: - raise CharacteristicMissingError(READ_CHAR_UUID) + self._read_char = READ_CHAR_UUID + _LOGGER.error(CharacteristicMissingError(READ_CHAR_UUID)) self._write_char = services.get_characteristic(WRITE_CHAR_UUID) if not self._write_char: - raise CharacteristicMissingError(WRITE_CHAR_UUID) + self._write_char = WRITE_CHAR_UUID + _LOGGER.error(CharacteristicMissingError(WRITE_CHAR_UUID)) def _reset_disconnect_timer(self): """Reset disconnect timer.""" self._cancel_disconnect_timer() self._expected_disconnect = False - self._disconnect_timer = self.loop.call_later( - DISCONNECT_DELAY, self._disconnect_from_timer - ) + self._disconnect_timer = self.loop.call_later(DISCONNECT_DELAY, self._disconnect_from_timer) def _disconnected(self, client: BleakClientWithServiceCache) -> None: """Disconnected callback.""" if self._expected_disconnect: - _LOGGER.debug( - "%s: Disconnected from device; RSSI: %s", self.name, self.rssi - ) + _LOGGER.debug("%s: Disconnected from device; RSSI: %s", self.name, self.rssi) return _LOGGER.warning( "%s: Device unexpectedly disconnected; RSSI: %s", @@ -518,9 +594,7 @@ def _disconnect_from_timer(self): self._reset_disconnect_timer() return self._cancel_disconnect_timer() - self._timed_disconnect_task = asyncio.create_task( - self._execute_timed_disconnect() - ) + self._timed_disconnect_task = asyncio.create_task(self._execute_timed_disconnect()) def _cancel_disconnect_timer(self): """Cancel disconnect timer.""" @@ -568,10 +642,11 @@ async def _execute_disconnect_with_lock(self) -> None: _LOGGER.debug("%s: Disconnecting", self.name) try: """We reset what command the robot last heard before disconnecting.""" - command_bytes = self._commands.send_todev_ble_sync(2) - await self._message.post_custom_data_bytes(command_bytes) - await client.stop_notify(self._read_char) - await client.disconnect() + if client.is_connected: + command_bytes = self._commands.send_todev_ble_sync(2) + await self._message.post_custom_data_bytes(command_bytes) + await client.stop_notify(self._read_char) + await client.disconnect() except BLEAK_RETRY_EXCEPTIONS as ex: _LOGGER.warning( "%s: Error disconnecting: %s; RSSI: %s", @@ -605,6 +680,7 @@ def __init__( self.iot_id = iot_id self.nick_name = nick_name self._command_futures = {} + self._commands: MammotionCommand = MammotionCommand(device_name) self.loop = asyncio.get_event_loop() def _on_mqtt_message(self, topic: str, payload: str) -> None: @@ -621,9 +697,8 @@ def _on_mqtt_message(self, topic: str, payload: str) -> None: async def _send_command(self, key: str, retry: int | None = None) -> bytes | None: """Send command to device via MQTT and read response.""" future = self.loop.create_future() - message_id = self._mqtt_client.get_cloud_client().send_cloud_command( - self.iot_id, key - ) + command_bytes = getattr(self._commands, key)() + message_id = self._mqtt_client.get_cloud_client().send_cloud_command(self.iot_id, command_bytes) if message_id != "": self._command_futures[message_id] = future try: @@ -634,6 +709,16 @@ async def _send_command(self, key: str, retry: int | None = None) -> bytes | Non async def _send_command_with_args(self, key: str, **kwargs: any) -> bytes | None: """Send command with arguments to device via MQTT and read response.""" + future = self.loop.create_future() + command_bytes = getattr(self._commands, key)(**kwargs) + message_id = self._mqtt_client.get_cloud_client().send_cloud_command(self.iot_id, command_bytes) + if message_id != "": + self._command_futures[message_id] = future + try: + return await asyncio.wait_for(future, timeout=TIMEOUT_CLOUD_RESPONSE) + except asyncio.TimeoutError: + _LOGGER.error("Command '%s' timed out", key) + return None def _extract_message_id(self, payload: dict) -> str: """Extract the message ID from the payload.""" @@ -642,12 +727,7 @@ def _extract_message_id(self, payload: dict) -> str: def _extract_encoded_message(self, payload: dict) -> str: """Extract the encoded message from the payload.""" try: - content = ( - payload.get("data", {}) - .get("data", {}) - .get("params", {}) - .get("content", "") - ) + content = payload.get("data", {}).get("data", {}).get("params", {}).get("content", "") return str(content) except AttributeError: _LOGGER.error("Error extracting encoded message. Payload: %s", payload) diff --git a/pymammotion/mqtt/mammotion_mqtt.py b/pymammotion/mqtt/mammotion_mqtt.py index bdc476b..f5531ff 100644 --- a/pymammotion/mqtt/mammotion_mqtt.py +++ b/pymammotion/mqtt/mammotion_mqtt.py @@ -50,9 +50,7 @@ def __init__( if client_id is None: client_id = f"python-{device_name}" self._mqtt_client_id = f"{client_id}|securemode=2,signmethod=hmacsha1|" - sign_content = ( - f"clientId{client_id}deviceName{device_name}productKey{product_key}" - ) + sign_content = f"clientId{client_id}deviceName{device_name}productKey{product_key}" self._mqtt_password = hmac.new( device_secret.encode("utf-8"), sign_content.encode("utf-8"), hashlib.sha1 ).hexdigest() @@ -122,15 +120,9 @@ def _thing_on_thing_enable(self, user_data): self._linkkit_client.subscribe_topic( f"/sys/{self._product_key}/{self._device_name}/app/down/thing/event/property/post_reply" ) - self._linkkit_client.subscribe_topic( - f"/sys/{self._product_key}/{self._device_name}/app/down/thing/events" - ) - self._linkkit_client.subscribe_topic( - f"/sys/{self._product_key}/{self._device_name}/app/down/thing/status" - ) - self._linkkit_client.subscribe_topic( - f"/sys/{self._product_key}/{self._device_name}/app/down/thing/properties" - ) + self._linkkit_client.subscribe_topic(f"/sys/{self._product_key}/{self._device_name}/app/down/thing/events") + self._linkkit_client.subscribe_topic(f"/sys/{self._product_key}/{self._device_name}/app/down/thing/status") + self._linkkit_client.subscribe_topic(f"/sys/{self._product_key}/{self._device_name}/app/down/thing/properties") self._linkkit_client.subscribe_topic( f"/sys/{self._product_key}/{self._device_name}/app/down/thing/model/down_raw" ) @@ -175,9 +167,7 @@ def _on_connect(self, _client, _userdata, _flags: dict, rc: int): if rc == 0: logger.debug("Connected") self._client.subscribe(f"/sys/{self._product_key}/{self._device_name}/#") - self._client.subscribe( - f"/sys/{self._product_key}/{self._device_name}/app/down/account/bind_reply" - ) + self._client.subscribe(f"/sys/{self._product_key}/{self._device_name}/app/down/account/bind_reply") self._client.publish( f"/sys/{self._product_key}/{self._device_name}/app/up/account/bind", @@ -216,9 +206,7 @@ def _on_message(self, _client, _userdata, message: MQTTMessage): if params.identifier == "device_protobuf_msg_event": content = cast(luba_msg_pb2, params.value.content) - logger.info( - "Unhandled protobuf event: %s", content.WhichOneof("subMsg") - ) + logger.info("Unhandled protobuf event: %s", content.WhichOneof("subMsg")) elif params.identifier == "device_warning_event": logger.debug("identifier event: %s", params.identifier) else: @@ -233,6 +221,6 @@ def _on_message(self, _client, _userdata, message: MQTTMessage): logger.debug("Unhandled topic: %s", message.topic) logger.debug(payload) - def _get_cloud_client(self) -> Optional[CloudIOTGateway]: + def get_cloud_client(self) -> Optional[CloudIOTGateway]: """Return internal cloud client.""" return self._cloud_client diff --git a/pymammotion/utility/datatype_converter.py b/pymammotion/utility/datatype_converter.py index d9335d0..76ccda1 100644 --- a/pymammotion/utility/datatype_converter.py +++ b/pymammotion/utility/datatype_converter.py @@ -93,12 +93,8 @@ def _printBase64Binary_core(bArr, i, i2, cArr, i3): DatatypeConverter.init_encode_map() # Ensure encode_map is initialized while i2 >= 3: cArr[i3] = DatatypeConverter.encode(bArr[i] >> 2) - cArr[i3 + 1] = DatatypeConverter.encode( - ((bArr[i] & 3) << 4) | ((bArr[i + 1] >> 4) & 15) - ) - cArr[i3 + 2] = DatatypeConverter.encode( - ((bArr[i + 1] & 15) << 2) | ((bArr[i + 2] >> 6) & 3) - ) + cArr[i3 + 1] = DatatypeConverter.encode(((bArr[i] & 3) << 4) | ((bArr[i + 1] >> 4) & 15)) + cArr[i3 + 2] = DatatypeConverter.encode(((bArr[i + 1] & 15) << 2) | ((bArr[i + 2] >> 6) & 3)) cArr[i3 + 3] = DatatypeConverter.encode(bArr[i + 2] & 63) i2 -= 3 i += 3 @@ -112,9 +108,7 @@ def _printBase64Binary_core(bArr, i, i2, cArr, i3): if i2 == 2: cArr[i3] = DatatypeConverter.encode(bArr[i] >> 2) - cArr[i3 + 1] = DatatypeConverter.encode( - ((bArr[i] & 3) << 4) | ((bArr[i + 1] >> 4) & 15) - ) + cArr[i3 + 1] = DatatypeConverter.encode(((bArr[i] & 3) << 4) | ((bArr[i + 1] >> 4) & 15)) cArr[i3 + 2] = DatatypeConverter.encode((bArr[i + 1] & 15) << 2) cArr[i3 + 3] = "=" diff --git a/pymammotion/utility/device_type.py b/pymammotion/utility/device_type.py index d6aaca1..676bbf9 100644 --- a/pymammotion/utility/device_type.py +++ b/pymammotion/utility/device_type.py @@ -75,21 +75,13 @@ def value_of_str(device_name, product_key=""): substring = device_name[:3] substring2 = device_name[:7] - if DeviceType.RTK.name in substring or DeviceType.contain_rtk_product_key( - product_key - ): + if DeviceType.RTK.name in substring or DeviceType.contain_rtk_product_key(product_key): return DeviceType.RTK - elif ( - DeviceType.LUBA_2.name in substring2 - or DeviceType.contain_luba_2_product_key(product_key) - ): + elif DeviceType.LUBA_2.name in substring2 or DeviceType.contain_luba_2_product_key(product_key): return DeviceType.LUBA_2 elif DeviceType.LUBA_YUKA.name in substring2: return DeviceType.LUBA_YUKA - elif ( - DeviceType.LUBA.name in substring2 - or DeviceType.contain_luba_product_key(product_key) - ): + elif DeviceType.LUBA.name in substring2 or DeviceType.contain_luba_product_key(product_key): return DeviceType.LUBA else: return DeviceType.UNKNOWN @@ -178,10 +170,7 @@ def is_yuka(device_name): """ - return ( - DeviceType.value_of_str(device_name).get_value() - == DeviceType.LUBA_YUKA.get_value() - ) + return DeviceType.value_of_str(device_name).get_value() == DeviceType.LUBA_YUKA.get_value() @staticmethod def is_rtk(device_name, product_key=""): @@ -205,11 +194,7 @@ def is_rtk(device_name, product_key=""): else: device_type = DeviceType.value_of_str(device_name, product_key) - return ( - DeviceType.RTK.get_value() - <= device_type.get_value() - < DeviceType.LUBA.get_value() - ) + return DeviceType.RTK.get_value() <= device_type.get_value() < DeviceType.LUBA.get_value() @staticmethod def contain_rtk_product_key(product_key): diff --git a/pyproject.toml b/pyproject.toml index c3f6af4..25a74cb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,7 +13,7 @@ packages = [{include = "pymammotion"}] [tool.poetry.dependencies] -python = ">=3.12,<3.13" +python = "~3.12.0" bleak = ">=0.21.0" protobuf = ">=4.23.1" py-jsonic = "^0.0.2" @@ -31,6 +31,7 @@ orjson = "^3.9.15" betterproto = "^1.2.5" pyjoystick = "^1.2.4" nest-asyncio = "^1.6.0" +pyproj = "^3.6.1" [tool.poetry.group.dev.dependencies] @@ -48,7 +49,7 @@ pre-commit = "^3.7.1" [tool.bumpver] -current_version = "0.0.1" +current_version = "0.0.40" version_pattern = "MAJOR.MINOR.PATCH" commit_message = "Bump version {old_version} -> {new_version}" commit = true @@ -368,12 +369,13 @@ overgeneral-exceptions = [ runtime-typing = false [tool.pylint.CODE_STYLE] -max-line-length-suggestions = 72 +max-line-length-suggestions = 120 [tool.ruff] required-version = ">=0.4.3" exclude = ['pymammotion/proto/*', 'tests/*'] +line-length = 120 [tool.ruff.lint] select = [ diff --git a/tests/fixtures.py b/tests/fixtures.py index 0856751..8ae46f7 100644 --- a/tests/fixtures.py +++ b/tests/fixtures.py @@ -7,60 +7,6 @@ systemTardStateTunnel = b'\x08\xf4\x01\x10\x01\x18\x07(\xbf\x96\x0b0\x01R`\xd2\x01]\n[\x0b\x01d<\x00\x00\xbc\xda\xcf\xf6\xf9\x98\xc2\xa8h\xb3\xe7\xcc\x90\xc3\x8e\x89\xbbm\xe1\x80\x84\x03\x00\x00\xba\xf3\xfe\xf1\xd6\x96\x91\xf2\x15\x81\xb2\xff\xff\xff\xff\xff\xff\xff\x01\xcc\x98\xfc\xff\xff\xff\xff\xff\xff\x01\x00\x00\x00\x89\xaf\xb7\xe7\xf7\x84\xc6\xd3L\x00\xb9\x95\x8c\xf6\xe6\xeb\xc1\xe1Y\xde\xd9\xd2\xfc\xab\xc2\x9b\x903\x00' - -""" -esp { - toapp_wifi_iot_status { - wifi_connected: true - iot_connected: true - productkey: "a1BmXWlsdbA" - devicename: "Luba-MTAJTZ7T" - } -} - -""" -esp_device = b'\x08\xf8\x01\x10\x01\x18\x070\x01B"r \x08\x01\x10\x01\x1a\x0ba1BmXWlsdbA"\rLuba-MTAJTZ7T' - - -#await luba_client.get_all_boundary_hash_list(3) lineHashList - -toapp_gethash_ack = b'\x08\xf0\x01\x10\x01\x18\x07(\x84\xab\x0b0\x01Z\x85\x01\xfa\x01\x81\x01\x08\x01\x10\x03\x18\x01 \x010hju\x9f\xc8\x83\xbc\xac\xe0\x9f\xda\x1c\xb4\xe4\xa9\x8e\xb2\xeb\x9f\xbeU\xe5\xad\xe1\x85\x98\xaa\x92\xfc\x11\x90\xee\xe7\x9b\xf3\xe3\xf7\xe8,\xbd\x81\xe3\xd2\x93\xab\xb6\xe5t\x98\xa1\xb3\xc1\xfe\xfe\xce\xc3\x04\x8b\xf5\x9c\x92\xbf\xef\xc3\xbf^\x97\xb3\xe4\xd6\xab\xdc\x81\xcbA\x9f\x8e\xd1\xa9\x81\xc3\xe2\xd4P\x81\xc1\xc4\xe2\xd7\xf5\x99\xc1\x02\xfd\x8b\x9f\xa2\x80\xa6\x91\x9a\x07\xef\xcd\xd1\xe4\xce\x99\xd5\xb6\x11\x82\x8c\xa1\x91\xe1\xa8\x92\x9a%' - -""" -toapp_gethash_ack { - pver: 1 - totalFrame: 1 - currentFrame: 1 - hashLen: 152 - dataCouple: 8656065632562971511 - dataCouple: 5326333396143256633 - dataCouple: 541647029314729441 - dataCouple: 4870790062671685143 - dataCouple: 6316048569363781876 - dataCouple: 8693838767690150729 - dataCouple: 5386431019338482578 - dataCouple: 2719756689538040248 - dataCouple: 52888279395493412 - dataCouple: 3326491527753915659 - dataCouple: 4337736833720920333 - dataCouple: 1827638544161716385 - dataCouple: 1577461315515955642 - dataCouple: 6863400705154845420 - dataCouple: 8809571020336040838 - dataCouple: 1070358128924616908 - dataCouple: 7279593094795908334 - dataCouple: 989182222171962820 - dataCouple: 5490038377814536159 - } - -""" -# await luba_client.get_all_boundary_hash_list(0) hashList -toapp_gethash_ack2 = b'\x08\xf0\x01\x10\x01\x18\x07(\x9a\xad\x0b0\x01Z\xba\x01\xfa\x01\xb6\x01\x08\x01\x18\x01 \x010\x98\x01j\xaa\x01\xf7\x86\x88\xeb\xcb\xba\xa1\x90x\xb9\xe8\xac\x83\x8f\x80\xbc\xf5I\xe1\xeb\xcc\xbf\xa7\xa3\x94\xc2\x07\x97\xcc\xb1\xa8\x96\xb8\xa1\xccC\xf4\xb1\xab\x88\xdc\x96\xc7\xd3W\xc9\xe6\xc3\xd5\xc1\x89\xae\xd3x\x92\x87\xc3\xd6\x93\xcf\x9c\xe0J\xb8\x83\xa1\xdb\xc9\x89\xa1\xdf%\xa4\xcc\x99\x91\xc2\xb3\xf9]\x8b\xba\xf9\xa0\xb8\xcd\x84\x95.\x8d\xd2\xc0\xf8\xaf\x95\xaf\x99<\xa1\xf1\xc8\xd4\xa9\xf2\xc4\xae\x19\xba\xf3\xfe\xf1\xd6\x96\x91\xf2\x15\xec\x95\xae\xaf\xbd\xd2\xec\x9f_\x86\x97\xd2\xd5\xaf\xc5\xf8\xa0z\xcc\xd1\x83\xc8\xc1\xa1\xab\xed\x0e\xee\xa9\xc9\xe5\x9c\xeb\x93\x83e\xc4\xfb\xc3\xd5\xd7\xff\x91\xdd\r\xdf\xdf\x96\x87\x93\x9a\xa2\x98L' - -# 8656065632562971511 -toapp_get_commondata_ack = b'\x18\x01\x08\xf0\x01\x10\x01\x18\x07(\xdc\xda\x0c0\x01Z\x88\x02\x8a\x02\x84\x02\x08\x01 \x081w\x03b\xbd\xd4\x85 xH\x02P\x01`\xa0\x01j\n\r\xef\xabY\xc1\x15;\x9d\n@j\n\r\xc0\x08<\xc1\x15\xd9\xfcW@j\n\r\xff\xa98\xc1\x15\xe2\x96\xaf@j\n\r}\xd83\xc1\x15\xe5\x83\xdb@j\n\r\x10*<\xc1\x15@\x97\xda@j\n\r"^a\xc1\x15-g\xc6@j\n\r\xdc\x13\x82\xc1\x154n\xad@j\n\r)\xd4\x82\xc1\x15R\r\x9e@j\n\r\x02k\x85\xc1\x15\x91K\x8b@j\n\r\xc0\xeb\x8a\xc1\x15\x15\xbdm@j\n\rQP\x92\xc1\x15z\xe0)@j\n\rQ\xc2\x95\xc1\x15\x1f\x18)@j\n\rW\xb2\x95\xc1\x15\xd8\x82\x17@j\n\r{\xc5\x8d\xc1\x15G\x82\xa6\xbfj\n\rW\xbb\x8b\xc1\x15;\xec\xa9\xbfj\n\r\x94\xd0\x88\xc1\x15t9\x90\xbfj\n\r5{\x80\xc1\x15z\xc6\xb8\xbej\n\rT\xb9}\xc1\x15Ip\xcc\xbdj\n\r\xd1\x8a{\xc1\x15^\xbb\x14?j\n\r\x15\x95t\xc1\x15\xef\xa1S?' - - single_hash_result = b'\x00\x01\x08\xf0\x01\x10\x01\x18\x07(\xe8\xda\x0c0\x01Z\xf0\x01\x8a\x02\xec\x01\x08\x01 \x08194k\xf0\x00\xf0\xeaIH\x01P\x01`\x90\x01j\n\r\x0cg\x9c\xc1\x15,\x00\x92@j\n\r\x860\x9f\xc1\x15:R\x8b@j\n\r^\xb7\xa0\xc1\x15\x06\xa0z@j\n\r\xf6\xa7\x9e\xc1\x15%\xfe\n@j\n\r\xc0\x06\x96\xc1\x15Jb\xd2\xbfj\n\ry\xd4\x9a\xc1\x15\xcbs\xf3\xbfj\n\r\x1a\xbd\xa3\xc1\x151\x9b\x08\xc0j\n\r\xe5B\xa5\xc1\x15\x88\xc7\xfb\xbfj\n\rR;\xa7\xc1\x15\x96\xce\xb3\xbfj\n\r\\\xa3\xa7\xc1\x15\x9e\x86}\xbfj\n\r\xc3\xaa\xa9\xc1\x15N;\x07\xbfj\n\rb\x91\xad\xc1\x15\xb9\xe6>?j\n\r\xf1\xdc\xb4\xc1\x15\x1e\xba`@j\n\rBZ\xb8\xc1\x15\x17Jl@j\n\rL"\xb9\xc1\x15i\xda\x82@j\n\r\xa5\x06\xa2\xc1\x15%\x96\x99@j\n\r-\x8e\x9d\xc1\x15\x113\x9d@j\n\r\x0cg\x9c\xc1\x15,\x00\x92@' # working @@ -114,20 +60,6 @@ } -# sync 2 - -msgtype: MSG_CMD_TYPE_ESP -sender: DEV_MOBILEAPP -msgattr: MSG_ATTR_REQ -seqs: 1 -version: 1 -subtype: 1 -net { - todev_ble_sync: 2 -} - - - msgtype: MSG_CMD_TYPE_EMBED_SYS sender: DEV_MOBILEAPP rcver: DEV_MAINCTL @@ -213,53 +145,6 @@ } } -# get_all_boundary_hash_list 3 -msgtype: MSG_CMD_TYPE_NAV -sender: DEV_MOBILEAPP -rcver: DEV_MAINCTL -msgattr: MSG_ATTR_REQ -seqs: 1 -version: 1 -subtype: 1 -nav { - todev_gethash { - pver: 1 - subCmd: 3 - } -} - -# all powerful RW //allpowerfullRWAdapterX3 for yuka -msgtype: MSG_CMD_TYPE_EMBED_SYS -sender: DEV_MOBILEAPP -rcver: DEV_MAINCTL -msgattr: MSG_ATTR_REQ -seqs: 1 -version: 1 -subtype: 1 -sys { - bidire_comm_cmd { - rw: 1 - id: 5 - context: 1 - } -} - -# returns update buf -msgtype: MSG_CMD_TYPE_EMBED_SYS -sender: DEV_MOBILEAPP -rcver: DEV_MAINCTL -msgattr: MSG_ATTR_REQ -seqs: 1 -version: 1 -subtype: 1 -sys { - bidire_comm_cmd { - rw: 1 - id: 5 - context: 2 - } -} - # more update buf data system_update_buf { @@ -304,23 +189,6 @@ } -# get hash total frame -msgtype: MSG_CMD_TYPE_NAV -sender: DEV_MOBILEAPP -rcver: DEV_MAINCTL -msgattr: MSG_ATTR_REQ -seqs: 1 -version: 1 -subtype: 1 -nav { - todev_gethash { - pver: 1 - subCmd: 2 - totalFrame: 2 - currentFrame: 1 - } -} - # synchronize_hash_data 3 or get_area_tobe_transferred msgtype: MSG_CMD_TYPE_NAV @@ -339,50 +207,11 @@ } } -# get_hash_response total 2 current 2 - -msgtype: MSG_CMD_TYPE_NAV -sender: DEV_MOBILEAPP -rcver: DEV_MAINCTL -msgattr: MSG_ATTR_REQ -seqs: 1 -version: 1 -subtype: 1 -nav { - todev_gethash { - pver: 1 - subCmd: 2 - totalFrame: 2 - currentFrame: 2 - } -} - -# unknown large thing -# get_hash_response total 1 current 1 - -msgtype: MSG_CMD_TYPE_NAV -sender: DEV_MOBILEAPP -rcver: DEV_MAINCTL -msgattr: MSG_ATTR_REQ -seqs: 1 -version: 1 -subtype: 1 -nav { - todev_get_commondata { - pver: 1 - subCmd: 2 - action: 8 - type: 3 - totalFrame: 1 - currentFrame: 1 - } -} - # get all the hash data - +# getLineInfoList msgtype: MSG_CMD_TYPE_NAV sender: DEV_MOBILEAPP rcver: DEV_MAINCTL @@ -500,24 +329,6 @@ } } - -msgtype: MSG_CMD_TYPE_EMBED_SYS -sender: DEV_MOBILEAPP -rcver: DEV_MAINCTL -msgattr: MSG_ATTR_REQ -seqs: 1 -version: 1 -subtype: 1 -sys { - bidire_comm_cmd { - rw: 1 - id: 5 - context: 3 - } -} - - - # just have to call ble sync and get all this data back :) toapp_report_data = '\x08\xf4\x01\x10\x01\x18\x07(\xc170\x01R\xb8\x01\xba\x02\xb4\x01\n\x18\x08\x01\x10\xb8\xff\xff\xff\xff\xff\xff\xff\xff\x01\x18\xcf\xff\xff\xff\xff\xff\xff\xff\xff\x01\x12\x0e\x08\x0b\x10\x02\x18d(\x0e0\x95\xaf\xe5\xb1\x06\x1a\x13\x08\x04\x10\x02\x18 @\x80\x80\xb4\xf9\x91\x80\x80\x80\x03P\x980"-\x08\xa0\xab\xf7\xff\xff\xff\xff\xff\xff\x01\x10\xe4\xe0\xfc\xff\xff\xff\xff\xff\xff\x01\x18\xe7\xc8\xf8\xff\xff\xff\xff\xff\xff\x01 \x050\xe5\xa7\xe3\xd2\x93\xd2\xd5\x98**D\x10\xcf\xd6\xfa\xf5\xb5\xc1\xef\x9eC\x18\xd6\x80\xd8\x02 n0\xf0\xe0\x81\xc0\xa4\xe5\x81\xc5G8\x84\xa4\x07@\xfd\xf6\x07`\x99\xf0\x9b\xe0\xce\x88\xe2\x96Gp\xe2\xa5\xde\xf0\xe3\xbc\xaf\x8aQx\xfc\xb5\xf4\xf2\x8d\xa5\x80\xe7q\xa0\x01<' diff --git a/tests/test2_instance.py b/tests/test2_instance.py index 4b6b01a..88f2ab6 100644 --- a/tests/test2_instance.py +++ b/tests/test2_instance.py @@ -11,7 +11,8 @@ bleNotificationEvt = BleNotificationEvent() logging.basicConfig() -logging.getLogger().setLevel(logging.DEBUG) +logging.getLogger().setLevel(logging.INFO) + async def ble_heartbeat(luba_client): while True: @@ -62,12 +63,12 @@ async def run(loop): await asyncio.sleep(2) await luba_ble.start_sync(0) await asyncio.sleep(2) - print(luba_ble.luba_msg.sys.toapp_report_data.dev) + # print(luba_ble.luba_msg.sys.toapp_report_data.dev) # if has_field(luba_ble.luba_msg.sys.toapp_report_data.dev): # dev = luba_ble.luba_msg.sys.toapp_report_data.dev # if dev.sys_status == 11: # await luba_ble.command("start_job") - await luba_ble.command("get_report_cfg") + # await luba_ble.command("get_report_cfg") print(luba_ble.luba_msg.sys.toapp_report_data.dev.charge_state) await asyncio.sleep(5) @@ -84,7 +85,7 @@ async def run(loop): # await luba_ble.command("return_to_dock") # await luba_ble.command("get_hash_response", total_frame=1, current_frame=1) counter = 30 - while(counter > 0): + while (counter > 0): luba_device = await scan_for_luba() if luba_device is not None: luba_ble.update_device(luba_device) @@ -93,8 +94,9 @@ async def run(loop): # await luba_ble._execute_disconnect_with_lock() await asyncio.sleep(60) - counter-=1 + counter -= 1 + # app_request_cover_paths_t use hashlist from ?? # asyncio.run(await ble_heartbeat(luba_ble)) print("end run?") diff --git a/tests/test_bytes.py b/tests/test_bytes.py deleted file mode 100644 index d1b6494..0000000 --- a/tests/test_bytes.py +++ /dev/null @@ -1,18 +0,0 @@ - -test = b'M\x04\x00\xdf\x08\xf8\x01\x10\x01\x18\x07 \x02(\x010\x018\x80\x80 B\xcb\x01b\xc8\x01\n\x12\x08\x01\x10\x06\x18\x01"\n1.10.5.237\n\x1e\x08\x01\x10\x03\x18\x01"\x161.6.22.2040 (3be066bf)\n\x1c\x08\x02\x10\x03\x18\x01"\x141.1.1.622 (a993d995)\n\x1b\x08\x03\x10\x03\x18\x01"\x132.2.0.150 (2cf62fc)\n\x1b\x08\x04\x10\x03\x18\x01"\x132.2.0.150 (2cf62fc)\n\x0c\x08\x05\x10\x03\x18\x01"\x047361\n\x1e\x08\x06\x10\x03\x18\x01"\x161.6.22.2040 (3be066bf)\n\x0c\x08\x07\x10\x03\x18\x01"\x041.28' - -sys_rapid_state_tunnel = b'\x08\xf4\x01\x10\x01\x18\x07(\xfc\xed\x0e0\x01R&\xca\x01#\n!\x04\x02+\xb4\xbf\x01IL\x1b\xea\xbe\xf6\xff\xff\xff\xff\xff\xff\x01\x9a$\xfe\x96\xda\xff\xff\xff\xff\xff\xff\x01\x05\x00' - -systemTardStateTunnel = b'\x08\xf4\x01\x10\x01\x18\x07(\xbf\x96\x0b0\x01R`\xd2\x01]\n[\x0b\x01d<\x00\x00\xbc\xda\xcf\xf6\xf9\x98\xc2\xa8h\xb3\xe7\xcc\x90\xc3\x8e\x89\xbbm\xe1\x80\x84\x03\x00\x00\xba\xf3\xfe\xf1\xd6\x96\x91\xf2\x15\x81\xb2\xff\xff\xff\xff\xff\xff\xff\x01\xcc\x98\xfc\xff\xff\xff\xff\xff\xff\x01\x00\x00\x00\x89\xaf\xb7\xe7\xf7\x84\xc6\xd3L\x00\xb9\x95\x8c\xf6\xe6\xeb\xc1\xe1Y\xde\xd9\xd2\xfc\xab\xc2\x9b\x903\x00' - -get_base_info = b'M\x04\x00%\x08\xf8\x01\x10\x01\x18\x07 \x02(\x010\x01B\x16b\x14\n\x12\x08\x01\x10\x06\x18\x01"\n1.10.5.242' - -# print(systemTardStateTunnel.hex()) - -thing = b'M\x00\x06\x1c\x08\xf0\x01\x10\x07\x18\x01 \x01(\x010\x018\x01Z\x0b\xf2\x01\x08\x08\x01\x10\x02\x18\x01 \x01' -print(thing.hex()) -# print(get_base_info.hex()) -# -# message = BleMessage(None) -# -# message.parseNotification()