Compare commits
16 Commits
Author | SHA1 | Date | |
---|---|---|---|
dca2466e25 | |||
f24d664c62 | |||
e9de91a02e | |||
e25f636ebc | |||
1a9ddbe93e | |||
3e49e5adbd | |||
92bd17ce30 | |||
8b13798eec | |||
48000aa067 | |||
39e481fa22 | |||
611cd3a414 | |||
65b016664c | |||
e79b9fe213 | |||
26b9c8474b | |||
1f573f44fe | |||
da52b296f8 |
@ -1,20 +1,38 @@
|
||||
image: python:latest
|
||||
|
||||
lint:
|
||||
stage: test
|
||||
before_script:
|
||||
stages:
|
||||
- lint
|
||||
- test
|
||||
- deploy
|
||||
|
||||
before_script:
|
||||
- pip install poetry
|
||||
- poetry install --no-root
|
||||
|
||||
lint:
|
||||
stage: lint
|
||||
script:
|
||||
- poetry run ruff check ./src
|
||||
- poetry run ruff format --check ./src
|
||||
- poetry run ruff check
|
||||
- poetry run ruff format --check
|
||||
|
||||
test:
|
||||
stage: test
|
||||
script:
|
||||
- poetry run pytest -v --cov=. --cov-report=xml
|
||||
after_script:
|
||||
- bash <(curl -s https://codecov.io/bash)
|
||||
artifacts:
|
||||
reports:
|
||||
coverage_report:
|
||||
coverage_format: cobertura
|
||||
path: coverage.xml
|
||||
|
||||
deploy_to_pypi:
|
||||
stage: deploy
|
||||
only:
|
||||
refs:
|
||||
- master
|
||||
before_script:
|
||||
- pip install poetry
|
||||
- poetry install --no-root
|
||||
changes:
|
||||
- pyproject.toml
|
||||
script:
|
||||
- POETRY_PYPI_TOKEN_PYPI=$PYPI_PASSWORD poetry publish --build
|
||||
|
16
README.md
16
README.md
@ -1,5 +1,18 @@
|
||||
# UTE API Wrapper 🇺🇾
|
||||
|
||||
# THIS API NO LONGER WORKS
|
||||
|
||||
UTE deprecated the API that this wrapper uses on April 15th 2024. More information [here](https://github.com/rogsme/ute_homeassistant_integration/issues/3#issuecomment-2054332575).
|
||||
|
||||
I'll archive this repository in a few days.
|
||||
|
||||
<p align="center">
|
||||
<img src="https://gitlab.com/uploads/-/system/project/avatar/48558040/icon.png" alt="ute-wrapper"/>
|
||||
</p>
|
||||
|
||||
[](https://codecov.io/gl/rogs/ute)
|
||||
[](https://badge.fury.io/py/ute-wrapper)
|
||||
|
||||
This Python package provides a convenient wrapper for interacting with the [UTE (Administración Nacional de Usinas y Trasmisiones Eléctricas)](https://portal.ute.com.uy/) API in Uruguay 🇺🇾. It allows you to retrieve various information related to your UTE account, electricity consumption, network status, and more.
|
||||
|
||||
## Table of Contents
|
||||
@ -45,6 +58,7 @@ ute_client = UTEClient(email, phone_number, device_id, average_cost_per_kwh, pow
|
||||
- `get_current_usage_info()`: Get current usage information for the specified device ID.
|
||||
- `get_average_price(plan)`: Get the average price for a specific UTE plan ("triple" or "doble").
|
||||
|
||||
|
||||
## Examples
|
||||
|
||||
### Get Historic Consumption
|
||||
@ -63,7 +77,7 @@ print(current_usage_info)
|
||||
|
||||
## Contributing
|
||||
|
||||
Contributions are welcome! If you find a bug or have a suggestion, please create an issue or submit Merge Request on [Gitlab](https://gitlab.com/rogs/ute).
|
||||
Contributions are welcome! If you find a bug or have a suggestion, please create an issue or submit a Merge Request on [Gitlab](https://gitlab.com/rogs/ute).
|
||||
|
||||
## License
|
||||
|
||||
|
159
poetry.lock
generated
159
poetry.lock
generated
@ -165,6 +165,84 @@ files = [
|
||||
{file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "colorama"
|
||||
version = "0.4.6"
|
||||
description = "Cross-platform colored terminal text."
|
||||
optional = false
|
||||
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
|
||||
files = [
|
||||
{file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
|
||||
{file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "coverage"
|
||||
version = "7.4.3"
|
||||
description = "Code coverage measurement for Python"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "coverage-7.4.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8580b827d4746d47294c0e0b92854c85a92c2227927433998f0d3320ae8a71b6"},
|
||||
{file = "coverage-7.4.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:718187eeb9849fc6cc23e0d9b092bc2348821c5e1a901c9f8975df0bc785bfd4"},
|
||||
{file = "coverage-7.4.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:767b35c3a246bcb55b8044fd3a43b8cd553dd1f9f2c1eeb87a302b1f8daa0524"},
|
||||
{file = "coverage-7.4.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae7f19afe0cce50039e2c782bff379c7e347cba335429678450b8fe81c4ef96d"},
|
||||
{file = "coverage-7.4.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba3a8aaed13770e970b3df46980cb068d1c24af1a1968b7818b69af8c4347efb"},
|
||||
{file = "coverage-7.4.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:ee866acc0861caebb4f2ab79f0b94dbfbdbfadc19f82e6e9c93930f74e11d7a0"},
|
||||
{file = "coverage-7.4.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:506edb1dd49e13a2d4cac6a5173317b82a23c9d6e8df63efb4f0380de0fbccbc"},
|
||||
{file = "coverage-7.4.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd6545d97c98a192c5ac995d21c894b581f1fd14cf389be90724d21808b657e2"},
|
||||
{file = "coverage-7.4.3-cp310-cp310-win32.whl", hash = "sha256:f6a09b360d67e589236a44f0c39218a8efba2593b6abdccc300a8862cffc2f94"},
|
||||
{file = "coverage-7.4.3-cp310-cp310-win_amd64.whl", hash = "sha256:18d90523ce7553dd0b7e23cbb28865db23cddfd683a38fb224115f7826de78d0"},
|
||||
{file = "coverage-7.4.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cbbe5e739d45a52f3200a771c6d2c7acf89eb2524890a4a3aa1a7fa0695d2a47"},
|
||||
{file = "coverage-7.4.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:489763b2d037b164846ebac0cbd368b8a4ca56385c4090807ff9fad817de4113"},
|
||||
{file = "coverage-7.4.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:451f433ad901b3bb00184d83fd83d135fb682d780b38af7944c9faeecb1e0bfe"},
|
||||
{file = "coverage-7.4.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fcc66e222cf4c719fe7722a403888b1f5e1682d1679bd780e2b26c18bb648cdc"},
|
||||
{file = "coverage-7.4.3-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b3ec74cfef2d985e145baae90d9b1b32f85e1741b04cd967aaf9cfa84c1334f3"},
|
||||
{file = "coverage-7.4.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:abbbd8093c5229c72d4c2926afaee0e6e3140de69d5dcd918b2921f2f0c8baba"},
|
||||
{file = "coverage-7.4.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:35eb581efdacf7b7422af677b92170da4ef34500467381e805944a3201df2079"},
|
||||
{file = "coverage-7.4.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8249b1c7334be8f8c3abcaaa996e1e4927b0e5a23b65f5bf6cfe3180d8ca7840"},
|
||||
{file = "coverage-7.4.3-cp311-cp311-win32.whl", hash = "sha256:cf30900aa1ba595312ae41978b95e256e419d8a823af79ce670835409fc02ad3"},
|
||||
{file = "coverage-7.4.3-cp311-cp311-win_amd64.whl", hash = "sha256:18c7320695c949de11a351742ee001849912fd57e62a706d83dfc1581897fa2e"},
|
||||
{file = "coverage-7.4.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b51bfc348925e92a9bd9b2e48dad13431b57011fd1038f08316e6bf1df107d10"},
|
||||
{file = "coverage-7.4.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d6cdecaedea1ea9e033d8adf6a0ab11107b49571bbb9737175444cea6eb72328"},
|
||||
{file = "coverage-7.4.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3b2eccb883368f9e972e216c7b4c7c06cabda925b5f06dde0650281cb7666a30"},
|
||||
{file = "coverage-7.4.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6c00cdc8fa4e50e1cc1f941a7f2e3e0f26cb2a1233c9696f26963ff58445bac7"},
|
||||
{file = "coverage-7.4.3-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b9a4a8dd3dcf4cbd3165737358e4d7dfbd9d59902ad11e3b15eebb6393b0446e"},
|
||||
{file = "coverage-7.4.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:062b0a75d9261e2f9c6d071753f7eef0fc9caf3a2c82d36d76667ba7b6470003"},
|
||||
{file = "coverage-7.4.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:ebe7c9e67a2d15fa97b77ea6571ce5e1e1f6b0db71d1d5e96f8d2bf134303c1d"},
|
||||
{file = "coverage-7.4.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:c0a120238dd71c68484f02562f6d446d736adcc6ca0993712289b102705a9a3a"},
|
||||
{file = "coverage-7.4.3-cp312-cp312-win32.whl", hash = "sha256:37389611ba54fd6d278fde86eb2c013c8e50232e38f5c68235d09d0a3f8aa352"},
|
||||
{file = "coverage-7.4.3-cp312-cp312-win_amd64.whl", hash = "sha256:d25b937a5d9ffa857d41be042b4238dd61db888533b53bc76dc082cb5a15e914"},
|
||||
{file = "coverage-7.4.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:28ca2098939eabab044ad68850aac8f8db6bf0b29bc7f2887d05889b17346454"},
|
||||
{file = "coverage-7.4.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:280459f0a03cecbe8800786cdc23067a8fc64c0bd51dc614008d9c36e1659d7e"},
|
||||
{file = "coverage-7.4.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c0cdedd3500e0511eac1517bf560149764b7d8e65cb800d8bf1c63ebf39edd2"},
|
||||
{file = "coverage-7.4.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9a9babb9466fe1da12417a4aed923e90124a534736de6201794a3aea9d98484e"},
|
||||
{file = "coverage-7.4.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dec9de46a33cf2dd87a5254af095a409ea3bf952d85ad339751e7de6d962cde6"},
|
||||
{file = "coverage-7.4.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:16bae383a9cc5abab9bb05c10a3e5a52e0a788325dc9ba8499e821885928968c"},
|
||||
{file = "coverage-7.4.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:2c854ce44e1ee31bda4e318af1dbcfc929026d12c5ed030095ad98197eeeaed0"},
|
||||
{file = "coverage-7.4.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:ce8c50520f57ec57aa21a63ea4f325c7b657386b3f02ccaedeccf9ebe27686e1"},
|
||||
{file = "coverage-7.4.3-cp38-cp38-win32.whl", hash = "sha256:708a3369dcf055c00ddeeaa2b20f0dd1ce664eeabde6623e516c5228b753654f"},
|
||||
{file = "coverage-7.4.3-cp38-cp38-win_amd64.whl", hash = "sha256:1bf25fbca0c8d121a3e92a2a0555c7e5bc981aee5c3fdaf4bb7809f410f696b9"},
|
||||
{file = "coverage-7.4.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3b253094dbe1b431d3a4ac2f053b6d7ede2664ac559705a704f621742e034f1f"},
|
||||
{file = "coverage-7.4.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:77fbfc5720cceac9c200054b9fab50cb2a7d79660609200ab83f5db96162d20c"},
|
||||
{file = "coverage-7.4.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6679060424faa9c11808598504c3ab472de4531c571ab2befa32f4971835788e"},
|
||||
{file = "coverage-7.4.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4af154d617c875b52651dd8dd17a31270c495082f3d55f6128e7629658d63765"},
|
||||
{file = "coverage-7.4.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8640f1fde5e1b8e3439fe482cdc2b0bb6c329f4bb161927c28d2e8879c6029ee"},
|
||||
{file = "coverage-7.4.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:69b9f6f66c0af29642e73a520b6fed25ff9fd69a25975ebe6acb297234eda501"},
|
||||
{file = "coverage-7.4.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:0842571634f39016a6c03e9d4aba502be652a6e4455fadb73cd3a3a49173e38f"},
|
||||
{file = "coverage-7.4.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a78ed23b08e8ab524551f52953a8a05d61c3a760781762aac49f8de6eede8c45"},
|
||||
{file = "coverage-7.4.3-cp39-cp39-win32.whl", hash = "sha256:c0524de3ff096e15fcbfe8f056fdb4ea0bf497d584454f344d59fce069d3e6e9"},
|
||||
{file = "coverage-7.4.3-cp39-cp39-win_amd64.whl", hash = "sha256:0209a6369ccce576b43bb227dc8322d8ef9e323d089c6f3f26a597b09cb4d2aa"},
|
||||
{file = "coverage-7.4.3-pp38.pp39.pp310-none-any.whl", hash = "sha256:7cbde573904625509a3f37b6fecea974e363460b556a627c60dc2f47e2fffa51"},
|
||||
{file = "coverage-7.4.3.tar.gz", hash = "sha256:276f6077a5c61447a48d133ed13e759c09e62aff0dc84274a68dc18660104d52"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.11.0a6\" and extra == \"toml\""}
|
||||
|
||||
[package.extras]
|
||||
toml = ["tomli"]
|
||||
|
||||
[[package]]
|
||||
name = "distlib"
|
||||
version = "0.3.8"
|
||||
@ -261,6 +339,17 @@ docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.link
|
||||
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 = "iniconfig"
|
||||
version = "2.0.0"
|
||||
description = "brain-dead simple config-ini parsing"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"},
|
||||
{file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "jedi"
|
||||
version = "0.19.1"
|
||||
@ -309,6 +398,17 @@ files = [
|
||||
[package.dependencies]
|
||||
setuptools = "*"
|
||||
|
||||
[[package]]
|
||||
name = "packaging"
|
||||
version = "23.2"
|
||||
description = "Core utilities for Python packages"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"},
|
||||
{file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parso"
|
||||
version = "0.8.3"
|
||||
@ -372,6 +472,63 @@ nodeenv = ">=0.11.1"
|
||||
pyyaml = ">=5.1"
|
||||
virtualenv = ">=20.10.0"
|
||||
|
||||
[[package]]
|
||||
name = "pytest"
|
||||
version = "8.1.1"
|
||||
description = "pytest: simple powerful testing with Python"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "pytest-8.1.1-py3-none-any.whl", hash = "sha256:2a8386cfc11fa9d2c50ee7b2a57e7d898ef90470a7a34c4b949ff59662bb78b7"},
|
||||
{file = "pytest-8.1.1.tar.gz", hash = "sha256:ac978141a75948948817d360297b7aae0fcb9d6ff6bc9ec6d514b85d5a65c044"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
colorama = {version = "*", markers = "sys_platform == \"win32\""}
|
||||
exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""}
|
||||
iniconfig = "*"
|
||||
packaging = "*"
|
||||
pluggy = ">=1.4,<2.0"
|
||||
tomli = {version = ">=1", markers = "python_version < \"3.11\""}
|
||||
|
||||
[package.extras]
|
||||
testing = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"]
|
||||
|
||||
[[package]]
|
||||
name = "pytest-cov"
|
||||
version = "4.1.0"
|
||||
description = "Pytest plugin for measuring coverage."
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "pytest-cov-4.1.0.tar.gz", hash = "sha256:3904b13dfbfec47f003b8e77fd5b589cd11904a21ddf1ab38a64f204d6a10ef6"},
|
||||
{file = "pytest_cov-4.1.0-py3-none-any.whl", hash = "sha256:6ba70b9e97e69fcc3fb45bfeab2d0a138fb65c4d0d6a41ef33983ad114be8c3a"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
coverage = {version = ">=5.2.1", extras = ["toml"]}
|
||||
pytest = ">=4.6"
|
||||
|
||||
[package.extras]
|
||||
testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtualenv"]
|
||||
|
||||
[[package]]
|
||||
name = "pytest-mock"
|
||||
version = "3.12.0"
|
||||
description = "Thin-wrapper around the mock package for easier use with pytest"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "pytest-mock-3.12.0.tar.gz", hash = "sha256:31a40f038c22cad32287bb43932054451ff5583ff094bca6f675df2f8bc1a6e9"},
|
||||
{file = "pytest_mock-3.12.0-py3-none-any.whl", hash = "sha256:0972719a7263072da3a21c7f4773069bcc7486027d7e8e1f81d98a47e701bc4f"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
pytest = ">=5.0"
|
||||
|
||||
[package.extras]
|
||||
dev = ["pre-commit", "pytest-asyncio", "tox"]
|
||||
|
||||
[[package]]
|
||||
name = "python-lsp-jsonrpc"
|
||||
version = "1.1.2"
|
||||
@ -717,4 +874,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p
|
||||
[metadata]
|
||||
lock-version = "2.0"
|
||||
python-versions = ">=3.9"
|
||||
content-hash = "0a6f86cf51e05d548af0f27608079383cc10b8bf036c7669500f51208cdd0b46"
|
||||
content-hash = "3af2371329597b4b40f1b2b56d61cbca6009d76b97f1283b64475aee7261fc35"
|
||||
|
@ -1,7 +1,7 @@
|
||||
[tool.poetry]
|
||||
name = "ute-wrapper"
|
||||
version = "2.2.1"
|
||||
description = "A wrapper to interact with UTE's API"
|
||||
version = "2.5.1"
|
||||
description = "[DEPRECATED] A wrapper to interact with UTE's API"
|
||||
authors = ["Roger Gonzalez <roger@rogs.me>"]
|
||||
license = "GPL-3.0-or-later"
|
||||
readme = "README.md"
|
||||
@ -23,6 +23,9 @@ requests = ">=2.0.0, <3.0.0"
|
||||
python-lsp-server = "^1.10.0"
|
||||
python-lsp-ruff = "^2.2.0"
|
||||
pre-commit = "^3.6.2"
|
||||
pytest = "^8.1.1"
|
||||
pytest-mock = "^3.12.0"
|
||||
pytest-cov = "^4.1.0"
|
||||
|
||||
[build-system]
|
||||
requires = ["poetry-core"]
|
||||
@ -65,7 +68,7 @@ target-version = "py39"
|
||||
|
||||
[tool.ruff.lint]
|
||||
select = ["E", "F", "T20", "PL", "B", "A", "C4", "TID", "ERA", "RET", "W", "C90", "ARG", "Q", "FLY", "SIM", "COM", "D"]
|
||||
ignore = ["E402"]
|
||||
ignore = ["E402", "PLW2901", "COM812", "PLR2004"]
|
||||
|
||||
[tool.ruff.lint.pylint]
|
||||
max-args = 6
|
||||
|
@ -1,4 +1,6 @@
|
||||
"""Constants used in the application."""
|
||||
|
||||
HTTP_200_OK = 200
|
||||
TRIPHASIC = 3
|
||||
API_VERSION_1 = "https://rocme.ute.com.uy/api/v1"
|
||||
API_VERSION_2 = "https://rocme.ute.com.uy/api/v2"
|
||||
TRIPHASIC = 3
|
||||
|
@ -1,4 +1,4 @@
|
||||
"""This module contains all the exceptions used in the project."""
|
||||
"""Custom exceptions for the UTE wrapper."""
|
||||
|
||||
|
||||
class InvalidPowerFactorException(Exception):
|
||||
@ -14,7 +14,7 @@ class MultipleDevicesException(Exception):
|
||||
|
||||
|
||||
class UnsupportedMethodException(Exception):
|
||||
"""Raised when an unsupported method is used."""
|
||||
"""Raised when an unsupported HTTP method is used."""
|
||||
|
||||
pass
|
||||
|
||||
@ -25,12 +25,6 @@ class InvalidPlanException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class TariffException(Exception):
|
||||
"""Raised when the tariff is not valid."""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class ReadingRequestFailedException(Exception):
|
||||
"""Raised when the reading request fails."""
|
||||
|
||||
@ -41,3 +35,9 @@ class ReadingResponseInvalidException(Exception):
|
||||
"""Raised when the reading response is invalid."""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class TariffException(Exception):
|
||||
"""Raised when the tariff is not valid."""
|
||||
|
||||
pass
|
||||
|
26
src/ute_wrapper/models.py
Normal file
26
src/ute_wrapper/models.py
Normal file
@ -0,0 +1,26 @@
|
||||
"""Models for the UTE Wrapper."""
|
||||
|
||||
from typing import TypedDict
|
||||
|
||||
|
||||
class EnergyEntry(TypedDict):
|
||||
"""Energy entry dict."""
|
||||
|
||||
kwh: float
|
||||
aproximated_cost_in_uyu: float
|
||||
day_in_week: str
|
||||
|
||||
|
||||
class TotalEntry(TypedDict, total=False):
|
||||
"""Total entry dict."""
|
||||
|
||||
sum_in_kwh: float
|
||||
aproximated_cost_in_uyu: float
|
||||
daily_average_cost: float
|
||||
|
||||
|
||||
class ActiveEnergy(TypedDict, total=False):
|
||||
"""Active energy dict."""
|
||||
|
||||
total: TotalEntry
|
||||
dates: dict[str, EnergyEntry]
|
@ -21,11 +21,11 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
import time
|
||||
from datetime import datetime, timedelta
|
||||
from time import sleep
|
||||
from typing import Dict, List, Optional, TypedDict
|
||||
from typing import Optional
|
||||
|
||||
import requests
|
||||
|
||||
from .constants import HTTP_200_OK, TRIPHASIC
|
||||
from .constants import API_VERSION_1, API_VERSION_2, TRIPHASIC
|
||||
from .exceptions import (
|
||||
InvalidPlanException,
|
||||
InvalidPowerFactorException,
|
||||
@ -35,53 +35,11 @@ from .exceptions import (
|
||||
TariffException,
|
||||
UnsupportedMethodException,
|
||||
)
|
||||
|
||||
API_VERSION_1 = "https://rocme.ute.com.uy/api/v1"
|
||||
API_VERSION_2 = "https://rocme.ute.com.uy/api/v2"
|
||||
|
||||
|
||||
class EnergyEntry(TypedDict):
|
||||
"""Energy entry dict."""
|
||||
|
||||
kwh: float
|
||||
aproximated_cost_in_uyu: float
|
||||
day_in_week: str
|
||||
|
||||
|
||||
class TotalEntry(TypedDict, total=False):
|
||||
"""Total entry dict."""
|
||||
|
||||
sum_in_kwh: float
|
||||
aproximated_cost_in_uyu: float
|
||||
daily_average_cost: float
|
||||
|
||||
|
||||
class ActiveEnergy(TypedDict, total=False):
|
||||
"""Active energy dict."""
|
||||
|
||||
total: TotalEntry
|
||||
dates: Dict[str, EnergyEntry]
|
||||
from .models import ActiveEnergy
|
||||
|
||||
|
||||
class UTEClient:
|
||||
"""
|
||||
UTE (Administración Nacional de Usinas y Trasmisiones Eléctricas) API Wrapper.
|
||||
|
||||
Args:
|
||||
email (str): User email for authentication
|
||||
phone_number (str): User phone number for authentication
|
||||
device_id (str): UTE Device id
|
||||
average_cost_per_kwh (float): Average cost per kwh
|
||||
power_factor (float): Power factor
|
||||
|
||||
Raises:
|
||||
InvalidPowerFactorException: If the power factor is not between 0 and 1
|
||||
MultipleDevicesException: If there are multiple devices associated with the account
|
||||
UnsupportedMethodException: If an unsupported method is used
|
||||
InvalidPlanException: If the plan is not valid
|
||||
ReadingRequestException: If the reading request is not valid
|
||||
TariffException: If the tariff is not valid
|
||||
"""
|
||||
"""UTE (Administración Nacional de Usinas y Trasmisiones Eléctricas) API Wrapper."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@ -113,8 +71,8 @@ class UTEClient:
|
||||
self.phone_number = phone_number
|
||||
self.device_id = device_id
|
||||
self.average_cost_per_kwh = average_cost_per_kwh
|
||||
self.authorization = self._login()
|
||||
self.power_factor = power_factor
|
||||
self.authorization = None
|
||||
self._validate_power_factor()
|
||||
self._initialize_device_id()
|
||||
self._initialize_average_cost_per_kwh()
|
||||
@ -154,7 +112,7 @@ class UTEClient:
|
||||
delay: float = 2,
|
||||
) -> requests.Response:
|
||||
"""
|
||||
Make a HTTP request with retries.
|
||||
Make a HTTP request with retries and handle expired authorization.
|
||||
|
||||
Args:
|
||||
method (str): The HTTP method to use. Accepted methods are ``GET``, ``POST``.
|
||||
@ -176,20 +134,20 @@ class UTEClient:
|
||||
"Connection": "Keep-Alive",
|
||||
}
|
||||
|
||||
try:
|
||||
for attempt in range(retries):
|
||||
if self.authorization:
|
||||
headers["Authorization"] = f"Bearer {self.authorization}"
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
for attempt in range(retries):
|
||||
try:
|
||||
response = getattr(requests, method.lower(), self._method_not_supported)(url, headers=headers, json=data)
|
||||
if response.status_code == requests.codes.unauthorized:
|
||||
self._login()
|
||||
continue
|
||||
response.raise_for_status()
|
||||
return response
|
||||
except (requests.RequestException, Exception) as e:
|
||||
except (requests.RequestException, Exception):
|
||||
if attempt == retries - 1:
|
||||
raise e
|
||||
break
|
||||
time.sleep(delay)
|
||||
|
||||
raise Exception("All retries failed.")
|
||||
@ -201,10 +159,6 @@ class UTEClient:
|
||||
"""
|
||||
Login to UTE.
|
||||
|
||||
Args:
|
||||
email (str): User email for authentication
|
||||
phone_number (str): User phone number for authentication
|
||||
|
||||
Returns:
|
||||
str: Authorization token
|
||||
"""
|
||||
@ -214,15 +168,20 @@ class UTEClient:
|
||||
"PhoneNumber": self.phone_number,
|
||||
}
|
||||
|
||||
return self._make_request("POST", url, data=data).text
|
||||
response = self._make_request("POST", url, data=data)
|
||||
self.authorization = response.text
|
||||
return self.authorization
|
||||
|
||||
def get_devices_list(self) -> List[dict]:
|
||||
def get_devices_list(self) -> list[dict]:
|
||||
"""
|
||||
Get UTE devices list.
|
||||
|
||||
Returns:
|
||||
List[dict]: List of devices
|
||||
list[dict]: List of devices
|
||||
"""
|
||||
if not self.authorization:
|
||||
self._login()
|
||||
|
||||
accounts_url = f"{API_VERSION_1}/accounts"
|
||||
return self._make_request("GET", accounts_url).json()["data"]
|
||||
|
||||
@ -233,6 +192,9 @@ class UTEClient:
|
||||
Returns:
|
||||
dict: UTE account information
|
||||
"""
|
||||
if not self.authorization:
|
||||
self._login()
|
||||
|
||||
accounts_by_id_url = f"{API_VERSION_1}/accounts/{self.device_id}"
|
||||
return self._make_request("GET", accounts_by_id_url).json()["data"]
|
||||
|
||||
@ -243,16 +205,22 @@ class UTEClient:
|
||||
Returns:
|
||||
dict: UTE peak info
|
||||
"""
|
||||
if not self.authorization:
|
||||
self._login()
|
||||
|
||||
peak_by_id_url = f"{API_VERSION_1}/accounts/{self.device_id}/peak"
|
||||
return self._make_request("GET", peak_by_id_url).json()["data"]
|
||||
|
||||
def get_network_status(self) -> List[dict]:
|
||||
def get_network_status(self) -> list[dict]:
|
||||
"""
|
||||
Get UTE network status from device id.
|
||||
|
||||
Returns:
|
||||
dict: UTE network status
|
||||
"""
|
||||
if not self.authorization:
|
||||
self._login()
|
||||
|
||||
network_status_url = f"{API_VERSION_1}/info/network/status"
|
||||
return self._make_request("GET", network_status_url).json()["data"]["summary"]
|
||||
|
||||
@ -263,6 +231,9 @@ class UTEClient:
|
||||
Returns:
|
||||
str: UTE renewable sources percentage
|
||||
"""
|
||||
if not self.authorization:
|
||||
self._login()
|
||||
|
||||
global_demand_url = f"{API_VERSION_1}/info/demand/global"
|
||||
return self._make_request("GET", global_demand_url).json()["data"]["renewableSources"]
|
||||
|
||||
@ -281,6 +252,9 @@ class UTEClient:
|
||||
Returns:
|
||||
dict: UTE info
|
||||
"""
|
||||
if not self.authorization:
|
||||
self._login()
|
||||
|
||||
if date_start is None or date_end is None:
|
||||
yesterday = datetime.now() - timedelta(days=1)
|
||||
yesterday_formatted = yesterday.strftime("%Y-%m-%d")
|
||||
@ -324,12 +298,12 @@ class UTEClient:
|
||||
|
||||
return active_energy
|
||||
|
||||
def _convert_powers_to_power_in_watts(self, readings: List[dict]) -> float:
|
||||
def _convert_powers_to_power_in_watts(self, readings: list[dict]) -> float:
|
||||
"""
|
||||
Convert powers to power in watts and determine the system type (monophasic, biphasic, triphasic) automatically.
|
||||
|
||||
Args:
|
||||
readings (List[dict]): List of readings
|
||||
readings (list[dict]): List of readings
|
||||
|
||||
Returns:
|
||||
float: Power in watts
|
||||
@ -367,6 +341,9 @@ class UTEClient:
|
||||
ReadingRequestFailedException: If the reading request fails.
|
||||
ReadingResponseInvalidException: If the reading response is invalid.
|
||||
"""
|
||||
if not self.authorization:
|
||||
self._login()
|
||||
|
||||
reading_request_url = f"{API_VERSION_1}/device/readingRequest"
|
||||
reading_url = f"{API_VERSION_1}/device/{self.device_id}/lastReading/30"
|
||||
|
||||
@ -374,7 +351,7 @@ class UTEClient:
|
||||
|
||||
reading_request = self._make_request("POST", reading_request_url, data=data)
|
||||
|
||||
if reading_request.status_code != HTTP_200_OK:
|
||||
if reading_request.status_code != requests.codes.ok:
|
||||
raise ReadingRequestFailedException("Error getting reading request")
|
||||
|
||||
response = self._make_request("GET", reading_url).json()
|
||||
|
0
tests/__init__.py
Normal file
0
tests/__init__.py
Normal file
338
tests/test_ute.py
Normal file
338
tests/test_ute.py
Normal file
@ -0,0 +1,338 @@
|
||||
"""Unit tests for UTEClient class."""
|
||||
|
||||
import time
|
||||
|
||||
import pytest
|
||||
import requests
|
||||
from pytest_mock import MockerFixture
|
||||
|
||||
from src.ute_wrapper.exceptions import (
|
||||
InvalidPlanException,
|
||||
InvalidPowerFactorException,
|
||||
MultipleDevicesException,
|
||||
ReadingRequestFailedException,
|
||||
ReadingResponseInvalidException,
|
||||
TariffException,
|
||||
UnsupportedMethodException,
|
||||
)
|
||||
from src.ute_wrapper.ute import UTEClient
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def ute_client(mocker: MockerFixture):
|
||||
"""Return a UTEClient instance with mocked methods."""
|
||||
mocker.patch.object(UTEClient, "_login", return_value="mocked_token")
|
||||
mocker.patch.object(
|
||||
UTEClient,
|
||||
"get_devices_list",
|
||||
return_value=[{"name": "Device 1", "accountServicePointId": "device_id_1"}],
|
||||
)
|
||||
mocker.patch.object(UTEClient, "get_account", return_value={"meterInfo": {"tariffType": "TRIPLE"}})
|
||||
return UTEClient("test@example.com", "1234567890")
|
||||
|
||||
|
||||
def test_make_request_success(ute_client, mocker: MockerFixture):
|
||||
"""Test the _make_request method with a successful request."""
|
||||
mocked_response = mocker.Mock(status_code=200, json=lambda: {"success": True})
|
||||
mocker.patch("src.ute_wrapper.ute.requests.get", return_value=mocked_response)
|
||||
response = ute_client._make_request("GET", "http://example.com")
|
||||
assert response.status_code == requests.codes.ok
|
||||
assert response.json()["success"] is True
|
||||
|
||||
|
||||
def test_make_request_no_authorization(ute_client, mocker: MockerFixture):
|
||||
"""Test the _make_request method when there is no authorization token."""
|
||||
ute_client.authorization = None
|
||||
mocked_response = mocker.Mock(status_code=requests.codes.ok, json=lambda: {"success": True})
|
||||
mocker.patch("requests.get", return_value=mocked_response)
|
||||
response = ute_client._make_request("GET", "http://example.com")
|
||||
assert response.status_code == requests.codes.ok
|
||||
assert response.json()["success"] is True
|
||||
|
||||
|
||||
def test_make_request_expired_authorization(ute_client, mocker: MockerFixture):
|
||||
"""Test the _make_request method when the authorization code has expired."""
|
||||
mocked_unauthorized_response = mocker.Mock(status_code=requests.codes.unauthorized)
|
||||
mocked_success_response = mocker.Mock(status_code=requests.codes.ok, json=lambda: {"success": True})
|
||||
mocker.patch("requests.get", side_effect=[mocked_unauthorized_response, mocked_success_response])
|
||||
mocker.patch.object(ute_client, "_login")
|
||||
response = ute_client._make_request("GET", "http://example.com")
|
||||
assert response.status_code == requests.codes.ok
|
||||
assert response.json()["success"] is True
|
||||
ute_client._login.assert_called_once()
|
||||
|
||||
|
||||
def test_make_request_all_retries_failed(ute_client, mocker: MockerFixture):
|
||||
"""Test the _make_request method when all retries fail."""
|
||||
mocked_response = mocker.Mock()
|
||||
mocked_response.raise_for_status.side_effect = requests.RequestException
|
||||
mocker.patch("requests.get", return_value=mocked_response)
|
||||
mocker.patch("time.sleep")
|
||||
total_call_count = 3
|
||||
with pytest.raises(Exception, match="All retries failed."):
|
||||
ute_client._make_request("GET", "http://example.com", retries=total_call_count)
|
||||
assert mocked_response.raise_for_status.call_count == total_call_count
|
||||
assert time.sleep.call_count == total_call_count - 1
|
||||
|
||||
|
||||
def test_method_not_supported(ute_client):
|
||||
"""Test the _method_not_supported method."""
|
||||
with pytest.raises(UnsupportedMethodException):
|
||||
ute_client._method_not_supported()
|
||||
|
||||
|
||||
def test_login(ute_client, mocker: MockerFixture):
|
||||
"""Test the _login method."""
|
||||
mocked_response = mocker.Mock(text="mocked_token")
|
||||
mocker.patch.object(ute_client, "_make_request", return_value=mocked_response)
|
||||
token = ute_client._login()
|
||||
assert token == "mocked_token"
|
||||
|
||||
|
||||
def test_validate_power_factor(ute_client):
|
||||
"""Test the _validate_power_factor method."""
|
||||
with pytest.raises(InvalidPowerFactorException):
|
||||
ute_client.power_factor = 1.5
|
||||
ute_client._validate_power_factor()
|
||||
|
||||
|
||||
def test_initialize_device_id(ute_client, mocker: MockerFixture):
|
||||
"""Test the _initialize_device_id method."""
|
||||
ute_client.device_id = ""
|
||||
mocker.patch.object(ute_client, "_select_device_id", return_value="selected_device_id")
|
||||
ute_client._initialize_device_id()
|
||||
assert ute_client.device_id == "selected_device_id"
|
||||
|
||||
|
||||
def test_initialize_average_cost_per_kwh(ute_client, mocker: MockerFixture):
|
||||
"""Test the _initialize_average_cost_per_kwh method."""
|
||||
ute_client.average_cost_per_kwh = 0.0
|
||||
mocker.patch.object(ute_client, "_determine_average_cost", return_value=5.0)
|
||||
ute_client._initialize_average_cost_per_kwh()
|
||||
assert ute_client.average_cost_per_kwh == 5.0
|
||||
|
||||
|
||||
def test_select_device_id_multiple_devices(ute_client, mocker: MockerFixture):
|
||||
"""Test the _select_device_id method when there are multiple devices."""
|
||||
mocker.patch.object(
|
||||
ute_client,
|
||||
"get_devices_list",
|
||||
return_value=[
|
||||
{"name": "Device 1", "accountServicePointId": "device_id_1"},
|
||||
{"name": "Device 2", "accountServicePointId": "device_id_2"},
|
||||
],
|
||||
)
|
||||
with pytest.raises(MultipleDevicesException):
|
||||
ute_client._select_device_id()
|
||||
|
||||
|
||||
def test_determine_average_cost_invalid_tariff(ute_client, mocker: MockerFixture):
|
||||
"""Test the _determine_average_cost method with an invalid tariff."""
|
||||
mocker.patch.object(ute_client, "get_account", return_value={"meterInfo": {"tariffType": "INVALID"}})
|
||||
with pytest.raises(InvalidPlanException):
|
||||
ute_client._determine_average_cost()
|
||||
|
||||
|
||||
def test_determine_average_cost_invalid_tariff_key(ute_client, mocker: MockerFixture):
|
||||
"""Test the _determine_average_cost method with an invalid tariff key."""
|
||||
mocker.patch.object(ute_client, "get_account", side_effect=KeyError)
|
||||
with pytest.raises(TariffException, match="Tariff type not standard. Explicit definition required."):
|
||||
ute_client._determine_average_cost()
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"date_start, date_end",
|
||||
[
|
||||
("2023-05-01", "2023-05-02"),
|
||||
(None, None),
|
||||
],
|
||||
)
|
||||
def test_get_historic_consumption(ute_client, mocker: MockerFixture, date_start, date_end):
|
||||
"""Test the get_historic_consumption method."""
|
||||
mocked_response = {
|
||||
"data": [
|
||||
{"magnitudeVO": "IMPORT_ACTIVE_ENERGY", "date": "2023-05-01T00:00:00+00:00", "value": "10.0"},
|
||||
{"magnitudeVO": "IMPORT_ACTIVE_ENERGY", "date": "2023-05-02T00:00:00+00:00", "value": "20.0"},
|
||||
],
|
||||
}
|
||||
mocker.patch.object(ute_client, "_login")
|
||||
mocker.patch.object(ute_client, "_make_request", return_value=mocker.Mock(json=lambda: mocked_response))
|
||||
result = ute_client.get_historic_consumption(date_start, date_end)
|
||||
assert result["total"]["sum_in_kwh"] == 30.0
|
||||
assert result["total"]["aproximated_cost_in_uyu"] == 136.579
|
||||
assert len(result["dates"]) == 2
|
||||
|
||||
|
||||
def test_get_current_usage_info_success(ute_client, mocker: MockerFixture):
|
||||
"""Test the get_current_usage_info method with a successful request."""
|
||||
readings = [
|
||||
{"tipoLecturaMGMI": "I1", "valor": "10"},
|
||||
{"tipoLecturaMGMI": "V1", "valor": "220"},
|
||||
]
|
||||
mocked_reading_request = mocker.Mock(status_code=requests.codes.ok)
|
||||
mocked_reading_response = mocker.Mock(json=lambda: {"success": True, "data": {"readings": readings}})
|
||||
mocker.patch.object(ute_client, "_login")
|
||||
mocker.patch.object(ute_client, "_make_request", side_effect=[mocked_reading_request, mocked_reading_response])
|
||||
|
||||
result = ute_client.get_current_usage_info()
|
||||
|
||||
assert result["success"] is True
|
||||
assert result["data"]["readings"] == readings
|
||||
assert result["data"]["power_in_watts"] == 2200.0
|
||||
assert result["data"]["using_power_factor"] is True
|
||||
|
||||
|
||||
def test_get_current_usage_info_failed_request(ute_client, mocker: MockerFixture):
|
||||
"""Test the get_current_usage_info method with a failed request."""
|
||||
mocker.patch.object(ute_client, "_login")
|
||||
mocker.patch.object(
|
||||
ute_client,
|
||||
"_make_request",
|
||||
side_effect=[mocker.Mock(status_code=400), mocker.Mock(json=lambda: {"success": False})],
|
||||
)
|
||||
with pytest.raises(ReadingRequestFailedException):
|
||||
ute_client.get_current_usage_info()
|
||||
|
||||
|
||||
def test_get_current_usage_info_invalid_response(ute_client, mocker: MockerFixture):
|
||||
"""Test the get_current_usage_info method with an invalid response."""
|
||||
mocker.patch.object(ute_client, "_login")
|
||||
mocker.patch.object(
|
||||
ute_client,
|
||||
"_make_request",
|
||||
side_effect=[
|
||||
mocker.Mock(status_code=requests.codes.ok),
|
||||
mocker.Mock(json=lambda: {"success": True, "data": {}}),
|
||||
],
|
||||
)
|
||||
with pytest.raises(ReadingResponseInvalidException):
|
||||
ute_client.get_current_usage_info()
|
||||
|
||||
|
||||
def test_get_average_price_invalid_plan(ute_client):
|
||||
"""Test the get_average_price method with an invalid plan."""
|
||||
with pytest.raises(InvalidPlanException):
|
||||
ute_client.get_average_price("invalid_plan")
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"plan, expected_price",
|
||||
[
|
||||
("triple", 4.5526324),
|
||||
("doble", 5.523887),
|
||||
],
|
||||
)
|
||||
def test_get_average_price(ute_client, plan, expected_price):
|
||||
"""Test the get_average_price method."""
|
||||
result = ute_client.get_average_price(plan)
|
||||
assert result == expected_price
|
||||
|
||||
|
||||
def test_get_peak(ute_client, mocker: MockerFixture):
|
||||
"""Test the get_peak method."""
|
||||
expected_peak_data = {
|
||||
"deviceId": "test_device_id",
|
||||
"peak": {
|
||||
"value": 123.45,
|
||||
"date": "2023-06-01T10:00:00Z",
|
||||
},
|
||||
}
|
||||
|
||||
mocked_response = mocker.Mock(json=lambda: {"data": expected_peak_data})
|
||||
mocker.patch.object(ute_client, "_login")
|
||||
mocker.patch.object(ute_client, "_make_request", return_value=mocked_response)
|
||||
|
||||
result = ute_client.get_peak()
|
||||
|
||||
assert result == expected_peak_data
|
||||
ute_client._make_request.assert_called_once_with(
|
||||
"GET",
|
||||
f"https://rocme.ute.com.uy/api/v1/accounts/{ute_client.device_id}/peak",
|
||||
)
|
||||
|
||||
|
||||
def test_get_network_status(ute_client, mocker: MockerFixture):
|
||||
"""Test the get_network_status method."""
|
||||
expected_network_status = [
|
||||
{
|
||||
"departmentId": 1,
|
||||
"clientsWithoutService": 100,
|
||||
"percentageClientsWithoutService": 0.5,
|
||||
},
|
||||
{
|
||||
"departmentId": 2,
|
||||
"clientsWithoutService": requests.codes.ok,
|
||||
"percentageClientsWithoutService": 1.0,
|
||||
},
|
||||
]
|
||||
|
||||
mocked_response = mocker.Mock(json=lambda: {"data": {"summary": expected_network_status}})
|
||||
mocker.patch.object(ute_client, "_login")
|
||||
mocker.patch.object(ute_client, "_make_request", return_value=mocked_response)
|
||||
|
||||
result = ute_client.get_network_status()
|
||||
|
||||
assert result == expected_network_status
|
||||
ute_client._make_request.assert_called_once_with(
|
||||
"GET",
|
||||
"https://rocme.ute.com.uy/api/v1/info/network/status",
|
||||
)
|
||||
|
||||
|
||||
def test_get_renewable_sources(ute_client, mocker: MockerFixture):
|
||||
"""Test the get_renewable_sources method."""
|
||||
expected_renewable_sources = "50.0%"
|
||||
|
||||
mocked_response = mocker.Mock(json=lambda: {"data": {"renewableSources": expected_renewable_sources}})
|
||||
mocker.patch.object(ute_client, "_login")
|
||||
mocker.patch.object(ute_client, "_make_request", return_value=mocked_response)
|
||||
|
||||
result = ute_client.get_renewable_sources()
|
||||
|
||||
assert result == expected_renewable_sources
|
||||
ute_client._make_request.assert_called_once_with(
|
||||
"GET",
|
||||
"https://rocme.ute.com.uy/api/v1/info/demand/global",
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"readings, expected_power",
|
||||
[
|
||||
(
|
||||
[
|
||||
{"tipoLecturaMGMI": "I1", "valor": "10"},
|
||||
{"tipoLecturaMGMI": "V1", "valor": "220"},
|
||||
],
|
||||
2200.0,
|
||||
),
|
||||
(
|
||||
[
|
||||
{"tipoLecturaMGMI": "I1", "valor": "10"},
|
||||
{"tipoLecturaMGMI": "I2", "valor": "10"},
|
||||
{"tipoLecturaMGMI": "V1", "valor": "220"},
|
||||
{"tipoLecturaMGMI": "V2", "valor": "220"},
|
||||
],
|
||||
2200.0,
|
||||
),
|
||||
(
|
||||
[
|
||||
{"tipoLecturaMGMI": "I1", "valor": "10"},
|
||||
{"tipoLecturaMGMI": "I2", "valor": "10"},
|
||||
{"tipoLecturaMGMI": "I3", "valor": "10"},
|
||||
{"tipoLecturaMGMI": "V1", "valor": "220"},
|
||||
{"tipoLecturaMGMI": "V2", "valor": "220"},
|
||||
{"tipoLecturaMGMI": "V3", "valor": "220"},
|
||||
],
|
||||
3810.4,
|
||||
),
|
||||
(
|
||||
[],
|
||||
0.0,
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_convert_powers_to_power_in_watts(ute_client, readings, expected_power):
|
||||
"""Test the _convert_powers_to_power_in_watts method."""
|
||||
result = ute_client._convert_powers_to_power_in_watts(readings)
|
||||
assert result == expected_power
|
Reference in New Issue
Block a user