From 4ef5b3a53c4f2885992886a5f7de7995d3ea8402 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B6rrle?= Date: Mon, 1 Jan 2024 22:39:55 +0100 Subject: [PATCH 01/68] poetry update and use stub files in dev dependencies for better hints --- poetry.lock | 371 ++++++++++++++++++++++++++++++++++++++++--------- pyproject.toml | 4 +- 2 files changed, 311 insertions(+), 64 deletions(-) diff --git a/poetry.lock b/poetry.lock index 4d7ee6e..fd73b66 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.7.0 and should not be changed by hand. [[package]] name = "aiohttp" @@ -152,6 +152,17 @@ files = [ [package.dependencies] frozenlist = ">=1.1.0" +[[package]] +name = "annotated-types" +version = "0.6.0" +description = "Reusable constraint types to use with typing.Annotated" +optional = false +python-versions = ">=3.8" +files = [ + {file = "annotated_types-0.6.0-py3-none-any.whl", hash = "sha256:0641064de18ba7a25dee8f96403ebc39113d0cb953a01429249d5c7564666a43"}, + {file = "annotated_types-0.6.0.tar.gz", hash = "sha256:563339e807e53ffd9c267e99fc6d9ea23eb8443c08f112651963e24e22f84a5d"}, +] + [[package]] name = "anyio" version = "4.2.0" @@ -687,6 +698,25 @@ files = [ {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, ] +[[package]] +name = "hishel" +version = "0.0.19" +description = "Persistent cache implementation for httpx and httpcore" +optional = false +python-versions = ">=3.8" +files = [ + {file = "hishel-0.0.19-py3-none-any.whl", hash = "sha256:4606e82c2e569d35bb3413837f2b52e174d26d1b13baa416e17e156eba61a3e6"}, + {file = "hishel-0.0.19.tar.gz", hash = "sha256:a58f9ccfad8a61d84422c4fcf31f428621a3d33d1b1e545df69ad3b443f4094e"}, +] + +[package.dependencies] +httpx = ">=0.22.0" + +[package.extras] +redis = ["redis (==5.0.0)"] +sqlite = ["anysqlite (>=0.0.5)"] +yaml = ["pyyaml (==6.0.1)"] + [[package]] name = "home-assistant-bluetooth" version = "1.10.4" @@ -741,6 +771,20 @@ voluptuous = "0.13.1" voluptuous-serialize = "2.6.0" yarl = "1.9.2" +[[package]] +name = "homeassistant-stubs" +version = "2023.12.4" +description = "PEP 484 typing stubs for Home Assistant Core" +optional = false +python-versions = ">=3.11,<4.0" +files = [ + {file = "homeassistant_stubs-2023.12.4-py3-none-any.whl", hash = "sha256:2e8083149cefa771c45279d5893a67cb932a39f3410a7f1ed5322ce5675d041d"}, + {file = "homeassistant_stubs-2023.12.4.tar.gz", hash = "sha256:778867d768e5d9767e75525ffe48978fa3188b65b3af5efa17e404b85feedced"}, +] + +[package.dependencies] +homeassistant = "2023.12.4" + [[package]] name = "httpcore" version = "0.18.0" @@ -973,16 +1017,6 @@ files = [ {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac"}, {file = "MarkupSafe-2.1.3-cp311-cp311-win32.whl", hash = "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb"}, {file = "MarkupSafe-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f698de3fd0c4e6972b92290a45bd9b1536bffe8c6759c62471efaa8acb4c37bc"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aa57bd9cf8ae831a362185ee444e15a93ecb2e344c8e52e4d721ea3ab6ef1823"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffcc3f7c66b5f5b7931a5aa68fc9cecc51e685ef90282f4a82f0f5e9b704ad11"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47d4f1c5f80fc62fdd7777d0d40a2e9dda0a05883ab11374334f6c4de38adffd"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1f67c7038d560d92149c060157d623c542173016c4babc0c1913cca0564b9939"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:9aad3c1755095ce347e26488214ef77e0485a3c34a50c5a5e2471dff60b9dd9c"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:14ff806850827afd6b07a5f32bd917fb7f45b046ba40c57abdb636674a8b559c"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8f9293864fe09b8149f0cc42ce56e3f0e54de883a9de90cd427f191c346eb2e1"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-win32.whl", hash = "sha256:715d3562f79d540f251b99ebd6d8baa547118974341db04f5ad06d5ea3eb8007"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-win_amd64.whl", hash = "sha256:1b8dd8c3fd14349433c79fa8abeb573a55fc0fdd769133baac1f5e07abf54aeb"}, {file = "MarkupSafe-2.1.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2"}, {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b"}, {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707"}, @@ -1098,21 +1132,81 @@ files = [ {file = "multidict-6.0.4.tar.gz", hash = "sha256:3666906492efb76453c0e7b97f2cf459b0682e7402c0489a95484965dbc1da49"}, ] +[[package]] +name = "mypy" +version = "1.8.0" +description = "Optional static typing for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "mypy-1.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:485a8942f671120f76afffff70f259e1cd0f0cfe08f81c05d8816d958d4577d3"}, + {file = "mypy-1.8.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:df9824ac11deaf007443e7ed2a4a26bebff98d2bc43c6da21b2b64185da011c4"}, + {file = "mypy-1.8.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2afecd6354bbfb6e0160f4e4ad9ba6e4e003b767dd80d85516e71f2e955ab50d"}, + {file = "mypy-1.8.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8963b83d53ee733a6e4196954502b33567ad07dfd74851f32be18eb932fb1cb9"}, + {file = "mypy-1.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:e46f44b54ebddbeedbd3d5b289a893219065ef805d95094d16a0af6630f5d410"}, + {file = "mypy-1.8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:855fe27b80375e5c5878492f0729540db47b186509c98dae341254c8f45f42ae"}, + {file = "mypy-1.8.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4c886c6cce2d070bd7df4ec4a05a13ee20c0aa60cb587e8d1265b6c03cf91da3"}, + {file = "mypy-1.8.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d19c413b3c07cbecf1f991e2221746b0d2a9410b59cb3f4fb9557f0365a1a817"}, + {file = "mypy-1.8.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9261ed810972061388918c83c3f5cd46079d875026ba97380f3e3978a72f503d"}, + {file = "mypy-1.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:51720c776d148bad2372ca21ca29256ed483aa9a4cdefefcef49006dff2a6835"}, + {file = "mypy-1.8.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:52825b01f5c4c1c4eb0db253ec09c7aa17e1a7304d247c48b6f3599ef40db8bd"}, + {file = "mypy-1.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f5ac9a4eeb1ec0f1ccdc6f326bcdb464de5f80eb07fb38b5ddd7b0de6bc61e55"}, + {file = "mypy-1.8.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afe3fe972c645b4632c563d3f3eff1cdca2fa058f730df2b93a35e3b0c538218"}, + {file = "mypy-1.8.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:42c6680d256ab35637ef88891c6bd02514ccb7e1122133ac96055ff458f93fc3"}, + {file = "mypy-1.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:720a5ca70e136b675af3af63db533c1c8c9181314d207568bbe79051f122669e"}, + {file = "mypy-1.8.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:028cf9f2cae89e202d7b6593cd98db6759379f17a319b5faf4f9978d7084cdc6"}, + {file = "mypy-1.8.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4e6d97288757e1ddba10dd9549ac27982e3e74a49d8d0179fc14d4365c7add66"}, + {file = "mypy-1.8.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f1478736fcebb90f97e40aff11a5f253af890c845ee0c850fe80aa060a267c6"}, + {file = "mypy-1.8.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:42419861b43e6962a649068a61f4a4839205a3ef525b858377a960b9e2de6e0d"}, + {file = "mypy-1.8.0-cp38-cp38-win_amd64.whl", hash = "sha256:2b5b6c721bd4aabaadead3a5e6fa85c11c6c795e0c81a7215776ef8afc66de02"}, + {file = "mypy-1.8.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5c1538c38584029352878a0466f03a8ee7547d7bd9f641f57a0f3017a7c905b8"}, + {file = "mypy-1.8.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4ef4be7baf08a203170f29e89d79064463b7fc7a0908b9d0d5114e8009c3a259"}, + {file = "mypy-1.8.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7178def594014aa6c35a8ff411cf37d682f428b3b5617ca79029d8ae72f5402b"}, + {file = "mypy-1.8.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ab3c84fa13c04aeeeabb2a7f67a25ef5d77ac9d6486ff33ded762ef353aa5592"}, + {file = "mypy-1.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:99b00bc72855812a60d253420d8a2eae839b0afa4938f09f4d2aa9bb4654263a"}, + {file = "mypy-1.8.0-py3-none-any.whl", hash = "sha256:538fd81bb5e430cc1381a443971c0475582ff9f434c16cd46d2c66763ce85d9d"}, + {file = "mypy-1.8.0.tar.gz", hash = "sha256:6ff8b244d7085a0b425b56d327b480c3b29cafbd2eff27316a004f9a7391ae07"}, +] + +[package.dependencies] +mypy-extensions = ">=1.0.0" +typing-extensions = ">=4.1.0" + +[package.extras] +dmypy = ["psutil (>=4.0)"] +install-types = ["pip"] +mypyc = ["setuptools (>=50)"] +reports = ["lxml"] + +[[package]] +name = "mypy-extensions" +version = "1.0.0" +description = "Type system extensions for programs checked with the mypy type checker." +optional = false +python-versions = ">=3.5" +files = [ + {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, + {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, +] + [[package]] name = "mytoyota" -version = "0.9.3" +version = "1.0.0" description = "Python client for Toyota Connected Services." optional = false python-versions = ">=3.8.1,<4.0.0" files = [ - {file = "mytoyota-0.9.3-py3-none-any.whl", hash = "sha256:b4c29a583a456eb3c96910571d5f60c57080ce0885b175d0ecc3fe96bb299c21"}, - {file = "mytoyota-0.9.3.tar.gz", hash = "sha256:5c601f42717086ca5c49cae8507bfc25fcd7f453e60f209a14be3167b2cacc31"}, + {file = "mytoyota-1.0.0-py3-none-any.whl", hash = "sha256:05f2b4f4cd980e323c4d9af5ae05c762e43bdc7cc5eddfa6c059dd61c723887e"}, + {file = "mytoyota-1.0.0.tar.gz", hash = "sha256:5ce0d2bc82ca80a4062b255e06862f5d85ea7f314644142266167fd5ed21dd0d"}, ] [package.dependencies] arrow = ">=1.1,<2.0" +hishel = ">=0.0.19,<0.0.20" httpx = ">=0.18.1" langcodes = ">=3.1,<4.0" +pydantic = ">=2.5.1,<3.0.0" +pyjwt = ">=2.8.0,<3.0.0" [[package]] name = "nodeenv" @@ -1253,6 +1347,142 @@ files = [ {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"}, ] +[[package]] +name = "pydantic" +version = "2.5.3" +description = "Data validation using Python type hints" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pydantic-2.5.3-py3-none-any.whl", hash = "sha256:d0caf5954bee831b6bfe7e338c32b9e30c85dfe080c843680783ac2b631673b4"}, + {file = "pydantic-2.5.3.tar.gz", hash = "sha256:b3ef57c62535b0941697cce638c08900d87fcb67e29cfa99e8a68f747f393f7a"}, +] + +[package.dependencies] +annotated-types = ">=0.4.0" +pydantic-core = "2.14.6" +typing-extensions = ">=4.6.1" + +[package.extras] +email = ["email-validator (>=2.0.0)"] + +[[package]] +name = "pydantic-core" +version = "2.14.6" +description = "" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pydantic_core-2.14.6-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:72f9a942d739f09cd42fffe5dc759928217649f070056f03c70df14f5770acf9"}, + {file = "pydantic_core-2.14.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6a31d98c0d69776c2576dda4b77b8e0c69ad08e8b539c25c7d0ca0dc19a50d6c"}, + {file = "pydantic_core-2.14.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5aa90562bc079c6c290f0512b21768967f9968e4cfea84ea4ff5af5d917016e4"}, + {file = "pydantic_core-2.14.6-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:370ffecb5316ed23b667d99ce4debe53ea664b99cc37bfa2af47bc769056d534"}, + {file = "pydantic_core-2.14.6-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f85f3843bdb1fe80e8c206fe6eed7a1caeae897e496542cee499c374a85c6e08"}, + {file = "pydantic_core-2.14.6-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9862bf828112e19685b76ca499b379338fd4c5c269d897e218b2ae8fcb80139d"}, + {file = "pydantic_core-2.14.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:036137b5ad0cb0004c75b579445a1efccd072387a36c7f217bb8efd1afbe5245"}, + {file = "pydantic_core-2.14.6-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:92879bce89f91f4b2416eba4429c7b5ca22c45ef4a499c39f0c5c69257522c7c"}, + {file = "pydantic_core-2.14.6-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0c08de15d50fa190d577e8591f0329a643eeaed696d7771760295998aca6bc66"}, + {file = "pydantic_core-2.14.6-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:36099c69f6b14fc2c49d7996cbf4f87ec4f0e66d1c74aa05228583225a07b590"}, + {file = "pydantic_core-2.14.6-cp310-none-win32.whl", hash = "sha256:7be719e4d2ae6c314f72844ba9d69e38dff342bc360379f7c8537c48e23034b7"}, + {file = "pydantic_core-2.14.6-cp310-none-win_amd64.whl", hash = "sha256:36fa402dcdc8ea7f1b0ddcf0df4254cc6b2e08f8cd80e7010d4c4ae6e86b2a87"}, + {file = "pydantic_core-2.14.6-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:dea7fcd62915fb150cdc373212141a30037e11b761fbced340e9db3379b892d4"}, + {file = "pydantic_core-2.14.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ffff855100bc066ff2cd3aa4a60bc9534661816b110f0243e59503ec2df38421"}, + {file = "pydantic_core-2.14.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1b027c86c66b8627eb90e57aee1f526df77dc6d8b354ec498be9a757d513b92b"}, + {file = "pydantic_core-2.14.6-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:00b1087dabcee0b0ffd104f9f53d7d3eaddfaa314cdd6726143af6bc713aa27e"}, + {file = "pydantic_core-2.14.6-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:75ec284328b60a4e91010c1acade0c30584f28a1f345bc8f72fe8b9e46ec6a96"}, + {file = "pydantic_core-2.14.6-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7e1f4744eea1501404b20b0ac059ff7e3f96a97d3e3f48ce27a139e053bb370b"}, + {file = "pydantic_core-2.14.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b2602177668f89b38b9f84b7b3435d0a72511ddef45dc14446811759b82235a1"}, + {file = "pydantic_core-2.14.6-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6c8edaea3089bf908dd27da8f5d9e395c5b4dc092dbcce9b65e7156099b4b937"}, + {file = "pydantic_core-2.14.6-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:478e9e7b360dfec451daafe286998d4a1eeaecf6d69c427b834ae771cad4b622"}, + {file = "pydantic_core-2.14.6-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:b6ca36c12a5120bad343eef193cc0122928c5c7466121da7c20f41160ba00ba2"}, + {file = "pydantic_core-2.14.6-cp311-none-win32.whl", hash = "sha256:2b8719037e570639e6b665a4050add43134d80b687288ba3ade18b22bbb29dd2"}, + {file = "pydantic_core-2.14.6-cp311-none-win_amd64.whl", hash = "sha256:78ee52ecc088c61cce32b2d30a826f929e1708f7b9247dc3b921aec367dc1b23"}, + {file = "pydantic_core-2.14.6-cp311-none-win_arm64.whl", hash = "sha256:a19b794f8fe6569472ff77602437ec4430f9b2b9ec7a1105cfd2232f9ba355e6"}, + {file = "pydantic_core-2.14.6-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:667aa2eac9cd0700af1ddb38b7b1ef246d8cf94c85637cbb03d7757ca4c3fdec"}, + {file = "pydantic_core-2.14.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:cdee837710ef6b56ebd20245b83799fce40b265b3b406e51e8ccc5b85b9099b7"}, + {file = "pydantic_core-2.14.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2c5bcf3414367e29f83fd66f7de64509a8fd2368b1edf4351e862910727d3e51"}, + {file = "pydantic_core-2.14.6-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:26a92ae76f75d1915806b77cf459811e772d8f71fd1e4339c99750f0e7f6324f"}, + {file = "pydantic_core-2.14.6-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a983cca5ed1dd9a35e9e42ebf9f278d344603bfcb174ff99a5815f953925140a"}, + {file = "pydantic_core-2.14.6-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cb92f9061657287eded380d7dc455bbf115430b3aa4741bdc662d02977e7d0af"}, + {file = "pydantic_core-2.14.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4ace1e220b078c8e48e82c081e35002038657e4b37d403ce940fa679e57113b"}, + {file = "pydantic_core-2.14.6-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ef633add81832f4b56d3b4c9408b43d530dfca29e68fb1b797dcb861a2c734cd"}, + {file = "pydantic_core-2.14.6-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7e90d6cc4aad2cc1f5e16ed56e46cebf4877c62403a311af20459c15da76fd91"}, + {file = "pydantic_core-2.14.6-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:e8a5ac97ea521d7bde7621d86c30e86b798cdecd985723c4ed737a2aa9e77d0c"}, + {file = "pydantic_core-2.14.6-cp312-none-win32.whl", hash = "sha256:f27207e8ca3e5e021e2402ba942e5b4c629718e665c81b8b306f3c8b1ddbb786"}, + {file = "pydantic_core-2.14.6-cp312-none-win_amd64.whl", hash = "sha256:b3e5fe4538001bb82e2295b8d2a39356a84694c97cb73a566dc36328b9f83b40"}, + {file = "pydantic_core-2.14.6-cp312-none-win_arm64.whl", hash = "sha256:64634ccf9d671c6be242a664a33c4acf12882670b09b3f163cd00a24cffbd74e"}, + {file = "pydantic_core-2.14.6-cp37-cp37m-macosx_10_7_x86_64.whl", hash = "sha256:24368e31be2c88bd69340fbfe741b405302993242ccb476c5c3ff48aeee1afe0"}, + {file = "pydantic_core-2.14.6-cp37-cp37m-macosx_11_0_arm64.whl", hash = "sha256:e33b0834f1cf779aa839975f9d8755a7c2420510c0fa1e9fa0497de77cd35d2c"}, + {file = "pydantic_core-2.14.6-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6af4b3f52cc65f8a0bc8b1cd9676f8c21ef3e9132f21fed250f6958bd7223bed"}, + {file = "pydantic_core-2.14.6-cp37-cp37m-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d15687d7d7f40333bd8266f3814c591c2e2cd263fa2116e314f60d82086e353a"}, + {file = "pydantic_core-2.14.6-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:095b707bb287bfd534044166ab767bec70a9bba3175dcdc3371782175c14e43c"}, + {file = "pydantic_core-2.14.6-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:94fc0e6621e07d1e91c44e016cc0b189b48db053061cc22d6298a611de8071bb"}, + {file = "pydantic_core-2.14.6-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ce830e480f6774608dedfd4a90c42aac4a7af0a711f1b52f807130c2e434c06"}, + {file = "pydantic_core-2.14.6-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a306cdd2ad3a7d795d8e617a58c3a2ed0f76c8496fb7621b6cd514eb1532cae8"}, + {file = "pydantic_core-2.14.6-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:2f5fa187bde8524b1e37ba894db13aadd64faa884657473b03a019f625cee9a8"}, + {file = "pydantic_core-2.14.6-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:438027a975cc213a47c5d70672e0d29776082155cfae540c4e225716586be75e"}, + {file = "pydantic_core-2.14.6-cp37-none-win32.whl", hash = "sha256:f96ae96a060a8072ceff4cfde89d261837b4294a4f28b84a28765470d502ccc6"}, + {file = "pydantic_core-2.14.6-cp37-none-win_amd64.whl", hash = "sha256:e646c0e282e960345314f42f2cea5e0b5f56938c093541ea6dbf11aec2862391"}, + {file = "pydantic_core-2.14.6-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:db453f2da3f59a348f514cfbfeb042393b68720787bbef2b4c6068ea362c8149"}, + {file = "pydantic_core-2.14.6-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3860c62057acd95cc84044e758e47b18dcd8871a328ebc8ccdefd18b0d26a21b"}, + {file = "pydantic_core-2.14.6-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:36026d8f99c58d7044413e1b819a67ca0e0b8ebe0f25e775e6c3d1fabb3c38fb"}, + {file = "pydantic_core-2.14.6-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8ed1af8692bd8d2a29d702f1a2e6065416d76897d726e45a1775b1444f5928a7"}, + {file = "pydantic_core-2.14.6-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:314ccc4264ce7d854941231cf71b592e30d8d368a71e50197c905874feacc8a8"}, + {file = "pydantic_core-2.14.6-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:982487f8931067a32e72d40ab6b47b1628a9c5d344be7f1a4e668fb462d2da42"}, + {file = "pydantic_core-2.14.6-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2dbe357bc4ddda078f79d2a36fc1dd0494a7f2fad83a0a684465b6f24b46fe80"}, + {file = "pydantic_core-2.14.6-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2f6ffc6701a0eb28648c845f4945a194dc7ab3c651f535b81793251e1185ac3d"}, + {file = "pydantic_core-2.14.6-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:7f5025db12fc6de7bc1104d826d5aee1d172f9ba6ca936bf6474c2148ac336c1"}, + {file = "pydantic_core-2.14.6-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:dab03ed811ed1c71d700ed08bde8431cf429bbe59e423394f0f4055f1ca0ea60"}, + {file = "pydantic_core-2.14.6-cp38-none-win32.whl", hash = "sha256:dfcbebdb3c4b6f739a91769aea5ed615023f3c88cb70df812849aef634c25fbe"}, + {file = "pydantic_core-2.14.6-cp38-none-win_amd64.whl", hash = "sha256:99b14dbea2fdb563d8b5a57c9badfcd72083f6006caf8e126b491519c7d64ca8"}, + {file = "pydantic_core-2.14.6-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:4ce8299b481bcb68e5c82002b96e411796b844d72b3e92a3fbedfe8e19813eab"}, + {file = "pydantic_core-2.14.6-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b9a9d92f10772d2a181b5ca339dee066ab7d1c9a34ae2421b2a52556e719756f"}, + {file = "pydantic_core-2.14.6-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fd9e98b408384989ea4ab60206b8e100d8687da18b5c813c11e92fd8212a98e0"}, + {file = "pydantic_core-2.14.6-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4f86f1f318e56f5cbb282fe61eb84767aee743ebe32c7c0834690ebea50c0a6b"}, + {file = "pydantic_core-2.14.6-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:86ce5fcfc3accf3a07a729779d0b86c5d0309a4764c897d86c11089be61da160"}, + {file = "pydantic_core-2.14.6-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3dcf1978be02153c6a31692d4fbcc2a3f1db9da36039ead23173bc256ee3b91b"}, + {file = "pydantic_core-2.14.6-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eedf97be7bc3dbc8addcef4142f4b4164066df0c6f36397ae4aaed3eb187d8ab"}, + {file = "pydantic_core-2.14.6-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d5f916acf8afbcab6bacbb376ba7dc61f845367901ecd5e328fc4d4aef2fcab0"}, + {file = "pydantic_core-2.14.6-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:8a14c192c1d724c3acbfb3f10a958c55a2638391319ce8078cb36c02283959b9"}, + {file = "pydantic_core-2.14.6-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:0348b1dc6b76041516e8a854ff95b21c55f5a411c3297d2ca52f5528e49d8411"}, + {file = "pydantic_core-2.14.6-cp39-none-win32.whl", hash = "sha256:de2a0645a923ba57c5527497daf8ec5df69c6eadf869e9cd46e86349146e5975"}, + {file = "pydantic_core-2.14.6-cp39-none-win_amd64.whl", hash = "sha256:aca48506a9c20f68ee61c87f2008f81f8ee99f8d7f0104bff3c47e2d148f89d9"}, + {file = "pydantic_core-2.14.6-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:d5c28525c19f5bb1e09511669bb57353d22b94cf8b65f3a8d141c389a55dec95"}, + {file = "pydantic_core-2.14.6-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:78d0768ee59baa3de0f4adac9e3748b4b1fffc52143caebddfd5ea2961595277"}, + {file = "pydantic_core-2.14.6-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b93785eadaef932e4fe9c6e12ba67beb1b3f1e5495631419c784ab87e975670"}, + {file = "pydantic_core-2.14.6-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a874f21f87c485310944b2b2734cd6d318765bcbb7515eead33af9641816506e"}, + {file = "pydantic_core-2.14.6-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b89f4477d915ea43b4ceea6756f63f0288941b6443a2b28c69004fe07fde0d0d"}, + {file = "pydantic_core-2.14.6-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:172de779e2a153d36ee690dbc49c6db568d7b33b18dc56b69a7514aecbcf380d"}, + {file = "pydantic_core-2.14.6-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:dfcebb950aa7e667ec226a442722134539e77c575f6cfaa423f24371bb8d2e94"}, + {file = "pydantic_core-2.14.6-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:55a23dcd98c858c0db44fc5c04fc7ed81c4b4d33c653a7c45ddaebf6563a2f66"}, + {file = "pydantic_core-2.14.6-pp37-pypy37_pp73-macosx_10_7_x86_64.whl", hash = "sha256:4241204e4b36ab5ae466ecec5c4c16527a054c69f99bba20f6f75232a6a534e2"}, + {file = "pydantic_core-2.14.6-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e574de99d735b3fc8364cba9912c2bec2da78775eba95cbb225ef7dda6acea24"}, + {file = "pydantic_core-2.14.6-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1302a54f87b5cd8528e4d6d1bf2133b6aa7c6122ff8e9dc5220fbc1e07bffebd"}, + {file = "pydantic_core-2.14.6-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f8e81e4b55930e5ffab4a68db1af431629cf2e4066dbdbfef65348b8ab804ea8"}, + {file = "pydantic_core-2.14.6-pp37-pypy37_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:c99462ffc538717b3e60151dfaf91125f637e801f5ab008f81c402f1dff0cd0f"}, + {file = "pydantic_core-2.14.6-pp37-pypy37_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:e4cf2d5829f6963a5483ec01578ee76d329eb5caf330ecd05b3edd697e7d768a"}, + {file = "pydantic_core-2.14.6-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:cf10b7d58ae4a1f07fccbf4a0a956d705356fea05fb4c70608bb6fa81d103cda"}, + {file = "pydantic_core-2.14.6-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:399ac0891c284fa8eb998bcfa323f2234858f5d2efca3950ae58c8f88830f145"}, + {file = "pydantic_core-2.14.6-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9c6a5c79b28003543db3ba67d1df336f253a87d3112dac3a51b94f7d48e4c0e1"}, + {file = "pydantic_core-2.14.6-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:599c87d79cab2a6a2a9df4aefe0455e61e7d2aeede2f8577c1b7c0aec643ee8e"}, + {file = "pydantic_core-2.14.6-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:43e166ad47ba900f2542a80d83f9fc65fe99eb63ceec4debec160ae729824052"}, + {file = "pydantic_core-2.14.6-pp38-pypy38_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:3a0b5db001b98e1c649dd55afa928e75aa4087e587b9524a4992316fa23c9fba"}, + {file = "pydantic_core-2.14.6-pp38-pypy38_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:747265448cb57a9f37572a488a57d873fd96bf51e5bb7edb52cfb37124516da4"}, + {file = "pydantic_core-2.14.6-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:7ebe3416785f65c28f4f9441e916bfc8a54179c8dea73c23023f7086fa601c5d"}, + {file = "pydantic_core-2.14.6-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:86c963186ca5e50d5c8287b1d1c9d3f8f024cbe343d048c5bd282aec2d8641f2"}, + {file = "pydantic_core-2.14.6-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:e0641b506486f0b4cd1500a2a65740243e8670a2549bb02bc4556a83af84ae03"}, + {file = "pydantic_core-2.14.6-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:71d72ca5eaaa8d38c8df16b7deb1a2da4f650c41b58bb142f3fb75d5ad4a611f"}, + {file = "pydantic_core-2.14.6-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:27e524624eace5c59af499cd97dc18bb201dc6a7a2da24bfc66ef151c69a5f2a"}, + {file = "pydantic_core-2.14.6-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a3dde6cac75e0b0902778978d3b1646ca9f438654395a362cb21d9ad34b24acf"}, + {file = "pydantic_core-2.14.6-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:00646784f6cd993b1e1c0e7b0fdcbccc375d539db95555477771c27555e3c556"}, + {file = "pydantic_core-2.14.6-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:23598acb8ccaa3d1d875ef3b35cb6376535095e9405d91a3d57a8c7db5d29341"}, + {file = "pydantic_core-2.14.6-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7f41533d7e3cf9520065f610b41ac1c76bc2161415955fbcead4981b22c7611e"}, + {file = "pydantic_core-2.14.6.tar.gz", hash = "sha256:1fd0c1d395372843fba13a51c28e3bb9d59bd7aebfeb17358ffaaa1e4dbbe948"}, +] + +[package.dependencies] +typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" + [[package]] name = "pyjwt" version = "2.8.0" @@ -1437,13 +1667,13 @@ files = [ [[package]] name = "setuptools" -version = "69.0.2" +version = "69.0.3" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "setuptools-69.0.2-py3-none-any.whl", hash = "sha256:1e8fdff6797d3865f37397be788a4e3cba233608e9b509382a2777d25ebde7f2"}, - {file = "setuptools-69.0.2.tar.gz", hash = "sha256:735896e78a4742605974de002ac60562d286fa8051a7e2299445e8e8fbb01aa6"}, + {file = "setuptools-69.0.3-py3-none-any.whl", hash = "sha256:385eb4edd9c9d5c17540511303e39a147ce2fc04bc55289c322b9e5904fe2c05"}, + {file = "setuptools-69.0.3.tar.gz", hash = "sha256:be1af57fc409f93647f2e8e4573a142ed38724b8cdd389706a867bb4efcf1e78"}, ] [package.extras] @@ -1603,6 +1833,21 @@ files = [ [package.dependencies] voluptuous = "*" +[[package]] +name = "voluptuous-stubs" +version = "0.1.1" +description = "voluptuous stubs" +optional = false +python-versions = "*" +files = [ + {file = "voluptuous-stubs-0.1.1.tar.gz", hash = "sha256:70fb1c088242f20e11023252b5648cd77f831f692cd910c8f9713cc135cf8cc8"}, + {file = "voluptuous_stubs-0.1.1-py3-none-any.whl", hash = "sha256:f216c427ed7e190b8413e26cf4f67e1bda692ea8225ed0d875f7724d10b7cb10"}, +] + +[package.dependencies] +mypy = ">=0.720" +typing-extensions = ">=3.7.4" + [[package]] name = "yarl" version = "1.9.2" @@ -1692,57 +1937,57 @@ multidict = ">=4.0" [[package]] name = "zlib-ng" -version = "0.2.0" +version = "0.4.0" description = "Drop-in replacement for zlib and gzip modules using zlib-ng" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "zlib-ng-0.2.0.tar.gz", hash = "sha256:2b23707cb7e5bf27afd8422d290f68e82185af69741bde60914f18d16fb66e9b"}, - {file = "zlib_ng-0.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1f8e5f722e4541ab17461d0749cc8442dbaf2148410f52ec31754cee62ab1d2c"}, - {file = "zlib_ng-0.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f00cea2eaecf9fc0989373e4c47cf7bc1252d8ce2ed6bd961f4720d0fbc651d8"}, - {file = "zlib_ng-0.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:504eaafac05cd39cb450df4ba67bd7f2972b459cdf231dab1971824dfbabba9f"}, - {file = "zlib_ng-0.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:a4b83d09ae58ef778eda6e339f29e17d254d689bd1f03dddd3918445b800364c"}, - {file = "zlib_ng-0.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a0638f161b140e4bd6b031a57d6e0a2901e5de920c47ffad8c810fbaf3dc2ff0"}, - {file = "zlib_ng-0.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:609e0093f7d32e9bf66163d7f4256a076631aad530d6026e9d16ebd4e2167c64"}, - {file = "zlib_ng-0.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6448c3782673f696af659921857266912ff3ede494c59e7df3f591091d88ff79"}, - {file = "zlib_ng-0.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d4490047a5d6a6d4478751545abfd2cf8c715aba4987c5f65722c812447d6067"}, - {file = "zlib_ng-0.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:09b0375cded9f37bef399c9f97c4b66f17ac7e31a2c239e5320cd356029e6885"}, - {file = "zlib_ng-0.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:687e511de9d936134db86b5e8478a6c46a2f45b6f9fa50e90a2802907712a1f6"}, - {file = "zlib_ng-0.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:4ee368e75efeafef1355b20dc71497de7eb924738d0d81647245a5b82c6fbe46"}, - {file = "zlib_ng-0.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:6d0a727a51287f7ef5eb2889fc5824a7489d8ad9c3878af15f42c0974faa7910"}, - {file = "zlib_ng-0.2.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:53e10af6d9731b571f59efea1a6ce75c6c21bbab6b5c8d4da7206df8924484e8"}, - {file = "zlib_ng-0.2.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d7b3c3920cf1a9a405b281920d2de0767fd669f379510fa9093a8a3d22cf15e"}, - {file = "zlib_ng-0.2.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:83fd51d89e2a8b2cadcfb2c421eee18d6937d2529243ca13f77d0cdbf305a63d"}, - {file = "zlib_ng-0.2.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:97ac61514d133c5bed9936e49e8c2e9a65db216a0ae61e9f6e7b3aaa1db26260"}, - {file = "zlib_ng-0.2.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:950cc37655a94fb3d7eaf5aa8ce949ad13a6eebdfda077edb4a9e62a9efaa4f4"}, - {file = "zlib_ng-0.2.0-cp37-cp37m-win_amd64.whl", hash = "sha256:3fe6ff9f29bec1c892a338dd6cb00350df1827d2834b4ab53d9e73bbcaacd186"}, - {file = "zlib_ng-0.2.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1b90fab73308206cfcdcb242da36195a629b7ba9efbd1d82331d82d40cd9daa0"}, - {file = "zlib_ng-0.2.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0e777a83d99adc2c785595567b15ea4235b4155df64999b69b6a968aa9e17d12"}, - {file = "zlib_ng-0.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a1344314603d7b4a296e9477243a50c8c6610d845729049a747ae4ba464b1f82"}, - {file = "zlib_ng-0.2.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:3e2de9e29b8e7a5d48e6a9f94cbea5920148d65b676afdcbf694f161d1c29802"}, - {file = "zlib_ng-0.2.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:9c62a498be0e3661d441dc5d3920ff006608f92027999ced7315fbf79c066722"}, - {file = "zlib_ng-0.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:ad5569cc488a1604f51faec521bd114f65c9549f8a65728b7aae19813b144932"}, - {file = "zlib_ng-0.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8586b25c8509ece44e233b52715f827db11537b4ddb72cd8f5dcb3934627b552"}, - {file = "zlib_ng-0.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:af255cb7da55300dec12e0078ea2f8048b891b89a939043cbcff3359b1b19d68"}, - {file = "zlib_ng-0.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6ea8fca4825bcc0f08a1cab4e4f8c6fad214b17a6aceaa2f9b444a8a9c546d8"}, - {file = "zlib_ng-0.2.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d57f0e969b9371f27598ec42ed30e8c91f290d8751c475dfc574490b3d85eeaa"}, - {file = "zlib_ng-0.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:05641f2df2e93edd1e4c9d39f96e4d9a60f7601161cff41d4db6a8a2c80e5bff"}, - {file = "zlib_ng-0.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:5a3c1af663e0f0f59c7f4b4e7a12e5f6ec0625d1d047b3467093a73aba34d5fd"}, - {file = "zlib_ng-0.2.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:679bf8ac7d9c62e08661b674756a3bd7c262400fa7690c8ec6ba998c86de27d9"}, - {file = "zlib_ng-0.2.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4edac7c4c5ba5171253b3644e66d291136d9244514167d89cf1d31ac3a0a0b8"}, - {file = "zlib_ng-0.2.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:482aa62ac4ef1989518018e34167da160ee9cfb54b11a100eb0a3fd5e5b9962c"}, - {file = "zlib_ng-0.2.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:c80904bc2d8a513d3b814e7c7f83fc349272321d5d067aef3db99646e9096f5c"}, - {file = "zlib_ng-0.2.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:73763356a1d5534705e15bb46741844ed9bd1d6d9868f603db0fcf60de6da2b2"}, - {file = "zlib_ng-0.2.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:87cb3d53cc604b30796f53aeaae1c3f8796dc54329b71085ebcefd126433c53c"}, - {file = "zlib_ng-0.2.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a1a24db3fcfe16e925134dcb70d5c76fed4376708f28b5b749bcced779fb5741"}, - {file = "zlib_ng-0.2.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:400b8372e1a82046d86f96bc04ba6f0d20f9551e20f6fcbb1197b03b8c2adc5a"}, - {file = "zlib_ng-0.2.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:2cccc149f368d8d8ee41c4c65502ba920d9f30154c3541c31273ce0c39f6a8ae"}, - {file = "zlib_ng-0.2.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5ca35e078f39ec2ac257f50d849dd6b61f60da246a8b7eca93207ff464e266d6"}, - {file = "zlib_ng-0.2.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:97370df1065aa28bd068cc9558183266252e93fe66bd0d8c01deaecfaf37447c"}, - {file = "zlib_ng-0.2.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:8830af41376f27f86a36c738c96b199a757620c1448884d9bde5f7649082a83b"}, + {file = "zlib-ng-0.4.0.tar.gz", hash = "sha256:3b730881aaeb86f9a4995de5e22499406ccf92f8508b5c017c343d27570a8c0a"}, + {file = "zlib_ng-0.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9b53458b4baa0554df93430bfda71a6861510d6641ac75192e6b9c2485d01a3a"}, + {file = "zlib_ng-0.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8ac2405b42420abd9dccfe5d5f05c052aaf88ee66aec0d3fb4ee171826846d8a"}, + {file = "zlib_ng-0.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70e192695fd7bac2c3db529a873f57e10a8d42383223b0c5dc281793be4b1b83"}, + {file = "zlib_ng-0.4.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:9b49346d528da8e13575bb8bfa2ee5f74398422e81d4be6001afb5c0621dc412"}, + {file = "zlib_ng-0.4.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:55a47ce2249581bc00decc5fc4aadf1f48c5edde770ff5aa649c2f0b782c9aba"}, + {file = "zlib_ng-0.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:ec04f0a21e711a654a9ea1dc5966c29231301625cfc199ca1ec0cdedbf921377"}, + {file = "zlib_ng-0.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:096d319b94454c174dde78886a8d4a0f488186a4fbd006bd1819360e0e8b5348"}, + {file = "zlib_ng-0.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:07694a956028a66133c52ebf802d6185c6e986fbec5c4e403b997e044b30db8d"}, + {file = "zlib_ng-0.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cd4c9d4945f366a0f295e9356dd9ef291544adbe42cabcc121a28b202dd8809b"}, + {file = "zlib_ng-0.4.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:39f69f92c7f8d107f406d981c1383c749894d737699116138de14497b0e0b041"}, + {file = "zlib_ng-0.4.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:6db621bdd34ef500ec1b44a5190fe5e967eee9386140be6bc8769ec15e355c4b"}, + {file = "zlib_ng-0.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:8b2a635d018b3dbed6844ceca08c0f9a170ebdcc9299ab080e4f63b757faaeae"}, + {file = "zlib_ng-0.4.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:274da13e42dc2197f8c24e321cc9cc4d1eef790512485462d72832343fe8f72a"}, + {file = "zlib_ng-0.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b87aba7e64de1efb5a965d51551b63efc24d9cc77671b7ea28f336162edc733"}, + {file = "zlib_ng-0.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e926e2f8a31a3bfd0e1e2ffc3fb9956126ee17b4477ee98aa4e51b7bdc7ad41d"}, + {file = "zlib_ng-0.4.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ba917d5e574ae67b3984835791b5887592d0cb2877d5bfe22c3ab7ef30a28979"}, + {file = "zlib_ng-0.4.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:e1e122967cacce2f1f04b5ee1ea89642997f8a312be6b527dc4a8e92deb834dd"}, + {file = "zlib_ng-0.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:57c53634157142b208b6dd4dbb21b6b67392afb7b181be0e97a09bfc7201819b"}, + {file = "zlib_ng-0.4.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8faa04e00261afd0e532392f70e74428687d00a37b6c3e63e6eb27ad8a81a629"}, + {file = "zlib_ng-0.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7dca9af5f84edcc98408af60c4fd220fe2ba3f6e7324b6b97483ac430e1ba89b"}, + {file = "zlib_ng-0.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5f338be6e62e05636467b89c26e0404d0e3d726da74aa3510be1e19e7681832b"}, + {file = "zlib_ng-0.4.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:4edeb933440e94d2c47331314edfda20f51a3640eb8e12a7a478859874d35a4a"}, + {file = "zlib_ng-0.4.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:676221d0abb724d97a1b693b99b63fe164b65cd419c31556f5bf538f5a950031"}, + {file = "zlib_ng-0.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:08a52fb23236870b956d02400a372f1c3a8adef298552466b6476a05ba061027"}, + {file = "zlib_ng-0.4.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:690d1ee223a75c61bb628b7203d06d08ea4e10e88c822a4fe4fa8bdad0955608"}, + {file = "zlib_ng-0.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2b53d72a2787ad5170a1c4b2444f14f064017bdc575ac43547054fdf0e8f8c4e"}, + {file = "zlib_ng-0.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67d37a39ed6521dfc31230f78ba095141d2317ad41bed9270eddfd1a37b9f076"}, + {file = "zlib_ng-0.4.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:209a4a2bb0797598f49aa7b7a9e8714b9f69a64777957eba476209d26bfec17b"}, + {file = "zlib_ng-0.4.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:b585e8ddd357fe4677c0c738e5962ca867e157257f3c33f2fa8965e04bdb5836"}, + {file = "zlib_ng-0.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:4a05cafa6a15284406a8c92eed06faa439dfd26b6c9c697719be450b919b459d"}, + {file = "zlib_ng-0.4.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:d62b1eaee0ae8fd6f544e199b4de90c018deaf1572f5e0c67ea5eb1adac7bfd3"}, + {file = "zlib_ng-0.4.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1ec74451bf33678a77ebbb9f24364390469396d6a1be69114063343dc654167"}, + {file = "zlib_ng-0.4.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ae20fde7487931146ea1d95b5ea524012c2b20d26d8a8458bf6befff1feaf1b"}, + {file = "zlib_ng-0.4.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:ab9cf1fca3128da63a1b67490fb4c753b6a880b183d826d49d4cd0c61951d0fa"}, + {file = "zlib_ng-0.4.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:a3731a1e44290a2ca568690b8c6b62994377d929fd9b2808e60ea371f21781f4"}, + {file = "zlib_ng-0.4.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8430bbbca7689ce87735970bc3b9dcb1b6d1453aa6c01f5a6850a7c323e100c4"}, + {file = "zlib_ng-0.4.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9480339df63dc83dbe17ed01ac2fcac2e1e3fcf95811d86f9118823b6434ac58"}, + {file = "zlib_ng-0.4.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:1d4df3e5d779ded9451c3e14686233d0a75762512f2eaa74386eadf8fbb2850d"}, + {file = "zlib_ng-0.4.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:6cf9e47962c86973543fd5c8fe46148063950fbb591da5775cde54abf6aa95aa"}, + {file = "zlib_ng-0.4.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0261b43542d1525dfd3475a9e083b624b61dfc5b7fec2a3a7be5908af867fd1b"}, + {file = "zlib_ng-0.4.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7fd8a3cd1c108e714b08263a9b62d85d2bb1ba91ede319267ed998b6ac73bac8"}, + {file = "zlib_ng-0.4.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:959f8951cb7a44df190cbd69327c3ea467b6d6398c448727ecdbd520b6c4ba14"}, ] [metadata] lock-version = "2.0" python-versions = "^3.11" -content-hash = "44ee8b98f55a0927cb16b2444aa37ace4af645f767095080e58e310f59b6d031" +content-hash = "0f6ad524bceb6bd600a170b57e152c4d9aea1b46f6e7ef594f27bdb735d69106" diff --git a/pyproject.toml b/pyproject.toml index a459f02..3285696 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,12 +8,14 @@ license = "MIT" [tool.poetry.dependencies] python = "^3.11" homeassistant = "^2023.11" -mytoyota = "0.9.3" +mytoyota = "^1.0.0" arrow = "^1.1.1" [tool.poetry.dev-dependencies] pre-commit = "^3.5.0" ruff = "^0.1.5" +homeassistant-stubs = "^2023.11" +voluptuous-stubs = "^0.1" [tool.ruff] select = [ From 139e0571a39f025e2a61f3087523eb3e3197fa40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B6rrle?= Date: Mon, 1 Jan 2024 22:41:15 +0100 Subject: [PATCH 02/68] update mytoyota dependency in manifest file --- custom_components/toyota/manifest.json | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/custom_components/toyota/manifest.json b/custom_components/toyota/manifest.json index 04611ad..66fe74b 100644 --- a/custom_components/toyota/manifest.json +++ b/custom_components/toyota/manifest.json @@ -1,12 +1,20 @@ { "domain": "toyota", "name": "Toyota Connected Services", - "after_dependencies": ["cloud", "http"], - "codeowners": ["@DurgNomis-drol"], + "after_dependencies": [ + "cloud", + "http" + ], + "codeowners": [ + "@DurgNomis-drol" + ], "config_flow": true, "documentation": "https://github.com/DurgNomis-drol/ha_toyota", "iot_class": "cloud_polling", "issue_tracker": "https://github.com/DurgNomis-drol/ha_toyota/issues", - "requirements": ["mytoyota==0.9.3", "arrow"], + "requirements": [ + "mytoyota>=1.0.0", + "arrow" + ], "version": "v1.3.0" } From dae4a5b8342e9a2d9bb8eeb7d3eeffce776a82e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B6rrle?= Date: Mon, 1 Jan 2024 22:44:47 +0100 Subject: [PATCH 03/68] fix implicit string concatenation --- custom_components/toyota/__init__.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/custom_components/toyota/__init__.py b/custom_components/toyota/__init__.py index e89c604..137b29b 100644 --- a/custom_components/toyota/__init__.py +++ b/custom_components/toyota/__init__.py @@ -132,9 +132,7 @@ async def async_get_vehicle_data() -> list[VehicleData]: asyncioexceptions.TimeoutError, httpx.ReadTimeout, ) as ex: - raise UpdateFailed( - "Update canceled! Toyota's API was too slow to respond." " Will try again later..." - ) from ex + raise UpdateFailed("Update canceled! Toyota's API was too slow to respond. Will try again later...") from ex coordinator = DataUpdateCoordinator( hass, From 774e8d08dd0badc50cd1ee09c886eb421c8ca5a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B6rrle?= Date: Mon, 1 Jan 2024 23:02:28 +0100 Subject: [PATCH 04/68] adapt config flow to new api --- custom_components/toyota/__init__.py | 88 ++++++++++++------------- custom_components/toyota/config_flow.py | 10 +-- custom_components/toyota/const.py | 2 +- 3 files changed, 48 insertions(+), 52 deletions(-) diff --git a/custom_components/toyota/__init__.py b/custom_components/toyota/__init__.py index 137b29b..f40424a 100644 --- a/custom_components/toyota/__init__.py +++ b/custom_components/toyota/__init__.py @@ -24,8 +24,8 @@ from mytoyota.models.vehicle import Vehicle from .const import ( + CONF_METRIC_VALUES, CONF_UNIT_SYSTEM_IMPERIAL_LITERS, - CONF_USE_LITERS_PER_100_MILES, DOMAIN, PLATFORMS, STARTUP_MESSAGE, @@ -60,12 +60,11 @@ async def async_setup_entry( # pylint: disable=too-many-statements email = entry.data[CONF_EMAIL] password = entry.data[CONF_PASSWORD] - use_liters = entry.options.get(CONF_USE_LITERS_PER_100_MILES, False) + use_metric_values = entry.options.get(CONF_METRIC_VALUES, True) client = MyT( username=email, password=password, - disable_locale_check=True, ) try: @@ -73,51 +72,50 @@ async def async_setup_entry( # pylint: disable=too-many-statements except ToyotaLoginError as ex: raise ConfigEntryAuthFailed(ex) from ex except (httpx.ConnectTimeout, httpcore.ConnectTimeout) as ex: - raise ConfigEntryNotReady("Unable to connect to Toyota Connected Services") from ex + raise ConfigEntryNotReady( + "Unable to connect to Toyota Connected Services" + ) from ex async def async_get_vehicle_data() -> list[VehicleData]: """Fetch vehicle data from Toyota API.""" try: - vehicles = await asyncio.wait_for(client.get_vehicles(), 15) + vehicles = await asyncio.wait_for( + client.get_vehicles(metric=use_metric_values), 15 + ) vehicle_informations: list[VehicleData] = [] - for vehicle in vehicles: - vehicle_status = await client.get_vehicle_status(vehicle) - _LOGGER.debug(vars(vehicle_status)) - - vehicle_data = VehicleData(data=vehicle_status, statistics=None) - - unit_system_map = { - False: CONF_UNIT_SYSTEM_IMPERIAL, - True: CONF_UNIT_SYSTEM_IMPERIAL_LITERS, - } - unit = CONF_UNIT_SYSTEM_METRIC if vehicle_status.dashboard.is_metric else unit_system_map[use_liters] - - _LOGGER.debug(f"The car is reporting data in {unit}") - if use_liters and not vehicle_status.dashboard.is_metric: - _LOGGER.debug("Getting statistics in imperial and L/100 miles") - elif not vehicle_status.dashboard.is_metric: - _LOGGER.debug("Getting statistics in imperial and MPG") - - if vehicle_status.is_connected_services_enabled and vehicle_status.vin is not None: - # Use parallel request to get car statistics. - driving_statistics = await asyncio.gather( - client.get_driving_statistics(vehicle_status.vin, interval="day", unit=unit), - client.get_driving_statistics(vehicle_status.vin, interval="isoweek", unit=unit), - client.get_driving_statistics(vehicle_status.vin, unit=unit), - client.get_driving_statistics(vehicle_status.vin, interval="year", unit=unit), - ) - - vehicle_data["statistics"] = StatisticsData( - day=driving_statistics[0], - week=driving_statistics[1], - month=driving_statistics[2], - year=driving_statistics[3], - ) - - vehicle_informations.append(vehicle_data) - - _LOGGER.debug(vehicle_informations) - return vehicle_informations + if vehicles is not None: + for vehicle in vehicles: + await vehicle.update() + + + vehicle_data = VehicleData(data=vehicle_status, statistics=None) + + + # Use parallel request to get car statistics. + driving_statistics = await asyncio.gather( + client.get_driving_statistics( + vehicle_status.vin, interval="day", unit=unit + ), + client.get_driving_statistics( + vehicle_status.vin, interval="isoweek", unit=unit + ), + client.get_driving_statistics(vehicle_status.vin, unit=unit), + client.get_driving_statistics( + vehicle_status.vin, interval="year", unit=unit + ), + ) + + vehicle_data["statistics"] = StatisticsData( + day=driving_statistics[0], + week=driving_statistics[1], + month=driving_statistics[2], + year=driving_statistics[3], + ) + + vehicle_informations.append(vehicle_data) + + _LOGGER.debug(vehicle_informations) + return vehicle_informations except ToyotaLoginError as ex: _LOGGER.error(ex) @@ -132,7 +130,9 @@ async def async_get_vehicle_data() -> list[VehicleData]: asyncioexceptions.TimeoutError, httpx.ReadTimeout, ) as ex: - raise UpdateFailed("Update canceled! Toyota's API was too slow to respond. Will try again later...") from ex + raise UpdateFailed( + "Update canceled! Toyota's API was too slow to respond. Will try again later..." + ) from ex coordinator = DataUpdateCoordinator( hass, diff --git a/custom_components/toyota/config_flow.py b/custom_components/toyota/config_flow.py index ca25d34..7ca54d3 100644 --- a/custom_components/toyota/config_flow.py +++ b/custom_components/toyota/config_flow.py @@ -10,10 +10,7 @@ from mytoyota.exceptions import ToyotaInvalidUsername, ToyotaLoginError # https://github.com/PyCQA/pylint/issues/3202 -from .const import ( # pylint: disable=unused-import - CONF_USE_LITERS_PER_100_MILES, - DOMAIN, -) +from .const import CONF_METRIC_VALUES, DOMAIN # pylint: disable=unused-import _LOGGER = logging.getLogger(__name__) @@ -41,7 +38,6 @@ async def async_step_user(self, user_input=None) -> FlowResult: client = MyT( username=user_input[CONF_EMAIL], password=user_input[CONF_PASSWORD], - disable_locale_check=True, ) await client.login() @@ -86,8 +82,8 @@ async def async_step_init(self, user_input=None) -> FlowResult: data_schema=vol.Schema( { vol.Optional( - CONF_USE_LITERS_PER_100_MILES, - default=self.config_entry.options.get(CONF_USE_LITERS_PER_100_MILES, False), + CONF_METRIC_VALUES, + default=self.config_entry.options.get(CONF_METRIC_VALUES, True), ): bool, } ), diff --git a/custom_components/toyota/const.py b/custom_components/toyota/const.py index 73d4295..a1b23cb 100644 --- a/custom_components/toyota/const.py +++ b/custom_components/toyota/const.py @@ -15,7 +15,7 @@ "europe", ] CONF_UNIT_SYSTEM_IMPERIAL_LITERS = "imperial_liters" -CONF_USE_LITERS_PER_100_MILES = "use_liters" +CONF_METRIC_VALUES = "use_metric_values" # DEFAULTS DEFAULT_LOCALE = "en-gb" From dd96fc7ae5109943689e8b80f5767483da436ace Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B6rrle?= Date: Tue, 2 Jan 2024 21:19:00 +0100 Subject: [PATCH 05/68] adopt statistics gathering to upcoming mytoyota changes --- custom_components/toyota/__init__.py | 79 +++++++++++++--------------- 1 file changed, 36 insertions(+), 43 deletions(-) diff --git a/custom_components/toyota/__init__.py b/custom_components/toyota/__init__.py index f40424a..f5267f1 100644 --- a/custom_components/toyota/__init__.py +++ b/custom_components/toyota/__init__.py @@ -5,31 +5,22 @@ import asyncio.exceptions as asyncioexceptions import logging from datetime import timedelta -from typing import Any, Optional, TypedDict +from typing import Optional, TypedDict import httpcore import httpx +from arrow import Arrow from homeassistant.config_entries import ConfigEntry -from homeassistant.const import ( - CONF_EMAIL, - CONF_PASSWORD, - CONF_UNIT_SYSTEM_IMPERIAL, - CONF_UNIT_SYSTEM_METRIC, -) +from homeassistant.const import CONF_EMAIL, CONF_PASSWORD from homeassistant.core import HomeAssistant from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed from mytoyota import MyT from mytoyota.exceptions import ToyotaApiError, ToyotaInternalError, ToyotaLoginError +from mytoyota.models.summary import Summary, SummaryType from mytoyota.models.vehicle import Vehicle -from .const import ( - CONF_METRIC_VALUES, - CONF_UNIT_SYSTEM_IMPERIAL_LITERS, - DOMAIN, - PLATFORMS, - STARTUP_MESSAGE, -) +from .const import CONF_METRIC_VALUES, DOMAIN, PLATFORMS, STARTUP_MESSAGE _LOGGER = logging.getLogger(__name__) @@ -37,10 +28,10 @@ class StatisticsData(TypedDict): """Representing Statistics data.""" - day: list[dict[str, Any]] - week: list[dict[str, Any]] - month: list[dict[str, Any]] - year: list[dict[str, Any]] + day: Optional[Summary] + week: Optional[Summary] + month: Optional[Summary] + year: Optional[Summary] class VehicleData(TypedDict): @@ -72,44 +63,48 @@ async def async_setup_entry( # pylint: disable=too-many-statements except ToyotaLoginError as ex: raise ConfigEntryAuthFailed(ex) from ex except (httpx.ConnectTimeout, httpcore.ConnectTimeout) as ex: - raise ConfigEntryNotReady( - "Unable to connect to Toyota Connected Services" - ) from ex + raise ConfigEntryNotReady("Unable to connect to Toyota Connected Services") from ex - async def async_get_vehicle_data() -> list[VehicleData]: + async def async_get_vehicle_data() -> Optional[list[VehicleData]]: """Fetch vehicle data from Toyota API.""" try: - vehicles = await asyncio.wait_for( - client.get_vehicles(metric=use_metric_values), 15 - ) + vehicles = await asyncio.wait_for(client.get_vehicles(metric=use_metric_values), 15) vehicle_informations: list[VehicleData] = [] if vehicles is not None: for vehicle in vehicles: await vehicle.update() + vehicle_data = VehicleData(data=vehicle, statistics=None) - - vehicle_data = VehicleData(data=vehicle_status, statistics=None) - - + if vehicle.vin is not None: # Use parallel request to get car statistics. driving_statistics = await asyncio.gather( - client.get_driving_statistics( - vehicle_status.vin, interval="day", unit=unit + vehicle.get_summary( + Arrow.now().date(), + Arrow.now().date(), + summary_type=SummaryType.DAILY, + ), + vehicle.get_summary( + Arrow.now().floor("week").date(), + Arrow.now().date(), + summary_type=SummaryType.WEEKLY, ), - client.get_driving_statistics( - vehicle_status.vin, interval="isoweek", unit=unit + vehicle.get_summary( + Arrow.now().floor("month").date(), + Arrow.now().date(), + summary_type=SummaryType.MONTHLY, ), - client.get_driving_statistics(vehicle_status.vin, unit=unit), - client.get_driving_statistics( - vehicle_status.vin, interval="year", unit=unit + vehicle.get_summary( + Arrow.now().floor("year").date(), + Arrow.now().date(), + summary_type=SummaryType.YEARLY, ), ) vehicle_data["statistics"] = StatisticsData( - day=driving_statistics[0], - week=driving_statistics[1], - month=driving_statistics[2], - year=driving_statistics[3], + day=next(iter(driving_statistics[0] or []), None), + week=next(iter(driving_statistics[1] or []), None), + month=next(iter(driving_statistics[2] or []), None), + year=next(iter(driving_statistics[3] or []), None), ) vehicle_informations.append(vehicle_data) @@ -130,9 +125,7 @@ async def async_get_vehicle_data() -> list[VehicleData]: asyncioexceptions.TimeoutError, httpx.ReadTimeout, ) as ex: - raise UpdateFailed( - "Update canceled! Toyota's API was too slow to respond. Will try again later..." - ) from ex + raise UpdateFailed("Update canceled! Toyota's API was too slow to respond. Will try again later...") from ex coordinator = DataUpdateCoordinator( hass, From 9f5835a355aab590e1be4188028d6622091af222 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B6rrle?= Date: Tue, 2 Jan 2024 22:15:55 +0100 Subject: [PATCH 06/68] adopt device tracker to new API --- custom_components/toyota/const.py | 1 - custom_components/toyota/device_tracker.py | 10 +++++----- custom_components/toyota/entity.py | 2 +- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/custom_components/toyota/const.py b/custom_components/toyota/const.py index a1b23cb..a6a656c 100644 --- a/custom_components/toyota/const.py +++ b/custom_components/toyota/const.py @@ -40,7 +40,6 @@ HIGHWAY_DISTANCE = "highwayDistanceInKm" HIGHWAY_DISTANCE_PERCENTAGE = "highwayDistancePercentage" HYBRID = "hybrid" -IMAGE = "imageUrl" LAST_UPDATED = "last_updated" LICENSE_PLATE = "licensePlate" MAX_SPEED = "maxSpeedInKmph" diff --git a/custom_components/toyota/device_tracker.py b/custom_components/toyota/device_tracker.py index 5d8f4a4..a7fd245 100644 --- a/custom_components/toyota/device_tracker.py +++ b/custom_components/toyota/device_tracker.py @@ -11,7 +11,7 @@ from homeassistant.helpers.update_coordinator import DataUpdateCoordinator from . import VehicleData -from .const import DOMAIN, ICON_PARKING, IMAGE +from .const import DOMAIN, ICON_PARKING from .entity import ToyotaBaseEntity PARKING_TRACKER_DESCRIPTION: EntityDescription = EntityDescription( @@ -37,7 +37,7 @@ async def async_setup_entry( description=PARKING_TRACKER_DESCRIPTION, ) for index, vehicle in enumerate(coordinator.data) - if vehicle["data"].is_connected_services_enabled and vehicle["data"].parkinglocation + if vehicle["data"].location ) @@ -49,13 +49,13 @@ class ToyotaParkingTracker(ToyotaBaseEntity, TrackerEntity): @property def latitude(self) -> Optional[float]: """Return latitude value of the device.""" - parking = self.coordinator.data[self.index]["data"].parkinglocation + parking = self.coordinator.data[self.index]["data"].location return parking.latitude if parking else None @property def longitude(self) -> Optional[float]: """Return longitude value of the device.""" - parking = self.coordinator.data[self.index]["data"].parkinglocation + parking = self.coordinator.data[self.index]["data"].location return parking.longitude if parking else None @property @@ -66,4 +66,4 @@ def source_type(self) -> str: @property def entity_picture(self) -> Optional[str]: """Return entity picture.""" - return self.vehicle.details.get(IMAGE) + return self.vehicle._vehicle_info.image diff --git a/custom_components/toyota/entity.py b/custom_components/toyota/entity.py index a59e412..1c2fbb2 100644 --- a/custom_components/toyota/entity.py +++ b/custom_components/toyota/entity.py @@ -36,7 +36,7 @@ def __init__( self._attr_device_info = DeviceInfo( identifiers={(DOMAIN, self.vehicle.vin)}, name=self.vehicle.alias, - model=self.vehicle.details.get("modelName"), + model=self.vehicle._vehicle_info.car_model_name, manufacturer=DOMAIN.capitalize(), ) self.entity_description = description From 07eede1468b84210b0adc031afb0a3207b08c96f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B6rrle?= Date: Tue, 2 Jan 2024 22:38:37 +0100 Subject: [PATCH 07/68] update manifest file --- custom_components/toyota/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/custom_components/toyota/manifest.json b/custom_components/toyota/manifest.json index 66fe74b..6a04985 100644 --- a/custom_components/toyota/manifest.json +++ b/custom_components/toyota/manifest.json @@ -13,7 +13,7 @@ "iot_class": "cloud_polling", "issue_tracker": "https://github.com/DurgNomis-drol/ha_toyota/issues", "requirements": [ - "mytoyota>=1.0.0", + "mytoyota>=1.0", "arrow" ], "version": "v1.3.0" From 60bac8ce3a8506684b32259b4004ae4cf4d0e30c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B6rrle?= Date: Wed, 3 Jan 2024 12:18:55 +0100 Subject: [PATCH 08/68] add statistic to base entity --- custom_components/toyota/entity.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/custom_components/toyota/entity.py b/custom_components/toyota/entity.py index 1c2fbb2..b599fce 100644 --- a/custom_components/toyota/entity.py +++ b/custom_components/toyota/entity.py @@ -1,6 +1,8 @@ """Custom coordinator entity base classes for Toyota Connected Services integration.""" from __future__ import annotations +from typing import Optional + from homeassistant.core import callback from homeassistant.helpers.entity import DeviceInfo, EntityDescription from homeassistant.helpers.update_coordinator import ( @@ -9,7 +11,7 @@ ) from mytoyota.models.vehicle import Vehicle -from . import VehicleData +from . import StatisticsData, VehicleData from .const import DOMAIN @@ -29,22 +31,23 @@ def __init__( super().__init__(coordinator) self.index = vehicle_index + self.entity_description = description self.vehicle: Vehicle = coordinator.data[self.index]["data"] + self.statistics: Optional[StatisticsData] = coordinator.data[self.index]["statistics"] - self._attr_unique_id = f"{entry_id}_{self.vehicle.vin}/{description.key}" - + self._attr_unique_id = f"{entry_id}_{self.vehicle.vin}/{self.entity_description.key}" self._attr_device_info = DeviceInfo( identifiers={(DOMAIN, self.vehicle.vin)}, name=self.vehicle.alias, model=self.vehicle._vehicle_info.car_model_name, manufacturer=DOMAIN.capitalize(), ) - self.entity_description = description @callback def _handle_coordinator_update(self) -> None: """Handle updated data from the coordinator.""" self.vehicle = self.coordinator.data[self.index]["data"] + self.statistics = self.coordinator.data[self.index]["statistics"] super()._handle_coordinator_update() async def async_added_to_hass(self) -> None: From cd2af309fb7eeb13d213c69077c2e93785b29f7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B6rrle?= Date: Wed, 3 Jan 2024 12:20:05 +0100 Subject: [PATCH 09/68] bump version --- custom_components/toyota/manifest.json | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/custom_components/toyota/manifest.json b/custom_components/toyota/manifest.json index 6a04985..3cb116c 100644 --- a/custom_components/toyota/manifest.json +++ b/custom_components/toyota/manifest.json @@ -16,5 +16,5 @@ "mytoyota>=1.0", "arrow" ], - "version": "v1.3.0" + "version": "v2.0.0" } diff --git a/pyproject.toml b/pyproject.toml index 3285696..24b8992 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "toyota" -version = "v1.3.0" +version = "v2.0.0" description = "Toyota Connected Services integration for Home Assistant" authors = ["DurgNomis-drol "] license = "MIT" From 8086e1fc8a3d7b8d7305967939dd1d8d60f8c2fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B6rrle?= Date: Wed, 3 Jan 2024 12:24:24 +0100 Subject: [PATCH 10/68] using brand from vehicle info --- custom_components/toyota/entity.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/custom_components/toyota/entity.py b/custom_components/toyota/entity.py index b599fce..77647dc 100644 --- a/custom_components/toyota/entity.py +++ b/custom_components/toyota/entity.py @@ -40,7 +40,7 @@ def __init__( identifiers={(DOMAIN, self.vehicle.vin)}, name=self.vehicle.alias, model=self.vehicle._vehicle_info.car_model_name, - manufacturer=DOMAIN.capitalize(), + manufacturer=self.vehicle._vehicle_info.brand, ) @callback From bebc384caa4fc4d112fdf488caf574dfa494ce60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B6rrle?= Date: Wed, 3 Jan 2024 19:14:01 +0100 Subject: [PATCH 11/68] simplify genrating of device tracker --- custom_components/toyota/device_tracker.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/custom_components/toyota/device_tracker.py b/custom_components/toyota/device_tracker.py index a7fd245..a0e2e05 100644 --- a/custom_components/toyota/device_tracker.py +++ b/custom_components/toyota/device_tracker.py @@ -49,14 +49,14 @@ class ToyotaParkingTracker(ToyotaBaseEntity, TrackerEntity): @property def latitude(self) -> Optional[float]: """Return latitude value of the device.""" - parking = self.coordinator.data[self.index]["data"].location - return parking.latitude if parking else None + location = self.vehicle.location + return location.latitude if location else None @property def longitude(self) -> Optional[float]: """Return longitude value of the device.""" - parking = self.coordinator.data[self.index]["data"].location - return parking.longitude if parking else None + location = self.vehicle.location + return location.longitude if location else None @property def source_type(self) -> str: From 6cc1fac49f63c5ab87ff069fbf3bb4fec646aa1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B6rrle?= Date: Wed, 3 Jan 2024 19:16:21 +0100 Subject: [PATCH 12/68] bump required minimum mytoyota version to 1.1.0 --- custom_components/toyota/manifest.json | 2 +- poetry.lock | 258 ++++++++++--------------- pyproject.toml | 2 +- 3 files changed, 101 insertions(+), 161 deletions(-) diff --git a/custom_components/toyota/manifest.json b/custom_components/toyota/manifest.json index 3cb116c..8ea396d 100644 --- a/custom_components/toyota/manifest.json +++ b/custom_components/toyota/manifest.json @@ -13,7 +13,7 @@ "iot_class": "cloud_polling", "issue_tracker": "https://github.com/DurgNomis-drol/ha_toyota/issues", "requirements": [ - "mytoyota>=1.0", + "mytoyota>=1.1", "arrow" ], "version": "v2.0.0" diff --git a/poetry.lock b/poetry.lock index fd73b66..853ed5d 100644 --- a/poetry.lock +++ b/poetry.lock @@ -152,17 +152,6 @@ files = [ [package.dependencies] frozenlist = ">=1.1.0" -[[package]] -name = "annotated-types" -version = "0.6.0" -description = "Reusable constraint types to use with typing.Annotated" -optional = false -python-versions = ">=3.8" -files = [ - {file = "annotated_types-0.6.0-py3-none-any.whl", hash = "sha256:0641064de18ba7a25dee8f96403ebc39113d0cb953a01429249d5c7564666a43"}, - {file = "annotated_types-0.6.0.tar.gz", hash = "sha256:563339e807e53ffd9c267e99fc6d9ea23eb8443c08f112651963e24e22f84a5d"}, -] - [[package]] name = "anyio" version = "4.2.0" @@ -865,6 +854,25 @@ files = [ {file = "ifaddr-0.2.0.tar.gz", hash = "sha256:cc0cbfcaabf765d44595825fb96a99bb12c79716b73b44330ea38ee2b0c4aed4"}, ] +[[package]] +name = "importlib-metadata" +version = "7.0.1" +description = "Read metadata from Python packages" +optional = false +python-versions = ">=3.8" +files = [ + {file = "importlib_metadata-7.0.1-py3-none-any.whl", hash = "sha256:4805911c3a4ec7c3966410053e9ec6a1fecd629117df5adee56dfc9432a1081e"}, + {file = "importlib_metadata-7.0.1.tar.gz", hash = "sha256:f238736bb06590ae52ac1fab06a3a9ef1d8dce2b7a35b5ab329371d6c8f5d2cc"}, +] + +[package.dependencies] +zipp = ">=0.5" + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] +perf = ["ipython"] +testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)", "pytest-ruff"] + [[package]] name = "jinja2" version = "3.1.2" @@ -1191,21 +1199,22 @@ files = [ [[package]] name = "mytoyota" -version = "1.0.0" +version = "1.1.0" description = "Python client for Toyota Connected Services." optional = false python-versions = ">=3.8.1,<4.0.0" files = [ - {file = "mytoyota-1.0.0-py3-none-any.whl", hash = "sha256:05f2b4f4cd980e323c4d9af5ae05c762e43bdc7cc5eddfa6c059dd61c723887e"}, - {file = "mytoyota-1.0.0.tar.gz", hash = "sha256:5ce0d2bc82ca80a4062b255e06862f5d85ea7f314644142266167fd5ed21dd0d"}, + {file = "mytoyota-1.1.0-py3-none-any.whl", hash = "sha256:57f18ddc3f7be98db030fa74fe69d7a7309a324e05255ba979886a16606a0d20"}, + {file = "mytoyota-1.1.0.tar.gz", hash = "sha256:b1f1962fd49bef319a6bd370a608cdc8ad636c29b7a3e6607f05f165f86f9cf0"}, ] [package.dependencies] arrow = ">=1.1,<2.0" hishel = ">=0.0.19,<0.0.20" httpx = ">=0.18.1" +importlib-metadata = ">=7.0.1,<8.0.0" langcodes = ">=3.1,<4.0" -pydantic = ">=2.5.1,<3.0.0" +pydantic = ">=1.10.0,<2.0.0" pyjwt = ">=2.8.0,<3.0.0" [[package]] @@ -1349,139 +1358,55 @@ files = [ [[package]] name = "pydantic" -version = "2.5.3" -description = "Data validation using Python type hints" +version = "1.10.13" +description = "Data validation and settings management using python type hints" optional = false python-versions = ">=3.7" files = [ - {file = "pydantic-2.5.3-py3-none-any.whl", hash = "sha256:d0caf5954bee831b6bfe7e338c32b9e30c85dfe080c843680783ac2b631673b4"}, - {file = "pydantic-2.5.3.tar.gz", hash = "sha256:b3ef57c62535b0941697cce638c08900d87fcb67e29cfa99e8a68f747f393f7a"}, + {file = "pydantic-1.10.13-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:efff03cc7a4f29d9009d1c96ceb1e7a70a65cfe86e89d34e4a5f2ab1e5693737"}, + {file = "pydantic-1.10.13-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3ecea2b9d80e5333303eeb77e180b90e95eea8f765d08c3d278cd56b00345d01"}, + {file = "pydantic-1.10.13-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1740068fd8e2ef6eb27a20e5651df000978edce6da6803c2bef0bc74540f9548"}, + {file = "pydantic-1.10.13-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:84bafe2e60b5e78bc64a2941b4c071a4b7404c5c907f5f5a99b0139781e69ed8"}, + {file = "pydantic-1.10.13-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:bc0898c12f8e9c97f6cd44c0ed70d55749eaf783716896960b4ecce2edfd2d69"}, + {file = "pydantic-1.10.13-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:654db58ae399fe6434e55325a2c3e959836bd17a6f6a0b6ca8107ea0571d2e17"}, + {file = "pydantic-1.10.13-cp310-cp310-win_amd64.whl", hash = "sha256:75ac15385a3534d887a99c713aa3da88a30fbd6204a5cd0dc4dab3d770b9bd2f"}, + {file = "pydantic-1.10.13-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c553f6a156deb868ba38a23cf0df886c63492e9257f60a79c0fd8e7173537653"}, + {file = "pydantic-1.10.13-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5e08865bc6464df8c7d61439ef4439829e3ab62ab1669cddea8dd00cd74b9ffe"}, + {file = "pydantic-1.10.13-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e31647d85a2013d926ce60b84f9dd5300d44535a9941fe825dc349ae1f760df9"}, + {file = "pydantic-1.10.13-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:210ce042e8f6f7c01168b2d84d4c9eb2b009fe7bf572c2266e235edf14bacd80"}, + {file = "pydantic-1.10.13-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:8ae5dd6b721459bfa30805f4c25880e0dd78fc5b5879f9f7a692196ddcb5a580"}, + {file = "pydantic-1.10.13-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f8e81fc5fb17dae698f52bdd1c4f18b6ca674d7068242b2aff075f588301bbb0"}, + {file = "pydantic-1.10.13-cp311-cp311-win_amd64.whl", hash = "sha256:61d9dce220447fb74f45e73d7ff3b530e25db30192ad8d425166d43c5deb6df0"}, + {file = "pydantic-1.10.13-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:4b03e42ec20286f052490423682016fd80fda830d8e4119f8ab13ec7464c0132"}, + {file = "pydantic-1.10.13-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f59ef915cac80275245824e9d771ee939133be38215555e9dc90c6cb148aaeb5"}, + {file = "pydantic-1.10.13-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5a1f9f747851338933942db7af7b6ee8268568ef2ed86c4185c6ef4402e80ba8"}, + {file = "pydantic-1.10.13-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:97cce3ae7341f7620a0ba5ef6cf043975cd9d2b81f3aa5f4ea37928269bc1b87"}, + {file = "pydantic-1.10.13-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:854223752ba81e3abf663d685f105c64150873cc6f5d0c01d3e3220bcff7d36f"}, + {file = "pydantic-1.10.13-cp37-cp37m-win_amd64.whl", hash = "sha256:b97c1fac8c49be29486df85968682b0afa77e1b809aff74b83081cc115e52f33"}, + {file = "pydantic-1.10.13-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c958d053453a1c4b1c2062b05cd42d9d5c8eb67537b8d5a7e3c3032943ecd261"}, + {file = "pydantic-1.10.13-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4c5370a7edaac06daee3af1c8b1192e305bc102abcbf2a92374b5bc793818599"}, + {file = "pydantic-1.10.13-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7d6f6e7305244bddb4414ba7094ce910560c907bdfa3501e9db1a7fd7eaea127"}, + {file = "pydantic-1.10.13-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d3a3c792a58e1622667a2837512099eac62490cdfd63bd407993aaf200a4cf1f"}, + {file = "pydantic-1.10.13-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:c636925f38b8db208e09d344c7aa4f29a86bb9947495dd6b6d376ad10334fb78"}, + {file = "pydantic-1.10.13-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:678bcf5591b63cc917100dc50ab6caebe597ac67e8c9ccb75e698f66038ea953"}, + {file = "pydantic-1.10.13-cp38-cp38-win_amd64.whl", hash = "sha256:6cf25c1a65c27923a17b3da28a0bdb99f62ee04230c931d83e888012851f4e7f"}, + {file = "pydantic-1.10.13-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8ef467901d7a41fa0ca6db9ae3ec0021e3f657ce2c208e98cd511f3161c762c6"}, + {file = "pydantic-1.10.13-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:968ac42970f57b8344ee08837b62f6ee6f53c33f603547a55571c954a4225691"}, + {file = "pydantic-1.10.13-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9849f031cf8a2f0a928fe885e5a04b08006d6d41876b8bbd2fc68a18f9f2e3fd"}, + {file = "pydantic-1.10.13-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:56e3ff861c3b9c6857579de282ce8baabf443f42ffba355bf070770ed63e11e1"}, + {file = "pydantic-1.10.13-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f00790179497767aae6bcdc36355792c79e7bbb20b145ff449700eb076c5f96"}, + {file = "pydantic-1.10.13-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:75b297827b59bc229cac1a23a2f7a4ac0031068e5be0ce385be1462e7e17a35d"}, + {file = "pydantic-1.10.13-cp39-cp39-win_amd64.whl", hash = "sha256:e70ca129d2053fb8b728ee7d1af8e553a928d7e301a311094b8a0501adc8763d"}, + {file = "pydantic-1.10.13-py3-none-any.whl", hash = "sha256:b87326822e71bd5f313e7d3bfdc77ac3247035ac10b0c0618bd99dcf95b1e687"}, + {file = "pydantic-1.10.13.tar.gz", hash = "sha256:32c8b48dcd3b2ac4e78b0ba4af3a2c2eb6048cb75202f0ea7b34feb740efc340"}, ] [package.dependencies] -annotated-types = ">=0.4.0" -pydantic-core = "2.14.6" -typing-extensions = ">=4.6.1" +typing-extensions = ">=4.2.0" [package.extras] -email = ["email-validator (>=2.0.0)"] - -[[package]] -name = "pydantic-core" -version = "2.14.6" -description = "" -optional = false -python-versions = ">=3.7" -files = [ - {file = "pydantic_core-2.14.6-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:72f9a942d739f09cd42fffe5dc759928217649f070056f03c70df14f5770acf9"}, - {file = "pydantic_core-2.14.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6a31d98c0d69776c2576dda4b77b8e0c69ad08e8b539c25c7d0ca0dc19a50d6c"}, - {file = "pydantic_core-2.14.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5aa90562bc079c6c290f0512b21768967f9968e4cfea84ea4ff5af5d917016e4"}, - {file = "pydantic_core-2.14.6-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:370ffecb5316ed23b667d99ce4debe53ea664b99cc37bfa2af47bc769056d534"}, - {file = "pydantic_core-2.14.6-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f85f3843bdb1fe80e8c206fe6eed7a1caeae897e496542cee499c374a85c6e08"}, - {file = "pydantic_core-2.14.6-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9862bf828112e19685b76ca499b379338fd4c5c269d897e218b2ae8fcb80139d"}, - {file = "pydantic_core-2.14.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:036137b5ad0cb0004c75b579445a1efccd072387a36c7f217bb8efd1afbe5245"}, - {file = "pydantic_core-2.14.6-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:92879bce89f91f4b2416eba4429c7b5ca22c45ef4a499c39f0c5c69257522c7c"}, - {file = "pydantic_core-2.14.6-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0c08de15d50fa190d577e8591f0329a643eeaed696d7771760295998aca6bc66"}, - {file = "pydantic_core-2.14.6-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:36099c69f6b14fc2c49d7996cbf4f87ec4f0e66d1c74aa05228583225a07b590"}, - {file = "pydantic_core-2.14.6-cp310-none-win32.whl", hash = "sha256:7be719e4d2ae6c314f72844ba9d69e38dff342bc360379f7c8537c48e23034b7"}, - {file = "pydantic_core-2.14.6-cp310-none-win_amd64.whl", hash = "sha256:36fa402dcdc8ea7f1b0ddcf0df4254cc6b2e08f8cd80e7010d4c4ae6e86b2a87"}, - {file = "pydantic_core-2.14.6-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:dea7fcd62915fb150cdc373212141a30037e11b761fbced340e9db3379b892d4"}, - {file = "pydantic_core-2.14.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ffff855100bc066ff2cd3aa4a60bc9534661816b110f0243e59503ec2df38421"}, - {file = "pydantic_core-2.14.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1b027c86c66b8627eb90e57aee1f526df77dc6d8b354ec498be9a757d513b92b"}, - {file = "pydantic_core-2.14.6-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:00b1087dabcee0b0ffd104f9f53d7d3eaddfaa314cdd6726143af6bc713aa27e"}, - {file = "pydantic_core-2.14.6-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:75ec284328b60a4e91010c1acade0c30584f28a1f345bc8f72fe8b9e46ec6a96"}, - {file = "pydantic_core-2.14.6-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7e1f4744eea1501404b20b0ac059ff7e3f96a97d3e3f48ce27a139e053bb370b"}, - {file = "pydantic_core-2.14.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b2602177668f89b38b9f84b7b3435d0a72511ddef45dc14446811759b82235a1"}, - {file = "pydantic_core-2.14.6-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6c8edaea3089bf908dd27da8f5d9e395c5b4dc092dbcce9b65e7156099b4b937"}, - {file = "pydantic_core-2.14.6-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:478e9e7b360dfec451daafe286998d4a1eeaecf6d69c427b834ae771cad4b622"}, - {file = "pydantic_core-2.14.6-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:b6ca36c12a5120bad343eef193cc0122928c5c7466121da7c20f41160ba00ba2"}, - {file = "pydantic_core-2.14.6-cp311-none-win32.whl", hash = "sha256:2b8719037e570639e6b665a4050add43134d80b687288ba3ade18b22bbb29dd2"}, - {file = "pydantic_core-2.14.6-cp311-none-win_amd64.whl", hash = "sha256:78ee52ecc088c61cce32b2d30a826f929e1708f7b9247dc3b921aec367dc1b23"}, - {file = "pydantic_core-2.14.6-cp311-none-win_arm64.whl", hash = "sha256:a19b794f8fe6569472ff77602437ec4430f9b2b9ec7a1105cfd2232f9ba355e6"}, - {file = "pydantic_core-2.14.6-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:667aa2eac9cd0700af1ddb38b7b1ef246d8cf94c85637cbb03d7757ca4c3fdec"}, - {file = "pydantic_core-2.14.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:cdee837710ef6b56ebd20245b83799fce40b265b3b406e51e8ccc5b85b9099b7"}, - {file = "pydantic_core-2.14.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2c5bcf3414367e29f83fd66f7de64509a8fd2368b1edf4351e862910727d3e51"}, - {file = "pydantic_core-2.14.6-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:26a92ae76f75d1915806b77cf459811e772d8f71fd1e4339c99750f0e7f6324f"}, - {file = "pydantic_core-2.14.6-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a983cca5ed1dd9a35e9e42ebf9f278d344603bfcb174ff99a5815f953925140a"}, - {file = "pydantic_core-2.14.6-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cb92f9061657287eded380d7dc455bbf115430b3aa4741bdc662d02977e7d0af"}, - {file = "pydantic_core-2.14.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4ace1e220b078c8e48e82c081e35002038657e4b37d403ce940fa679e57113b"}, - {file = "pydantic_core-2.14.6-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ef633add81832f4b56d3b4c9408b43d530dfca29e68fb1b797dcb861a2c734cd"}, - {file = "pydantic_core-2.14.6-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7e90d6cc4aad2cc1f5e16ed56e46cebf4877c62403a311af20459c15da76fd91"}, - {file = "pydantic_core-2.14.6-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:e8a5ac97ea521d7bde7621d86c30e86b798cdecd985723c4ed737a2aa9e77d0c"}, - {file = "pydantic_core-2.14.6-cp312-none-win32.whl", hash = "sha256:f27207e8ca3e5e021e2402ba942e5b4c629718e665c81b8b306f3c8b1ddbb786"}, - {file = "pydantic_core-2.14.6-cp312-none-win_amd64.whl", hash = "sha256:b3e5fe4538001bb82e2295b8d2a39356a84694c97cb73a566dc36328b9f83b40"}, - {file = "pydantic_core-2.14.6-cp312-none-win_arm64.whl", hash = "sha256:64634ccf9d671c6be242a664a33c4acf12882670b09b3f163cd00a24cffbd74e"}, - {file = "pydantic_core-2.14.6-cp37-cp37m-macosx_10_7_x86_64.whl", hash = "sha256:24368e31be2c88bd69340fbfe741b405302993242ccb476c5c3ff48aeee1afe0"}, - {file = "pydantic_core-2.14.6-cp37-cp37m-macosx_11_0_arm64.whl", hash = "sha256:e33b0834f1cf779aa839975f9d8755a7c2420510c0fa1e9fa0497de77cd35d2c"}, - {file = "pydantic_core-2.14.6-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6af4b3f52cc65f8a0bc8b1cd9676f8c21ef3e9132f21fed250f6958bd7223bed"}, - {file = "pydantic_core-2.14.6-cp37-cp37m-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d15687d7d7f40333bd8266f3814c591c2e2cd263fa2116e314f60d82086e353a"}, - {file = "pydantic_core-2.14.6-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:095b707bb287bfd534044166ab767bec70a9bba3175dcdc3371782175c14e43c"}, - {file = "pydantic_core-2.14.6-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:94fc0e6621e07d1e91c44e016cc0b189b48db053061cc22d6298a611de8071bb"}, - {file = "pydantic_core-2.14.6-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ce830e480f6774608dedfd4a90c42aac4a7af0a711f1b52f807130c2e434c06"}, - {file = "pydantic_core-2.14.6-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a306cdd2ad3a7d795d8e617a58c3a2ed0f76c8496fb7621b6cd514eb1532cae8"}, - {file = "pydantic_core-2.14.6-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:2f5fa187bde8524b1e37ba894db13aadd64faa884657473b03a019f625cee9a8"}, - {file = "pydantic_core-2.14.6-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:438027a975cc213a47c5d70672e0d29776082155cfae540c4e225716586be75e"}, - {file = "pydantic_core-2.14.6-cp37-none-win32.whl", hash = "sha256:f96ae96a060a8072ceff4cfde89d261837b4294a4f28b84a28765470d502ccc6"}, - {file = "pydantic_core-2.14.6-cp37-none-win_amd64.whl", hash = "sha256:e646c0e282e960345314f42f2cea5e0b5f56938c093541ea6dbf11aec2862391"}, - {file = "pydantic_core-2.14.6-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:db453f2da3f59a348f514cfbfeb042393b68720787bbef2b4c6068ea362c8149"}, - {file = "pydantic_core-2.14.6-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3860c62057acd95cc84044e758e47b18dcd8871a328ebc8ccdefd18b0d26a21b"}, - {file = "pydantic_core-2.14.6-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:36026d8f99c58d7044413e1b819a67ca0e0b8ebe0f25e775e6c3d1fabb3c38fb"}, - {file = "pydantic_core-2.14.6-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8ed1af8692bd8d2a29d702f1a2e6065416d76897d726e45a1775b1444f5928a7"}, - {file = "pydantic_core-2.14.6-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:314ccc4264ce7d854941231cf71b592e30d8d368a71e50197c905874feacc8a8"}, - {file = "pydantic_core-2.14.6-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:982487f8931067a32e72d40ab6b47b1628a9c5d344be7f1a4e668fb462d2da42"}, - {file = "pydantic_core-2.14.6-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2dbe357bc4ddda078f79d2a36fc1dd0494a7f2fad83a0a684465b6f24b46fe80"}, - {file = "pydantic_core-2.14.6-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2f6ffc6701a0eb28648c845f4945a194dc7ab3c651f535b81793251e1185ac3d"}, - {file = "pydantic_core-2.14.6-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:7f5025db12fc6de7bc1104d826d5aee1d172f9ba6ca936bf6474c2148ac336c1"}, - {file = "pydantic_core-2.14.6-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:dab03ed811ed1c71d700ed08bde8431cf429bbe59e423394f0f4055f1ca0ea60"}, - {file = "pydantic_core-2.14.6-cp38-none-win32.whl", hash = "sha256:dfcbebdb3c4b6f739a91769aea5ed615023f3c88cb70df812849aef634c25fbe"}, - {file = "pydantic_core-2.14.6-cp38-none-win_amd64.whl", hash = "sha256:99b14dbea2fdb563d8b5a57c9badfcd72083f6006caf8e126b491519c7d64ca8"}, - {file = "pydantic_core-2.14.6-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:4ce8299b481bcb68e5c82002b96e411796b844d72b3e92a3fbedfe8e19813eab"}, - {file = "pydantic_core-2.14.6-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b9a9d92f10772d2a181b5ca339dee066ab7d1c9a34ae2421b2a52556e719756f"}, - {file = "pydantic_core-2.14.6-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fd9e98b408384989ea4ab60206b8e100d8687da18b5c813c11e92fd8212a98e0"}, - {file = "pydantic_core-2.14.6-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4f86f1f318e56f5cbb282fe61eb84767aee743ebe32c7c0834690ebea50c0a6b"}, - {file = "pydantic_core-2.14.6-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:86ce5fcfc3accf3a07a729779d0b86c5d0309a4764c897d86c11089be61da160"}, - {file = "pydantic_core-2.14.6-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3dcf1978be02153c6a31692d4fbcc2a3f1db9da36039ead23173bc256ee3b91b"}, - {file = "pydantic_core-2.14.6-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eedf97be7bc3dbc8addcef4142f4b4164066df0c6f36397ae4aaed3eb187d8ab"}, - {file = "pydantic_core-2.14.6-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d5f916acf8afbcab6bacbb376ba7dc61f845367901ecd5e328fc4d4aef2fcab0"}, - {file = "pydantic_core-2.14.6-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:8a14c192c1d724c3acbfb3f10a958c55a2638391319ce8078cb36c02283959b9"}, - {file = "pydantic_core-2.14.6-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:0348b1dc6b76041516e8a854ff95b21c55f5a411c3297d2ca52f5528e49d8411"}, - {file = "pydantic_core-2.14.6-cp39-none-win32.whl", hash = "sha256:de2a0645a923ba57c5527497daf8ec5df69c6eadf869e9cd46e86349146e5975"}, - {file = "pydantic_core-2.14.6-cp39-none-win_amd64.whl", hash = "sha256:aca48506a9c20f68ee61c87f2008f81f8ee99f8d7f0104bff3c47e2d148f89d9"}, - {file = "pydantic_core-2.14.6-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:d5c28525c19f5bb1e09511669bb57353d22b94cf8b65f3a8d141c389a55dec95"}, - {file = "pydantic_core-2.14.6-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:78d0768ee59baa3de0f4adac9e3748b4b1fffc52143caebddfd5ea2961595277"}, - {file = "pydantic_core-2.14.6-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b93785eadaef932e4fe9c6e12ba67beb1b3f1e5495631419c784ab87e975670"}, - {file = "pydantic_core-2.14.6-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a874f21f87c485310944b2b2734cd6d318765bcbb7515eead33af9641816506e"}, - {file = "pydantic_core-2.14.6-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b89f4477d915ea43b4ceea6756f63f0288941b6443a2b28c69004fe07fde0d0d"}, - {file = "pydantic_core-2.14.6-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:172de779e2a153d36ee690dbc49c6db568d7b33b18dc56b69a7514aecbcf380d"}, - {file = "pydantic_core-2.14.6-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:dfcebb950aa7e667ec226a442722134539e77c575f6cfaa423f24371bb8d2e94"}, - {file = "pydantic_core-2.14.6-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:55a23dcd98c858c0db44fc5c04fc7ed81c4b4d33c653a7c45ddaebf6563a2f66"}, - {file = "pydantic_core-2.14.6-pp37-pypy37_pp73-macosx_10_7_x86_64.whl", hash = "sha256:4241204e4b36ab5ae466ecec5c4c16527a054c69f99bba20f6f75232a6a534e2"}, - {file = "pydantic_core-2.14.6-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e574de99d735b3fc8364cba9912c2bec2da78775eba95cbb225ef7dda6acea24"}, - {file = "pydantic_core-2.14.6-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1302a54f87b5cd8528e4d6d1bf2133b6aa7c6122ff8e9dc5220fbc1e07bffebd"}, - {file = "pydantic_core-2.14.6-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f8e81e4b55930e5ffab4a68db1af431629cf2e4066dbdbfef65348b8ab804ea8"}, - {file = "pydantic_core-2.14.6-pp37-pypy37_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:c99462ffc538717b3e60151dfaf91125f637e801f5ab008f81c402f1dff0cd0f"}, - {file = "pydantic_core-2.14.6-pp37-pypy37_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:e4cf2d5829f6963a5483ec01578ee76d329eb5caf330ecd05b3edd697e7d768a"}, - {file = "pydantic_core-2.14.6-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:cf10b7d58ae4a1f07fccbf4a0a956d705356fea05fb4c70608bb6fa81d103cda"}, - {file = "pydantic_core-2.14.6-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:399ac0891c284fa8eb998bcfa323f2234858f5d2efca3950ae58c8f88830f145"}, - {file = "pydantic_core-2.14.6-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9c6a5c79b28003543db3ba67d1df336f253a87d3112dac3a51b94f7d48e4c0e1"}, - {file = "pydantic_core-2.14.6-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:599c87d79cab2a6a2a9df4aefe0455e61e7d2aeede2f8577c1b7c0aec643ee8e"}, - {file = "pydantic_core-2.14.6-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:43e166ad47ba900f2542a80d83f9fc65fe99eb63ceec4debec160ae729824052"}, - {file = "pydantic_core-2.14.6-pp38-pypy38_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:3a0b5db001b98e1c649dd55afa928e75aa4087e587b9524a4992316fa23c9fba"}, - {file = "pydantic_core-2.14.6-pp38-pypy38_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:747265448cb57a9f37572a488a57d873fd96bf51e5bb7edb52cfb37124516da4"}, - {file = "pydantic_core-2.14.6-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:7ebe3416785f65c28f4f9441e916bfc8a54179c8dea73c23023f7086fa601c5d"}, - {file = "pydantic_core-2.14.6-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:86c963186ca5e50d5c8287b1d1c9d3f8f024cbe343d048c5bd282aec2d8641f2"}, - {file = "pydantic_core-2.14.6-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:e0641b506486f0b4cd1500a2a65740243e8670a2549bb02bc4556a83af84ae03"}, - {file = "pydantic_core-2.14.6-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:71d72ca5eaaa8d38c8df16b7deb1a2da4f650c41b58bb142f3fb75d5ad4a611f"}, - {file = "pydantic_core-2.14.6-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:27e524624eace5c59af499cd97dc18bb201dc6a7a2da24bfc66ef151c69a5f2a"}, - {file = "pydantic_core-2.14.6-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a3dde6cac75e0b0902778978d3b1646ca9f438654395a362cb21d9ad34b24acf"}, - {file = "pydantic_core-2.14.6-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:00646784f6cd993b1e1c0e7b0fdcbccc375d539db95555477771c27555e3c556"}, - {file = "pydantic_core-2.14.6-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:23598acb8ccaa3d1d875ef3b35cb6376535095e9405d91a3d57a8c7db5d29341"}, - {file = "pydantic_core-2.14.6-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7f41533d7e3cf9520065f610b41ac1c76bc2161415955fbcead4981b22c7611e"}, - {file = "pydantic_core-2.14.6.tar.gz", hash = "sha256:1fd0c1d395372843fba13a51c28e3bb9d59bd7aebfeb17358ffaaa1e4dbbe948"}, -] - -[package.dependencies] -typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" +dotenv = ["python-dotenv (>=0.10.4)"] +email = ["email-validator (>=1.0.3)"] [[package]] name = "pyjwt" @@ -1641,28 +1566,28 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] [[package]] name = "ruff" -version = "0.1.9" +version = "0.1.11" description = "An extremely fast Python linter and code formatter, written in Rust." optional = false python-versions = ">=3.7" files = [ - {file = "ruff-0.1.9-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:e6a212f436122ac73df851f0cf006e0c6612fe6f9c864ed17ebefce0eff6a5fd"}, - {file = "ruff-0.1.9-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:28d920e319783d5303333630dae46ecc80b7ba294aeffedf946a02ac0b7cc3db"}, - {file = "ruff-0.1.9-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:104aa9b5e12cb755d9dce698ab1b97726b83012487af415a4512fedd38b1459e"}, - {file = "ruff-0.1.9-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1e63bf5a4a91971082a4768a0aba9383c12392d0d6f1e2be2248c1f9054a20da"}, - {file = "ruff-0.1.9-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4d0738917c203246f3e275b37006faa3aa96c828b284ebfe3e99a8cb413c8c4b"}, - {file = "ruff-0.1.9-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:69dac82d63a50df2ab0906d97a01549f814b16bc806deeac4f064ff95c47ddf5"}, - {file = "ruff-0.1.9-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2aec598fb65084e41a9c5d4b95726173768a62055aafb07b4eff976bac72a592"}, - {file = "ruff-0.1.9-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:744dfe4b35470fa3820d5fe45758aace6269c578f7ddc43d447868cfe5078bcb"}, - {file = "ruff-0.1.9-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:479ca4250cab30f9218b2e563adc362bd6ae6343df7c7b5a7865300a5156d5a6"}, - {file = "ruff-0.1.9-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:aa8344310f1ae79af9ccd6e4b32749e93cddc078f9b5ccd0e45bd76a6d2e8bb6"}, - {file = "ruff-0.1.9-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:837c739729394df98f342319f5136f33c65286b28b6b70a87c28f59354ec939b"}, - {file = "ruff-0.1.9-py3-none-musllinux_1_2_i686.whl", hash = "sha256:e6837202c2859b9f22e43cb01992373c2dbfeae5c0c91ad691a4a2e725392464"}, - {file = "ruff-0.1.9-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:331aae2cd4a0554667ac683243b151c74bd60e78fb08c3c2a4ac05ee1e606a39"}, - {file = "ruff-0.1.9-py3-none-win32.whl", hash = "sha256:8151425a60878e66f23ad47da39265fc2fad42aed06fb0a01130e967a7a064f4"}, - {file = "ruff-0.1.9-py3-none-win_amd64.whl", hash = "sha256:c497d769164df522fdaf54c6eba93f397342fe4ca2123a2e014a5b8fc7df81c7"}, - {file = "ruff-0.1.9-py3-none-win_arm64.whl", hash = "sha256:0e17f53bcbb4fff8292dfd84cf72d767b5e146f009cccd40c2fad27641f8a7a9"}, - {file = "ruff-0.1.9.tar.gz", hash = "sha256:b041dee2734719ddbb4518f762c982f2e912e7f28b8ee4fe1dee0b15d1b6e800"}, + {file = "ruff-0.1.11-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:a7f772696b4cdc0a3b2e527fc3c7ccc41cdcb98f5c80fdd4f2b8c50eb1458196"}, + {file = "ruff-0.1.11-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:934832f6ed9b34a7d5feea58972635c2039c7a3b434fe5ba2ce015064cb6e955"}, + {file = "ruff-0.1.11-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ea0d3e950e394c4b332bcdd112aa566010a9f9c95814844a7468325290aabfd9"}, + {file = "ruff-0.1.11-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9bd4025b9c5b429a48280785a2b71d479798a69f5c2919e7d274c5f4b32c3607"}, + {file = "ruff-0.1.11-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e1ad00662305dcb1e987f5ec214d31f7d6a062cae3e74c1cbccef15afd96611d"}, + {file = "ruff-0.1.11-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:4b077ce83f47dd6bea1991af08b140e8b8339f0ba8cb9b7a484c30ebab18a23f"}, + {file = "ruff-0.1.11-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c4a88efecec23c37b11076fe676e15c6cdb1271a38f2b415e381e87fe4517f18"}, + {file = "ruff-0.1.11-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5b25093dad3b055667730a9b491129c42d45e11cdb7043b702e97125bcec48a1"}, + {file = "ruff-0.1.11-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:231d8fb11b2cc7c0366a326a66dafc6ad449d7fcdbc268497ee47e1334f66f77"}, + {file = "ruff-0.1.11-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:09c415716884950080921dd6237767e52e227e397e2008e2bed410117679975b"}, + {file = "ruff-0.1.11-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:0f58948c6d212a6b8d41cd59e349751018797ce1727f961c2fa755ad6208ba45"}, + {file = "ruff-0.1.11-py3-none-musllinux_1_2_i686.whl", hash = "sha256:190a566c8f766c37074d99640cd9ca3da11d8deae2deae7c9505e68a4a30f740"}, + {file = "ruff-0.1.11-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:6464289bd67b2344d2a5d9158d5eb81025258f169e69a46b741b396ffb0cda95"}, + {file = "ruff-0.1.11-py3-none-win32.whl", hash = "sha256:9b8f397902f92bc2e70fb6bebfa2139008dc72ae5177e66c383fa5426cb0bf2c"}, + {file = "ruff-0.1.11-py3-none-win_amd64.whl", hash = "sha256:eb85ee287b11f901037a6683b2374bb0ec82928c5cbc984f575d0437979c521a"}, + {file = "ruff-0.1.11-py3-none-win_arm64.whl", hash = "sha256:97ce4d752f964ba559c7023a86e5f8e97f026d511e48013987623915431c7ea9"}, + {file = "ruff-0.1.11.tar.gz", hash = "sha256:f9d4d88cb6eeb4dfe20f9f0519bd2eaba8119bde87c3d5065c541dbae2b5a2cb"}, ] [[package]] @@ -1935,6 +1860,21 @@ files = [ idna = ">=2.0" multidict = ">=4.0" +[[package]] +name = "zipp" +version = "3.17.0" +description = "Backport of pathlib-compatible object wrapper for zip files" +optional = false +python-versions = ">=3.8" +files = [ + {file = "zipp-3.17.0-py3-none-any.whl", hash = "sha256:0e923e726174922dce09c53c59ad483ff7bbb8e572e00c7f7c46b88556409f31"}, + {file = "zipp-3.17.0.tar.gz", hash = "sha256:84e64a1c28cf7e91ed2078bb8cc8c259cb19b76942096c8d7b84947690cabaf0"}, +] + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] +testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy (>=0.9.1)", "pytest-ruff"] + [[package]] name = "zlib-ng" version = "0.4.0" @@ -1990,4 +1930,4 @@ files = [ [metadata] lock-version = "2.0" python-versions = "^3.11" -content-hash = "0f6ad524bceb6bd600a170b57e152c4d9aea1b46f6e7ef594f27bdb735d69106" +content-hash = "c2e197e23734cdf57eb86072bba7b0651d0ad11024b7633d216af81b9558ec90" diff --git a/pyproject.toml b/pyproject.toml index 24b8992..d41153d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,7 +8,7 @@ license = "MIT" [tool.poetry.dependencies] python = "^3.11" homeassistant = "^2023.11" -mytoyota = "^1.0.0" +mytoyota = "^1.1.0" arrow = "^1.1.1" [tool.poetry.dev-dependencies] From 1f97c9edfc294f1a40dcc6d689514195cc04b854 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B6rrle?= Date: Wed, 3 Jan 2024 20:37:39 +0100 Subject: [PATCH 13/68] remove unused binary sensors for now --- custom_components/toyota/binary_sensor.py | 624 +++++++++++----------- 1 file changed, 308 insertions(+), 316 deletions(-) diff --git a/custom_components/toyota/binary_sensor.py b/custom_components/toyota/binary_sensor.py index b015838..3b56b8e 100644 --- a/custom_components/toyota/binary_sensor.py +++ b/custom_components/toyota/binary_sensor.py @@ -37,17 +37,7 @@ class ToyotaBinaryEntityDescription(BinarySensorEntityDescription, ToyotaBinaryE """Describes a Toyota binary entity.""" -OVER_ALL_STATUS_ENTITY_DESCRIPTION = ToyotaBinaryEntityDescription( - key="over_all_status", - translation_key="over_all_status", - icon="mdi:alert", - entity_category=EntityCategory.DIAGNOSTIC, - device_class=BinarySensorDeviceClass.PROBLEM, - value_fn=lambda vehicle: vehicle.sensors.overallstatus == "OK", - attributes_fn=lambda vehicle: {LAST_UPDATED: vehicle.sensors.last_updated}, -) - -HOOD_ENTITY_DESCRIPTION = ToyotaBinaryEntityDescription( +HOOD_STATUS_ENTITY_DESCRIPTION = ToyotaBinaryEntityDescription( key="hood", translation_key="hood", icon="mdi:car-door", @@ -60,248 +50,186 @@ class ToyotaBinaryEntityDescription(BinarySensorEntityDescription, ToyotaBinaryE }, ) -KEY_ENTITY_DESCRIPTION = ToyotaBinaryEntityDescription( - key="key_in_car", - translation_key="key_in_car", - icon="mdi:car-key", +FRONT_DRIVER_DOOR_LOCK_STATUS_ENTITY_DESCRIPTION = ToyotaBinaryEntityDescription( + key="driverseat_lock", + translation_key="driverseat_lock", + icon="mdi:car-door", + entity_category=EntityCategory.DIAGNOSTIC, + device_class=BinarySensorDeviceClass.LOCK, + value_fn=lambda vehicle: vehicle.sensors.doors.driver_seat.locked, + attributes_fn=lambda vehicle: { + WARNING: vehicle.sensors.doors.driver_seat.warning, + LAST_UPDATED: vehicle.sensors.last_updated, + }, +) + +FRONT_DRIVER_DOOR_OPEN_STATUS_ENTITY_DESCRIPTION = ToyotaBinaryEntityDescription( + key="driverseat_door", + translation_key="driverseat_door", + icon="mdi:car-door", + entity_category=EntityCategory.DIAGNOSTIC, + device_class=BinarySensorDeviceClass.DOOR, + value_fn=lambda vehicle: not vehicle.sensors.doors.driver_seat.closed, + attributes_fn=lambda vehicle: { + WARNING: vehicle.sensors.doors.driver_seat.warning, + LAST_UPDATED: vehicle.sensors.last_updated, + }, +) + +FRONT_DRIVER_DOOR_WINDOW_STATUS_ENTITY_DESCRIPTION = ToyotaBinaryEntityDescription( + key="driverseat_window", + translation_key="driverseat_window", + icon="mdi:car-door", + entity_category=EntityCategory.DIAGNOSTIC, + device_class=BinarySensorDeviceClass.WINDOW, + value_fn=lambda vehicle: vehicle.sensors.windows.driver_seat.state != "close", + attributes_fn=lambda vehicle: { + WARNING: vehicle.sensors.windows.driver_seat.warning, + LAST_UPDATED: vehicle.sensors.last_updated, + }, +) + +FRONT_PASSENGER_DOOR_LOCK_STATUS_ENTITY_DESCRIPTION = ToyotaBinaryEntityDescription( + key="passengerseat_lock", + translation_key="passengerseat_lock", + icon="mdi:car-door-lock", entity_category=EntityCategory.DIAGNOSTIC, - value_fn=lambda vehicle: vehicle.sensors.key.in_car, + device_class=BinarySensorDeviceClass.LOCK, + value_fn=lambda vehicle: vehicle.sensors.doors.passenger_seat.locked, attributes_fn=lambda vehicle: { - WARNING: vehicle.sensors.key.warning, + WARNING: vehicle.sensors.doors.passenger_seat.warning, LAST_UPDATED: vehicle.sensors.last_updated, }, ) -DEFOGGER_ENTITY_DESCRIPTIONS: tuple[ToyotaBinaryEntityDescription, ...] = ( - ToyotaBinaryEntityDescription( - key="front_defogger", - translation_key="front_defogger", - icon="mdi:car-defrost-front", - entity_category=EntityCategory.DIAGNOSTIC, - value_fn=lambda vehicle: vehicle.hvac.front_defogger_is_on, - attributes_fn=lambda vehicle: None, # noqa : ARG005 - ), - ToyotaBinaryEntityDescription( - key="rear_defogger", - translation_key="rear_defogger", - icon="mdi:car-defrost-rear", - entity_category=EntityCategory.DIAGNOSTIC, - value_fn=lambda vehicle: vehicle.hvac.rear_defogger_is_on, - attributes_fn=lambda vehicle: None, # noqa : ARG005 - ), +FRONT_PASSENGER_DOOR_OPEN_STATUS_ENTITY_DESCRIPTION = ToyotaBinaryEntityDescription( + key="passengerseat_door", + translation_key="passengerseat_door", + icon="mdi:car-door", + entity_category=EntityCategory.DIAGNOSTIC, + device_class=BinarySensorDeviceClass.DOOR, + value_fn=lambda vehicle: not vehicle.sensors.doors.passenger_seat.closed, + attributes_fn=lambda vehicle: { + WARNING: vehicle.sensors.doors.passenger_seat.warning, + LAST_UPDATED: vehicle.sensors.last_updated, + }, ) -WINDOW_ENTITY_DESCRIPTIONS: tuple[ToyotaBinaryEntityDescription, ...] = ( - ToyotaBinaryEntityDescription( - key="driverseat_window", - translation_key="driverseat_window", - icon="mdi:car-door", - entity_category=EntityCategory.DIAGNOSTIC, - device_class=BinarySensorDeviceClass.WINDOW, - value_fn=lambda vehicle: vehicle.sensors.windows.driver_seat.state != "close", - attributes_fn=lambda vehicle: { - WARNING: vehicle.sensors.windows.driver_seat.warning, - LAST_UPDATED: vehicle.sensors.last_updated, - }, - ), - ToyotaBinaryEntityDescription( - key="passengerseat_window", - translation_key="passengerseat_window", - icon="mdi:car-door", - entity_category=EntityCategory.DIAGNOSTIC, - device_class=BinarySensorDeviceClass.WINDOW, - value_fn=lambda vehicle: vehicle.sensors.windows.passenger_seat.state != "close", - attributes_fn=lambda vehicle: { - WARNING: vehicle.sensors.windows.passenger_seat.warning, - LAST_UPDATED: vehicle.sensors.last_updated, - }, - ), - ToyotaBinaryEntityDescription( - key="leftrearseat_window", - translation_key="leftrearseat_window", - icon="mdi:car-door", - entity_category=EntityCategory.DIAGNOSTIC, - device_class=BinarySensorDeviceClass.WINDOW, - value_fn=lambda vehicle: vehicle.sensors.windows.leftrear_seat.state != "close", - attributes_fn=lambda vehicle: { - WARNING: vehicle.sensors.windows.leftrear_seat.warning, - LAST_UPDATED: vehicle.sensors.last_updated, - }, - ), - ToyotaBinaryEntityDescription( - key="rightrearseat_window", - translation_key="rightrearseat_window", - icon="mdi:car-door", - entity_category=EntityCategory.DIAGNOSTIC, - device_class=BinarySensorDeviceClass.WINDOW, - value_fn=lambda vehicle: vehicle.sensors.windows.rightrear_seat.state != "close", - attributes_fn=lambda vehicle: { - WARNING: vehicle.sensors.windows.rightrear_seat.warning, - LAST_UPDATED: vehicle.sensors.last_updated, - }, - ), +FRONT_PASSENGER_DOOR_WINDOW_STATUS_ENTITY_DESCRIPTION = ToyotaBinaryEntityDescription( + key="passengerseat_window", + translation_key="passengerseat_window", + icon="mdi:car-door", + entity_category=EntityCategory.DIAGNOSTIC, + device_class=BinarySensorDeviceClass.WINDOW, + value_fn=lambda vehicle: vehicle.sensors.windows.passenger_seat.state != "close", + attributes_fn=lambda vehicle: { + WARNING: vehicle.sensors.windows.passenger_seat.warning, + LAST_UPDATED: vehicle.sensors.last_updated, + }, ) -DOOR_ENTITY_DESCRIPTIONS: tuple[ToyotaBinaryEntityDescription, ...] = ( - ToyotaBinaryEntityDescription( - key="driverseat_door", - translation_key="driverseat_door", - icon="mdi:car-door", - entity_category=EntityCategory.DIAGNOSTIC, - device_class=BinarySensorDeviceClass.DOOR, - value_fn=lambda vehicle: not vehicle.sensors.doors.driver_seat.closed, - attributes_fn=lambda vehicle: { - WARNING: vehicle.sensors.doors.driver_seat.warning, - LAST_UPDATED: vehicle.sensors.last_updated, - }, - ), - ToyotaBinaryEntityDescription( - key="driverseat_lock", - translation_key="driverseat_lock", - icon="mdi:car-door", - entity_category=EntityCategory.DIAGNOSTIC, - device_class=BinarySensorDeviceClass.LOCK, - value_fn=lambda vehicle: vehicle.sensors.doors.driver_seat.locked, - attributes_fn=lambda vehicle: { - WARNING: vehicle.sensors.doors.driver_seat.warning, - LAST_UPDATED: vehicle.sensors.last_updated, - }, - ), - ToyotaBinaryEntityDescription( - key="passengerseat_door", - translation_key="passengerseat_door", - icon="mdi:car-door", - entity_category=EntityCategory.DIAGNOSTIC, - device_class=BinarySensorDeviceClass.DOOR, - value_fn=lambda vehicle: not vehicle.sensors.doors.passenger_seat.closed, - attributes_fn=lambda vehicle: { - WARNING: vehicle.sensors.doors.passenger_seat.warning, - LAST_UPDATED: vehicle.sensors.last_updated, - }, - ), - ToyotaBinaryEntityDescription( - key="passengerseat_lock", - translation_key="passengerseat_lock", - icon="mdi:car-door-lock", - entity_category=EntityCategory.DIAGNOSTIC, - device_class=BinarySensorDeviceClass.LOCK, - value_fn=lambda vehicle: vehicle.sensors.doors.passenger_seat.locked, - attributes_fn=lambda vehicle: { - WARNING: vehicle.sensors.doors.passenger_seat.warning, - LAST_UPDATED: vehicle.sensors.last_updated, - }, - ), - ToyotaBinaryEntityDescription( - key="leftrearseat_door", - translation_key="leftrearseat_door", - icon="mdi:car-door", - entity_category=EntityCategory.DIAGNOSTIC, - device_class=BinarySensorDeviceClass.DOOR, - value_fn=lambda vehicle: not vehicle.sensors.doors.leftrear_seat.closed, - attributes_fn=lambda vehicle: { - WARNING: vehicle.sensors.doors.leftrear_seat.warning, - LAST_UPDATED: vehicle.sensors.last_updated, - }, - ), - ToyotaBinaryEntityDescription( - key="leftrearseat_lock", - translation_key="leftrearseat_lock", - icon="mdi:car-door-lock", - entity_category=EntityCategory.DIAGNOSTIC, - device_class=BinarySensorDeviceClass.LOCK, - value_fn=lambda vehicle: vehicle.sensors.doors.leftrear_seat.locked, - attributes_fn=lambda vehicle: { - WARNING: vehicle.sensors.doors.leftrear_seat.warning, - LAST_UPDATED: vehicle.sensors.last_updated, - }, - ), - ToyotaBinaryEntityDescription( - key="rightrearseat_door", - translation_key="rightrearseat_door", - icon="mdi:car-door", - entity_category=EntityCategory.DIAGNOSTIC, - device_class=BinarySensorDeviceClass.DOOR, - value_fn=lambda vehicle: not vehicle.sensors.doors.rightrear_seat.closed, - attributes_fn=lambda vehicle: { - WARNING: vehicle.sensors.doors.rightrear_seat.warning, - LAST_UPDATED: vehicle.sensors.last_updated, - }, - ), - ToyotaBinaryEntityDescription( - key="rightrearseat_lock", - translation_key="rightrearseat_lock", - icon="mdi:car-door-lock", - entity_category=EntityCategory.DIAGNOSTIC, - device_class=BinarySensorDeviceClass.LOCK, - value_fn=lambda vehicle: vehicle.sensors.doors.rightrear_seat.locked, - attributes_fn=lambda vehicle: { - WARNING: vehicle.sensors.doors.rightrear_seat.warning, - LAST_UPDATED: vehicle.sensors.last_updated, - }, - ), - ToyotaBinaryEntityDescription( - key="trunk_door", - translation_key="trunk_door", - icon="mdi:car-door", - entity_category=EntityCategory.DIAGNOSTIC, - device_class=BinarySensorDeviceClass.WINDOW, - value_fn=lambda vehicle: not vehicle.sensors.doors.trunk.closed, - attributes_fn=lambda vehicle: { - WARNING: vehicle.sensors.doors.trunk.warning, - LAST_UPDATED: vehicle.sensors.last_updated, - }, - ), - ToyotaBinaryEntityDescription( - key="trunk_lock", - translation_key="trunk_lock", - icon="mdi:car-door-lock", - entity_category=EntityCategory.DIAGNOSTIC, - device_class=BinarySensorDeviceClass.LOCK, - value_fn=lambda vehicle: vehicle.sensors.doors.trunk.locked, - attributes_fn=lambda vehicle: { - WARNING: vehicle.sensors.doors.trunk.warning, - LAST_UPDATED: vehicle.sensors.last_updated, - }, - ), +REAR_DRIVER_DOOR_LOCK_STATUS_ENTITY_DESCRIPTION = ToyotaBinaryEntityDescription( + key="leftrearseat_lock", + translation_key="leftrearseat_lock", + icon="mdi:car-door-lock", + entity_category=EntityCategory.DIAGNOSTIC, + device_class=BinarySensorDeviceClass.LOCK, + value_fn=lambda vehicle: vehicle.sensors.doors.leftrear_seat.locked, + attributes_fn=lambda vehicle: { + WARNING: vehicle.sensors.doors.leftrear_seat.warning, + LAST_UPDATED: vehicle.sensors.last_updated, + }, ) -LIGHT_ENTITY_DESCRIPTIONS: tuple[ToyotaBinaryEntityDescription, ...] = ( - ToyotaBinaryEntityDescription( - key="hazardlights", - translation_key="hazardlights", - icon="mdi:car-light-high", - entity_category=EntityCategory.DIAGNOSTIC, - device_class=BinarySensorDeviceClass.LIGHT, - value_fn=lambda vehicle: vehicle.sensors.lights.hazardlights.off, - attributes_fn=lambda vehicle: { - WARNING: vehicle.sensors.lights.hazardlights.warning, - LAST_UPDATED: vehicle.sensors.last_updated, - }, - ), - ToyotaBinaryEntityDescription( - key="headlights", - translation_key="headlights", - icon="mdi:car-light-high", - entity_category=EntityCategory.DIAGNOSTIC, - device_class=BinarySensorDeviceClass.LIGHT, - value_fn=lambda vehicle: vehicle.sensors.lights.headlights.off, - attributes_fn=lambda vehicle: { - WARNING: vehicle.sensors.lights.headlights.warning, - LAST_UPDATED: vehicle.sensors.last_updated, - }, - ), - ToyotaBinaryEntityDescription( - key="taillights", - translation_key="taillights", - icon="mdi:car-light-high", - entity_category=EntityCategory.DIAGNOSTIC, - device_class=BinarySensorDeviceClass.LIGHT, - value_fn=lambda vehicle: vehicle.sensors.lights.taillights.off, - attributes_fn=lambda vehicle: { - WARNING: vehicle.sensors.lights.taillights.warning, - LAST_UPDATED: vehicle.sensors.last_updated, - }, - ), +REAR_DRIVER_DOOR_OPEN_STATUS_ENTITY_DESCRIPTION = ToyotaBinaryEntityDescription( + key="leftrearseat_door", + translation_key="leftrearseat_door", + icon="mdi:car-door", + entity_category=EntityCategory.DIAGNOSTIC, + device_class=BinarySensorDeviceClass.DOOR, + value_fn=lambda vehicle: not vehicle.sensors.doors.leftrear_seat.closed, + attributes_fn=lambda vehicle: { + WARNING: vehicle.sensors.doors.leftrear_seat.warning, + LAST_UPDATED: vehicle.sensors.last_updated, + }, +) + +REAR_DRIVER_DOOR_WINDOW_STATUS_ENTITY_DESCRIPTION = ToyotaBinaryEntityDescription( + key="leftrearseat_window", + translation_key="leftrearseat_window", + icon="mdi:car-door", + entity_category=EntityCategory.DIAGNOSTIC, + device_class=BinarySensorDeviceClass.WINDOW, + value_fn=lambda vehicle: vehicle.sensors.windows.leftrear_seat.state != "close", + attributes_fn=lambda vehicle: { + WARNING: vehicle.sensors.windows.leftrear_seat.warning, + LAST_UPDATED: vehicle.sensors.last_updated, + }, +) + +REAR_PASSENGER_DOOR_LOCK_STATUS_ENTITY_DESCRIPTION = ToyotaBinaryEntityDescription( + key="rightrearseat_lock", + translation_key="rightrearseat_lock", + icon="mdi:car-door-lock", + entity_category=EntityCategory.DIAGNOSTIC, + device_class=BinarySensorDeviceClass.LOCK, + value_fn=lambda vehicle: vehicle.sensors.doors.rightrear_seat.locked, + attributes_fn=lambda vehicle: { + WARNING: vehicle.sensors.doors.rightrear_seat.warning, + LAST_UPDATED: vehicle.sensors.last_updated, + }, +) + +REAR_PASSENGER_DOOR_OPEN_STATUS_ENTITY_DESCRIPTION = ToyotaBinaryEntityDescription( + key="rightrearseat_door", + translation_key="rightrearseat_door", + icon="mdi:car-door", + entity_category=EntityCategory.DIAGNOSTIC, + device_class=BinarySensorDeviceClass.DOOR, + value_fn=lambda vehicle: not vehicle.sensors.doors.rightrear_seat.closed, + attributes_fn=lambda vehicle: { + WARNING: vehicle.sensors.doors.rightrear_seat.warning, + LAST_UPDATED: vehicle.sensors.last_updated, + }, +) + +REAR_PASSENGER_DOOR_WINDOW_STATUS_ENTITY_DESCRIPTION = ToyotaBinaryEntityDescription( + key="rightrearseat_window", + translation_key="rightrearseat_window", + icon="mdi:car-door", + entity_category=EntityCategory.DIAGNOSTIC, + device_class=BinarySensorDeviceClass.WINDOW, + value_fn=lambda vehicle: vehicle.sensors.windows.rightrear_seat.state != "close", + attributes_fn=lambda vehicle: { + WARNING: vehicle.sensors.windows.rightrear_seat.warning, + LAST_UPDATED: vehicle.sensors.last_updated, + }, +) + +TRUNK_DOOR_LOCK_ENTITY_DESCRIPTION = ToyotaBinaryEntityDescription( + key="trunk_lock", + translation_key="trunk_lock", + icon="mdi:car-door-lock", + entity_category=EntityCategory.DIAGNOSTIC, + device_class=BinarySensorDeviceClass.LOCK, + value_fn=lambda vehicle: vehicle.sensors.doors.trunk.locked, + attributes_fn=lambda vehicle: { + WARNING: vehicle.sensors.doors.trunk.warning, + LAST_UPDATED: vehicle.sensors.last_updated, + }, +) + +TRUNK_DOOR_OPEN_ENTITY_DESCRIPTION = ToyotaBinaryEntityDescription( + key="trunk_door", + translation_key="trunk_door", + icon="mdi:car-door", + entity_category=EntityCategory.DIAGNOSTIC, + device_class=BinarySensorDeviceClass.WINDOW, + value_fn=lambda vehicle: not vehicle.sensors.doors.trunk.closed, + attributes_fn=lambda vehicle: { + WARNING: vehicle.sensors.doors.trunk.warning, + LAST_UPDATED: vehicle.sensors.last_updated, + }, ) @@ -317,81 +245,145 @@ async def async_setup_entry( # noqa: PLR0912 for index, _ in enumerate(coordinator.data): vehicle = coordinator.data[index]["data"] - if vehicle.is_connected_services_enabled: - if vehicle.hvac and vehicle.hvac.legacy: - for description in DEFOGGER_ENTITY_DESCRIPTIONS: - binary_sensors.append( - ToyotaBinarySensor( - coordinator=coordinator, - entry_id=entry.entry_id, - vehicle_index=index, - description=description, - ) - ) - - if vehicle.sensors: - if vehicle.sensors.overallstatus: - binary_sensors.append( - ToyotaBinarySensor( - coordinator=coordinator, - entry_id=entry.entry_id, - vehicle_index=index, - description=OVER_ALL_STATUS_ENTITY_DESCRIPTION, - ) - ) - - if vehicle.sensors.windows: - for description in WINDOW_ENTITY_DESCRIPTIONS: - binary_sensors.append( - ToyotaBinarySensor( - coordinator=coordinator, - entry_id=entry.entry_id, - vehicle_index=index, - description=description, - ) - ) - - if vehicle.sensors.lights: - for description in LIGHT_ENTITY_DESCRIPTIONS: - binary_sensors.append( - ToyotaBinarySensor( - coordinator=coordinator, - entry_id=entry.entry_id, - vehicle_index=index, - description=description, - ) - ) - - if vehicle.sensors.hood: - binary_sensors.append( - ToyotaBinarySensor( - coordinator=coordinator, - entry_id=entry.entry_id, - vehicle_index=index, - description=HOOD_ENTITY_DESCRIPTION, - ) - ) - - if vehicle.sensors.doors: - for description in DOOR_ENTITY_DESCRIPTIONS: - binary_sensors.append( - ToyotaBinarySensor( - coordinator=coordinator, - entry_id=entry.entry_id, - vehicle_index=index, - description=description, - ) - ) - - if vehicle.sensors.key: - binary_sensors.append( - ToyotaBinarySensor( - coordinator=coordinator, - entry_id=entry.entry_id, - vehicle_index=index, - description=KEY_ENTITY_DESCRIPTION, - ) - ) + if vehicle._vehicle_info.extended_capabilities.bonnet_status: + binary_sensors.append( + ToyotaBinarySensor( + coordinator=coordinator, + entry_id=entry.entry_id, + vehicle_index=index, + description=HOOD_STATUS_ENTITY_DESCRIPTION, + ) + ) + + if vehicle._vehicle_info.extended_capabilities.front_driver_door_lock_status: + binary_sensors.append( + ToyotaBinarySensor( + coordinator=coordinator, + entry_id=entry.entry_id, + vehicle_index=index, + description=FRONT_DRIVER_DOOR_LOCK_STATUS_ENTITY_DESCRIPTION, + ) + ) + if vehicle._vehicle_info.extended_capabilities.front_driver_door_open_status: + binary_sensors.append( + ToyotaBinarySensor( + coordinator=coordinator, + entry_id=entry.entry_id, + vehicle_index=index, + description=FRONT_DRIVER_DOOR_OPEN_STATUS_ENTITY_DESCRIPTION, + ) + ) + if vehicle._vehicle_info.extended_capabilities.front_driver_door_window_status: + binary_sensors.append( + ToyotaBinarySensor( + coordinator=coordinator, + entry_id=entry.entry_id, + vehicle_index=index, + description=FRONT_DRIVER_DOOR_WINDOW_STATUS_ENTITY_DESCRIPTION, + ) + ) + + if vehicle._vehicle_info.extended_capabilities.front_passenger_door_lock_status: + binary_sensors.append( + ToyotaBinarySensor( + coordinator=coordinator, + entry_id=entry.entry_id, + vehicle_index=index, + description=FRONT_PASSENGER_DOOR_LOCK_STATUS_ENTITY_DESCRIPTION, + ) + ) + if vehicle._vehicle_info.extended_capabilities.front_passenger_door_open_status: + binary_sensors.append( + ToyotaBinarySensor( + coordinator=coordinator, + entry_id=entry.entry_id, + vehicle_index=index, + description=FRONT_PASSENGER_DOOR_OPEN_STATUS_ENTITY_DESCRIPTION, + ) + ) + if vehicle._vehicle_info.extended_capabilities.front_passenger_door_window_status: + binary_sensors.append( + ToyotaBinarySensor( + coordinator=coordinator, + entry_id=entry.entry_id, + vehicle_index=index, + description=FRONT_PASSENGER_DOOR_WINDOW_STATUS_ENTITY_DESCRIPTION, + ) + ) + + if vehicle._vehicle_info.extended_capabilities.rear_driver_door_lock_status: + binary_sensors.append( + ToyotaBinarySensor( + coordinator=coordinator, + entry_id=entry.entry_id, + vehicle_index=index, + description=REAR_DRIVER_DOOR_LOCK_STATUS_ENTITY_DESCRIPTION, + ) + ) + if vehicle._vehicle_info.extended_capabilities.rear_driver_door_open_status: + binary_sensors.append( + ToyotaBinarySensor( + coordinator=coordinator, + entry_id=entry.entry_id, + vehicle_index=index, + description=REAR_DRIVER_DOOR_OPEN_STATUS_ENTITY_DESCRIPTION, + ) + ) + if vehicle._vehicle_info.extended_capabilities.rear_driver_door_window_status: + binary_sensors.append( + ToyotaBinarySensor( + coordinator=coordinator, + entry_id=entry.entry_id, + vehicle_index=index, + description=REAR_DRIVER_DOOR_WINDOW_STATUS_ENTITY_DESCRIPTION, + ) + ) + + if vehicle._vehicle_info.extended_capabilities.rear_passenger_door_lock_status: + binary_sensors.append( + ToyotaBinarySensor( + coordinator=coordinator, + entry_id=entry.entry_id, + vehicle_index=index, + description=REAR_PASSENGER_DOOR_LOCK_STATUS_ENTITY_DESCRIPTION, + ) + ) + if vehicle._vehicle_info.extended_capabilities.rear_passenger_door_open_status: + binary_sensors.append( + ToyotaBinarySensor( + coordinator=coordinator, + entry_id=entry.entry_id, + vehicle_index=index, + description=REAR_PASSENGER_DOOR_OPEN_STATUS_ENTITY_DESCRIPTION, + ) + ) + if vehicle._vehicle_info.extended_capabilities.rear_passenger_door_window_status: + binary_sensors.append( + ToyotaBinarySensor( + coordinator=coordinator, + entry_id=entry.entry_id, + vehicle_index=index, + description=REAR_PASSENGER_DOOR_WINDOW_STATUS_ENTITY_DESCRIPTION, + ) + ) + + # TODO: Find matching capabilities in _vehicle_info + binary_sensors.append( + ToyotaBinarySensor( + coordinator=coordinator, + entry_id=entry.entry_id, + vehicle_index=index, + description=TRUNK_DOOR_LOCK_ENTITY_DESCRIPTION, + ) + ) + binary_sensors.append( + ToyotaBinarySensor( + coordinator=coordinator, + entry_id=entry.entry_id, + vehicle_index=index, + description=TRUNK_DOOR_OPEN_ENTITY_DESCRIPTION, + ) + ) async_add_devices(binary_sensors, True) From c6ac34265b80cac707835e8a71c84d7a190902f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B6rrle?= Date: Wed, 3 Jan 2024 20:53:06 +0100 Subject: [PATCH 14/68] simplify capability check --- custom_components/toyota/binary_sensor.py | 187 ++++++++-------------- 1 file changed, 65 insertions(+), 122 deletions(-) diff --git a/custom_components/toyota/binary_sensor.py b/custom_components/toyota/binary_sensor.py index 3b56b8e..f9428e4 100644 --- a/custom_components/toyota/binary_sensor.py +++ b/custom_components/toyota/binary_sensor.py @@ -233,7 +233,7 @@ class ToyotaBinaryEntityDescription(BinarySensorEntityDescription, ToyotaBinaryE ) -async def async_setup_entry( # noqa: PLR0912 +async def async_setup_entry( hass: HomeAssistant, entry: ConfigEntry, async_add_devices: AddEntitiesCallback, @@ -244,128 +244,71 @@ async def async_setup_entry( # noqa: PLR0912 binary_sensors: list[ToyotaBinarySensor] = [] for index, _ in enumerate(coordinator.data): vehicle = coordinator.data[index]["data"] - - if vehicle._vehicle_info.extended_capabilities.bonnet_status: - binary_sensors.append( - ToyotaBinarySensor( - coordinator=coordinator, - entry_id=entry.entry_id, - vehicle_index=index, - description=HOOD_STATUS_ENTITY_DESCRIPTION, - ) - ) - - if vehicle._vehicle_info.extended_capabilities.front_driver_door_lock_status: - binary_sensors.append( - ToyotaBinarySensor( - coordinator=coordinator, - entry_id=entry.entry_id, - vehicle_index=index, - description=FRONT_DRIVER_DOOR_LOCK_STATUS_ENTITY_DESCRIPTION, - ) - ) - if vehicle._vehicle_info.extended_capabilities.front_driver_door_open_status: - binary_sensors.append( - ToyotaBinarySensor( - coordinator=coordinator, - entry_id=entry.entry_id, - vehicle_index=index, - description=FRONT_DRIVER_DOOR_OPEN_STATUS_ENTITY_DESCRIPTION, - ) - ) - if vehicle._vehicle_info.extended_capabilities.front_driver_door_window_status: - binary_sensors.append( - ToyotaBinarySensor( - coordinator=coordinator, - entry_id=entry.entry_id, - vehicle_index=index, - description=FRONT_DRIVER_DOOR_WINDOW_STATUS_ENTITY_DESCRIPTION, - ) - ) - - if vehicle._vehicle_info.extended_capabilities.front_passenger_door_lock_status: - binary_sensors.append( - ToyotaBinarySensor( - coordinator=coordinator, - entry_id=entry.entry_id, - vehicle_index=index, - description=FRONT_PASSENGER_DOOR_LOCK_STATUS_ENTITY_DESCRIPTION, - ) - ) - if vehicle._vehicle_info.extended_capabilities.front_passenger_door_open_status: - binary_sensors.append( - ToyotaBinarySensor( - coordinator=coordinator, - entry_id=entry.entry_id, - vehicle_index=index, - description=FRONT_PASSENGER_DOOR_OPEN_STATUS_ENTITY_DESCRIPTION, - ) - ) - if vehicle._vehicle_info.extended_capabilities.front_passenger_door_window_status: - binary_sensors.append( - ToyotaBinarySensor( - coordinator=coordinator, - entry_id=entry.entry_id, - vehicle_index=index, - description=FRONT_PASSENGER_DOOR_WINDOW_STATUS_ENTITY_DESCRIPTION, + capabilities_descriptions = [ + ( + vehicle._vehicle_info.extended_capabilities.bonnet_status, + HOOD_STATUS_ENTITY_DESCRIPTION, + ), + ( + vehicle._vehicle_info.extended_capabilities.front_driver_door_lock_status, + FRONT_DRIVER_DOOR_LOCK_STATUS_ENTITY_DESCRIPTION, + ), + ( + vehicle._vehicle_info.extended_capabilities.front_driver_door_open_status, + FRONT_DRIVER_DOOR_OPEN_STATUS_ENTITY_DESCRIPTION, + ), + ( + vehicle._vehicle_info.extended_capabilities.front_driver_door_window_status, + FRONT_DRIVER_DOOR_WINDOW_STATUS_ENTITY_DESCRIPTION, + ), + ( + vehicle._vehicle_info.extended_capabilities.front_passenger_door_lock_status, + FRONT_PASSENGER_DOOR_LOCK_STATUS_ENTITY_DESCRIPTION, + ), + ( + vehicle._vehicle_info.extended_capabilities.front_passenger_door_open_status, + FRONT_PASSENGER_DOOR_OPEN_STATUS_ENTITY_DESCRIPTION, + ), + ( + vehicle._vehicle_info.extended_capabilities.front_passenger_door_window_status, + FRONT_PASSENGER_DOOR_WINDOW_STATUS_ENTITY_DESCRIPTION, + ), + ( + vehicle._vehicle_info.extended_capabilities.rear_driver_door_lock_status, + REAR_DRIVER_DOOR_LOCK_STATUS_ENTITY_DESCRIPTION, + ), + ( + vehicle._vehicle_info.extended_capabilities.rear_driver_door_open_status, + REAR_DRIVER_DOOR_OPEN_STATUS_ENTITY_DESCRIPTION, + ), + ( + vehicle._vehicle_info.extended_capabilities.rear_driver_door_window_status, + REAR_DRIVER_DOOR_WINDOW_STATUS_ENTITY_DESCRIPTION, + ), + ( + vehicle._vehicle_info.extended_capabilities.rear_passenger_door_lock_status, + REAR_PASSENGER_DOOR_LOCK_STATUS_ENTITY_DESCRIPTION, + ), + ( + vehicle._vehicle_info.extended_capabilities.rear_passenger_door_open_status, + REAR_PASSENGER_DOOR_OPEN_STATUS_ENTITY_DESCRIPTION, + ), + ( + vehicle._vehicle_info.extended_capabilities.rear_passenger_door_window_status, + REAR_PASSENGER_DOOR_WINDOW_STATUS_ENTITY_DESCRIPTION, + ), + ] + + for capability, description in capabilities_descriptions: + if capability: + binary_sensors.append( + ToyotaBinarySensor( + coordinator=coordinator, + entry_id=entry.entry_id, + vehicle_index=index, + description=description, + ) ) - ) - - if vehicle._vehicle_info.extended_capabilities.rear_driver_door_lock_status: - binary_sensors.append( - ToyotaBinarySensor( - coordinator=coordinator, - entry_id=entry.entry_id, - vehicle_index=index, - description=REAR_DRIVER_DOOR_LOCK_STATUS_ENTITY_DESCRIPTION, - ) - ) - if vehicle._vehicle_info.extended_capabilities.rear_driver_door_open_status: - binary_sensors.append( - ToyotaBinarySensor( - coordinator=coordinator, - entry_id=entry.entry_id, - vehicle_index=index, - description=REAR_DRIVER_DOOR_OPEN_STATUS_ENTITY_DESCRIPTION, - ) - ) - if vehicle._vehicle_info.extended_capabilities.rear_driver_door_window_status: - binary_sensors.append( - ToyotaBinarySensor( - coordinator=coordinator, - entry_id=entry.entry_id, - vehicle_index=index, - description=REAR_DRIVER_DOOR_WINDOW_STATUS_ENTITY_DESCRIPTION, - ) - ) - - if vehicle._vehicle_info.extended_capabilities.rear_passenger_door_lock_status: - binary_sensors.append( - ToyotaBinarySensor( - coordinator=coordinator, - entry_id=entry.entry_id, - vehicle_index=index, - description=REAR_PASSENGER_DOOR_LOCK_STATUS_ENTITY_DESCRIPTION, - ) - ) - if vehicle._vehicle_info.extended_capabilities.rear_passenger_door_open_status: - binary_sensors.append( - ToyotaBinarySensor( - coordinator=coordinator, - entry_id=entry.entry_id, - vehicle_index=index, - description=REAR_PASSENGER_DOOR_OPEN_STATUS_ENTITY_DESCRIPTION, - ) - ) - if vehicle._vehicle_info.extended_capabilities.rear_passenger_door_window_status: - binary_sensors.append( - ToyotaBinarySensor( - coordinator=coordinator, - entry_id=entry.entry_id, - vehicle_index=index, - description=REAR_PASSENGER_DOOR_WINDOW_STATUS_ENTITY_DESCRIPTION, - ) - ) # TODO: Find matching capabilities in _vehicle_info binary_sensors.append( From 3576f649c9d944f966f70b135d316e12d78a08ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B6rrle?= Date: Wed, 3 Jan 2024 21:07:51 +0100 Subject: [PATCH 15/68] adopt binary sensors to new api models --- custom_components/toyota/binary_sensor.py | 77 +++++++++-------------- 1 file changed, 31 insertions(+), 46 deletions(-) diff --git a/custom_components/toyota/binary_sensor.py b/custom_components/toyota/binary_sensor.py index f9428e4..efdfda7 100644 --- a/custom_components/toyota/binary_sensor.py +++ b/custom_components/toyota/binary_sensor.py @@ -20,7 +20,7 @@ from mytoyota.models.vehicle import Vehicle from . import VehicleData -from .const import DOMAIN, LAST_UPDATED, WARNING +from .const import DOMAIN, LAST_UPDATED from .entity import ToyotaBaseEntity @@ -43,10 +43,9 @@ class ToyotaBinaryEntityDescription(BinarySensorEntityDescription, ToyotaBinaryE icon="mdi:car-door", entity_category=EntityCategory.DIAGNOSTIC, device_class=BinarySensorDeviceClass.DOOR, - value_fn=lambda vehicle: not vehicle.sensors.hood.closed, + value_fn=lambda vehicle: vehicle.lock_status.hood.closed, attributes_fn=lambda vehicle: { - WARNING: vehicle.sensors.hood.warning, - LAST_UPDATED: vehicle.sensors.last_updated, + LAST_UPDATED: vehicle.lock_status.last_updated, }, ) @@ -56,10 +55,9 @@ class ToyotaBinaryEntityDescription(BinarySensorEntityDescription, ToyotaBinaryE icon="mdi:car-door", entity_category=EntityCategory.DIAGNOSTIC, device_class=BinarySensorDeviceClass.LOCK, - value_fn=lambda vehicle: vehicle.sensors.doors.driver_seat.locked, + value_fn=lambda vehicle: vehicle.lock_status.doors.driver_seat.locked, attributes_fn=lambda vehicle: { - WARNING: vehicle.sensors.doors.driver_seat.warning, - LAST_UPDATED: vehicle.sensors.last_updated, + LAST_UPDATED: vehicle.lock_status.last_updated, }, ) @@ -69,10 +67,9 @@ class ToyotaBinaryEntityDescription(BinarySensorEntityDescription, ToyotaBinaryE icon="mdi:car-door", entity_category=EntityCategory.DIAGNOSTIC, device_class=BinarySensorDeviceClass.DOOR, - value_fn=lambda vehicle: not vehicle.sensors.doors.driver_seat.closed, + value_fn=lambda vehicle: vehicle.lock_status.doors.driver_seat.closed, attributes_fn=lambda vehicle: { - WARNING: vehicle.sensors.doors.driver_seat.warning, - LAST_UPDATED: vehicle.sensors.last_updated, + LAST_UPDATED: vehicle.lock_status.last_updated, }, ) @@ -82,10 +79,9 @@ class ToyotaBinaryEntityDescription(BinarySensorEntityDescription, ToyotaBinaryE icon="mdi:car-door", entity_category=EntityCategory.DIAGNOSTIC, device_class=BinarySensorDeviceClass.WINDOW, - value_fn=lambda vehicle: vehicle.sensors.windows.driver_seat.state != "close", + value_fn=lambda vehicle: vehicle.lock_status.windows.driver_seat.closed, attributes_fn=lambda vehicle: { - WARNING: vehicle.sensors.windows.driver_seat.warning, - LAST_UPDATED: vehicle.sensors.last_updated, + LAST_UPDATED: vehicle.lock_status.last_updated, }, ) @@ -95,10 +91,9 @@ class ToyotaBinaryEntityDescription(BinarySensorEntityDescription, ToyotaBinaryE icon="mdi:car-door-lock", entity_category=EntityCategory.DIAGNOSTIC, device_class=BinarySensorDeviceClass.LOCK, - value_fn=lambda vehicle: vehicle.sensors.doors.passenger_seat.locked, + value_fn=lambda vehicle: vehicle.lock_status.doors.passenger_seat.locked, attributes_fn=lambda vehicle: { - WARNING: vehicle.sensors.doors.passenger_seat.warning, - LAST_UPDATED: vehicle.sensors.last_updated, + LAST_UPDATED: vehicle.lock_status.last_updated, }, ) @@ -108,10 +103,9 @@ class ToyotaBinaryEntityDescription(BinarySensorEntityDescription, ToyotaBinaryE icon="mdi:car-door", entity_category=EntityCategory.DIAGNOSTIC, device_class=BinarySensorDeviceClass.DOOR, - value_fn=lambda vehicle: not vehicle.sensors.doors.passenger_seat.closed, + value_fn=lambda vehicle: vehicle.lock_status.doors.passenger_seat.closed, attributes_fn=lambda vehicle: { - WARNING: vehicle.sensors.doors.passenger_seat.warning, - LAST_UPDATED: vehicle.sensors.last_updated, + LAST_UPDATED: vehicle.lock_status.last_updated, }, ) @@ -121,10 +115,9 @@ class ToyotaBinaryEntityDescription(BinarySensorEntityDescription, ToyotaBinaryE icon="mdi:car-door", entity_category=EntityCategory.DIAGNOSTIC, device_class=BinarySensorDeviceClass.WINDOW, - value_fn=lambda vehicle: vehicle.sensors.windows.passenger_seat.state != "close", + value_fn=lambda vehicle: vehicle.lock_status.windows.passenger_seat.closed, attributes_fn=lambda vehicle: { - WARNING: vehicle.sensors.windows.passenger_seat.warning, - LAST_UPDATED: vehicle.sensors.last_updated, + LAST_UPDATED: vehicle.lock_status.last_updated, }, ) @@ -134,10 +127,9 @@ class ToyotaBinaryEntityDescription(BinarySensorEntityDescription, ToyotaBinaryE icon="mdi:car-door-lock", entity_category=EntityCategory.DIAGNOSTIC, device_class=BinarySensorDeviceClass.LOCK, - value_fn=lambda vehicle: vehicle.sensors.doors.leftrear_seat.locked, + value_fn=lambda vehicle: vehicle.lock_status.doors.driver_rear_seat.locked, attributes_fn=lambda vehicle: { - WARNING: vehicle.sensors.doors.leftrear_seat.warning, - LAST_UPDATED: vehicle.sensors.last_updated, + LAST_UPDATED: vehicle.lock_status.last_updated, }, ) @@ -147,10 +139,9 @@ class ToyotaBinaryEntityDescription(BinarySensorEntityDescription, ToyotaBinaryE icon="mdi:car-door", entity_category=EntityCategory.DIAGNOSTIC, device_class=BinarySensorDeviceClass.DOOR, - value_fn=lambda vehicle: not vehicle.sensors.doors.leftrear_seat.closed, + value_fn=lambda vehicle: vehicle.lock_status.doors.driver_rear_seat.closed, attributes_fn=lambda vehicle: { - WARNING: vehicle.sensors.doors.leftrear_seat.warning, - LAST_UPDATED: vehicle.sensors.last_updated, + LAST_UPDATED: vehicle.lock_status.last_updated, }, ) @@ -160,10 +151,9 @@ class ToyotaBinaryEntityDescription(BinarySensorEntityDescription, ToyotaBinaryE icon="mdi:car-door", entity_category=EntityCategory.DIAGNOSTIC, device_class=BinarySensorDeviceClass.WINDOW, - value_fn=lambda vehicle: vehicle.sensors.windows.leftrear_seat.state != "close", + value_fn=lambda vehicle: vehicle.lock_status.windows.driver_rear_seat.closed, attributes_fn=lambda vehicle: { - WARNING: vehicle.sensors.windows.leftrear_seat.warning, - LAST_UPDATED: vehicle.sensors.last_updated, + LAST_UPDATED: vehicle.lock_status.last_updated, }, ) @@ -173,10 +163,9 @@ class ToyotaBinaryEntityDescription(BinarySensorEntityDescription, ToyotaBinaryE icon="mdi:car-door-lock", entity_category=EntityCategory.DIAGNOSTIC, device_class=BinarySensorDeviceClass.LOCK, - value_fn=lambda vehicle: vehicle.sensors.doors.rightrear_seat.locked, + value_fn=lambda vehicle: vehicle.lock_status.doors.passenger_seat.locked, attributes_fn=lambda vehicle: { - WARNING: vehicle.sensors.doors.rightrear_seat.warning, - LAST_UPDATED: vehicle.sensors.last_updated, + LAST_UPDATED: vehicle.lock_status.last_updated, }, ) @@ -186,10 +175,9 @@ class ToyotaBinaryEntityDescription(BinarySensorEntityDescription, ToyotaBinaryE icon="mdi:car-door", entity_category=EntityCategory.DIAGNOSTIC, device_class=BinarySensorDeviceClass.DOOR, - value_fn=lambda vehicle: not vehicle.sensors.doors.rightrear_seat.closed, + value_fn=lambda vehicle: vehicle.lock_status.doors.passenger_rear_seat.closed, attributes_fn=lambda vehicle: { - WARNING: vehicle.sensors.doors.rightrear_seat.warning, - LAST_UPDATED: vehicle.sensors.last_updated, + LAST_UPDATED: vehicle.lock_status.last_updated, }, ) @@ -199,10 +187,9 @@ class ToyotaBinaryEntityDescription(BinarySensorEntityDescription, ToyotaBinaryE icon="mdi:car-door", entity_category=EntityCategory.DIAGNOSTIC, device_class=BinarySensorDeviceClass.WINDOW, - value_fn=lambda vehicle: vehicle.sensors.windows.rightrear_seat.state != "close", + value_fn=lambda vehicle: vehicle.lock_status.windows.passenger_rear_seat.closed, attributes_fn=lambda vehicle: { - WARNING: vehicle.sensors.windows.rightrear_seat.warning, - LAST_UPDATED: vehicle.sensors.last_updated, + LAST_UPDATED: vehicle.lock_status.last_updated, }, ) @@ -212,10 +199,9 @@ class ToyotaBinaryEntityDescription(BinarySensorEntityDescription, ToyotaBinaryE icon="mdi:car-door-lock", entity_category=EntityCategory.DIAGNOSTIC, device_class=BinarySensorDeviceClass.LOCK, - value_fn=lambda vehicle: vehicle.sensors.doors.trunk.locked, + value_fn=lambda vehicle: vehicle.lock_status.doors.trunk.locked, attributes_fn=lambda vehicle: { - WARNING: vehicle.sensors.doors.trunk.warning, - LAST_UPDATED: vehicle.sensors.last_updated, + LAST_UPDATED: vehicle.lock_status.last_updated, }, ) @@ -225,10 +211,9 @@ class ToyotaBinaryEntityDescription(BinarySensorEntityDescription, ToyotaBinaryE icon="mdi:car-door", entity_category=EntityCategory.DIAGNOSTIC, device_class=BinarySensorDeviceClass.WINDOW, - value_fn=lambda vehicle: not vehicle.sensors.doors.trunk.closed, + value_fn=lambda vehicle: vehicle.lock_status.doors.trunk.closed, attributes_fn=lambda vehicle: { - WARNING: vehicle.sensors.doors.trunk.warning, - LAST_UPDATED: vehicle.sensors.last_updated, + LAST_UPDATED: vehicle.lock_status.last_updated, }, ) From 87e497cb92463f4999c887af6b0de0a6b0b55a7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B6rrle?= Date: Wed, 3 Jan 2024 21:35:14 +0100 Subject: [PATCH 16/68] fix import error --- custom_components/toyota/config_flow.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/custom_components/toyota/config_flow.py b/custom_components/toyota/config_flow.py index 7ca54d3..45691c1 100644 --- a/custom_components/toyota/config_flow.py +++ b/custom_components/toyota/config_flow.py @@ -7,7 +7,7 @@ from homeassistant.core import callback from homeassistant.data_entry_flow import FlowResult from mytoyota.client import MyT -from mytoyota.exceptions import ToyotaInvalidUsername, ToyotaLoginError +from mytoyota.exceptions import ToyotaInvalidUsernameError, ToyotaLoginError # https://github.com/PyCQA/pylint/issues/3202 from .const import CONF_METRIC_VALUES, DOMAIN # pylint: disable=unused-import @@ -45,7 +45,7 @@ async def async_step_user(self, user_input=None) -> FlowResult: except ToyotaLoginError as ex: errors["base"] = "invalid_auth" _LOGGER.error(ex) - except ToyotaInvalidUsername as ex: + except ToyotaInvalidUsernameError as ex: errors["base"] = "invalid_username" _LOGGER.error(ex) except Exception as ex: # pylint: disable=broad-except From d9ad89ce8360324cf4db8d9df3296ea50f98081b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B6rrle?= Date: Wed, 3 Jan 2024 21:42:22 +0100 Subject: [PATCH 17/68] use last_parked capability for generating device_tracker --- custom_components/toyota/device_tracker.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/custom_components/toyota/device_tracker.py b/custom_components/toyota/device_tracker.py index a0e2e05..04606c0 100644 --- a/custom_components/toyota/device_tracker.py +++ b/custom_components/toyota/device_tracker.py @@ -37,7 +37,7 @@ async def async_setup_entry( description=PARKING_TRACKER_DESCRIPTION, ) for index, vehicle in enumerate(coordinator.data) - if vehicle["data"].location + if vehicle["data"]._vehicle_info.features.last_parked ) From 310f7e40114e945d8c24f1f050d9d01f4125cb86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B6rrle?= Date: Thu, 4 Jan 2024 22:44:19 +0100 Subject: [PATCH 18/68] make metric value choise a requirement --- custom_components/toyota/__init__.py | 2 +- custom_components/toyota/config_flow.py | 13 +------------ 2 files changed, 2 insertions(+), 13 deletions(-) diff --git a/custom_components/toyota/__init__.py b/custom_components/toyota/__init__.py index f5267f1..d916440 100644 --- a/custom_components/toyota/__init__.py +++ b/custom_components/toyota/__init__.py @@ -51,7 +51,7 @@ async def async_setup_entry( # pylint: disable=too-many-statements email = entry.data[CONF_EMAIL] password = entry.data[CONF_PASSWORD] - use_metric_values = entry.options.get(CONF_METRIC_VALUES, True) + use_metric_values = entry.data[CONF_METRIC_VALUES] client = MyT( username=email, diff --git a/custom_components/toyota/config_flow.py b/custom_components/toyota/config_flow.py index 45691c1..9e325a8 100644 --- a/custom_components/toyota/config_flow.py +++ b/custom_components/toyota/config_flow.py @@ -18,6 +18,7 @@ { vol.Required(CONF_EMAIL): str, vol.Required(CONF_PASSWORD): str, + vol.Required(CONF_METRIC_VALUES): bool, } ) @@ -76,15 +77,3 @@ async def async_step_init(self, user_input=None) -> FlowResult: if user_input is not None: self.options.update(user_input) return self.async_create_entry(title=self.config_entry.data.get(CONF_EMAIL), data=self.options) - - return self.async_show_form( - step_id="init", - data_schema=vol.Schema( - { - vol.Optional( - CONF_METRIC_VALUES, - default=self.config_entry.options.get(CONF_METRIC_VALUES, True), - ): bool, - } - ), - ) From 153d324bd7f23c818b600e224b83140cec12232c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B6rrle?= Date: Thu, 4 Jan 2024 22:51:40 +0100 Subject: [PATCH 19/68] make metric value choise a requirement --- custom_components/toyota/config_flow.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/custom_components/toyota/config_flow.py b/custom_components/toyota/config_flow.py index 9e325a8..727bcde 100644 --- a/custom_components/toyota/config_flow.py +++ b/custom_components/toyota/config_flow.py @@ -6,6 +6,7 @@ from homeassistant.const import CONF_EMAIL, CONF_PASSWORD from homeassistant.core import callback from homeassistant.data_entry_flow import FlowResult +from homeassistant.helpers import selector from mytoyota.client import MyT from mytoyota.exceptions import ToyotaInvalidUsernameError, ToyotaLoginError @@ -18,7 +19,10 @@ { vol.Required(CONF_EMAIL): str, vol.Required(CONF_PASSWORD): str, - vol.Required(CONF_METRIC_VALUES): bool, + vol.Required( + CONF_METRIC_VALUES, + default=True, + ): selector.BooleanSelector(), } ) From 50fd3b095e7a9488f07bf02d2f11ec91bfefb58f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B6rrle?= Date: Thu, 4 Jan 2024 23:05:11 +0100 Subject: [PATCH 20/68] add translations --- custom_components/toyota/const.py | 4 ---- custom_components/toyota/translations/ca.json | 5 +++-- custom_components/toyota/translations/da.json | 5 +++-- custom_components/toyota/translations/de.json | 3 ++- custom_components/toyota/translations/en.json | 5 +++-- custom_components/toyota/translations/es.json | 5 +++-- custom_components/toyota/translations/fr.json | 5 +++-- custom_components/toyota/translations/nb.json | 5 +++-- custom_components/toyota/translations/nl.json | 5 +++-- 9 files changed, 23 insertions(+), 19 deletions(-) diff --git a/custom_components/toyota/const.py b/custom_components/toyota/const.py index a6a656c..6e46f62 100644 --- a/custom_components/toyota/const.py +++ b/custom_components/toyota/const.py @@ -11,10 +11,6 @@ ISSUES_URL = "https://github.com/DurgNomis-drol/ha_toyota/issues" # CONF -CONF_REGION_SUPPORTED = [ - "europe", -] -CONF_UNIT_SYSTEM_IMPERIAL_LITERS = "imperial_liters" CONF_METRIC_VALUES = "use_metric_values" # DEFAULTS diff --git a/custom_components/toyota/translations/ca.json b/custom_components/toyota/translations/ca.json index f0c15fe..f139eb1 100644 --- a/custom_components/toyota/translations/ca.json +++ b/custom_components/toyota/translations/ca.json @@ -5,7 +5,8 @@ "description": "Introduïu el vostre correu electrònic i contrasenya de la aplicació MyT abaix", "data": { "email": "Correu electrònic", - "password": "Contrasenya" + "password": "Contrasenya", + "use_metric_values": "Use metric units (e.g. km instead of miles)" } } }, @@ -44,7 +45,7 @@ "name": "Current year statistics" } }, - "binary_sensor" :{ + "binary_sensor": { "over_all_status": { "name": "Over all status" }, diff --git a/custom_components/toyota/translations/da.json b/custom_components/toyota/translations/da.json index 2d84f8f..326a5df 100644 --- a/custom_components/toyota/translations/da.json +++ b/custom_components/toyota/translations/da.json @@ -5,7 +5,8 @@ "description": "Angiv venligst din email og adgangskode til MyT nedenfor.", "data": { "email": "Email", - "password": "Adgangskode" + "password": "Adgangskode", + "use_metric_values": "Brug metriske enheder (f.eks. km i stedet for miles)" } } }, @@ -56,7 +57,7 @@ "name": "Statistik for dette år" } }, - "binary_sensor" :{ + "binary_sensor": { "over_all_status": { "name": "Status" }, diff --git a/custom_components/toyota/translations/de.json b/custom_components/toyota/translations/de.json index 2d02884..e29f3ba 100644 --- a/custom_components/toyota/translations/de.json +++ b/custom_components/toyota/translations/de.json @@ -5,7 +5,8 @@ "description": "Bitte gebe unten deine E-Mail-Adresse und dein Passwort für MyT ein.", "data": { "email": "E-Mail", - "password": "Passwort" + "password": "Passwort", + "use_metric_values": "Benutze metrische Einheiten (bspw. km anstatt Meilen)" } } }, diff --git a/custom_components/toyota/translations/en.json b/custom_components/toyota/translations/en.json index f5c86bc..a764ade 100644 --- a/custom_components/toyota/translations/en.json +++ b/custom_components/toyota/translations/en.json @@ -5,7 +5,8 @@ "description": "Please input your email and password for MyT below.", "data": { "email": "Email", - "password": "Password" + "password": "Password", + "use_metric_values": "Use metric units (e.g. km instead of miles)" } } }, @@ -53,7 +54,7 @@ "name": "Current year statistics" } }, - "binary_sensor" :{ + "binary_sensor": { "over_all_status": { "name": "Over all status" }, diff --git a/custom_components/toyota/translations/es.json b/custom_components/toyota/translations/es.json index 8f6ce81..c8245ac 100644 --- a/custom_components/toyota/translations/es.json +++ b/custom_components/toyota/translations/es.json @@ -5,7 +5,8 @@ "description": "Ingrese su dirección de correo electrónico y contraseña para la aplicación de MyT abajo", "data": { "email": "Dirección de correo electonico", - "password": "Contraseña" + "password": "Contraseña", + "use_metric_values": "Utilizar unidades métricas (por ejemplo, km en lugar de millas)" } } }, @@ -44,7 +45,7 @@ "name": "Estadísticas de este año" } }, - "binary_sensor" :{ + "binary_sensor": { "over_all_status": { "name": "Estado general" }, diff --git a/custom_components/toyota/translations/fr.json b/custom_components/toyota/translations/fr.json index 23ce092..626f0d0 100644 --- a/custom_components/toyota/translations/fr.json +++ b/custom_components/toyota/translations/fr.json @@ -5,7 +5,8 @@ "description": "Merci d'insérer vos identifiant et mot de passe MyT ci-dessous.", "data": { "email": "Email", - "password": "Mot de passe" + "password": "Mot de passe", + "use_metric_values": "Utiliser des unités métriques (par exemple, km au lieu de miles)" } } }, @@ -53,7 +54,7 @@ "name": "Statistiques année en cours" } }, - "binary_sensor" :{ + "binary_sensor": { "over_all_status": { "name": "Situation globale" }, diff --git a/custom_components/toyota/translations/nb.json b/custom_components/toyota/translations/nb.json index bd27cca..2ba7e8c 100644 --- a/custom_components/toyota/translations/nb.json +++ b/custom_components/toyota/translations/nb.json @@ -5,7 +5,8 @@ "description": "Vennligst oppgi e-postadresse og passord for din MyT-konto nedenfor.", "data": { "email": "E-postadresse", - "password": "Passord" + "password": "Passord", + "use_metric_values": "Use metric units (e.g. km instead of miles)" } } }, @@ -53,7 +54,7 @@ "name": "Current year statistics" } }, - "binary_sensor" :{ + "binary_sensor": { "over_all_status": { "name": "Over all status" }, diff --git a/custom_components/toyota/translations/nl.json b/custom_components/toyota/translations/nl.json index c45dfea..9b89876 100644 --- a/custom_components/toyota/translations/nl.json +++ b/custom_components/toyota/translations/nl.json @@ -5,7 +5,8 @@ "description": "Voer uw e-mailadres en wachtwoord voor MyT in hieronder.", "data": { "email": "E-mail", - "password": "Wachtwoord" + "password": "Wachtwoord", + "use_metric_values": "Gebruik metrische eenheden (bijv. km in plaats van mijlen)" } } }, @@ -44,7 +45,7 @@ "name": "Current year statistics" } }, - "binary_sensor" :{ + "binary_sensor": { "over_all_status": { "name": "Over all status" }, From d8ca62c55f48788945b62f7944a3beb890907d1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B6rrle?= Date: Sat, 6 Jan 2024 21:44:43 +0100 Subject: [PATCH 21/68] bump minmum required mytoyota version --- custom_components/toyota/manifest.json | 2 +- poetry.lock | 16 ++++++++-------- pyproject.toml | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/custom_components/toyota/manifest.json b/custom_components/toyota/manifest.json index 8ea396d..7c6f021 100644 --- a/custom_components/toyota/manifest.json +++ b/custom_components/toyota/manifest.json @@ -13,7 +13,7 @@ "iot_class": "cloud_polling", "issue_tracker": "https://github.com/DurgNomis-drol/ha_toyota/issues", "requirements": [ - "mytoyota>=1.1", + "mytoyota>=1.1.2", "arrow" ], "version": "v2.0.0" diff --git a/poetry.lock b/poetry.lock index 853ed5d..a8d9fdf 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1199,13 +1199,13 @@ files = [ [[package]] name = "mytoyota" -version = "1.1.0" +version = "1.1.2" description = "Python client for Toyota Connected Services." optional = false python-versions = ">=3.8.1,<4.0.0" files = [ - {file = "mytoyota-1.1.0-py3-none-any.whl", hash = "sha256:57f18ddc3f7be98db030fa74fe69d7a7309a324e05255ba979886a16606a0d20"}, - {file = "mytoyota-1.1.0.tar.gz", hash = "sha256:b1f1962fd49bef319a6bd370a608cdc8ad636c29b7a3e6607f05f165f86f9cf0"}, + {file = "mytoyota-1.1.2-py3-none-any.whl", hash = "sha256:7e9fc9ab5c0502afad09c62ed829cbba08fd819ee14cc0273c60851430293819"}, + {file = "mytoyota-1.1.2.tar.gz", hash = "sha256:388d6d0485b58610063628ecd3d384fe1a67d0dd0e016143f1ce2683b4824f05"}, ] [package.dependencies] @@ -1641,13 +1641,13 @@ files = [ [[package]] name = "types-python-dateutil" -version = "2.8.19.14" +version = "2.8.19.20240106" description = "Typing stubs for python-dateutil" optional = false -python-versions = "*" +python-versions = ">=3.8" files = [ - {file = "types-python-dateutil-2.8.19.14.tar.gz", hash = "sha256:1f4f10ac98bb8b16ade9dbee3518d9ace017821d94b057a425b069f834737f4b"}, - {file = "types_python_dateutil-2.8.19.14-py3-none-any.whl", hash = "sha256:f977b8de27787639986b4e28963263fd0e5158942b3ecef91b9335c130cb1ce9"}, + {file = "types-python-dateutil-2.8.19.20240106.tar.gz", hash = "sha256:1f8db221c3b98e6ca02ea83a58371b22c374f42ae5bbdf186db9c9a76581459f"}, + {file = "types_python_dateutil-2.8.19.20240106-py3-none-any.whl", hash = "sha256:efbbdc54590d0f16152fa103c9879c7d4a00e82078f6e2cf01769042165acaa2"}, ] [[package]] @@ -1930,4 +1930,4 @@ files = [ [metadata] lock-version = "2.0" python-versions = "^3.11" -content-hash = "c2e197e23734cdf57eb86072bba7b0651d0ad11024b7633d216af81b9558ec90" +content-hash = "ed9f13a6da134be068a30cc2712c18ea03d7381ec54478f5a8cd693e56d9a017" diff --git a/pyproject.toml b/pyproject.toml index d41153d..4a9ad14 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,7 +8,7 @@ license = "MIT" [tool.poetry.dependencies] python = "^3.11" homeassistant = "^2023.11" -mytoyota = "^1.1.0" +mytoyota = "^1.1.2" arrow = "^1.1.1" [tool.poetry.dev-dependencies] From f2d71646f30c309c9842786a18e0987587e0221d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B6rrle?= Date: Sat, 6 Jan 2024 22:29:16 +0100 Subject: [PATCH 22/68] invert binary sensor logic --- custom_components/toyota/binary_sensor.py | 30 +++++++++++------------ 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/custom_components/toyota/binary_sensor.py b/custom_components/toyota/binary_sensor.py index efdfda7..3c30f64 100644 --- a/custom_components/toyota/binary_sensor.py +++ b/custom_components/toyota/binary_sensor.py @@ -43,7 +43,7 @@ class ToyotaBinaryEntityDescription(BinarySensorEntityDescription, ToyotaBinaryE icon="mdi:car-door", entity_category=EntityCategory.DIAGNOSTIC, device_class=BinarySensorDeviceClass.DOOR, - value_fn=lambda vehicle: vehicle.lock_status.hood.closed, + value_fn=lambda vehicle: not vehicle.lock_status.hood.closed, attributes_fn=lambda vehicle: { LAST_UPDATED: vehicle.lock_status.last_updated, }, @@ -55,7 +55,7 @@ class ToyotaBinaryEntityDescription(BinarySensorEntityDescription, ToyotaBinaryE icon="mdi:car-door", entity_category=EntityCategory.DIAGNOSTIC, device_class=BinarySensorDeviceClass.LOCK, - value_fn=lambda vehicle: vehicle.lock_status.doors.driver_seat.locked, + value_fn=lambda vehicle: not vehicle.lock_status.doors.driver_seat.locked, attributes_fn=lambda vehicle: { LAST_UPDATED: vehicle.lock_status.last_updated, }, @@ -67,7 +67,7 @@ class ToyotaBinaryEntityDescription(BinarySensorEntityDescription, ToyotaBinaryE icon="mdi:car-door", entity_category=EntityCategory.DIAGNOSTIC, device_class=BinarySensorDeviceClass.DOOR, - value_fn=lambda vehicle: vehicle.lock_status.doors.driver_seat.closed, + value_fn=lambda vehicle: not vehicle.lock_status.doors.driver_seat.closed, attributes_fn=lambda vehicle: { LAST_UPDATED: vehicle.lock_status.last_updated, }, @@ -79,7 +79,7 @@ class ToyotaBinaryEntityDescription(BinarySensorEntityDescription, ToyotaBinaryE icon="mdi:car-door", entity_category=EntityCategory.DIAGNOSTIC, device_class=BinarySensorDeviceClass.WINDOW, - value_fn=lambda vehicle: vehicle.lock_status.windows.driver_seat.closed, + value_fn=lambda vehicle: not vehicle.lock_status.windows.driver_seat.closed, attributes_fn=lambda vehicle: { LAST_UPDATED: vehicle.lock_status.last_updated, }, @@ -91,7 +91,7 @@ class ToyotaBinaryEntityDescription(BinarySensorEntityDescription, ToyotaBinaryE icon="mdi:car-door-lock", entity_category=EntityCategory.DIAGNOSTIC, device_class=BinarySensorDeviceClass.LOCK, - value_fn=lambda vehicle: vehicle.lock_status.doors.passenger_seat.locked, + value_fn=lambda vehicle: not vehicle.lock_status.doors.passenger_seat.locked, attributes_fn=lambda vehicle: { LAST_UPDATED: vehicle.lock_status.last_updated, }, @@ -103,7 +103,7 @@ class ToyotaBinaryEntityDescription(BinarySensorEntityDescription, ToyotaBinaryE icon="mdi:car-door", entity_category=EntityCategory.DIAGNOSTIC, device_class=BinarySensorDeviceClass.DOOR, - value_fn=lambda vehicle: vehicle.lock_status.doors.passenger_seat.closed, + value_fn=lambda vehicle: not vehicle.lock_status.doors.passenger_seat.closed, attributes_fn=lambda vehicle: { LAST_UPDATED: vehicle.lock_status.last_updated, }, @@ -115,7 +115,7 @@ class ToyotaBinaryEntityDescription(BinarySensorEntityDescription, ToyotaBinaryE icon="mdi:car-door", entity_category=EntityCategory.DIAGNOSTIC, device_class=BinarySensorDeviceClass.WINDOW, - value_fn=lambda vehicle: vehicle.lock_status.windows.passenger_seat.closed, + value_fn=lambda vehicle: not vehicle.lock_status.windows.passenger_seat.closed, attributes_fn=lambda vehicle: { LAST_UPDATED: vehicle.lock_status.last_updated, }, @@ -127,7 +127,7 @@ class ToyotaBinaryEntityDescription(BinarySensorEntityDescription, ToyotaBinaryE icon="mdi:car-door-lock", entity_category=EntityCategory.DIAGNOSTIC, device_class=BinarySensorDeviceClass.LOCK, - value_fn=lambda vehicle: vehicle.lock_status.doors.driver_rear_seat.locked, + value_fn=lambda vehicle: not vehicle.lock_status.doors.driver_rear_seat.locked, attributes_fn=lambda vehicle: { LAST_UPDATED: vehicle.lock_status.last_updated, }, @@ -139,7 +139,7 @@ class ToyotaBinaryEntityDescription(BinarySensorEntityDescription, ToyotaBinaryE icon="mdi:car-door", entity_category=EntityCategory.DIAGNOSTIC, device_class=BinarySensorDeviceClass.DOOR, - value_fn=lambda vehicle: vehicle.lock_status.doors.driver_rear_seat.closed, + value_fn=lambda vehicle: not vehicle.lock_status.doors.driver_rear_seat.closed, attributes_fn=lambda vehicle: { LAST_UPDATED: vehicle.lock_status.last_updated, }, @@ -151,7 +151,7 @@ class ToyotaBinaryEntityDescription(BinarySensorEntityDescription, ToyotaBinaryE icon="mdi:car-door", entity_category=EntityCategory.DIAGNOSTIC, device_class=BinarySensorDeviceClass.WINDOW, - value_fn=lambda vehicle: vehicle.lock_status.windows.driver_rear_seat.closed, + value_fn=lambda vehicle: not vehicle.lock_status.windows.driver_rear_seat.closed, attributes_fn=lambda vehicle: { LAST_UPDATED: vehicle.lock_status.last_updated, }, @@ -163,7 +163,7 @@ class ToyotaBinaryEntityDescription(BinarySensorEntityDescription, ToyotaBinaryE icon="mdi:car-door-lock", entity_category=EntityCategory.DIAGNOSTIC, device_class=BinarySensorDeviceClass.LOCK, - value_fn=lambda vehicle: vehicle.lock_status.doors.passenger_seat.locked, + value_fn=lambda vehicle: not vehicle.lock_status.doors.passenger_seat.locked, attributes_fn=lambda vehicle: { LAST_UPDATED: vehicle.lock_status.last_updated, }, @@ -175,7 +175,7 @@ class ToyotaBinaryEntityDescription(BinarySensorEntityDescription, ToyotaBinaryE icon="mdi:car-door", entity_category=EntityCategory.DIAGNOSTIC, device_class=BinarySensorDeviceClass.DOOR, - value_fn=lambda vehicle: vehicle.lock_status.doors.passenger_rear_seat.closed, + value_fn=lambda vehicle: not vehicle.lock_status.doors.passenger_rear_seat.closed, attributes_fn=lambda vehicle: { LAST_UPDATED: vehicle.lock_status.last_updated, }, @@ -187,7 +187,7 @@ class ToyotaBinaryEntityDescription(BinarySensorEntityDescription, ToyotaBinaryE icon="mdi:car-door", entity_category=EntityCategory.DIAGNOSTIC, device_class=BinarySensorDeviceClass.WINDOW, - value_fn=lambda vehicle: vehicle.lock_status.windows.passenger_rear_seat.closed, + value_fn=lambda vehicle: not vehicle.lock_status.windows.passenger_rear_seat.closed, attributes_fn=lambda vehicle: { LAST_UPDATED: vehicle.lock_status.last_updated, }, @@ -199,7 +199,7 @@ class ToyotaBinaryEntityDescription(BinarySensorEntityDescription, ToyotaBinaryE icon="mdi:car-door-lock", entity_category=EntityCategory.DIAGNOSTIC, device_class=BinarySensorDeviceClass.LOCK, - value_fn=lambda vehicle: vehicle.lock_status.doors.trunk.locked, + value_fn=lambda vehicle: not vehicle.lock_status.doors.trunk.locked, attributes_fn=lambda vehicle: { LAST_UPDATED: vehicle.lock_status.last_updated, }, @@ -211,7 +211,7 @@ class ToyotaBinaryEntityDescription(BinarySensorEntityDescription, ToyotaBinaryE icon="mdi:car-door", entity_category=EntityCategory.DIAGNOSTIC, device_class=BinarySensorDeviceClass.WINDOW, - value_fn=lambda vehicle: vehicle.lock_status.doors.trunk.closed, + value_fn=lambda vehicle: not vehicle.lock_status.doors.trunk.closed, attributes_fn=lambda vehicle: { LAST_UPDATED: vehicle.lock_status.last_updated, }, From d0b2d31a9ea412f84a3c596b145e02c2d90db0bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B6rrle?= Date: Mon, 8 Jan 2024 09:08:57 +0100 Subject: [PATCH 23/68] only create trunk status binary_sensor if bonnet_status capability is reported by car --- custom_components/toyota/binary_sensor.py | 37 +++++++++-------------- 1 file changed, 14 insertions(+), 23 deletions(-) diff --git a/custom_components/toyota/binary_sensor.py b/custom_components/toyota/binary_sensor.py index 3c30f64..b6aeb90 100644 --- a/custom_components/toyota/binary_sensor.py +++ b/custom_components/toyota/binary_sensor.py @@ -282,37 +282,28 @@ async def async_setup_entry( vehicle._vehicle_info.extended_capabilities.rear_passenger_door_window_status, REAR_PASSENGER_DOOR_WINDOW_STATUS_ENTITY_DESCRIPTION, ), + # TODO: Find correct matching capabilities in _vehicle_info + ( + vehicle._vehicle_info.extended_capabilities.bonnet_status, + TRUNK_DOOR_LOCK_ENTITY_DESCRIPTION, + ), + # TODO: Find correct matching capabilities in _vehicle_info + ( + vehicle._vehicle_info.extended_capabilities.bonnet_status, + TRUNK_DOOR_OPEN_ENTITY_DESCRIPTION, + ), ] - for capability, description in capabilities_descriptions: - if capability: - binary_sensors.append( - ToyotaBinarySensor( - coordinator=coordinator, - entry_id=entry.entry_id, - vehicle_index=index, - description=description, - ) - ) - - # TODO: Find matching capabilities in _vehicle_info - binary_sensors.append( + binary_sensors.extend( ToyotaBinarySensor( coordinator=coordinator, entry_id=entry.entry_id, vehicle_index=index, - description=TRUNK_DOOR_LOCK_ENTITY_DESCRIPTION, + description=description, ) + for capability, description in capabilities_descriptions + if capability ) - binary_sensors.append( - ToyotaBinarySensor( - coordinator=coordinator, - entry_id=entry.entry_id, - vehicle_index=index, - description=TRUNK_DOOR_OPEN_ENTITY_DESCRIPTION, - ) - ) - async_add_devices(binary_sensors, True) From 758eb67f778becced5a444979ef951008452c93b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B6rrle?= Date: Mon, 8 Jan 2024 09:10:23 +0100 Subject: [PATCH 24/68] run pre-commit on all files --- custom_components/toyota/manifest.json | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/custom_components/toyota/manifest.json b/custom_components/toyota/manifest.json index 7c6f021..3347d37 100644 --- a/custom_components/toyota/manifest.json +++ b/custom_components/toyota/manifest.json @@ -1,20 +1,12 @@ { "domain": "toyota", "name": "Toyota Connected Services", - "after_dependencies": [ - "cloud", - "http" - ], - "codeowners": [ - "@DurgNomis-drol" - ], + "after_dependencies": ["cloud", "http"], + "codeowners": ["@DurgNomis-drol"], "config_flow": true, "documentation": "https://github.com/DurgNomis-drol/ha_toyota", "iot_class": "cloud_polling", "issue_tracker": "https://github.com/DurgNomis-drol/ha_toyota/issues", - "requirements": [ - "mytoyota>=1.1.2", - "arrow" - ], + "requirements": ["mytoyota>=1.1.2", "arrow"], "version": "v2.0.0" } From f27b42d6fe9429ba24109c7cbffe7f3a5ce0c86b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B6rrle?= Date: Mon, 8 Jan 2024 09:22:01 +0100 Subject: [PATCH 25/68] return None if try block fails --- custom_components/toyota/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/custom_components/toyota/__init__.py b/custom_components/toyota/__init__.py index d916440..4934854 100644 --- a/custom_components/toyota/__init__.py +++ b/custom_components/toyota/__init__.py @@ -126,6 +126,7 @@ async def async_get_vehicle_data() -> Optional[list[VehicleData]]: httpx.ReadTimeout, ) as ex: raise UpdateFailed("Update canceled! Toyota's API was too slow to respond. Will try again later...") from ex + return None coordinator = DataUpdateCoordinator( hass, From eeb17798f00f8983da892170e33ab60d0acd596c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B6rrle?= Date: Mon, 8 Jan 2024 09:23:19 +0100 Subject: [PATCH 26/68] increase update_interval to 5 minutes --- custom_components/toyota/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/custom_components/toyota/__init__.py b/custom_components/toyota/__init__.py index 4934854..b1f7eed 100644 --- a/custom_components/toyota/__init__.py +++ b/custom_components/toyota/__init__.py @@ -133,7 +133,7 @@ async def async_get_vehicle_data() -> Optional[list[VehicleData]]: _LOGGER, name=DOMAIN, update_method=async_get_vehicle_data, - update_interval=timedelta(seconds=120), + update_interval=timedelta(seconds=360), ) await coordinator.async_config_entry_first_refresh() From 1eec460b969700ba597fce307783b7a003a076bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B6rrle?= Date: Mon, 8 Jan 2024 09:27:36 +0100 Subject: [PATCH 27/68] adjust driver door lock icon --- custom_components/toyota/binary_sensor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/custom_components/toyota/binary_sensor.py b/custom_components/toyota/binary_sensor.py index b6aeb90..c23c012 100644 --- a/custom_components/toyota/binary_sensor.py +++ b/custom_components/toyota/binary_sensor.py @@ -52,7 +52,7 @@ class ToyotaBinaryEntityDescription(BinarySensorEntityDescription, ToyotaBinaryE FRONT_DRIVER_DOOR_LOCK_STATUS_ENTITY_DESCRIPTION = ToyotaBinaryEntityDescription( key="driverseat_lock", translation_key="driverseat_lock", - icon="mdi:car-door", + icon="mdi:car-door-lock", entity_category=EntityCategory.DIAGNOSTIC, device_class=BinarySensorDeviceClass.LOCK, value_fn=lambda vehicle: not vehicle.lock_status.doors.driver_seat.locked, From 588d6a3b38dd9222a2fbe0e5a73b85edc917710d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B6rrle?= Date: Mon, 8 Jan 2024 13:49:11 +0100 Subject: [PATCH 28/68] make metric value information available for further steps --- custom_components/toyota/__init__.py | 3 +- custom_components/toyota/entity.py | 1 + custom_components/toyota/sensor.py | 158 ++++++++++++--------------- 3 files changed, 74 insertions(+), 88 deletions(-) diff --git a/custom_components/toyota/__init__.py b/custom_components/toyota/__init__.py index b1f7eed..0897125 100644 --- a/custom_components/toyota/__init__.py +++ b/custom_components/toyota/__init__.py @@ -39,6 +39,7 @@ class VehicleData(TypedDict): data: Vehicle statistics: Optional[StatisticsData] + metric_values: bool async def async_setup_entry( # pylint: disable=too-many-statements @@ -73,7 +74,7 @@ async def async_get_vehicle_data() -> Optional[list[VehicleData]]: if vehicles is not None: for vehicle in vehicles: await vehicle.update() - vehicle_data = VehicleData(data=vehicle, statistics=None) + vehicle_data = VehicleData(data=vehicle, statistics=None, metric_values=use_metric_values) if vehicle.vin is not None: # Use parallel request to get car statistics. diff --git a/custom_components/toyota/entity.py b/custom_components/toyota/entity.py index 77647dc..c27bca9 100644 --- a/custom_components/toyota/entity.py +++ b/custom_components/toyota/entity.py @@ -34,6 +34,7 @@ def __init__( self.entity_description = description self.vehicle: Vehicle = coordinator.data[self.index]["data"] self.statistics: Optional[StatisticsData] = coordinator.data[self.index]["statistics"] + self.metric_values: bool = coordinator.data[self.index]["metric_values"] self._attr_unique_id = f"{entry_id}_{self.vehicle.vin}/{self.entity_description.key}" self._attr_device_info = DeviceInfo( diff --git a/custom_components/toyota/sensor.py b/custom_components/toyota/sensor.py index 1be1c6a..562fbe0 100644 --- a/custom_components/toyota/sensor.py +++ b/custom_components/toyota/sensor.py @@ -4,7 +4,7 @@ import logging from collections.abc import Callable from dataclasses import dataclass -from typing import Any, Optional, Union +from typing import Any, Literal, Optional, Union import arrow from homeassistant.components.sensor import ( @@ -108,7 +108,7 @@ class ToyotaSensorEntityDescription(SensorEntityDescription, ToyotaSensorEntityD class ToyotaStatisticsSensorEntityDescriptionMixin: """Mixin for required keys.""" - period: str + period: Literal["day", "week", "month", "year"] @dataclass @@ -116,43 +116,44 @@ class ToyotaStatisticsSensorEntityDescription(SensorEntityDescription, ToyotaSta """Describes a Toyota statistics sensor entity.""" -STATISTICS_ENTITY_DESCRIPTIONS: tuple[ToyotaStatisticsSensorEntityDescription, ...] = ( - ToyotaStatisticsSensorEntityDescription( - key="current_day_statistics", - translation_key="current_day_statistics", - icon="mdi:history", - device_class=SensorDeviceClass.DISTANCE, - state_class=SensorStateClass.MEASUREMENT, - suggested_display_precision=0, - period="day", - ), - ToyotaStatisticsSensorEntityDescription( - key="current_week_statistics", - translation_key="current_week_statistics", - icon="mdi:history", - device_class=SensorDeviceClass.DISTANCE, - state_class=SensorStateClass.MEASUREMENT, - suggested_display_precision=0, - period="week", - ), - ToyotaStatisticsSensorEntityDescription( - key="current_month_statistics", - translation_key="current_month_statistics", - icon="mdi:history", - device_class=SensorDeviceClass.DISTANCE, - state_class=SensorStateClass.MEASUREMENT, - suggested_display_precision=0, - period="month", - ), - ToyotaStatisticsSensorEntityDescription( - key="current_year_statistics", - translation_key="current_year_statistics", - icon="mdi:history", - device_class=SensorDeviceClass.DISTANCE, - state_class=SensorStateClass.MEASUREMENT, - suggested_display_precision=0, - period="year", - ), +STATISTICS_ENTITY_DESCRIPTIONS_DAILY = ToyotaStatisticsSensorEntityDescription( + key="current_day_statistics", + translation_key="current_day_statistics", + icon="mdi:history", + device_class=SensorDeviceClass.DISTANCE, + state_class=SensorStateClass.MEASUREMENT, + suggested_display_precision=0, + period="day", +) + +STATISTICS_ENTITY_DESCRIPTIONS_WEEKLY = ToyotaStatisticsSensorEntityDescription( + key="current_week_statistics", + translation_key="current_week_statistics", + icon="mdi:history", + device_class=SensorDeviceClass.DISTANCE, + state_class=SensorStateClass.MEASUREMENT, + suggested_display_precision=0, + period="week", +) + +STATISTICS_ENTITY_DESCRIPTIONS_MONTHLY = ToyotaStatisticsSensorEntityDescription( + key="current_month_statistics", + translation_key="current_month_statistics", + icon="mdi:history", + device_class=SensorDeviceClass.DISTANCE, + state_class=SensorStateClass.MEASUREMENT, + suggested_display_precision=0, + period="month", +) + +STATISTICS_ENTITY_DESCRIPTIONS_YEARLY = ToyotaStatisticsSensorEntityDescription( + key="current_year_statistics", + translation_key="current_year_statistics", + icon="mdi:history", + device_class=SensorDeviceClass.DISTANCE, + state_class=SensorStateClass.MEASUREMENT, + suggested_display_precision=0, + period="year", ) @@ -167,55 +168,38 @@ async def async_setup_entry( sensors: list[Union[ToyotaSensor, ToyotaStatisticsSensor]] = [] for index, _ in enumerate(coordinator.data): vehicle = coordinator.data[index]["data"] - - sensors.append( - ToyotaSensor( + capabilities_descriptions = [ + ( + vehicle._vehicle_info.extended_capabilities.telemetry_capable, + STATISTICS_ENTITY_DESCRIPTIONS_DAILY, + ToyotaStatisticsSensor, + ), + ( + vehicle._vehicle_info.extended_capabilities.telemetry_capable, + STATISTICS_ENTITY_DESCRIPTIONS_WEEKLY, + ToyotaStatisticsSensor, + ), + ( + vehicle._vehicle_info.extended_capabilities.telemetry_capable, + STATISTICS_ENTITY_DESCRIPTIONS_MONTHLY, + ToyotaStatisticsSensor, + ), + ( + vehicle._vehicle_info.extended_capabilities.telemetry_capable, + STATISTICS_ENTITY_DESCRIPTIONS_YEARLY, + ToyotaStatisticsSensor, + ), + ] + + sensors.extend( + sensor_type( coordinator=coordinator, entry_id=entry.entry_id, vehicle_index=index, - description=LICENSE_PLATE_ENTITY_DESCRIPTION, - ) - ) - - if vehicle.is_connected_services_enabled: - for description in STATISTICS_ENTITY_DESCRIPTIONS: - sensors.append( - ToyotaStatisticsSensor( - coordinator=coordinator, - entry_id=entry.entry_id, - vehicle_index=index, - description=description, - ) - ) - - if vehicle.details.get("batteryHealth") is not None: - sensors.append( - ToyotaSensor( - coordinator=coordinator, - entry_id=entry.entry_id, - vehicle_index=index, - description=STARTER_BATTERY_HEALTH_ENTITY_DESCRIPTIONS, - ) - ) - - sensors.append( - ToyotaSensor( - coordinator=coordinator, - entry_id=entry.entry_id, - vehicle_index=index, - description=ODOMETER_ENTITY_DESCRIPTION_KM - if vehicle.dashboard.is_metric - else ODOMETER_ENTITY_DESCRIPTION_MILES, - ) - ) - - sensors.append( - ToyotaSensor( - coordinator=coordinator, - entry_id=entry.entry_id, - vehicle_index=index, - description=FUEL_LEVEL_ENTITY_DESCRIPTION, + description=description, ) + for capability, description, sensor_type in capabilities_descriptions + if capability ) async_add_devices(sensors) @@ -249,13 +233,13 @@ def __init__( ) -> None: """Initialise the ToyotaStatisticsSensor class.""" super().__init__(coordinator, entry_id, vehicle_index, description) - self.period = description.period - self._attr_native_unit_of_measurement = LENGTH_KILOMETERS if self.vehicle.dashboard.is_metric else LENGTH_MILES + self.period: Literal["day", "week", "month", "year"] = description.period + self._attr_native_unit_of_measurement = LENGTH_KILOMETERS if self.metric_values else LENGTH_MILES @property def native_value(self) -> StateType: """Return the state of the sensor.""" - data = self.coordinator.data[self.index]["statistics"][self.period][0] + data = self.statistics[self.period] return round(data[DATA][TOTAL_DISTANCE], 1) if DATA in data else None def _get_time_period_attributes(self, data: dict[str, Any]): From 241113c89f48eff2aff01546ad4b7b14ac614b07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B6rrle?= Date: Mon, 8 Jan 2024 14:09:40 +0100 Subject: [PATCH 29/68] adopt statistics sensors to new api --- custom_components/toyota/sensor.py | 43 ++++++------------------------ custom_components/toyota/utils.py | 5 ++-- 2 files changed, 11 insertions(+), 37 deletions(-) diff --git a/custom_components/toyota/sensor.py b/custom_components/toyota/sensor.py index 562fbe0..a06175d 100644 --- a/custom_components/toyota/sensor.py +++ b/custom_components/toyota/sensor.py @@ -6,7 +6,6 @@ from dataclasses import dataclass from typing import Any, Literal, Optional, Union -import arrow from homeassistant.components.sensor import ( SensorDeviceClass, SensorEntity, @@ -20,7 +19,7 @@ PERCENTAGE, STATE_UNKNOWN, ) -from homeassistant.core import HomeAssistant, callback +from homeassistant.core import HomeAssistant from homeassistant.helpers.entity import EntityCategory from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.typing import StateType @@ -28,7 +27,7 @@ from mytoyota.models.vehicle import Vehicle from . import StatisticsData, VehicleData -from .const import BUCKET, DATA, DOMAIN, LICENSE_PLATE, PERIODE_START, TOTAL_DISTANCE +from .const import DOMAIN, LICENSE_PLATE from .entity import ToyotaBaseEntity from .utils import format_statistics_attributes, round_number @@ -240,39 +239,13 @@ def __init__( def native_value(self) -> StateType: """Return the state of the sensor.""" data = self.statistics[self.period] - return round(data[DATA][TOTAL_DISTANCE], 1) if DATA in data else None - - def _get_time_period_attributes(self, data: dict[str, Any]): - """Get time period attributes.""" - now = arrow.now() - if self.period == "day": - dt = now.floor("day").format("YYYY-MM-DD") - return {"Day": data[BUCKET]["date"] if BUCKET in data else dt} - elif self.period == "week": - from_dt = now.floor("week").format("YYYY-MM-DD") - to_dt = now.ceil("week").format("YYYY-MM-DD") - return { - "From": data[BUCKET][PERIODE_START] if BUCKET in data else from_dt, - "To": to_dt, - } - elif self.period == "month": - from_month = now.floor("month").format("MMMM") - return {"Month": from_month} - elif self.period == "year": - from_year = now.floor("year").format("YYYY") - return {"Year": data[BUCKET]["year"] if BUCKET in data else from_year} - return None + return round(data.distance, 1) if data else None @property def extra_state_attributes(self): """Return the state attributes.""" - data = self.coordinator.data[self.index]["statistics"][self.period][0] - attributes = format_statistics_attributes(data.get(DATA, {}), self.vehicle.hybrid) - attributes.update(self._get_time_period_attributes(data)) - return attributes - - @callback - def _handle_coordinator_update(self) -> None: - """Handle updated data from the coordinator.""" - self.statistics = self.coordinator.data[self.index]["statistics"] - super()._handle_coordinator_update() + data = self.statistics[self.period] + if data is not None: + return format_statistics_attributes(data, self.vehicle.hybrid) + else: + return None diff --git a/custom_components/toyota/utils.py b/custom_components/toyota/utils.py index 24c7721..fe4f3f3 100644 --- a/custom_components/toyota/utils.py +++ b/custom_components/toyota/utils.py @@ -2,7 +2,8 @@ from __future__ import annotations from datetime import timedelta -from typing import Any + +from mytoyota.models.summary import Summary from .const import ( AVERAGE_SPEED, @@ -31,7 +32,7 @@ def round_number(number: int | float | None, places: int = 0) -> int | float | N return None if number is None else round(number, places) -def format_statistics_attributes(statistics: dict[str, Any], is_hybrid: bool): +def format_statistics_attributes(statistics: Summary, is_hybrid: bool): """Format and returns statistics attributes.""" def get_timedelta(time): From 4fb4ee66f58ff96a276eb1f0fd36460169b3bff2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B6rrle?= Date: Mon, 8 Jan 2024 15:56:43 +0100 Subject: [PATCH 30/68] update statistics utils and delete unsused constants --- custom_components/toyota/const.py | 19 -------- custom_components/toyota/sensor.py | 2 +- custom_components/toyota/utils.py | 78 ++++++------------------------ 3 files changed, 16 insertions(+), 83 deletions(-) diff --git a/custom_components/toyota/const.py b/custom_components/toyota/const.py index 6e46f62..c585842 100644 --- a/custom_components/toyota/const.py +++ b/custom_components/toyota/const.py @@ -17,34 +17,15 @@ DEFAULT_LOCALE = "en-gb" # DATA COORDINATOR ATTRIBUTES -AVERAGE_SPEED = "averageSpeedInKmph" BUCKET = "bucket" -COACHING_ADVICE = "coachingAdviceMostOccurrence" DATA = "data" -DRIVER_SCORE = "averageDriverScore" -DRIVER_SCORE_ACCELERATIONS = "averageAccelerationDriverScore" -DRIVER_SCORE_BRAKING = "averageBrakingDriverScore" ENGINE = "engine" -EV_DISTANCE = "evDistanceInKm" -EV_DURATION = "evDurationInSec" -EV_DISTANCE_PERCENTAGE = "evDistancePercentage" -EV_DURATION_PERCENTAGE = "evDurationPercentage" -FUEL_CONSUMED = "totalFuelConsumedInL" FUEL_TYPE = "fuel" -HARD_ACCELERATION = "hardAccelerationCount" -HARD_BRAKING = "hardBrakingCount" -HIGHWAY_DISTANCE = "highwayDistanceInKm" -HIGHWAY_DISTANCE_PERCENTAGE = "highwayDistancePercentage" HYBRID = "hybrid" LAST_UPDATED = "last_updated" LICENSE_PLATE = "licensePlate" -MAX_SPEED = "maxSpeedInKmph" -NIGHT_TRIPS = "nightTripsCount" PERIODE_START = "periode_start" STATISTICS = "statistics" -TOTAL_DURATION = "totalDurationInSec" -TOTAL_DISTANCE = "totalDistanceInKm" -TRIPS = "tripCount" WARNING = "warning" # ICONS diff --git a/custom_components/toyota/sensor.py b/custom_components/toyota/sensor.py index a06175d..700a4c2 100644 --- a/custom_components/toyota/sensor.py +++ b/custom_components/toyota/sensor.py @@ -246,6 +246,6 @@ def extra_state_attributes(self): """Return the state attributes.""" data = self.statistics[self.period] if data is not None: - return format_statistics_attributes(data, self.vehicle.hybrid) + return format_statistics_attributes(data, self.vehicle._vehicle_info) else: return None diff --git a/custom_components/toyota/utils.py b/custom_components/toyota/utils.py index fe4f3f3..d5773a6 100644 --- a/custom_components/toyota/utils.py +++ b/custom_components/toyota/utils.py @@ -1,86 +1,38 @@ """Utilities for Toyota integration.""" from __future__ import annotations -from datetime import timedelta - +from mytoyota.models.endpoints.vehicle_guid import VehicleGuidModel from mytoyota.models.summary import Summary -from .const import ( - AVERAGE_SPEED, - COACHING_ADVICE, - DRIVER_SCORE, - DRIVER_SCORE_ACCELERATIONS, - DRIVER_SCORE_BRAKING, - EV_DISTANCE, - EV_DISTANCE_PERCENTAGE, - EV_DURATION, - EV_DURATION_PERCENTAGE, - FUEL_CONSUMED, - HARD_ACCELERATION, - HARD_BRAKING, - HIGHWAY_DISTANCE, - HIGHWAY_DISTANCE_PERCENTAGE, - MAX_SPEED, - NIGHT_TRIPS, - TOTAL_DURATION, - TRIPS, -) - def round_number(number: int | float | None, places: int = 0) -> int | float | None: """Round a number if it is not None.""" return None if number is None else round(number, places) -def format_statistics_attributes(statistics: Summary, is_hybrid: bool): +def format_statistics_attributes(statistics: Summary, vehicle_info: VehicleGuidModel): """Format and returns statistics attributes.""" - - def get_timedelta(time): - return str(timedelta(seconds=time)) - attr = { - "Highway_distance": round(statistics.get(HIGHWAY_DISTANCE, 0), 1), - "Highway_percentage": round(statistics.get(HIGHWAY_DISTANCE_PERCENTAGE, 0), 1), - "Number_of_trips": statistics.get(TRIPS, 0), - "Number_of_night_trips": statistics.get(NIGHT_TRIPS, 0), - "Total_driving_time": get_timedelta(statistics.get(TOTAL_DURATION, 0)), - "Average_speed": round(statistics.get(AVERAGE_SPEED, 0), 1), - "Max_speed": round(statistics.get(MAX_SPEED, 0), 1), - "Hard_acceleration_count": statistics.get(HARD_ACCELERATION, 0), - "Hard_braking_count": statistics.get(HARD_BRAKING, 0), + "Average_speed": round(statistics.average_speed, 1) if statistics.average_speed else None, + "Countries": statistics.countries or [], } - if FUEL_CONSUMED in statistics: - attr.update( - { - "Average_fuel_consumed": round(statistics.get(FUEL_CONSUMED, 0), 2), - } - ) + if vehicle_info.fuel_type is not None: + attr["Fuel_consumed"] = round(statistics.fuel_consumed, 3) if statistics.fuel_consumed else None - if COACHING_ADVICE in statistics: + if vehicle_info.electrical_platform_code == 15: attr.update( { - "Coaching_advice_most_occurrence": statistics.get(COACHING_ADVICE, 0), + "EV_distance": round(statistics.ev_distance, 1) if statistics.ev_distance else None, + "EV_duration": statistics.ev_duration, } ) - if DRIVER_SCORE in statistics: - attr.update( - { - "Average_driver_score": round(statistics.get(DRIVER_SCORE, 0), 1), - "Average_driver_score_accelerations": round(statistics.get(DRIVER_SCORE_ACCELERATIONS, 0), 1), - "Average_driver_score_braking": round(statistics.get(DRIVER_SCORE_BRAKING, 0), 1), - } - ) - - if is_hybrid: - attr.update( - { - "EV_distance": round(statistics.get(EV_DISTANCE, 0), 1), - "EV_driving_time": get_timedelta(statistics.get(EV_DURATION, 0)), - "EV_distance_percentage": round(statistics.get(EV_DISTANCE_PERCENTAGE, 0), 1), - "EV_duration_percentage": round(statistics.get(EV_DURATION_PERCENTAGE, 0), 1), - } - ) + attr.update( + { + "From_date": statistics.from_date, + "To_date": statistics.to_date, + } + ) return attr From c9cda604c338dbf13b11e8cdff67a77e14449bd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B6rrle?= Date: Mon, 8 Jan 2024 16:50:03 +0100 Subject: [PATCH 31/68] add vin sensor --- custom_components/toyota/const.py | 2 +- custom_components/toyota/sensor.py | 19 ++++++++++++------- custom_components/toyota/translations/ca.json | 3 +++ custom_components/toyota/translations/da.json | 3 +++ custom_components/toyota/translations/de.json | 3 +++ custom_components/toyota/translations/en.json | 3 +++ custom_components/toyota/translations/es.json | 3 +++ custom_components/toyota/translations/fr.json | 3 +++ custom_components/toyota/translations/nb.json | 3 +++ custom_components/toyota/translations/nl.json | 3 +++ 10 files changed, 37 insertions(+), 8 deletions(-) diff --git a/custom_components/toyota/const.py b/custom_components/toyota/const.py index c585842..3e610d1 100644 --- a/custom_components/toyota/const.py +++ b/custom_components/toyota/const.py @@ -23,7 +23,7 @@ FUEL_TYPE = "fuel" HYBRID = "hybrid" LAST_UPDATED = "last_updated" -LICENSE_PLATE = "licensePlate" +VIN = "vin" PERIODE_START = "periode_start" STATISTICS = "statistics" WARNING = "warning" diff --git a/custom_components/toyota/sensor.py b/custom_components/toyota/sensor.py index 700a4c2..40e313c 100644 --- a/custom_components/toyota/sensor.py +++ b/custom_components/toyota/sensor.py @@ -17,7 +17,6 @@ LENGTH_KILOMETERS, LENGTH_MILES, PERCENTAGE, - STATE_UNKNOWN, ) from homeassistant.core import HomeAssistant from homeassistant.helpers.entity import EntityCategory @@ -27,7 +26,7 @@ from mytoyota.models.vehicle import Vehicle from . import StatisticsData, VehicleData -from .const import DOMAIN, LICENSE_PLATE +from .const import DOMAIN from .entity import ToyotaBaseEntity from .utils import format_statistics_attributes, round_number @@ -47,16 +46,17 @@ class ToyotaSensorEntityDescription(SensorEntityDescription, ToyotaSensorEntityD """Describes a Toyota sensor entity.""" -LICENSE_PLATE_ENTITY_DESCRIPTION = ToyotaSensorEntityDescription( - key="license_plate", - translation_key="license_plate", +# TODO: There is currently no information on the licence plate. Add it, wehen available +VIN_ENTITY_DESCRIPTION = ToyotaSensorEntityDescription( + key="vin", + translation_key="vin", icon="mdi:car-info", entity_category=EntityCategory.DIAGNOSTIC, device_class=SensorDeviceClass.ENUM, native_unit_of_measurement=None, state_class=None, - value_fn=lambda vehicle: vehicle.details.get(LICENSE_PLATE, STATE_UNKNOWN), - attributes_fn=lambda vehicle: vehicle.details, + value_fn=lambda vehicle: vehicle.vin, + attributes_fn=lambda vehicle: vehicle._vehicle_info.extended_capabilities.dict(), ) STARTER_BATTERY_HEALTH_ENTITY_DESCRIPTIONS = ToyotaSensorEntityDescription( key="starter_battery_health", @@ -168,6 +168,11 @@ async def async_setup_entry( for index, _ in enumerate(coordinator.data): vehicle = coordinator.data[index]["data"] capabilities_descriptions = [ + ( + True, + VIN_ENTITY_DESCRIPTION, + ToyotaSensor, + ), ( vehicle._vehicle_info.extended_capabilities.telemetry_capable, STATISTICS_ENTITY_DESCRIPTIONS_DAILY, diff --git a/custom_components/toyota/translations/ca.json b/custom_components/toyota/translations/ca.json index f139eb1..b91254c 100644 --- a/custom_components/toyota/translations/ca.json +++ b/custom_components/toyota/translations/ca.json @@ -23,6 +23,9 @@ } }, "sensor": { + "vin": { + "name": "Vehicle-Identify-Number" + }, "starter_battery_health": { "name": "Starter battery health" }, diff --git a/custom_components/toyota/translations/da.json b/custom_components/toyota/translations/da.json index 326a5df..75f0bf3 100644 --- a/custom_components/toyota/translations/da.json +++ b/custom_components/toyota/translations/da.json @@ -32,6 +32,9 @@ } }, "sensor": { + "vin": { + "name": "Vehicle-Identify-Number" + }, "starter_battery_health": { "name": "Starter batteri tilstand", "state": { diff --git a/custom_components/toyota/translations/de.json b/custom_components/toyota/translations/de.json index e29f3ba..a4a3ba1 100644 --- a/custom_components/toyota/translations/de.json +++ b/custom_components/toyota/translations/de.json @@ -32,6 +32,9 @@ } }, "sensor": { + "vin": { + "name": "Fahrzeug-Identifizierungsnummer" + }, "starter_battery_health": { "name": "Zustand Starterbatterie" }, diff --git a/custom_components/toyota/translations/en.json b/custom_components/toyota/translations/en.json index a764ade..705decf 100644 --- a/custom_components/toyota/translations/en.json +++ b/custom_components/toyota/translations/en.json @@ -32,6 +32,9 @@ } }, "sensor": { + "vin": { + "name": "Vehicle-Identify-Number" + }, "starter_battery_health": { "name": "Starter battery health" }, diff --git a/custom_components/toyota/translations/es.json b/custom_components/toyota/translations/es.json index c8245ac..bcb16e2 100644 --- a/custom_components/toyota/translations/es.json +++ b/custom_components/toyota/translations/es.json @@ -23,6 +23,9 @@ } }, "sensor": { + "vin": { + "name": "Vehicle-Identify-Number" + }, "starter_battery_health": { "name": "Salud de la batería de arranque" }, diff --git a/custom_components/toyota/translations/fr.json b/custom_components/toyota/translations/fr.json index 626f0d0..4412417 100644 --- a/custom_components/toyota/translations/fr.json +++ b/custom_components/toyota/translations/fr.json @@ -32,6 +32,9 @@ } }, "sensor": { + "vin": { + "name": "Vehicle-Identify-Number" + }, "starter_battery_health": { "name": "État de la batterie de démarrage" }, diff --git a/custom_components/toyota/translations/nb.json b/custom_components/toyota/translations/nb.json index 2ba7e8c..71dcb51 100644 --- a/custom_components/toyota/translations/nb.json +++ b/custom_components/toyota/translations/nb.json @@ -32,6 +32,9 @@ } }, "sensor": { + "vin": { + "name": "Vehicle-Identify-Number" + }, "starter_battery_health": { "name": "Starter battery health" }, diff --git a/custom_components/toyota/translations/nl.json b/custom_components/toyota/translations/nl.json index 9b89876..db3109b 100644 --- a/custom_components/toyota/translations/nl.json +++ b/custom_components/toyota/translations/nl.json @@ -23,6 +23,9 @@ } }, "sensor": { + "vin": { + "name": "Vehicle-Identify-Number" + }, "starter_battery_health": { "name": "Starter battery health" }, From 97de4bdac5e5fc6c45cf29ef0c8fd2372dee947f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B6rrle?= Date: Tue, 9 Jan 2024 08:23:20 +0100 Subject: [PATCH 32/68] display all vehicle informations in vin sensor --- custom_components/toyota/sensor.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/custom_components/toyota/sensor.py b/custom_components/toyota/sensor.py index 40e313c..88f4e9f 100644 --- a/custom_components/toyota/sensor.py +++ b/custom_components/toyota/sensor.py @@ -13,11 +13,7 @@ SensorStateClass, ) from homeassistant.config_entries import ConfigEntry -from homeassistant.const import ( - LENGTH_KILOMETERS, - LENGTH_MILES, - PERCENTAGE, -) +from homeassistant.const import LENGTH_KILOMETERS, LENGTH_MILES, PERCENTAGE from homeassistant.core import HomeAssistant from homeassistant.helpers.entity import EntityCategory from homeassistant.helpers.entity_platform import AddEntitiesCallback @@ -56,7 +52,7 @@ class ToyotaSensorEntityDescription(SensorEntityDescription, ToyotaSensorEntityD native_unit_of_measurement=None, state_class=None, value_fn=lambda vehicle: vehicle.vin, - attributes_fn=lambda vehicle: vehicle._vehicle_info.extended_capabilities.dict(), + attributes_fn=lambda vehicle: vehicle._vehicle_info.dict(), ) STARTER_BATTERY_HEALTH_ENTITY_DESCRIPTIONS = ToyotaSensorEntityDescription( key="starter_battery_health", From 30fad2427cc7732b1420be272e578652c4838d84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B6rrle?= Date: Tue, 9 Jan 2024 08:24:59 +0100 Subject: [PATCH 33/68] display ev summary also for pure electric vehicles --- custom_components/toyota/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/custom_components/toyota/utils.py b/custom_components/toyota/utils.py index d5773a6..a180af5 100644 --- a/custom_components/toyota/utils.py +++ b/custom_components/toyota/utils.py @@ -20,7 +20,7 @@ def format_statistics_attributes(statistics: Summary, vehicle_info: VehicleGuidM if vehicle_info.fuel_type is not None: attr["Fuel_consumed"] = round(statistics.fuel_consumed, 3) if statistics.fuel_consumed else None - if vehicle_info.electrical_platform_code == 15: + if vehicle_info.electrical_platform_code == 15 or vehicle_info.ev_vehicle is True: attr.update( { "EV_distance": round(statistics.ev_distance, 1) if statistics.ev_distance else None, From 5ac3febe139c72cf38125c15314af98f294b050a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B6rrle?= Date: Tue, 9 Jan 2024 13:32:46 +0100 Subject: [PATCH 34/68] return timdelta and date as string --- custom_components/toyota/utils.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/custom_components/toyota/utils.py b/custom_components/toyota/utils.py index a180af5..a01bad8 100644 --- a/custom_components/toyota/utils.py +++ b/custom_components/toyota/utils.py @@ -24,14 +24,14 @@ def format_statistics_attributes(statistics: Summary, vehicle_info: VehicleGuidM attr.update( { "EV_distance": round(statistics.ev_distance, 1) if statistics.ev_distance else None, - "EV_duration": statistics.ev_duration, + "EV_duration": str(statistics.ev_duration), } ) attr.update( { - "From_date": statistics.from_date, - "To_date": statistics.to_date, + "From_date": statistics.from_date.strftime("%Y-%m-%d"), + "To_date": statistics.to_date.strftime("%Y-%m-%d"), } ) From e3258331412c23fcd3b16806110b06efd7fb5237 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B6rrle?= Date: Tue, 9 Jan 2024 16:03:37 +0100 Subject: [PATCH 35/68] add odometer and fuel sensors --- custom_components/toyota/sensor.py | 89 ++++++++++++++++++++++++------ 1 file changed, 72 insertions(+), 17 deletions(-) diff --git a/custom_components/toyota/sensor.py b/custom_components/toyota/sensor.py index 88f4e9f..f135651 100644 --- a/custom_components/toyota/sensor.py +++ b/custom_components/toyota/sensor.py @@ -22,9 +22,9 @@ from mytoyota.models.vehicle import Vehicle from . import StatisticsData, VehicleData -from .const import DOMAIN +from .const import CONF_METRIC_VALUES, DOMAIN from .entity import ToyotaBaseEntity -from .utils import format_statistics_attributes, round_number +from .utils import format_statistics_attributes _LOGGER = logging.getLogger(__name__) @@ -54,24 +54,14 @@ class ToyotaSensorEntityDescription(SensorEntityDescription, ToyotaSensorEntityD value_fn=lambda vehicle: vehicle.vin, attributes_fn=lambda vehicle: vehicle._vehicle_info.dict(), ) -STARTER_BATTERY_HEALTH_ENTITY_DESCRIPTIONS = ToyotaSensorEntityDescription( - key="starter_battery_health", - translation_key="starter_battery_health", - icon="mdi:car_battery", - device_class=SensorDeviceClass.ENUM, - native_unit_of_measurement=None, - state_class=None, - value_fn=lambda vehicle: vehicle.details.get("batteryHealth").capitalize(), - attributes_fn=lambda vehicle: None, # noqa : ARG005 -) ODOMETER_ENTITY_DESCRIPTION_KM = ToyotaSensorEntityDescription( key="odometer", translation_key="odometer", icon="mdi:counter", device_class=SensorDeviceClass.DISTANCE, native_unit_of_measurement=LENGTH_KILOMETERS, - state_class=SensorStateClass.MEASUREMENT, - value_fn=lambda vehicle: vehicle.dashboard.odometer, + state_class=SensorStateClass.TOTAL_INCREASING, + value_fn=lambda vehicle: None if vehicle.dashboard is None else vehicle.dashboard.odometer, suggested_display_precision=0, attributes_fn=lambda vehicle: None, # noqa : ARG005 ) @@ -81,8 +71,8 @@ class ToyotaSensorEntityDescription(SensorEntityDescription, ToyotaSensorEntityD icon="mdi:counter", device_class=SensorDeviceClass.DISTANCE, native_unit_of_measurement=LENGTH_MILES, - state_class=SensorStateClass.MEASUREMENT, - value_fn=lambda vehicle: vehicle.dashboard.odometer, + state_class=SensorStateClass.TOTAL_INCREASING, + value_fn=lambda vehicle: None if vehicle.dashboard is None else vehicle.dashboard.odometer, suggested_display_precision=0, attributes_fn=lambda vehicle: None, # noqa : ARG005 ) @@ -93,7 +83,40 @@ class ToyotaSensorEntityDescription(SensorEntityDescription, ToyotaSensorEntityD device_class=None, native_unit_of_measurement=PERCENTAGE, state_class=SensorStateClass.MEASUREMENT, - value_fn=lambda vehicle: round_number(vehicle.dashboard.fuel_level, 0), + value_fn=lambda vehicle: None if vehicle.dashboard is None else vehicle.dashboard.fuel_level, + suggested_display_precision=0, + attributes_fn=lambda vehicle: None, # noqa : ARG005 +) +FUEL_RANGE_ENTITY_DESCRIPTION_KM = ToyotaSensorEntityDescription( + key="fuel_range", + translation_key="fuel_range", + icon="mdi:map-marker-distance", + device_class=SensorDeviceClass.DISTANCE, + native_unit_of_measurement=LENGTH_KILOMETERS, + state_class=SensorStateClass.MEASUREMENT, + value_fn=lambda vehicle: None if vehicle.dashboard is None else vehicle.dashboard.fuel_range, + suggested_display_precision=0, + attributes_fn=lambda vehicle: None, # noqa : ARG005 +) +FUEL_RANGE_ENTITY_DESCRIPTION_MILES = ToyotaSensorEntityDescription( + key="fuel_range", + translation_key="fuel_range", + icon="mdi:map-marker-distance", + device_class=SensorDeviceClass.DISTANCE, + native_unit_of_measurement=LENGTH_MILES, + state_class=SensorStateClass.MEASUREMENT, + value_fn=lambda vehicle: None if vehicle.dashboard is None else vehicle.dashboard.fuel_range, + suggested_display_precision=0, + attributes_fn=lambda vehicle: None, # noqa : ARG005 +) +BATTERY_LEVEL_ENTITY_DESCRIPTION = ToyotaSensorEntityDescription( + key="battery_level", + translation_key="battery_level", + icon="mdi:car-electric", + device_class=None, + native_unit_of_measurement=PERCENTAGE, + state_class=SensorStateClass.MEASUREMENT, + value_fn=lambda vehicle: None if vehicle.dashboard is None else vehicle.dashboard.fuel_level, suggested_display_precision=0, attributes_fn=lambda vehicle: None, # noqa : ARG005 ) @@ -169,6 +192,38 @@ async def async_setup_entry( VIN_ENTITY_DESCRIPTION, ToyotaSensor, ), + ( + entry.data[CONF_METRIC_VALUES] is True, + ODOMETER_ENTITY_DESCRIPTION_KM, + ToyotaSensor, + ), + ( + entry.data[CONF_METRIC_VALUES] is False, + ODOMETER_ENTITY_DESCRIPTION_MILES, + ToyotaSensor, + ), + ( + vehicle._vehicle_info.extended_capabilities.fuel_level_available, + FUEL_LEVEL_ENTITY_DESCRIPTION, + ToyotaSensor, + ), + ( + entry.data[CONF_METRIC_VALUES] is True + and vehicle._vehicle_info.extended_capabilities.fuel_range_available, + FUEL_RANGE_ENTITY_DESCRIPTION_KM, + ToyotaSensor, + ), + ( + entry.data[CONF_METRIC_VALUES] is False + and vehicle._vehicle_info.extended_capabilities.fuel_range_available, + FUEL_RANGE_ENTITY_DESCRIPTION_MILES, + ToyotaSensor, + ), + ( + vehicle._vehicle_info.extended_capabilities.battery_status, + BATTERY_LEVEL_ENTITY_DESCRIPTION, + ToyotaSensor, + ), ( vehicle._vehicle_info.extended_capabilities.telemetry_capable, STATISTICS_ENTITY_DESCRIPTIONS_DAILY, From 6af3f53c0f8239be2cf8781fed4f7c2445f7a470 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B6rrle?= Date: Tue, 9 Jan 2024 16:08:10 +0100 Subject: [PATCH 36/68] clean up sensor translations --- custom_components/toyota/translations/ca.json | 9 ++++++--- custom_components/toyota/translations/da.json | 12 ++++++------ custom_components/toyota/translations/de.json | 9 ++++++--- custom_components/toyota/translations/en.json | 9 ++++++--- custom_components/toyota/translations/es.json | 9 ++++++--- custom_components/toyota/translations/fr.json | 9 ++++++--- custom_components/toyota/translations/nb.json | 9 ++++++--- custom_components/toyota/translations/nl.json | 9 ++++++--- 8 files changed, 48 insertions(+), 27 deletions(-) diff --git a/custom_components/toyota/translations/ca.json b/custom_components/toyota/translations/ca.json index b91254c..010f795 100644 --- a/custom_components/toyota/translations/ca.json +++ b/custom_components/toyota/translations/ca.json @@ -26,15 +26,18 @@ "vin": { "name": "Vehicle-Identify-Number" }, - "starter_battery_health": { - "name": "Starter battery health" - }, "odometer": { "name": "Odometer" }, "fuel_level": { "name": "Fuel level" }, + "fuel_range": { + "name": "Fuel range" + }, + "battery_level": { + "name": "Battery level" + }, "current_day_statistics": { "name": "Current day statistics" }, diff --git a/custom_components/toyota/translations/da.json b/custom_components/toyota/translations/da.json index 75f0bf3..0b47c46 100644 --- a/custom_components/toyota/translations/da.json +++ b/custom_components/toyota/translations/da.json @@ -35,18 +35,18 @@ "vin": { "name": "Vehicle-Identify-Number" }, - "starter_battery_health": { - "name": "Starter batteri tilstand", - "state": { - "Good": "God" - } - }, "odometer": { "name": "Odometer" }, "fuel_level": { "name": "Brændstof niveau" }, + "fuel_range": { + "name": "Fuel range" + }, + "battery_level": { + "name": "Battery level" + }, "current_day_statistics": { "name": "Statistik for denne dag" }, diff --git a/custom_components/toyota/translations/de.json b/custom_components/toyota/translations/de.json index a4a3ba1..bb049f2 100644 --- a/custom_components/toyota/translations/de.json +++ b/custom_components/toyota/translations/de.json @@ -35,15 +35,18 @@ "vin": { "name": "Fahrzeug-Identifizierungsnummer" }, - "starter_battery_health": { - "name": "Zustand Starterbatterie" - }, "odometer": { "name": "Kilometerzähler" }, "fuel_level": { "name": "Kraftstoffstand" }, + "fuel_range": { + "name": "Tankreichweite" + }, + "battery_level": { + "name": "Batteriestand" + }, "current_day_statistics": { "name": "Aktuelle Tagesstatistiken" }, diff --git a/custom_components/toyota/translations/en.json b/custom_components/toyota/translations/en.json index 705decf..8d4d3df 100644 --- a/custom_components/toyota/translations/en.json +++ b/custom_components/toyota/translations/en.json @@ -35,15 +35,18 @@ "vin": { "name": "Vehicle-Identify-Number" }, - "starter_battery_health": { - "name": "Starter battery health" - }, "odometer": { "name": "Odometer" }, "fuel_level": { "name": "Fuel level" }, + "fuel_range": { + "name": "Fuel range" + }, + "battery_level": { + "name": "Battery level" + }, "current_day_statistics": { "name": "Current day statistics" }, diff --git a/custom_components/toyota/translations/es.json b/custom_components/toyota/translations/es.json index bcb16e2..2224627 100644 --- a/custom_components/toyota/translations/es.json +++ b/custom_components/toyota/translations/es.json @@ -26,15 +26,18 @@ "vin": { "name": "Vehicle-Identify-Number" }, - "starter_battery_health": { - "name": "Salud de la batería de arranque" - }, "odometer": { "name": "Odometro" }, "fuel_level": { "name": "Nivel de combustible" }, + "fuel_range": { + "name": "Fuel range" + }, + "battery_level": { + "name": "Battery level" + }, "current_day_statistics": { "name": "Estadísticas de hoy" }, diff --git a/custom_components/toyota/translations/fr.json b/custom_components/toyota/translations/fr.json index 4412417..54a5dbb 100644 --- a/custom_components/toyota/translations/fr.json +++ b/custom_components/toyota/translations/fr.json @@ -35,15 +35,18 @@ "vin": { "name": "Vehicle-Identify-Number" }, - "starter_battery_health": { - "name": "État de la batterie de démarrage" - }, "odometer": { "name": "Odomètre" }, "fuel_level": { "name": "Niveau de carburant" }, + "fuel_range": { + "name": "Fuel range" + }, + "battery_level": { + "name": "Battery level" + }, "current_day_statistics": { "name": "Statistiques aujourd'hui" }, diff --git a/custom_components/toyota/translations/nb.json b/custom_components/toyota/translations/nb.json index 71dcb51..d9baa94 100644 --- a/custom_components/toyota/translations/nb.json +++ b/custom_components/toyota/translations/nb.json @@ -35,15 +35,18 @@ "vin": { "name": "Vehicle-Identify-Number" }, - "starter_battery_health": { - "name": "Starter battery health" - }, "odometer": { "name": "Odometer" }, "fuel_level": { "name": "Fuel level" }, + "fuel_range": { + "name": "Fuel range" + }, + "battery_level": { + "name": "Battery level" + }, "current_day_statistics": { "name": "Current day statistics" }, diff --git a/custom_components/toyota/translations/nl.json b/custom_components/toyota/translations/nl.json index db3109b..b971f32 100644 --- a/custom_components/toyota/translations/nl.json +++ b/custom_components/toyota/translations/nl.json @@ -26,15 +26,18 @@ "vin": { "name": "Vehicle-Identify-Number" }, - "starter_battery_health": { - "name": "Starter battery health" - }, "odometer": { "name": "Odometer" }, "fuel_level": { "name": "Fuel level" }, + "fuel_range": { + "name": "Fuel range" + }, + "battery_level": { + "name": "Battery level" + }, "current_day_statistics": { "name": "Current day statistics" }, From 5c1f2d3626bd089111109d08f9fe19b50fa23f08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B6rrle?= Date: Tue, 9 Jan 2024 16:40:38 +0100 Subject: [PATCH 37/68] format vin sensor attributes --- custom_components/toyota/sensor.py | 4 ++-- custom_components/toyota/utils.py | 36 +++++++++++++++++++++++++++++- 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/custom_components/toyota/sensor.py b/custom_components/toyota/sensor.py index f135651..be0e4dc 100644 --- a/custom_components/toyota/sensor.py +++ b/custom_components/toyota/sensor.py @@ -24,7 +24,7 @@ from . import StatisticsData, VehicleData from .const import CONF_METRIC_VALUES, DOMAIN from .entity import ToyotaBaseEntity -from .utils import format_statistics_attributes +from .utils import format_statistics_attributes, format_vin_sensor_attributes _LOGGER = logging.getLogger(__name__) @@ -52,7 +52,7 @@ class ToyotaSensorEntityDescription(SensorEntityDescription, ToyotaSensorEntityD native_unit_of_measurement=None, state_class=None, value_fn=lambda vehicle: vehicle.vin, - attributes_fn=lambda vehicle: vehicle._vehicle_info.dict(), + attributes_fn=lambda vehicle: format_vin_sensor_attributes(vehicle._vehicle_info), ) ODOMETER_ENTITY_DESCRIPTION_KM = ToyotaSensorEntityDescription( key="odometer", diff --git a/custom_components/toyota/utils.py b/custom_components/toyota/utils.py index a01bad8..122a558 100644 --- a/custom_components/toyota/utils.py +++ b/custom_components/toyota/utils.py @@ -1,6 +1,8 @@ """Utilities for Toyota integration.""" from __future__ import annotations +from typing import Optional, Union + from mytoyota.models.endpoints.vehicle_guid import VehicleGuidModel from mytoyota.models.summary import Summary @@ -10,7 +12,39 @@ def round_number(number: int | float | None, places: int = 0) -> int | float | N return None if number is None else round(number, places) -def format_statistics_attributes(statistics: Summary, vehicle_info: VehicleGuidModel): +def format_vin_sensor_attributes( + vehicle_info: VehicleGuidModel, +) -> dict[str, Optional[Union[str, bool, dict[str, bool]]]]: + """Format and returns vin sensor attributes.""" + return { + "Vin": vehicle_info.vin, + "Contract_id": vehicle_info.contract_id, + "Katashiki_code": vehicle_info.katashiki_code, + "Asi_code": vehicle_info.asi_code, + "Imei": vehicle_info.imei, + "Brand": vehicle_info.brand, + "Car_line_name": vehicle_info.car_line_name, + "Car_model_year": vehicle_info.car_model_year, + "Car_model_name": vehicle_info.car_line_name, + "Color": vehicle_info.color, + "Generation": vehicle_info.generation, + "Manufactured_date": None + if vehicle_info.manufactured_date is None + else vehicle_info.manufactured_date.strftime("%Y-%m-%d"), + "Date_of_first_use": None + if vehicle_info.date_of_first_use is None + else vehicle_info.date_of_first_use.strftime("%Y-%m-%d"), + "Transmission_type": vehicle_info.transmission_type, + "Fuel_type": vehicle_info.fuel_type, + "Electrical_platform_code": vehicle_info.electrical_platform_code, + "EV_vehicle": vehicle_info.ev_vehicle, + "Features": vehicle_info.features.dict(), + "Extended_capabilities": vehicle_info.extended_capabilities.dict(), + "Remote_service_capabilities": vehicle_info.remote_service_capabilities.dict(), + } + + +def format_statistics_attributes(statistics: Summary, vehicle_info: VehicleGuidModel) -> dict[str, Optional[str]]: """Format and returns statistics attributes.""" attr = { "Average_speed": round(statistics.average_speed, 1) if statistics.average_speed else None, From a7e1bbaabd12205a6de46808d61196d803855ab5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B6rrle?= Date: Tue, 9 Jan 2024 16:45:16 +0100 Subject: [PATCH 38/68] use car_model_name --- custom_components/toyota/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/custom_components/toyota/utils.py b/custom_components/toyota/utils.py index 122a558..8305d0f 100644 --- a/custom_components/toyota/utils.py +++ b/custom_components/toyota/utils.py @@ -25,7 +25,7 @@ def format_vin_sensor_attributes( "Brand": vehicle_info.brand, "Car_line_name": vehicle_info.car_line_name, "Car_model_year": vehicle_info.car_model_year, - "Car_model_name": vehicle_info.car_line_name, + "Car_model_name": vehicle_info.car_model_name, "Color": vehicle_info.color, "Generation": vehicle_info.generation, "Manufactured_date": None From 87f30c7c15499d4cd00c2b1247c632c3c90f07e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B6rrle?= Date: Tue, 9 Jan 2024 17:10:24 +0100 Subject: [PATCH 39/68] make battery_level sensor available for all ev vehicles --- custom_components/toyota/sensor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/custom_components/toyota/sensor.py b/custom_components/toyota/sensor.py index be0e4dc..b75fc9f 100644 --- a/custom_components/toyota/sensor.py +++ b/custom_components/toyota/sensor.py @@ -220,7 +220,7 @@ async def async_setup_entry( ToyotaSensor, ), ( - vehicle._vehicle_info.extended_capabilities.battery_status, + vehicle._vehicle_info.extended_capabilities.battery_status or vehicle._vehicle_info.ev_vehicle is True, BATTERY_LEVEL_ENTITY_DESCRIPTION, ToyotaSensor, ), From c20a4ae08b0cfc862d3d6f573a449e3228e5230a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B6rrle?= Date: Tue, 9 Jan 2024 17:13:40 +0100 Subject: [PATCH 40/68] use upper case for asi_code and imei --- custom_components/toyota/utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/custom_components/toyota/utils.py b/custom_components/toyota/utils.py index 8305d0f..aa29ab0 100644 --- a/custom_components/toyota/utils.py +++ b/custom_components/toyota/utils.py @@ -20,8 +20,8 @@ def format_vin_sensor_attributes( "Vin": vehicle_info.vin, "Contract_id": vehicle_info.contract_id, "Katashiki_code": vehicle_info.katashiki_code, - "Asi_code": vehicle_info.asi_code, - "Imei": vehicle_info.imei, + "ASI_code": vehicle_info.asi_code, + "IMEI": vehicle_info.imei, "Brand": vehicle_info.brand, "Car_line_name": vehicle_info.car_line_name, "Car_model_year": vehicle_info.car_model_year, From 6c4438af58d3dc0989078e8f01c216c255529b22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B6rrle?= Date: Tue, 9 Jan 2024 18:55:09 +0100 Subject: [PATCH 41/68] fix battery_level sensor --- custom_components/toyota/sensor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/custom_components/toyota/sensor.py b/custom_components/toyota/sensor.py index b75fc9f..b2f1112 100644 --- a/custom_components/toyota/sensor.py +++ b/custom_components/toyota/sensor.py @@ -116,7 +116,7 @@ class ToyotaSensorEntityDescription(SensorEntityDescription, ToyotaSensorEntityD device_class=None, native_unit_of_measurement=PERCENTAGE, state_class=SensorStateClass.MEASUREMENT, - value_fn=lambda vehicle: None if vehicle.dashboard is None else vehicle.dashboard.fuel_level, + value_fn=lambda vehicle: None if vehicle.dashboard is None else vehicle.dashboard.battery_level, suggested_display_precision=0, attributes_fn=lambda vehicle: None, # noqa : ARG005 ) From 8d05180f4c6d215fddfaff4b0a383d6fab2b9e2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B6rrle?= Date: Tue, 9 Jan 2024 19:07:58 +0100 Subject: [PATCH 42/68] return only true capabilities --- custom_components/toyota/utils.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/custom_components/toyota/utils.py b/custom_components/toyota/utils.py index aa29ab0..3f244cf 100644 --- a/custom_components/toyota/utils.py +++ b/custom_components/toyota/utils.py @@ -14,7 +14,7 @@ def round_number(number: int | float | None, places: int = 0) -> int | float | N def format_vin_sensor_attributes( vehicle_info: VehicleGuidModel, -) -> dict[str, Optional[Union[str, bool, dict[str, bool]]]]: +) -> dict[str, Optional[Union[str, bool, list[Optional[str]]]]]: """Format and returns vin sensor attributes.""" return { "Vin": vehicle_info.vin, @@ -38,9 +38,11 @@ def format_vin_sensor_attributes( "Fuel_type": vehicle_info.fuel_type, "Electrical_platform_code": vehicle_info.electrical_platform_code, "EV_vehicle": vehicle_info.ev_vehicle, - "Features": vehicle_info.features.dict(), - "Extended_capabilities": vehicle_info.extended_capabilities.dict(), - "Remote_service_capabilities": vehicle_info.remote_service_capabilities.dict(), + "Features": [key for key, value in vehicle_info.features.dict() if value is True], + "Extended_capabilities": [key for key, value in vehicle_info.extended_capabilities.dict() if value is True], + "Remote_service_capabilities": [ + key for key, value in vehicle_info.remote_service_capabilities.dict() if value is True + ], } From aec7cdafb34f582f86ce6a619ad26320fa2d327c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B6rrle?= Date: Tue, 9 Jan 2024 20:20:11 +0100 Subject: [PATCH 43/68] add battery_range --- custom_components/toyota/sensor.py | 40 +++++++++++++++++++ custom_components/toyota/translations/ca.json | 3 ++ custom_components/toyota/translations/da.json | 3 ++ custom_components/toyota/translations/de.json | 3 ++ custom_components/toyota/translations/en.json | 3 ++ custom_components/toyota/translations/es.json | 3 ++ custom_components/toyota/translations/fr.json | 3 ++ custom_components/toyota/translations/nb.json | 3 ++ custom_components/toyota/translations/nl.json | 3 ++ 9 files changed, 64 insertions(+) diff --git a/custom_components/toyota/sensor.py b/custom_components/toyota/sensor.py index b2f1112..1bb7875 100644 --- a/custom_components/toyota/sensor.py +++ b/custom_components/toyota/sensor.py @@ -120,6 +120,28 @@ class ToyotaSensorEntityDescription(SensorEntityDescription, ToyotaSensorEntityD suggested_display_precision=0, attributes_fn=lambda vehicle: None, # noqa : ARG005 ) +BATTERY_RANGE_ENTITY_DESCRIPTION_KM = ToyotaSensorEntityDescription( + key="battery_range", + translation_key="battery_range", + icon="mdi:map-marker-distance", + device_class=SensorDeviceClass.DISTANCE, + native_unit_of_measurement=LENGTH_KILOMETERS, + state_class=SensorStateClass.MEASUREMENT, + value_fn=lambda vehicle: None if vehicle.dashboard is None else vehicle.dashboard.battery_range, + suggested_display_precision=0, + attributes_fn=lambda vehicle: None, # noqa : ARG005 +) +BATTERY_RANGE_ENTITY_DESCRIPTION_MILES = ToyotaSensorEntityDescription( + key="battery_range", + translation_key="battery_range", + icon="mdi:map-marker-distance", + device_class=SensorDeviceClass.DISTANCE, + native_unit_of_measurement=LENGTH_MILES, + state_class=SensorStateClass.MEASUREMENT, + value_fn=lambda vehicle: None if vehicle.dashboard is None else vehicle.dashboard.battery_range, + suggested_display_precision=0, + attributes_fn=lambda vehicle: None, # noqa : ARG005 +) @dataclass @@ -224,6 +246,24 @@ async def async_setup_entry( BATTERY_LEVEL_ENTITY_DESCRIPTION, ToyotaSensor, ), + ( + entry.data[CONF_METRIC_VALUES] is True + and ( + vehicle._vehicle_info.extended_capabilities.battery_status + or vehicle._vehicle_info.ev_vehicle is True + ), + BATTERY_RANGE_ENTITY_DESCRIPTION_KM, + ToyotaSensor, + ), + ( + entry.data[CONF_METRIC_VALUES] is False + and ( + vehicle._vehicle_info.extended_capabilities.battery_status + or vehicle._vehicle_info.ev_vehicle is True + ), + BATTERY_RANGE_ENTITY_DESCRIPTION_MILES, + ToyotaSensor, + ), ( vehicle._vehicle_info.extended_capabilities.telemetry_capable, STATISTICS_ENTITY_DESCRIPTIONS_DAILY, diff --git a/custom_components/toyota/translations/ca.json b/custom_components/toyota/translations/ca.json index 010f795..4d4e1fc 100644 --- a/custom_components/toyota/translations/ca.json +++ b/custom_components/toyota/translations/ca.json @@ -38,6 +38,9 @@ "battery_level": { "name": "Battery level" }, + "battery_range": { + "name": "Battery range" + }, "current_day_statistics": { "name": "Current day statistics" }, diff --git a/custom_components/toyota/translations/da.json b/custom_components/toyota/translations/da.json index 0b47c46..fd2edc4 100644 --- a/custom_components/toyota/translations/da.json +++ b/custom_components/toyota/translations/da.json @@ -47,6 +47,9 @@ "battery_level": { "name": "Battery level" }, + "battery_range": { + "name": "Battery range" + }, "current_day_statistics": { "name": "Statistik for denne dag" }, diff --git a/custom_components/toyota/translations/de.json b/custom_components/toyota/translations/de.json index bb049f2..a5b46bf 100644 --- a/custom_components/toyota/translations/de.json +++ b/custom_components/toyota/translations/de.json @@ -47,6 +47,9 @@ "battery_level": { "name": "Batteriestand" }, + "battery_range": { + "name": "Batteriereichweite" + }, "current_day_statistics": { "name": "Aktuelle Tagesstatistiken" }, diff --git a/custom_components/toyota/translations/en.json b/custom_components/toyota/translations/en.json index 8d4d3df..60e608f 100644 --- a/custom_components/toyota/translations/en.json +++ b/custom_components/toyota/translations/en.json @@ -47,6 +47,9 @@ "battery_level": { "name": "Battery level" }, + "battery_range": { + "name": "Battery range" + }, "current_day_statistics": { "name": "Current day statistics" }, diff --git a/custom_components/toyota/translations/es.json b/custom_components/toyota/translations/es.json index 2224627..bbcadc4 100644 --- a/custom_components/toyota/translations/es.json +++ b/custom_components/toyota/translations/es.json @@ -38,6 +38,9 @@ "battery_level": { "name": "Battery level" }, + "battery_range": { + "name": "Battery range" + }, "current_day_statistics": { "name": "Estadísticas de hoy" }, diff --git a/custom_components/toyota/translations/fr.json b/custom_components/toyota/translations/fr.json index 54a5dbb..36ee00e 100644 --- a/custom_components/toyota/translations/fr.json +++ b/custom_components/toyota/translations/fr.json @@ -47,6 +47,9 @@ "battery_level": { "name": "Battery level" }, + "battery_range": { + "name": "Battery range" + }, "current_day_statistics": { "name": "Statistiques aujourd'hui" }, diff --git a/custom_components/toyota/translations/nb.json b/custom_components/toyota/translations/nb.json index d9baa94..ed6a148 100644 --- a/custom_components/toyota/translations/nb.json +++ b/custom_components/toyota/translations/nb.json @@ -47,6 +47,9 @@ "battery_level": { "name": "Battery level" }, + "battery_range": { + "name": "Battery range" + }, "current_day_statistics": { "name": "Current day statistics" }, diff --git a/custom_components/toyota/translations/nl.json b/custom_components/toyota/translations/nl.json index b971f32..2667aa4 100644 --- a/custom_components/toyota/translations/nl.json +++ b/custom_components/toyota/translations/nl.json @@ -38,6 +38,9 @@ "battery_level": { "name": "Battery level" }, + "battery_range": { + "name": "Battery range" + }, "current_day_statistics": { "name": "Current day statistics" }, From 90ded8d262e95ecb057bea2161615568faed1552 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B6rrle?= Date: Tue, 9 Jan 2024 20:36:53 +0100 Subject: [PATCH 44/68] add total_range --- custom_components/toyota/sensor.py | 42 +++++++++++++++++++ custom_components/toyota/translations/ca.json | 3 ++ custom_components/toyota/translations/da.json | 3 ++ custom_components/toyota/translations/de.json | 3 ++ custom_components/toyota/translations/en.json | 3 ++ custom_components/toyota/translations/es.json | 3 ++ custom_components/toyota/translations/fr.json | 3 ++ custom_components/toyota/translations/nb.json | 3 ++ custom_components/toyota/translations/nl.json | 3 ++ 9 files changed, 66 insertions(+) diff --git a/custom_components/toyota/sensor.py b/custom_components/toyota/sensor.py index 1bb7875..152d1fb 100644 --- a/custom_components/toyota/sensor.py +++ b/custom_components/toyota/sensor.py @@ -142,6 +142,28 @@ class ToyotaSensorEntityDescription(SensorEntityDescription, ToyotaSensorEntityD suggested_display_precision=0, attributes_fn=lambda vehicle: None, # noqa : ARG005 ) +TOTAL_RANGE_ENTITY_DESCRIPTION_KM = ToyotaSensorEntityDescription( + key="total_range", + translation_key="total_range", + icon="mdi:map-marker-distance", + device_class=SensorDeviceClass.DISTANCE, + native_unit_of_measurement=LENGTH_KILOMETERS, + state_class=SensorStateClass.MEASUREMENT, + value_fn=lambda vehicle: None if vehicle.dashboard is None else vehicle.dashboard.range, + suggested_display_precision=0, + attributes_fn=lambda vehicle: None, # noqa : ARG005 +) +TOTAL_RANGE_ENTITY_DESCRIPTION_MILES = ToyotaSensorEntityDescription( + key="total_range", + translation_key="total_range", + icon="mdi:map-marker-distance", + device_class=SensorDeviceClass.DISTANCE, + native_unit_of_measurement=LENGTH_MILES, + state_class=SensorStateClass.MEASUREMENT, + value_fn=lambda vehicle: None if vehicle.dashboard is None else vehicle.dashboard.range, + suggested_display_precision=0, + attributes_fn=lambda vehicle: None, # noqa : ARG005 +) @dataclass @@ -264,6 +286,26 @@ async def async_setup_entry( BATTERY_RANGE_ENTITY_DESCRIPTION_MILES, ToyotaSensor, ), + ( + entry.data[CONF_METRIC_VALUES] is True + and ( + vehicle._vehicle_info.extended_capabilities.battery_status + or vehicle._vehicle_info.ev_vehicle is True + ) + and vehicle._vehicle_info.extended_capabilities.fuel_range_available, + TOTAL_RANGE_ENTITY_DESCRIPTION_KM, + ToyotaSensor, + ), + ( + entry.data[CONF_METRIC_VALUES] is False + and ( + vehicle._vehicle_info.extended_capabilities.battery_status + or vehicle._vehicle_info.ev_vehicle is True + ) + and vehicle._vehicle_info.extended_capabilities.fuel_range_available, + TOTAL_RANGE_ENTITY_DESCRIPTION_MILES, + ToyotaSensor, + ), ( vehicle._vehicle_info.extended_capabilities.telemetry_capable, STATISTICS_ENTITY_DESCRIPTIONS_DAILY, diff --git a/custom_components/toyota/translations/ca.json b/custom_components/toyota/translations/ca.json index 4d4e1fc..9058c25 100644 --- a/custom_components/toyota/translations/ca.json +++ b/custom_components/toyota/translations/ca.json @@ -41,6 +41,9 @@ "battery_range": { "name": "Battery range" }, + "total_range": { + "name": "Total range" + }, "current_day_statistics": { "name": "Current day statistics" }, diff --git a/custom_components/toyota/translations/da.json b/custom_components/toyota/translations/da.json index fd2edc4..ae69f0a 100644 --- a/custom_components/toyota/translations/da.json +++ b/custom_components/toyota/translations/da.json @@ -50,6 +50,9 @@ "battery_range": { "name": "Battery range" }, + "total_range": { + "name": "Total range" + }, "current_day_statistics": { "name": "Statistik for denne dag" }, diff --git a/custom_components/toyota/translations/de.json b/custom_components/toyota/translations/de.json index a5b46bf..2460ba6 100644 --- a/custom_components/toyota/translations/de.json +++ b/custom_components/toyota/translations/de.json @@ -50,6 +50,9 @@ "battery_range": { "name": "Batteriereichweite" }, + "total_range": { + "name": "Gesamtreichweite" + }, "current_day_statistics": { "name": "Aktuelle Tagesstatistiken" }, diff --git a/custom_components/toyota/translations/en.json b/custom_components/toyota/translations/en.json index 60e608f..e589e80 100644 --- a/custom_components/toyota/translations/en.json +++ b/custom_components/toyota/translations/en.json @@ -50,6 +50,9 @@ "battery_range": { "name": "Battery range" }, + "total_range": { + "name": "Total range" + }, "current_day_statistics": { "name": "Current day statistics" }, diff --git a/custom_components/toyota/translations/es.json b/custom_components/toyota/translations/es.json index bbcadc4..e886796 100644 --- a/custom_components/toyota/translations/es.json +++ b/custom_components/toyota/translations/es.json @@ -41,6 +41,9 @@ "battery_range": { "name": "Battery range" }, + "total_range": { + "name": "Total range" + }, "current_day_statistics": { "name": "Estadísticas de hoy" }, diff --git a/custom_components/toyota/translations/fr.json b/custom_components/toyota/translations/fr.json index 36ee00e..07f9f42 100644 --- a/custom_components/toyota/translations/fr.json +++ b/custom_components/toyota/translations/fr.json @@ -50,6 +50,9 @@ "battery_range": { "name": "Battery range" }, + "total_range": { + "name": "Total range" + }, "current_day_statistics": { "name": "Statistiques aujourd'hui" }, diff --git a/custom_components/toyota/translations/nb.json b/custom_components/toyota/translations/nb.json index ed6a148..e4a438c 100644 --- a/custom_components/toyota/translations/nb.json +++ b/custom_components/toyota/translations/nb.json @@ -50,6 +50,9 @@ "battery_range": { "name": "Battery range" }, + "total_range": { + "name": "Total range" + }, "current_day_statistics": { "name": "Current day statistics" }, diff --git a/custom_components/toyota/translations/nl.json b/custom_components/toyota/translations/nl.json index 2667aa4..782d597 100644 --- a/custom_components/toyota/translations/nl.json +++ b/custom_components/toyota/translations/nl.json @@ -41,6 +41,9 @@ "battery_range": { "name": "Battery range" }, + "total_range": { + "name": "Total range" + }, "current_day_statistics": { "name": "Current day statistics" }, From 3c514bd151c9358083082eb8cb2ed1576c8eb09a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B6rrle?= Date: Tue, 9 Jan 2024 20:42:03 +0100 Subject: [PATCH 45/68] add battery_range_ac --- custom_components/toyota/sensor.py | 40 +++++++++++++++++++ custom_components/toyota/translations/ca.json | 3 ++ custom_components/toyota/translations/da.json | 3 ++ custom_components/toyota/translations/de.json | 3 ++ custom_components/toyota/translations/en.json | 3 ++ custom_components/toyota/translations/es.json | 3 ++ custom_components/toyota/translations/fr.json | 3 ++ custom_components/toyota/translations/nb.json | 3 ++ custom_components/toyota/translations/nl.json | 3 ++ 9 files changed, 64 insertions(+) diff --git a/custom_components/toyota/sensor.py b/custom_components/toyota/sensor.py index 152d1fb..3157b7b 100644 --- a/custom_components/toyota/sensor.py +++ b/custom_components/toyota/sensor.py @@ -142,6 +142,28 @@ class ToyotaSensorEntityDescription(SensorEntityDescription, ToyotaSensorEntityD suggested_display_precision=0, attributes_fn=lambda vehicle: None, # noqa : ARG005 ) +BATTERY_RANGE_AC_ENTITY_DESCRIPTION_KM = ToyotaSensorEntityDescription( + key="battery_range_ac", + translation_key="battery_range_ac", + icon="mdi:map-marker-distance", + device_class=SensorDeviceClass.DISTANCE, + native_unit_of_measurement=LENGTH_KILOMETERS, + state_class=SensorStateClass.MEASUREMENT, + value_fn=lambda vehicle: None if vehicle.dashboard is None else vehicle.dashboard.battery_range_with_ac, + suggested_display_precision=0, + attributes_fn=lambda vehicle: None, # noqa : ARG005 +) +BATTERY_RANGE_AC_ENTITY_DESCRIPTION_MILES = ToyotaSensorEntityDescription( + key="battery_range_ac", + translation_key="battery_range_ac", + icon="mdi:map-marker-distance", + device_class=SensorDeviceClass.DISTANCE, + native_unit_of_measurement=LENGTH_MILES, + state_class=SensorStateClass.MEASUREMENT, + value_fn=lambda vehicle: None if vehicle.dashboard is None else vehicle.dashboard.battery_range_with_ac, + suggested_display_precision=0, + attributes_fn=lambda vehicle: None, # noqa : ARG005 +) TOTAL_RANGE_ENTITY_DESCRIPTION_KM = ToyotaSensorEntityDescription( key="total_range", translation_key="total_range", @@ -286,6 +308,24 @@ async def async_setup_entry( BATTERY_RANGE_ENTITY_DESCRIPTION_MILES, ToyotaSensor, ), + ( + entry.data[CONF_METRIC_VALUES] is True + and ( + vehicle._vehicle_info.extended_capabilities.battery_status + or vehicle._vehicle_info.ev_vehicle is True + ), + BATTERY_RANGE_AC_ENTITY_DESCRIPTION_KM, + ToyotaSensor, + ), + ( + entry.data[CONF_METRIC_VALUES] is False + and ( + vehicle._vehicle_info.extended_capabilities.battery_status + or vehicle._vehicle_info.ev_vehicle is True + ), + BATTERY_RANGE_AC_ENTITY_DESCRIPTION_MILES, + ToyotaSensor, + ), ( entry.data[CONF_METRIC_VALUES] is True and ( diff --git a/custom_components/toyota/translations/ca.json b/custom_components/toyota/translations/ca.json index 9058c25..f28b006 100644 --- a/custom_components/toyota/translations/ca.json +++ b/custom_components/toyota/translations/ca.json @@ -41,6 +41,9 @@ "battery_range": { "name": "Battery range" }, + "battery_range_ac": { + "name": "Battery range with AC" + }, "total_range": { "name": "Total range" }, diff --git a/custom_components/toyota/translations/da.json b/custom_components/toyota/translations/da.json index ae69f0a..1ff71eb 100644 --- a/custom_components/toyota/translations/da.json +++ b/custom_components/toyota/translations/da.json @@ -50,6 +50,9 @@ "battery_range": { "name": "Battery range" }, + "battery_range_ac": { + "name": "Battery range with AC" + }, "total_range": { "name": "Total range" }, diff --git a/custom_components/toyota/translations/de.json b/custom_components/toyota/translations/de.json index 2460ba6..1457208 100644 --- a/custom_components/toyota/translations/de.json +++ b/custom_components/toyota/translations/de.json @@ -50,6 +50,9 @@ "battery_range": { "name": "Batteriereichweite" }, + "battery_range_ac": { + "name": "Batteriereichweite mit AC" + }, "total_range": { "name": "Gesamtreichweite" }, diff --git a/custom_components/toyota/translations/en.json b/custom_components/toyota/translations/en.json index e589e80..c7713c8 100644 --- a/custom_components/toyota/translations/en.json +++ b/custom_components/toyota/translations/en.json @@ -47,6 +47,9 @@ "battery_level": { "name": "Battery level" }, + "battery_range_ac": { + "name": "Battery range with AC" + }, "battery_range": { "name": "Battery range" }, diff --git a/custom_components/toyota/translations/es.json b/custom_components/toyota/translations/es.json index e886796..2847b6a 100644 --- a/custom_components/toyota/translations/es.json +++ b/custom_components/toyota/translations/es.json @@ -41,6 +41,9 @@ "battery_range": { "name": "Battery range" }, + "battery_range_ac": { + "name": "Battery range with AC" + }, "total_range": { "name": "Total range" }, diff --git a/custom_components/toyota/translations/fr.json b/custom_components/toyota/translations/fr.json index 07f9f42..a460ee6 100644 --- a/custom_components/toyota/translations/fr.json +++ b/custom_components/toyota/translations/fr.json @@ -50,6 +50,9 @@ "battery_range": { "name": "Battery range" }, + "battery_range_ac": { + "name": "Battery range with AC" + }, "total_range": { "name": "Total range" }, diff --git a/custom_components/toyota/translations/nb.json b/custom_components/toyota/translations/nb.json index e4a438c..737b852 100644 --- a/custom_components/toyota/translations/nb.json +++ b/custom_components/toyota/translations/nb.json @@ -50,6 +50,9 @@ "battery_range": { "name": "Battery range" }, + "battery_range_ac": { + "name": "Battery range with AC" + }, "total_range": { "name": "Total range" }, diff --git a/custom_components/toyota/translations/nl.json b/custom_components/toyota/translations/nl.json index 782d597..037fdfe 100644 --- a/custom_components/toyota/translations/nl.json +++ b/custom_components/toyota/translations/nl.json @@ -41,6 +41,9 @@ "battery_range": { "name": "Battery range" }, + "battery_range_ac": { + "name": "Battery range with AC" + }, "total_range": { "name": "Total range" }, From e8fc10d9b9755a0decb7caa24a0fe97db4e4d203 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B6rrle?= Date: Tue, 9 Jan 2024 20:55:31 +0100 Subject: [PATCH 46/68] fix unpacking --- custom_components/toyota/utils.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/custom_components/toyota/utils.py b/custom_components/toyota/utils.py index 3f244cf..f192277 100644 --- a/custom_components/toyota/utils.py +++ b/custom_components/toyota/utils.py @@ -38,10 +38,12 @@ def format_vin_sensor_attributes( "Fuel_type": vehicle_info.fuel_type, "Electrical_platform_code": vehicle_info.electrical_platform_code, "EV_vehicle": vehicle_info.ev_vehicle, - "Features": [key for key, value in vehicle_info.features.dict() if value is True], - "Extended_capabilities": [key for key, value in vehicle_info.extended_capabilities.dict() if value is True], + "Features": [key for key, value in vehicle_info.features.dict().items() if value is True], + "Extended_capabilities": [ + key for key, value in vehicle_info.extended_capabilities.dict().items() if value is True + ], "Remote_service_capabilities": [ - key for key, value in vehicle_info.remote_service_capabilities.dict() if value is True + key for key, value in vehicle_info.remote_service_capabilities.dict().items() if value is True ], } From d5cc6c51546194b9560837a031e1152d1d9d07d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B6rrle?= Date: Tue, 9 Jan 2024 21:06:26 +0100 Subject: [PATCH 47/68] reurn dict instead of list --- custom_components/toyota/utils.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/custom_components/toyota/utils.py b/custom_components/toyota/utils.py index f192277..203ac51 100644 --- a/custom_components/toyota/utils.py +++ b/custom_components/toyota/utils.py @@ -14,7 +14,7 @@ def round_number(number: int | float | None, places: int = 0) -> int | float | N def format_vin_sensor_attributes( vehicle_info: VehicleGuidModel, -) -> dict[str, Optional[Union[str, bool, list[Optional[str]]]]]: +) -> dict[str, Optional[Union[str, bool, dict[str, bool]]]]: """Format and returns vin sensor attributes.""" return { "Vin": vehicle_info.vin, @@ -38,13 +38,13 @@ def format_vin_sensor_attributes( "Fuel_type": vehicle_info.fuel_type, "Electrical_platform_code": vehicle_info.electrical_platform_code, "EV_vehicle": vehicle_info.ev_vehicle, - "Features": [key for key, value in vehicle_info.features.dict().items() if value is True], - "Extended_capabilities": [ - key for key, value in vehicle_info.extended_capabilities.dict().items() if value is True - ], - "Remote_service_capabilities": [ - key for key, value in vehicle_info.remote_service_capabilities.dict().items() if value is True - ], + "Features": {key: value for key, value in vehicle_info.features.dict().items() if value is True}, + "Extended_capabilities": { + key: value for key, value in vehicle_info.extended_capabilities.dict().items() if value is True + }, + "Remote_service_capabilities": { + key: value for key, value in vehicle_info.remote_service_capabilities.dict().items() if value is True + }, } From fe5455d3122a914dc420d4a91d10798fc348a1cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B6rrle?= Date: Tue, 9 Jan 2024 21:26:45 +0100 Subject: [PATCH 48/68] mask pii data in attributes --- custom_components/toyota/utils.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/custom_components/toyota/utils.py b/custom_components/toyota/utils.py index 203ac51..470dd81 100644 --- a/custom_components/toyota/utils.py +++ b/custom_components/toyota/utils.py @@ -12,16 +12,21 @@ def round_number(number: int | float | None, places: int = 0) -> int | float | N return None if number is None else round(number, places) +def mask_string(string: str) -> str: + """Mask all except the last 5 digits of a given string with asteriks.""" + return "*" * (len(string) - 5) + string[-5:] if len(string) >= 5 else "*****" + + def format_vin_sensor_attributes( vehicle_info: VehicleGuidModel, ) -> dict[str, Optional[Union[str, bool, dict[str, bool]]]]: """Format and returns vin sensor attributes.""" return { - "Vin": vehicle_info.vin, - "Contract_id": vehicle_info.contract_id, - "Katashiki_code": vehicle_info.katashiki_code, + "Vin": mask_string(vehicle_info.vin), + "Contract_id": mask_string(vehicle_info.contract_id), + "Katashiki_code": mask_string(vehicle_info.katashiki_code), "ASI_code": vehicle_info.asi_code, - "IMEI": vehicle_info.imei, + "IMEI": mask_string(vehicle_info.imei), "Brand": vehicle_info.brand, "Car_line_name": vehicle_info.car_line_name, "Car_model_year": vehicle_info.car_model_year, From 119234eb581e2e19462e11658d71d35952d76949 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B6rrle?= Date: Tue, 9 Jan 2024 21:39:54 +0100 Subject: [PATCH 49/68] round range and level values --- custom_components/toyota/sensor.py | 34 ++++++++++++++++++------------ 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/custom_components/toyota/sensor.py b/custom_components/toyota/sensor.py index 3157b7b..74d03be 100644 --- a/custom_components/toyota/sensor.py +++ b/custom_components/toyota/sensor.py @@ -24,7 +24,11 @@ from . import StatisticsData, VehicleData from .const import CONF_METRIC_VALUES, DOMAIN from .entity import ToyotaBaseEntity -from .utils import format_statistics_attributes, format_vin_sensor_attributes +from .utils import ( + format_statistics_attributes, + format_vin_sensor_attributes, + round_number, +) _LOGGER = logging.getLogger(__name__) @@ -61,7 +65,7 @@ class ToyotaSensorEntityDescription(SensorEntityDescription, ToyotaSensorEntityD device_class=SensorDeviceClass.DISTANCE, native_unit_of_measurement=LENGTH_KILOMETERS, state_class=SensorStateClass.TOTAL_INCREASING, - value_fn=lambda vehicle: None if vehicle.dashboard is None else vehicle.dashboard.odometer, + value_fn=lambda vehicle: None if vehicle.dashboard is None else round_number(vehicle.dashboard.odometer), suggested_display_precision=0, attributes_fn=lambda vehicle: None, # noqa : ARG005 ) @@ -72,7 +76,7 @@ class ToyotaSensorEntityDescription(SensorEntityDescription, ToyotaSensorEntityD device_class=SensorDeviceClass.DISTANCE, native_unit_of_measurement=LENGTH_MILES, state_class=SensorStateClass.TOTAL_INCREASING, - value_fn=lambda vehicle: None if vehicle.dashboard is None else vehicle.dashboard.odometer, + value_fn=lambda vehicle: None if vehicle.dashboard is None else round_number(vehicle.dashboard.odometer), suggested_display_precision=0, attributes_fn=lambda vehicle: None, # noqa : ARG005 ) @@ -83,7 +87,7 @@ class ToyotaSensorEntityDescription(SensorEntityDescription, ToyotaSensorEntityD device_class=None, native_unit_of_measurement=PERCENTAGE, state_class=SensorStateClass.MEASUREMENT, - value_fn=lambda vehicle: None if vehicle.dashboard is None else vehicle.dashboard.fuel_level, + value_fn=lambda vehicle: None if vehicle.dashboard is None else round_number(vehicle.dashboard.fuel_level), suggested_display_precision=0, attributes_fn=lambda vehicle: None, # noqa : ARG005 ) @@ -94,7 +98,7 @@ class ToyotaSensorEntityDescription(SensorEntityDescription, ToyotaSensorEntityD device_class=SensorDeviceClass.DISTANCE, native_unit_of_measurement=LENGTH_KILOMETERS, state_class=SensorStateClass.MEASUREMENT, - value_fn=lambda vehicle: None if vehicle.dashboard is None else vehicle.dashboard.fuel_range, + value_fn=lambda vehicle: None if vehicle.dashboard is None else round_number(vehicle.dashboard.fuel_range), suggested_display_precision=0, attributes_fn=lambda vehicle: None, # noqa : ARG005 ) @@ -105,7 +109,7 @@ class ToyotaSensorEntityDescription(SensorEntityDescription, ToyotaSensorEntityD device_class=SensorDeviceClass.DISTANCE, native_unit_of_measurement=LENGTH_MILES, state_class=SensorStateClass.MEASUREMENT, - value_fn=lambda vehicle: None if vehicle.dashboard is None else vehicle.dashboard.fuel_range, + value_fn=lambda vehicle: None if vehicle.dashboard is None else round_number(vehicle.dashboard.fuel_range), suggested_display_precision=0, attributes_fn=lambda vehicle: None, # noqa : ARG005 ) @@ -116,7 +120,7 @@ class ToyotaSensorEntityDescription(SensorEntityDescription, ToyotaSensorEntityD device_class=None, native_unit_of_measurement=PERCENTAGE, state_class=SensorStateClass.MEASUREMENT, - value_fn=lambda vehicle: None if vehicle.dashboard is None else vehicle.dashboard.battery_level, + value_fn=lambda vehicle: None if vehicle.dashboard is None else round_number(vehicle.dashboard.battery_level), suggested_display_precision=0, attributes_fn=lambda vehicle: None, # noqa : ARG005 ) @@ -127,7 +131,7 @@ class ToyotaSensorEntityDescription(SensorEntityDescription, ToyotaSensorEntityD device_class=SensorDeviceClass.DISTANCE, native_unit_of_measurement=LENGTH_KILOMETERS, state_class=SensorStateClass.MEASUREMENT, - value_fn=lambda vehicle: None if vehicle.dashboard is None else vehicle.dashboard.battery_range, + value_fn=lambda vehicle: None if vehicle.dashboard is None else round_number(vehicle.dashboard.battery_range), suggested_display_precision=0, attributes_fn=lambda vehicle: None, # noqa : ARG005 ) @@ -138,7 +142,7 @@ class ToyotaSensorEntityDescription(SensorEntityDescription, ToyotaSensorEntityD device_class=SensorDeviceClass.DISTANCE, native_unit_of_measurement=LENGTH_MILES, state_class=SensorStateClass.MEASUREMENT, - value_fn=lambda vehicle: None if vehicle.dashboard is None else vehicle.dashboard.battery_range, + value_fn=lambda vehicle: None if vehicle.dashboard is None else round_number(vehicle.dashboard.battery_range), suggested_display_precision=0, attributes_fn=lambda vehicle: None, # noqa : ARG005 ) @@ -149,7 +153,9 @@ class ToyotaSensorEntityDescription(SensorEntityDescription, ToyotaSensorEntityD device_class=SensorDeviceClass.DISTANCE, native_unit_of_measurement=LENGTH_KILOMETERS, state_class=SensorStateClass.MEASUREMENT, - value_fn=lambda vehicle: None if vehicle.dashboard is None else vehicle.dashboard.battery_range_with_ac, + value_fn=lambda vehicle: None + if vehicle.dashboard is None + else round_number(vehicle.dashboard.battery_range_with_ac), suggested_display_precision=0, attributes_fn=lambda vehicle: None, # noqa : ARG005 ) @@ -160,7 +166,9 @@ class ToyotaSensorEntityDescription(SensorEntityDescription, ToyotaSensorEntityD device_class=SensorDeviceClass.DISTANCE, native_unit_of_measurement=LENGTH_MILES, state_class=SensorStateClass.MEASUREMENT, - value_fn=lambda vehicle: None if vehicle.dashboard is None else vehicle.dashboard.battery_range_with_ac, + value_fn=lambda vehicle: None + if vehicle.dashboard is None + else round_number(vehicle.dashboard.battery_range_with_ac), suggested_display_precision=0, attributes_fn=lambda vehicle: None, # noqa : ARG005 ) @@ -171,7 +179,7 @@ class ToyotaSensorEntityDescription(SensorEntityDescription, ToyotaSensorEntityD device_class=SensorDeviceClass.DISTANCE, native_unit_of_measurement=LENGTH_KILOMETERS, state_class=SensorStateClass.MEASUREMENT, - value_fn=lambda vehicle: None if vehicle.dashboard is None else vehicle.dashboard.range, + value_fn=lambda vehicle: None if vehicle.dashboard is None else round_number(vehicle.dashboard.range), suggested_display_precision=0, attributes_fn=lambda vehicle: None, # noqa : ARG005 ) @@ -182,7 +190,7 @@ class ToyotaSensorEntityDescription(SensorEntityDescription, ToyotaSensorEntityD device_class=SensorDeviceClass.DISTANCE, native_unit_of_measurement=LENGTH_MILES, state_class=SensorStateClass.MEASUREMENT, - value_fn=lambda vehicle: None if vehicle.dashboard is None else vehicle.dashboard.range, + value_fn=lambda vehicle: None if vehicle.dashboard is None else round_number(vehicle.dashboard.range), suggested_display_precision=0, attributes_fn=lambda vehicle: None, # noqa : ARG005 ) From 8df5b438c7ebb96c346f1c47d6bd789641467f52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B6rrle?= Date: Tue, 9 Jan 2024 21:53:07 +0100 Subject: [PATCH 50/68] bump minimum required mytoyota version to 1.1.3 --- custom_components/toyota/manifest.json | 2 +- poetry.lock | 20 +++++++++++++++----- pyproject.toml | 2 +- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/custom_components/toyota/manifest.json b/custom_components/toyota/manifest.json index 3347d37..798ff70 100644 --- a/custom_components/toyota/manifest.json +++ b/custom_components/toyota/manifest.json @@ -7,6 +7,6 @@ "documentation": "https://github.com/DurgNomis-drol/ha_toyota", "iot_class": "cloud_polling", "issue_tracker": "https://github.com/DurgNomis-drol/ha_toyota/issues", - "requirements": ["mytoyota>=1.1.2", "arrow"], + "requirements": ["mytoyota>=1.1.3", "arrow"], "version": "v2.0.0" } diff --git a/poetry.lock b/poetry.lock index 46a78fb..98e159a 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.7.0 and should not be changed by hand. [[package]] name = "aiohttp" @@ -1216,13 +1216,13 @@ files = [ [[package]] name = "mytoyota" -version = "1.1.2" +version = "1.1.3" description = "Python client for Toyota Connected Services." optional = false python-versions = ">=3.8.1,<4.0.0" files = [ - {file = "mytoyota-1.1.2-py3-none-any.whl", hash = "sha256:7e9fc9ab5c0502afad09c62ed829cbba08fd819ee14cc0273c60851430293819"}, - {file = "mytoyota-1.1.2.tar.gz", hash = "sha256:388d6d0485b58610063628ecd3d384fe1a67d0dd0e016143f1ce2683b4824f05"}, + {file = "mytoyota-1.1.3-py3-none-any.whl", hash = "sha256:c0c74e857403fc47245ff5bfb71c7d6272294e68db8b2cbf099af88279f50151"}, + {file = "mytoyota-1.1.3.tar.gz", hash = "sha256:e3fd3308fefe521dc50b24354fa930cac6ae783c8f14a67e030dccfc5d3e54b8"}, ] [package.dependencies] @@ -1527,6 +1527,7 @@ files = [ {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, + {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, @@ -1534,8 +1535,15 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, + {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, + {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, + {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, + {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, @@ -1552,6 +1560,7 @@ files = [ {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, + {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, @@ -1559,6 +1568,7 @@ files = [ {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, + {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, @@ -2028,4 +2038,4 @@ files = [ [metadata] lock-version = "2.0" python-versions = "^3.11" -content-hash = "395ee953edfd07911decfdf933e028139cda281e70e97fe94cf79b3f29a962a1" +content-hash = "8c92fee6bd3b9867ea5b08955533abd41741b6ad204e24f692095c57eb46a5f7" diff --git a/pyproject.toml b/pyproject.toml index 9903a40..3f9983c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,7 +8,7 @@ license = "MIT" [tool.poetry.dependencies] python = "^3.11" homeassistant = "^2023.11" -mytoyota = "^1.1.2" +mytoyota = "^1.1.3" arrow = "^1.1.1" [tool.poetry.dev-dependencies] From fd03a9761123a50d99992385e593449c8750b411 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B6rrle?= Date: Tue, 9 Jan 2024 22:05:04 +0100 Subject: [PATCH 51/68] reduce line-length --- custom_components/toyota/__init__.py | 8 +++- custom_components/toyota/binary_sensor.py | 4 +- custom_components/toyota/config_flow.py | 4 +- custom_components/toyota/sensor.py | 51 +++++++++++++++++------ custom_components/toyota/utils.py | 24 ++++++++--- pyproject.toml | 2 +- 6 files changed, 69 insertions(+), 24 deletions(-) diff --git a/custom_components/toyota/__init__.py b/custom_components/toyota/__init__.py index 0897125..3f117bd 100644 --- a/custom_components/toyota/__init__.py +++ b/custom_components/toyota/__init__.py @@ -74,7 +74,9 @@ async def async_get_vehicle_data() -> Optional[list[VehicleData]]: if vehicles is not None: for vehicle in vehicles: await vehicle.update() - vehicle_data = VehicleData(data=vehicle, statistics=None, metric_values=use_metric_values) + vehicle_data = VehicleData( + data=vehicle, statistics=None, metric_values=use_metric_values + ) if vehicle.vin is not None: # Use parallel request to get car statistics. @@ -126,7 +128,9 @@ async def async_get_vehicle_data() -> Optional[list[VehicleData]]: asyncioexceptions.TimeoutError, httpx.ReadTimeout, ) as ex: - raise UpdateFailed("Update canceled! Toyota's API was too slow to respond. Will try again later...") from ex + raise UpdateFailed( + "Update canceled! Toyota's API was too slow to respond. Will try again later..." + ) from ex return None coordinator = DataUpdateCoordinator( diff --git a/custom_components/toyota/binary_sensor.py b/custom_components/toyota/binary_sensor.py index c23c012..9a65f4e 100644 --- a/custom_components/toyota/binary_sensor.py +++ b/custom_components/toyota/binary_sensor.py @@ -33,7 +33,9 @@ class ToyotaBinaryEntityDescriptionMixin: @dataclass -class ToyotaBinaryEntityDescription(BinarySensorEntityDescription, ToyotaBinaryEntityDescriptionMixin): +class ToyotaBinaryEntityDescription( + BinarySensorEntityDescription, ToyotaBinaryEntityDescriptionMixin +): """Describes a Toyota binary entity.""" diff --git a/custom_components/toyota/config_flow.py b/custom_components/toyota/config_flow.py index 727bcde..d498949 100644 --- a/custom_components/toyota/config_flow.py +++ b/custom_components/toyota/config_flow.py @@ -80,4 +80,6 @@ async def async_step_init(self, user_input=None) -> FlowResult: """Manage the options.""" if user_input is not None: self.options.update(user_input) - return self.async_create_entry(title=self.config_entry.data.get(CONF_EMAIL), data=self.options) + return self.async_create_entry( + title=self.config_entry.data.get(CONF_EMAIL), data=self.options + ) diff --git a/custom_components/toyota/sensor.py b/custom_components/toyota/sensor.py index 74d03be..41f9e7f 100644 --- a/custom_components/toyota/sensor.py +++ b/custom_components/toyota/sensor.py @@ -65,7 +65,9 @@ class ToyotaSensorEntityDescription(SensorEntityDescription, ToyotaSensorEntityD device_class=SensorDeviceClass.DISTANCE, native_unit_of_measurement=LENGTH_KILOMETERS, state_class=SensorStateClass.TOTAL_INCREASING, - value_fn=lambda vehicle: None if vehicle.dashboard is None else round_number(vehicle.dashboard.odometer), + value_fn=lambda vehicle: None + if vehicle.dashboard is None + else round_number(vehicle.dashboard.odometer), suggested_display_precision=0, attributes_fn=lambda vehicle: None, # noqa : ARG005 ) @@ -76,7 +78,9 @@ class ToyotaSensorEntityDescription(SensorEntityDescription, ToyotaSensorEntityD device_class=SensorDeviceClass.DISTANCE, native_unit_of_measurement=LENGTH_MILES, state_class=SensorStateClass.TOTAL_INCREASING, - value_fn=lambda vehicle: None if vehicle.dashboard is None else round_number(vehicle.dashboard.odometer), + value_fn=lambda vehicle: None + if vehicle.dashboard is None + else round_number(vehicle.dashboard.odometer), suggested_display_precision=0, attributes_fn=lambda vehicle: None, # noqa : ARG005 ) @@ -87,7 +91,9 @@ class ToyotaSensorEntityDescription(SensorEntityDescription, ToyotaSensorEntityD device_class=None, native_unit_of_measurement=PERCENTAGE, state_class=SensorStateClass.MEASUREMENT, - value_fn=lambda vehicle: None if vehicle.dashboard is None else round_number(vehicle.dashboard.fuel_level), + value_fn=lambda vehicle: None + if vehicle.dashboard is None + else round_number(vehicle.dashboard.fuel_level), suggested_display_precision=0, attributes_fn=lambda vehicle: None, # noqa : ARG005 ) @@ -98,7 +104,9 @@ class ToyotaSensorEntityDescription(SensorEntityDescription, ToyotaSensorEntityD device_class=SensorDeviceClass.DISTANCE, native_unit_of_measurement=LENGTH_KILOMETERS, state_class=SensorStateClass.MEASUREMENT, - value_fn=lambda vehicle: None if vehicle.dashboard is None else round_number(vehicle.dashboard.fuel_range), + value_fn=lambda vehicle: None + if vehicle.dashboard is None + else round_number(vehicle.dashboard.fuel_range), suggested_display_precision=0, attributes_fn=lambda vehicle: None, # noqa : ARG005 ) @@ -109,7 +117,9 @@ class ToyotaSensorEntityDescription(SensorEntityDescription, ToyotaSensorEntityD device_class=SensorDeviceClass.DISTANCE, native_unit_of_measurement=LENGTH_MILES, state_class=SensorStateClass.MEASUREMENT, - value_fn=lambda vehicle: None if vehicle.dashboard is None else round_number(vehicle.dashboard.fuel_range), + value_fn=lambda vehicle: None + if vehicle.dashboard is None + else round_number(vehicle.dashboard.fuel_range), suggested_display_precision=0, attributes_fn=lambda vehicle: None, # noqa : ARG005 ) @@ -120,7 +130,9 @@ class ToyotaSensorEntityDescription(SensorEntityDescription, ToyotaSensorEntityD device_class=None, native_unit_of_measurement=PERCENTAGE, state_class=SensorStateClass.MEASUREMENT, - value_fn=lambda vehicle: None if vehicle.dashboard is None else round_number(vehicle.dashboard.battery_level), + value_fn=lambda vehicle: None + if vehicle.dashboard is None + else round_number(vehicle.dashboard.battery_level), suggested_display_precision=0, attributes_fn=lambda vehicle: None, # noqa : ARG005 ) @@ -131,7 +143,9 @@ class ToyotaSensorEntityDescription(SensorEntityDescription, ToyotaSensorEntityD device_class=SensorDeviceClass.DISTANCE, native_unit_of_measurement=LENGTH_KILOMETERS, state_class=SensorStateClass.MEASUREMENT, - value_fn=lambda vehicle: None if vehicle.dashboard is None else round_number(vehicle.dashboard.battery_range), + value_fn=lambda vehicle: None + if vehicle.dashboard is None + else round_number(vehicle.dashboard.battery_range), suggested_display_precision=0, attributes_fn=lambda vehicle: None, # noqa : ARG005 ) @@ -142,7 +156,9 @@ class ToyotaSensorEntityDescription(SensorEntityDescription, ToyotaSensorEntityD device_class=SensorDeviceClass.DISTANCE, native_unit_of_measurement=LENGTH_MILES, state_class=SensorStateClass.MEASUREMENT, - value_fn=lambda vehicle: None if vehicle.dashboard is None else round_number(vehicle.dashboard.battery_range), + value_fn=lambda vehicle: None + if vehicle.dashboard is None + else round_number(vehicle.dashboard.battery_range), suggested_display_precision=0, attributes_fn=lambda vehicle: None, # noqa : ARG005 ) @@ -179,7 +195,9 @@ class ToyotaSensorEntityDescription(SensorEntityDescription, ToyotaSensorEntityD device_class=SensorDeviceClass.DISTANCE, native_unit_of_measurement=LENGTH_KILOMETERS, state_class=SensorStateClass.MEASUREMENT, - value_fn=lambda vehicle: None if vehicle.dashboard is None else round_number(vehicle.dashboard.range), + value_fn=lambda vehicle: None + if vehicle.dashboard is None + else round_number(vehicle.dashboard.range), suggested_display_precision=0, attributes_fn=lambda vehicle: None, # noqa : ARG005 ) @@ -190,7 +208,9 @@ class ToyotaSensorEntityDescription(SensorEntityDescription, ToyotaSensorEntityD device_class=SensorDeviceClass.DISTANCE, native_unit_of_measurement=LENGTH_MILES, state_class=SensorStateClass.MEASUREMENT, - value_fn=lambda vehicle: None if vehicle.dashboard is None else round_number(vehicle.dashboard.range), + value_fn=lambda vehicle: None + if vehicle.dashboard is None + else round_number(vehicle.dashboard.range), suggested_display_precision=0, attributes_fn=lambda vehicle: None, # noqa : ARG005 ) @@ -204,7 +224,9 @@ class ToyotaStatisticsSensorEntityDescriptionMixin: @dataclass -class ToyotaStatisticsSensorEntityDescription(SensorEntityDescription, ToyotaStatisticsSensorEntityDescriptionMixin): +class ToyotaStatisticsSensorEntityDescription( + SensorEntityDescription, ToyotaStatisticsSensorEntityDescriptionMixin +): """Describes a Toyota statistics sensor entity.""" @@ -294,7 +316,8 @@ async def async_setup_entry( ToyotaSensor, ), ( - vehicle._vehicle_info.extended_capabilities.battery_status or vehicle._vehicle_info.ev_vehicle is True, + vehicle._vehicle_info.extended_capabilities.battery_status + or vehicle._vehicle_info.ev_vehicle is True, BATTERY_LEVEL_ENTITY_DESCRIPTION, ToyotaSensor, ), @@ -419,7 +442,9 @@ def __init__( """Initialise the ToyotaStatisticsSensor class.""" super().__init__(coordinator, entry_id, vehicle_index, description) self.period: Literal["day", "week", "month", "year"] = description.period - self._attr_native_unit_of_measurement = LENGTH_KILOMETERS if self.metric_values else LENGTH_MILES + self._attr_native_unit_of_measurement = ( + LENGTH_KILOMETERS if self.metric_values else LENGTH_MILES + ) @property def native_value(self) -> StateType: diff --git a/custom_components/toyota/utils.py b/custom_components/toyota/utils.py index 470dd81..c34679d 100644 --- a/custom_components/toyota/utils.py +++ b/custom_components/toyota/utils.py @@ -43,17 +43,25 @@ def format_vin_sensor_attributes( "Fuel_type": vehicle_info.fuel_type, "Electrical_platform_code": vehicle_info.electrical_platform_code, "EV_vehicle": vehicle_info.ev_vehicle, - "Features": {key: value for key, value in vehicle_info.features.dict().items() if value is True}, + "Features": { + key: value for key, value in vehicle_info.features.dict().items() if value is True + }, "Extended_capabilities": { - key: value for key, value in vehicle_info.extended_capabilities.dict().items() if value is True + key: value + for key, value in vehicle_info.extended_capabilities.dict().items() + if value is True }, "Remote_service_capabilities": { - key: value for key, value in vehicle_info.remote_service_capabilities.dict().items() if value is True + key: value + for key, value in vehicle_info.remote_service_capabilities.dict().items() + if value is True }, } -def format_statistics_attributes(statistics: Summary, vehicle_info: VehicleGuidModel) -> dict[str, Optional[str]]: +def format_statistics_attributes( + statistics: Summary, vehicle_info: VehicleGuidModel +) -> dict[str, Optional[str]]: """Format and returns statistics attributes.""" attr = { "Average_speed": round(statistics.average_speed, 1) if statistics.average_speed else None, @@ -61,12 +69,16 @@ def format_statistics_attributes(statistics: Summary, vehicle_info: VehicleGuidM } if vehicle_info.fuel_type is not None: - attr["Fuel_consumed"] = round(statistics.fuel_consumed, 3) if statistics.fuel_consumed else None + attr["Fuel_consumed"] = ( + round(statistics.fuel_consumed, 3) if statistics.fuel_consumed else None + ) if vehicle_info.electrical_platform_code == 15 or vehicle_info.ev_vehicle is True: attr.update( { - "EV_distance": round(statistics.ev_distance, 1) if statistics.ev_distance else None, + "EV_distance": round(statistics.ev_distance, 1) + if statistics.ev_distance + else None, "EV_duration": str(statistics.ev_duration), } ) diff --git a/pyproject.toml b/pyproject.toml index 3f9983c..28c4ec3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -47,7 +47,7 @@ select = [ "I" ] extend-ignore = ["PLR2004", "D203", "D213", "COM812"] -line-length = 120 +line-length = 99 fix = true [build-system] From 2780ab1eaa225ba6695d3e168a7cfd8c3a18cbb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B6rrle?= Date: Wed, 10 Jan 2024 13:32:46 +0100 Subject: [PATCH 52/68] no need for masking Katashiki_code --- custom_components/toyota/utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/custom_components/toyota/utils.py b/custom_components/toyota/utils.py index c34679d..787c278 100644 --- a/custom_components/toyota/utils.py +++ b/custom_components/toyota/utils.py @@ -24,9 +24,9 @@ def format_vin_sensor_attributes( return { "Vin": mask_string(vehicle_info.vin), "Contract_id": mask_string(vehicle_info.contract_id), - "Katashiki_code": mask_string(vehicle_info.katashiki_code), - "ASI_code": vehicle_info.asi_code, "IMEI": mask_string(vehicle_info.imei), + "Katashiki_code": vehicle_info.katashiki_code, + "ASI_code": vehicle_info.asi_code, "Brand": vehicle_info.brand, "Car_line_name": vehicle_info.car_line_name, "Car_model_year": vehicle_info.car_model_year, From e1919aa0aa9070df1e2fdc6e197f9fdbd2cb135d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B6rrle?= Date: Wed, 10 Jan 2024 13:38:06 +0100 Subject: [PATCH 53/68] add duration and distance to summary attributes --- custom_components/toyota/utils.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/custom_components/toyota/utils.py b/custom_components/toyota/utils.py index 787c278..8f1f879 100644 --- a/custom_components/toyota/utils.py +++ b/custom_components/toyota/utils.py @@ -66,6 +66,8 @@ def format_statistics_attributes( attr = { "Average_speed": round(statistics.average_speed, 1) if statistics.average_speed else None, "Countries": statistics.countries or [], + "Distance": round(statistics.distance, 1) if statistics.distance else None, + "Duration": str(statistics.duration) if statistics.duration else None, } if vehicle_info.fuel_type is not None: @@ -73,13 +75,13 @@ def format_statistics_attributes( round(statistics.fuel_consumed, 3) if statistics.fuel_consumed else None ) - if vehicle_info.electrical_platform_code == 15 or vehicle_info.ev_vehicle is True: + if vehicle_info.extended_capabilities.hybrid_pulse or vehicle_info.ev_vehicle is True: attr.update( { "EV_distance": round(statistics.ev_distance, 1) if statistics.ev_distance else None, - "EV_duration": str(statistics.ev_duration), + "EV_duration": str(statistics.ev_duration) if statistics.ev_duration else None, } ) From 2d59460dfaa8e2ed65da854a116a70e1c230ddca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B6rrle?= Date: Wed, 10 Jan 2024 15:49:23 +0100 Subject: [PATCH 54/68] remove redundant vin information in attributes --- custom_components/toyota/utils.py | 1 - 1 file changed, 1 deletion(-) diff --git a/custom_components/toyota/utils.py b/custom_components/toyota/utils.py index 8f1f879..a347545 100644 --- a/custom_components/toyota/utils.py +++ b/custom_components/toyota/utils.py @@ -22,7 +22,6 @@ def format_vin_sensor_attributes( ) -> dict[str, Optional[Union[str, bool, dict[str, bool]]]]: """Format and returns vin sensor attributes.""" return { - "Vin": mask_string(vehicle_info.vin), "Contract_id": mask_string(vehicle_info.contract_id), "IMEI": mask_string(vehicle_info.imei), "Katashiki_code": vehicle_info.katashiki_code, From 3d531acd8f01481d352daa03126a01ca4e2362a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B6rrle?= Date: Wed, 10 Jan 2024 21:47:44 +0100 Subject: [PATCH 55/68] remove redundant information --- custom_components/toyota/utils.py | 1 - 1 file changed, 1 deletion(-) diff --git a/custom_components/toyota/utils.py b/custom_components/toyota/utils.py index a347545..712d8ad 100644 --- a/custom_components/toyota/utils.py +++ b/custom_components/toyota/utils.py @@ -65,7 +65,6 @@ def format_statistics_attributes( attr = { "Average_speed": round(statistics.average_speed, 1) if statistics.average_speed else None, "Countries": statistics.countries or [], - "Distance": round(statistics.distance, 1) if statistics.distance else None, "Duration": str(statistics.duration) if statistics.duration else None, } From c9427fd77fa9e407735b5ab4a4f83f495d57ec50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B6rrle?= Date: Wed, 10 Jan 2024 21:49:08 +0100 Subject: [PATCH 56/68] rename fuel consumption --- custom_components/toyota/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/custom_components/toyota/utils.py b/custom_components/toyota/utils.py index 712d8ad..2aba3f8 100644 --- a/custom_components/toyota/utils.py +++ b/custom_components/toyota/utils.py @@ -69,7 +69,7 @@ def format_statistics_attributes( } if vehicle_info.fuel_type is not None: - attr["Fuel_consumed"] = ( + attr["Total_fuel_consumed"] = ( round(statistics.fuel_consumed, 3) if statistics.fuel_consumed else None ) From b41eb6966d65f59d42ab92ced7c13042de57c7cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B6rrle?= Date: Thu, 11 Jan 2024 14:32:06 +0100 Subject: [PATCH 57/68] bump minimum required mytoyota version to 1.2.0 --- custom_components/toyota/manifest.json | 2 +- poetry.lock | 20 +++++--------------- pyproject.toml | 2 +- 3 files changed, 7 insertions(+), 17 deletions(-) diff --git a/custom_components/toyota/manifest.json b/custom_components/toyota/manifest.json index 798ff70..9dbe10a 100644 --- a/custom_components/toyota/manifest.json +++ b/custom_components/toyota/manifest.json @@ -7,6 +7,6 @@ "documentation": "https://github.com/DurgNomis-drol/ha_toyota", "iot_class": "cloud_polling", "issue_tracker": "https://github.com/DurgNomis-drol/ha_toyota/issues", - "requirements": ["mytoyota>=1.1.3", "arrow"], + "requirements": ["mytoyota>=1.2.0", "arrow"], "version": "v2.0.0" } diff --git a/poetry.lock b/poetry.lock index 98e159a..6c3138f 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.7.0 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand. [[package]] name = "aiohttp" @@ -1216,13 +1216,13 @@ files = [ [[package]] name = "mytoyota" -version = "1.1.3" +version = "1.2.0" description = "Python client for Toyota Connected Services." optional = false python-versions = ">=3.8.1,<4.0.0" files = [ - {file = "mytoyota-1.1.3-py3-none-any.whl", hash = "sha256:c0c74e857403fc47245ff5bfb71c7d6272294e68db8b2cbf099af88279f50151"}, - {file = "mytoyota-1.1.3.tar.gz", hash = "sha256:e3fd3308fefe521dc50b24354fa930cac6ae783c8f14a67e030dccfc5d3e54b8"}, + {file = "mytoyota-1.2.0-py3-none-any.whl", hash = "sha256:c6e6228c557665adf71bf8171402a60489a96d14e422b145bca97d223f78af2e"}, + {file = "mytoyota-1.2.0.tar.gz", hash = "sha256:a6a1b62af06ed5ada7ca5df6ffc380917405c7679cfcc849a5a7752db7915180"}, ] [package.dependencies] @@ -1527,7 +1527,6 @@ files = [ {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, - {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, @@ -1535,15 +1534,8 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, - {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, - {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, - {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, - {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, - {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, - {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, - {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, @@ -1560,7 +1552,6 @@ files = [ {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, - {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, @@ -1568,7 +1559,6 @@ files = [ {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, - {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, @@ -2038,4 +2028,4 @@ files = [ [metadata] lock-version = "2.0" python-versions = "^3.11" -content-hash = "8c92fee6bd3b9867ea5b08955533abd41741b6ad204e24f692095c57eb46a5f7" +content-hash = "272f8ece140ed8bc2593d76d4b1e4557ea8118ec6bddfb8e0a97fa29de7e541d" diff --git a/pyproject.toml b/pyproject.toml index 28c4ec3..a3bfc6d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,7 +8,7 @@ license = "MIT" [tool.poetry.dependencies] python = "^3.11" homeassistant = "^2023.11" -mytoyota = "^1.1.3" +mytoyota = "^1.2.0" arrow = "^1.1.1" [tool.poetry.dev-dependencies] From a8283c73442cf606cf8b066b470b989e080b78d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B6rrle?= Date: Thu, 11 Jan 2024 14:34:24 +0100 Subject: [PATCH 58/68] add average_fuel_consumed to vin sensor attributes --- custom_components/toyota/utils.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/custom_components/toyota/utils.py b/custom_components/toyota/utils.py index 2aba3f8..413bbc9 100644 --- a/custom_components/toyota/utils.py +++ b/custom_components/toyota/utils.py @@ -72,6 +72,11 @@ def format_statistics_attributes( attr["Total_fuel_consumed"] = ( round(statistics.fuel_consumed, 3) if statistics.fuel_consumed else None ) + attr["Average_fuel_consumed"] = ( + round(statistics.average_fuel_consumed, 3) + if statistics.average_fuel_consumed + else None + ) if vehicle_info.extended_capabilities.hybrid_pulse or vehicle_info.ev_vehicle is True: attr.update( From 3619f37e092931b4cb4ec8d366062ba94d78db42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B6rrle?= Date: Thu, 11 Jan 2024 14:39:56 +0100 Subject: [PATCH 59/68] use dictionary merging --- custom_components/toyota/utils.py | 36 +++++++++++++------------------ 1 file changed, 15 insertions(+), 21 deletions(-) diff --git a/custom_components/toyota/utils.py b/custom_components/toyota/utils.py index 413bbc9..6130867 100644 --- a/custom_components/toyota/utils.py +++ b/custom_components/toyota/utils.py @@ -69,30 +69,24 @@ def format_statistics_attributes( } if vehicle_info.fuel_type is not None: - attr["Total_fuel_consumed"] = ( - round(statistics.fuel_consumed, 3) if statistics.fuel_consumed else None - ) - attr["Average_fuel_consumed"] = ( - round(statistics.average_fuel_consumed, 3) + attr |= { + "Total_fuel_consumed": round(statistics.fuel_consumed, 3) + if statistics.fuel_consumed + else None, + "Average_fuel_consumed": round(statistics.average_fuel_consumed, 3) if statistics.average_fuel_consumed - else None - ) + else None, + } if vehicle_info.extended_capabilities.hybrid_pulse or vehicle_info.ev_vehicle is True: - attr.update( - { - "EV_distance": round(statistics.ev_distance, 1) - if statistics.ev_distance - else None, - "EV_duration": str(statistics.ev_duration) if statistics.ev_duration else None, - } - ) - - attr.update( - { - "From_date": statistics.from_date.strftime("%Y-%m-%d"), - "To_date": statistics.to_date.strftime("%Y-%m-%d"), + attr |= { + "EV_distance": round(statistics.ev_distance, 1) if statistics.ev_distance else None, + "EV_duration": str(statistics.ev_duration) if statistics.ev_duration else None, } - ) + + attr |= { + "From_date": statistics.from_date.strftime("%Y-%m-%d"), + "To_date": statistics.to_date.strftime("%Y-%m-%d"), + } return attr From 0daba1d55383060c961b5a7579fb4581f6c5653c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B6rrle?= Date: Thu, 11 Jan 2024 15:01:40 +0100 Subject: [PATCH 60/68] Make use of new helper functions for statistics --- custom_components/toyota/__init__.py | 35 +++++++--------------------- 1 file changed, 9 insertions(+), 26 deletions(-) diff --git a/custom_components/toyota/__init__.py b/custom_components/toyota/__init__.py index 3f117bd..997cf74 100644 --- a/custom_components/toyota/__init__.py +++ b/custom_components/toyota/__init__.py @@ -9,7 +9,6 @@ import httpcore import httpx -from arrow import Arrow from homeassistant.config_entries import ConfigEntry from homeassistant.const import CONF_EMAIL, CONF_PASSWORD from homeassistant.core import HomeAssistant @@ -17,7 +16,7 @@ from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed from mytoyota import MyT from mytoyota.exceptions import ToyotaApiError, ToyotaInternalError, ToyotaLoginError -from mytoyota.models.summary import Summary, SummaryType +from mytoyota.models.summary import Summary from mytoyota.models.vehicle import Vehicle from .const import CONF_METRIC_VALUES, DOMAIN, PLATFORMS, STARTUP_MESSAGE @@ -81,33 +80,17 @@ async def async_get_vehicle_data() -> Optional[list[VehicleData]]: if vehicle.vin is not None: # Use parallel request to get car statistics. driving_statistics = await asyncio.gather( - vehicle.get_summary( - Arrow.now().date(), - Arrow.now().date(), - summary_type=SummaryType.DAILY, - ), - vehicle.get_summary( - Arrow.now().floor("week").date(), - Arrow.now().date(), - summary_type=SummaryType.WEEKLY, - ), - vehicle.get_summary( - Arrow.now().floor("month").date(), - Arrow.now().date(), - summary_type=SummaryType.MONTHLY, - ), - vehicle.get_summary( - Arrow.now().floor("year").date(), - Arrow.now().date(), - summary_type=SummaryType.YEARLY, - ), + vehicle.get_current_day_summary(), + vehicle.get_current_week_summary(), + vehicle.get_current_month_summary(), + vehicle.get_current_year_summary(), ) vehicle_data["statistics"] = StatisticsData( - day=next(iter(driving_statistics[0] or []), None), - week=next(iter(driving_statistics[1] or []), None), - month=next(iter(driving_statistics[2] or []), None), - year=next(iter(driving_statistics[3] or []), None), + day=driving_statistics[0], + week=driving_statistics[1], + month=driving_statistics[2], + year=driving_statistics[3], ) vehicle_informations.append(vehicle_data) From 279c9feac202e47438df8992c6e7497142f0fbb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B6rrle?= Date: Thu, 11 Jan 2024 16:17:09 +0100 Subject: [PATCH 61/68] Update readme --- README.md | 107 ++++++++++++++++++++++++------------------------------ 1 file changed, 47 insertions(+), 60 deletions(-) diff --git a/README.md b/README.md index 689c74d..56cd3e4 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ ## About This is a custom integration the retrieves' data from the -Toyota EU MyT API and makes them available in Home Assistant as different types of sensors. +Toyota EU MyToyota ctpa-oneapi API and makes them available in Home Assistant as different types of sensors. As there is no official API from Toyota, I will try my best to keep it working, but there are no promises. @@ -30,47 +30,42 @@ See [here](https://github.com/widewing/ha-toyota-na) for North America. ### Overview -- Numberplate and starter battery sensors +- VIN (Vehicle Identification Number) sensor - Fuel, battery and odometer information -- Current week, month and year statistics. -- HVAC, Window and lights sensors +- Current day, week, month and year statistics. - Door and door lock sensors, including hood and trunk sensor. -- Is key in car and over all status sensor. ### Binary sensor(s) -|
Name
| Description | -| --------------------------------------- | ----------------------------------------------------------------------------------- | -| `binary_sensor.corolla_hood` | If the hood is open of not. | -| `binary_sensor.corolla_*_defogger` | Defogger is on sensor, one is created for front and rear if available | -| `binary_sensor.corolla_*_door` | Door sensor, one is created for each door and trunk. | -| `binary_sensor.corolla_*_lock` | Lock sensor, one is created for each door and trunk. | -| `binary_sensor.corolla_*_lights` | Light sensor, one is created for front, back and hazard lights. | -| `binary_sensor.corolla_over_all_status` | Over all status of the vehicle, if warning is true for a sensor, this will show it. | -| `binary_sensor.corolla_key_in_car` | If key is in the car. | -| `binary_sensor.corolla_*_window` | Window sensor, one is created for window. | +|
Name
| Description | +| ---------------------------------------- | ----------------------------------------------------- | +| `binary_sensor._hood` | If the hood is open of not. | +| `binary_sensor._*_door` | Door sensors, one is created for each door and trunk. | +| `binary_sensor._*_lock` | Lock sensors, one is created for each door and trunk. | +| `binary_sensor._*_window` | Window sensors, one is created for window. | ### Device tracker(s) -|
Name
| Description | -| ----------------------------------- | ---------------------------------- | -| `device_tracker.corolla` | Shows you last parked information. | +|
Name
| Description | +| ----------------------------------- | ----------------------------------- | +| `device_tracker.` | Shows you last parking information. | ### Sensor(s) -|
Name
| Description | -| ------------------------------------ | ------------------------------------------------------------------------ | -| `sensor.corolla` | Static data about your car. | -| `sensor.corolla_ev_battery_status` | EV battery information | -| `sensor.corolla_ev_remaining_charge` | EV battery remaining charge (in per cent of full capacity) | -| `sensor.corolla_fuel_tank` | Fuel tank information. | -| `sensor.corolla_hvac` | HVAC sensor showing current and target temperature, including other data | -| `sensor.corolla_odometer` | Odometer information. | -| `sensor.corolla_range` | Remaining range sensor | -| `sensor.aygo_starter_battery` | Starter battery health. | -| `sensor.corolla_current_week_stats` | Statistics for current week. | -| `sensor.corolla_current_month_stats` | Statistics for current month. | -| `sensor.corolla_current_year_stats` | Statistics for current year. | +|
Name
| Description | +| -------------------------------------------- | -------------------------------------------------- | +| `sensor._vin` | Static data about your car. | +| `sensor._odometer` | Odometer information. | +| `sensor._fuel_level` | Fuel level information. | +| `sensor._fuel_range` | Fuel range information. | +| `sensor._battery_level` | Battery level information. | +| `sensor._battery_range` | Battery range information. | +| `sensor._battery_range_ac` | Battery range information when AC is on. | +| `sensor._total_range` | Information about combined fuel and battery range. | +| `sensor._current_day_stats` | Statistics for current day. | +| `sensor._current_week_stats` | Statistics for current week. | +| `sensor._current_month_stats` | Statistics for current month. | +| `sensor._current_year_stats` | Statistics for current year. | ### Statistics sensors @@ -83,34 +78,26 @@ Due to this, this integration will list sensors as unavailable when no data is a **Disclaimer: Attributes available depends on your car model and year.** -All values will show zero if no data is available for the periode. - -| Attribute | Description | -| ------------------------------------ | --------------------------------------------------------------------------------------------------- | -| `Highway_distance` | Distance driven on Highway/Motorway. | -| `Highway_percentage` | Percentage driven on Highway/Motorway. | -| `Number_of_trips` | Number of trips performed. A trip is started when you start the engine. | -| `Number_of_night_trips` | Number of trips performed at night. | -| `Total_driving_time` | Total time driven. | -| `Average_speed` | Average speed. | -| `Max_speed` | Max speed achieved. | -| `Hard_acceleration_count` | Hard accelerations counter. Can be very sensitive. | -| `Hard_braking_count` | Hard braking counter. Can be very sensitive. | -| `Average_fuel_consumed` | Average fuel consumed. If car is in km then this will show L/100km. If in mi then it will show Mpg. | -| `Coaching_advice_most_occurrence` | Coaching advice most occurrence. | -| `Average_driver_score` | Average driver score. | -| `Average_driver_score_accelerations` | Average driver score for accelerations. | -| `Average_driver_score_braking` | Average driver score for braking. | -| `EV_distance` | Distance which have been driven on electric. | -| `EV_distance_percentage` | Percentage of the distance driven on electric. | -| `EV_driving_time` | Driving time on electric. | -| `EV_duration_percentage` | Percentage of the driving time on electric. | +All values will show `None` if no data is available for the periode. + +| Attribute | Description | +| ----------------------- | ------------------------------------------------------------------------------- | +| `Distance` | Distance driven (Displayed as sensor value). | +| `Average_speed` | The average speed in the respective period (can be km/h or mph). | +| `Countries` | The countries travelled through in the respective period. | +| `Duration` | The total driving time in the respective period. | +| `Total_fuel_consumed` | The total fuel consumption in the respective period (can be litres or gallons). | +| `Average_fuel_consumed` | The average fuel consumption in the respective period (can be l/100km or mpg). | +| `EV_distance` | The driving distiance in EV mode in the respective period . | +| `EV_duration` | The driving time in EV mode in the respective period . | +| `From_date` | Start date of the calculation period. | +| `To_date` | End date of the calculation period. | ## Getting started ### Prerequisites -Use Home Assistant build 2021.4 or above. +Use Home Assistant build 2023.12 or above. If you can confirm that it is working as advertised on older version please open a PR. @@ -138,16 +125,16 @@ Now you can clone the repository somewhere else and symlink it to Home Assistant 1. Clone the repo. -```shell -git clone https://github.com/DurgNomis-drol/ha_toyota.git -``` + ```shell + git clone https://github.com/DurgNomis-drol/ha_toyota.git + ``` 2. Create the symlink to `toyota` in the configuration directory. If you have non-standard directory for configuration, use it instead. -```shell -ln -s ha_toyota/custom_components/toyota ~/.homeassistant/custom_components/toyota -``` + ```shell + ln -s ha_toyota/custom_components/toyota ~/.homeassistant/custom_components/toyota + ``` #### Copy method From 785aa4789b7e4f5c650fd07bdd063a8c93c9f1d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B6rrle?= Date: Thu, 11 Jan 2024 20:13:33 +0100 Subject: [PATCH 62/68] generate battery sensors only for ev vehicles --- custom_components/toyota/sensor.py | 37 ++++++------------------------ 1 file changed, 7 insertions(+), 30 deletions(-) diff --git a/custom_components/toyota/sensor.py b/custom_components/toyota/sensor.py index 41f9e7f..06d2b2f 100644 --- a/custom_components/toyota/sensor.py +++ b/custom_components/toyota/sensor.py @@ -316,63 +316,40 @@ async def async_setup_entry( ToyotaSensor, ), ( - vehicle._vehicle_info.extended_capabilities.battery_status - or vehicle._vehicle_info.ev_vehicle is True, + vehicle._vehicle_info.ev_vehicle, BATTERY_LEVEL_ENTITY_DESCRIPTION, ToyotaSensor, ), ( - entry.data[CONF_METRIC_VALUES] is True - and ( - vehicle._vehicle_info.extended_capabilities.battery_status - or vehicle._vehicle_info.ev_vehicle is True - ), + entry.data[CONF_METRIC_VALUES] is True and vehicle._vehicle_info.ev_vehicle, BATTERY_RANGE_ENTITY_DESCRIPTION_KM, ToyotaSensor, ), ( - entry.data[CONF_METRIC_VALUES] is False - and ( - vehicle._vehicle_info.extended_capabilities.battery_status - or vehicle._vehicle_info.ev_vehicle is True - ), + entry.data[CONF_METRIC_VALUES] is False and vehicle._vehicle_info.ev_vehicle, BATTERY_RANGE_ENTITY_DESCRIPTION_MILES, ToyotaSensor, ), ( - entry.data[CONF_METRIC_VALUES] is True - and ( - vehicle._vehicle_info.extended_capabilities.battery_status - or vehicle._vehicle_info.ev_vehicle is True - ), + entry.data[CONF_METRIC_VALUES] is True and vehicle._vehicle_info.ev_vehicle, BATTERY_RANGE_AC_ENTITY_DESCRIPTION_KM, ToyotaSensor, ), ( - entry.data[CONF_METRIC_VALUES] is False - and ( - vehicle._vehicle_info.extended_capabilities.battery_status - or vehicle._vehicle_info.ev_vehicle is True - ), + entry.data[CONF_METRIC_VALUES] is False and vehicle._vehicle_info.ev_vehicle, BATTERY_RANGE_AC_ENTITY_DESCRIPTION_MILES, ToyotaSensor, ), ( entry.data[CONF_METRIC_VALUES] is True - and ( - vehicle._vehicle_info.extended_capabilities.battery_status - or vehicle._vehicle_info.ev_vehicle is True - ) + and vehicle._vehicle_info.ev_vehicle and vehicle._vehicle_info.extended_capabilities.fuel_range_available, TOTAL_RANGE_ENTITY_DESCRIPTION_KM, ToyotaSensor, ), ( entry.data[CONF_METRIC_VALUES] is False - and ( - vehicle._vehicle_info.extended_capabilities.battery_status - or vehicle._vehicle_info.ev_vehicle is True - ) + and vehicle._vehicle_info.ev_vehicle and vehicle._vehicle_info.extended_capabilities.fuel_range_available, TOTAL_RANGE_ENTITY_DESCRIPTION_MILES, ToyotaSensor, From ec683f28bee2171e174cf928d6c5d5b17cfa3dcd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B6rrle?= Date: Thu, 11 Jan 2024 20:32:29 +0100 Subject: [PATCH 63/68] Use Mapping for brand names --- custom_components/toyota/const.py | 1 + custom_components/toyota/entity.py | 4 ++-- custom_components/toyota/utils.py | 4 +++- poetry.lock | 12 +++++++++++- 4 files changed, 17 insertions(+), 4 deletions(-) diff --git a/custom_components/toyota/const.py b/custom_components/toyota/const.py index 3e610d1..7227d1e 100644 --- a/custom_components/toyota/const.py +++ b/custom_components/toyota/const.py @@ -11,6 +11,7 @@ ISSUES_URL = "https://github.com/DurgNomis-drol/ha_toyota/issues" # CONF +CONF_BRAND_MAPPING = {"T": "Toyota"} CONF_METRIC_VALUES = "use_metric_values" # DEFAULTS diff --git a/custom_components/toyota/entity.py b/custom_components/toyota/entity.py index c27bca9..d957715 100644 --- a/custom_components/toyota/entity.py +++ b/custom_components/toyota/entity.py @@ -12,7 +12,7 @@ from mytoyota.models.vehicle import Vehicle from . import StatisticsData, VehicleData -from .const import DOMAIN +from .const import CONF_BRAND_MAPPING, DOMAIN class ToyotaBaseEntity(CoordinatorEntity): @@ -41,7 +41,7 @@ def __init__( identifiers={(DOMAIN, self.vehicle.vin)}, name=self.vehicle.alias, model=self.vehicle._vehicle_info.car_model_name, - manufacturer=self.vehicle._vehicle_info.brand, + manufacturer=CONF_BRAND_MAPPING.get(self.vehicle._vehicle_info.brand), ) @callback diff --git a/custom_components/toyota/utils.py b/custom_components/toyota/utils.py index 6130867..01885d2 100644 --- a/custom_components/toyota/utils.py +++ b/custom_components/toyota/utils.py @@ -6,6 +6,8 @@ from mytoyota.models.endpoints.vehicle_guid import VehicleGuidModel from mytoyota.models.summary import Summary +from .const import CONF_BRAND_MAPPING + def round_number(number: int | float | None, places: int = 0) -> int | float | None: """Round a number if it is not None.""" @@ -26,7 +28,7 @@ def format_vin_sensor_attributes( "IMEI": mask_string(vehicle_info.imei), "Katashiki_code": vehicle_info.katashiki_code, "ASI_code": vehicle_info.asi_code, - "Brand": vehicle_info.brand, + "Brand": CONF_BRAND_MAPPING.get(vehicle_info.brand), "Car_line_name": vehicle_info.car_line_name, "Car_model_year": vehicle_info.car_model_year, "Car_model_name": vehicle_info.car_model_name, diff --git a/poetry.lock b/poetry.lock index 6c3138f..c9aa9e1 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.7.0 and should not be changed by hand. [[package]] name = "aiohttp" @@ -1527,6 +1527,7 @@ files = [ {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, + {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, @@ -1534,8 +1535,15 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, + {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, + {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, + {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, + {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, @@ -1552,6 +1560,7 @@ files = [ {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, + {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, @@ -1559,6 +1568,7 @@ files = [ {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, + {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, From 69ad37f750267e188d80c5d97e26447f9d7d7a21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B6rrle?= Date: Thu, 11 Jan 2024 20:39:48 +0100 Subject: [PATCH 64/68] create odometer only when telemetry capable --- custom_components/toyota/sensor.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/custom_components/toyota/sensor.py b/custom_components/toyota/sensor.py index 06d2b2f..2dc21be 100644 --- a/custom_components/toyota/sensor.py +++ b/custom_components/toyota/sensor.py @@ -289,12 +289,14 @@ async def async_setup_entry( ToyotaSensor, ), ( - entry.data[CONF_METRIC_VALUES] is True, + entry.data[CONF_METRIC_VALUES] is True + and vehicle._vehicle_info.extended_capabilities.telemetry_capable, ODOMETER_ENTITY_DESCRIPTION_KM, ToyotaSensor, ), ( - entry.data[CONF_METRIC_VALUES] is False, + entry.data[CONF_METRIC_VALUES] is False + and vehicle._vehicle_info.extended_capabilities.telemetry_capable, ODOMETER_ENTITY_DESCRIPTION_MILES, ToyotaSensor, ), From ad00a008604fb9268b2b43a8f011899c6b14050f Mon Sep 17 00:00:00 2001 From: Pierre Belloy <151526296+pierrebelloy@users.noreply.github.com> Date: Thu, 11 Jan 2024 21:35:34 +0100 Subject: [PATCH 65/68] Update French translations (#203) Signed-off-by: Pierre Belloy --- custom_components/toyota/translations/fr.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/custom_components/toyota/translations/fr.json b/custom_components/toyota/translations/fr.json index a460ee6..ebb30a6 100644 --- a/custom_components/toyota/translations/fr.json +++ b/custom_components/toyota/translations/fr.json @@ -33,7 +33,7 @@ }, "sensor": { "vin": { - "name": "Vehicle-Identify-Number" + "name": "Numéro d'identification du véhicule" }, "odometer": { "name": "Odomètre" @@ -42,19 +42,19 @@ "name": "Niveau de carburant" }, "fuel_range": { - "name": "Fuel range" + "name": "Autonomie d'essence" }, "battery_level": { - "name": "Battery level" + "name": "Niveau de batterie" }, "battery_range": { - "name": "Battery range" + "name": "Autonomie électrique" }, "battery_range_ac": { - "name": "Battery range with AC" + "name": "Autonomie électrique avec AC" }, "total_range": { - "name": "Total range" + "name": "Autonomie totale" }, "current_day_statistics": { "name": "Statistiques aujourd'hui" From ec2b3bced683b80e7c9de0403db82a23fccb75ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B6rrle?= Date: Thu, 11 Jan 2024 21:48:44 +0100 Subject: [PATCH 66/68] Use same condition for ev vehicles like in mytoyota lib --- custom_components/toyota/sensor.py | 18 +++++++++++------- custom_components/toyota/utils.py | 5 ++++- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/custom_components/toyota/sensor.py b/custom_components/toyota/sensor.py index 2dc21be..1f79454 100644 --- a/custom_components/toyota/sensor.py +++ b/custom_components/toyota/sensor.py @@ -318,40 +318,44 @@ async def async_setup_entry( ToyotaSensor, ), ( - vehicle._vehicle_info.ev_vehicle, + vehicle._vehicle_info.extended_capabilities.econnect_vehicle_status_capable, BATTERY_LEVEL_ENTITY_DESCRIPTION, ToyotaSensor, ), ( - entry.data[CONF_METRIC_VALUES] is True and vehicle._vehicle_info.ev_vehicle, + entry.data[CONF_METRIC_VALUES] is True + and vehicle._vehicle_info.extended_capabilities.econnect_vehicle_status_capable, BATTERY_RANGE_ENTITY_DESCRIPTION_KM, ToyotaSensor, ), ( - entry.data[CONF_METRIC_VALUES] is False and vehicle._vehicle_info.ev_vehicle, + entry.data[CONF_METRIC_VALUES] is False + and vehicle._vehicle_info.extended_capabilities.econnect_vehicle_status_capable, BATTERY_RANGE_ENTITY_DESCRIPTION_MILES, ToyotaSensor, ), ( - entry.data[CONF_METRIC_VALUES] is True and vehicle._vehicle_info.ev_vehicle, + entry.data[CONF_METRIC_VALUES] is True + and vehicle._vehicle_info.extended_capabilities.econnect_vehicle_status_capable, BATTERY_RANGE_AC_ENTITY_DESCRIPTION_KM, ToyotaSensor, ), ( - entry.data[CONF_METRIC_VALUES] is False and vehicle._vehicle_info.ev_vehicle, + entry.data[CONF_METRIC_VALUES] is False + and vehicle._vehicle_info.extended_capabilities.econnect_vehicle_status_capable, BATTERY_RANGE_AC_ENTITY_DESCRIPTION_MILES, ToyotaSensor, ), ( entry.data[CONF_METRIC_VALUES] is True - and vehicle._vehicle_info.ev_vehicle + and vehicle._vehicle_info.extended_capabilities.econnect_vehicle_status_capable and vehicle._vehicle_info.extended_capabilities.fuel_range_available, TOTAL_RANGE_ENTITY_DESCRIPTION_KM, ToyotaSensor, ), ( entry.data[CONF_METRIC_VALUES] is False - and vehicle._vehicle_info.ev_vehicle + and vehicle._vehicle_info.extended_capabilities.econnect_vehicle_status_capable and vehicle._vehicle_info.extended_capabilities.fuel_range_available, TOTAL_RANGE_ENTITY_DESCRIPTION_MILES, ToyotaSensor, diff --git a/custom_components/toyota/utils.py b/custom_components/toyota/utils.py index 01885d2..88dd26d 100644 --- a/custom_components/toyota/utils.py +++ b/custom_components/toyota/utils.py @@ -80,7 +80,10 @@ def format_statistics_attributes( else None, } - if vehicle_info.extended_capabilities.hybrid_pulse or vehicle_info.ev_vehicle is True: + if ( + vehicle_info.extended_capabilities.hybrid_pulse + or vehicle_info.extended_capabilities.econnect_vehicle_status_capable + ): attr |= { "EV_distance": round(statistics.ev_distance, 1) if statistics.ev_distance else None, "EV_duration": str(statistics.ev_duration) if statistics.ev_duration else None, From d08a2b1f49232137919de72522a40ff07a3c0f95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B6rrle?= Date: Thu, 11 Jan 2024 21:53:18 +0100 Subject: [PATCH 67/68] use same condition for last_parked like in mytoyota lib --- custom_components/toyota/device_tracker.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/custom_components/toyota/device_tracker.py b/custom_components/toyota/device_tracker.py index 04606c0..bac40c1 100644 --- a/custom_components/toyota/device_tracker.py +++ b/custom_components/toyota/device_tracker.py @@ -37,7 +37,8 @@ async def async_setup_entry( description=PARKING_TRACKER_DESCRIPTION, ) for index, vehicle in enumerate(coordinator.data) - if vehicle["data"]._vehicle_info.features.last_parked + if vehicle["data"]._vehicle_info.extended_capabilities.last_parked_capable + or vehicle["data"]._vehicle_info.features.last_parked ) From d661f35a09b126d3da99d95d70de3d4bcb469d4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B6rrle?= Date: Thu, 11 Jan 2024 21:59:25 +0100 Subject: [PATCH 68/68] create statistics sensors by default for now --- custom_components/toyota/sensor.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/custom_components/toyota/sensor.py b/custom_components/toyota/sensor.py index 1f79454..ab2e8d7 100644 --- a/custom_components/toyota/sensor.py +++ b/custom_components/toyota/sensor.py @@ -361,22 +361,22 @@ async def async_setup_entry( ToyotaSensor, ), ( - vehicle._vehicle_info.extended_capabilities.telemetry_capable, + True, # TODO Unsure of the required capability STATISTICS_ENTITY_DESCRIPTIONS_DAILY, ToyotaStatisticsSensor, ), ( - vehicle._vehicle_info.extended_capabilities.telemetry_capable, + True, # TODO Unsure of the required capability STATISTICS_ENTITY_DESCRIPTIONS_WEEKLY, ToyotaStatisticsSensor, ), ( - vehicle._vehicle_info.extended_capabilities.telemetry_capable, + True, # TODO Unsure of the required capability STATISTICS_ENTITY_DESCRIPTIONS_MONTHLY, ToyotaStatisticsSensor, ), ( - vehicle._vehicle_info.extended_capabilities.telemetry_capable, + True, # TODO Unsure of the required capability STATISTICS_ENTITY_DESCRIPTIONS_YEARLY, ToyotaStatisticsSensor, ),