pax_global_header 0000666 0000000 0000000 00000000064 15017405234 0014513 g ustar 00root root 0000000 0000000 52 comment=a0746ca996a194bc75a2c4dbed7f4d8b0218528e
pyatmo-9.2.1/ 0000775 0000000 0000000 00000000000 15017405234 0013035 5 ustar 00root root 0000000 0000000 pyatmo-9.2.1/.devcontainer/ 0000775 0000000 0000000 00000000000 15017405234 0015574 5 ustar 00root root 0000000 0000000 pyatmo-9.2.1/.devcontainer/Dockerfile.dev 0000664 0000000 0000000 00000001221 15017405234 0020337 0 ustar 00root root 0000000 0000000 ARG VARIANT="3.11"
FROM mcr.microsoft.com/vscode/devcontainers/python:0-${VARIANT}
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
WORKDIR /workspaces
# Install Python dependencies from requirements
RUN pip3 install --upgrade pip \
&& pip3 install uv \
&& pip3 install pdbpp \
&& pip3 install pre-commit \
&& pip3 install time-machine \
&& pip3 install pytest-cov \
&& pip3 install anyio
# Remove any old pytest versions that might conflict
RUN python3 -m pip install --upgrade --force-reinstall pytest \
&& rm -rf /usr/local/py-utils/venvs/pytest/bin/pytest
# Set the default shell to bash instead of sh
ENV SHELL="/bin/bash"
pyatmo-9.2.1/.devcontainer/devcontainer.json 0000664 0000000 0000000 00000002535 15017405234 0021155 0 ustar 00root root 0000000 0000000 {
"name": "pyatmo Dev",
"context": ".",
"dockerFile": "./Dockerfile.dev",
"containerEnv": {
"DEVCONTAINER": "1"
},
"postCreateCommand": "pip3 install -e . && pre-commit run ruff",
"runArgs": [
"-e",
"GIT_EDITOR=code --wait"
],
"customizations": {
"vscode": {
"extensions": [
"ms-python.vscode-pylance",
"visualstudioexptteam.vscodeintellicode"
]
},
"settings": {
"python.pythonPath": "/usr/local/bin/python",
"python.defaultInterpreterPath": "/user/local/bin/python",
"python.linting.pylintEnabled": true,
"python.linting.enabled": true,
"python.formatting.provider": "black",
"python.testing.pytestArgs": [
"--no-cov"
],
"python.testing.unittestEnabled": false,
"python.testing.pytestEnabled": true,
"editor.formatOnPaste": false,
"editor.formatOnSave": true,
"editor.formatOnType": true,
"files.trimTrailingWhitespace": true,
"terminal.integrated.profiles.linux": {
"zsh": {
"path": "/usr/bin/zsh"
}
},
"terminal.integrated.defaultProfile.linux": "zsh"
}
}
}
pyatmo-9.2.1/.github/ 0000775 0000000 0000000 00000000000 15017405234 0014375 5 ustar 00root root 0000000 0000000 pyatmo-9.2.1/.github/dependabot.yml 0000664 0000000 0000000 00000001316 15017405234 0017226 0 ustar 00root root 0000000 0000000 # To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
# Check for updates to GitHub Actions every weekday
interval: "daily"
- package-ecosystem: "uv" # See documentation for possible values
directory: "/" # Location of package manifests
schedule:
interval: "weekly"
# Check for pip updates on Sundays
day: "sunday"
pyatmo-9.2.1/.github/workflows/ 0000775 0000000 0000000 00000000000 15017405234 0016432 5 ustar 00root root 0000000 0000000 pyatmo-9.2.1/.github/workflows/publish-to-pypi.yml 0000664 0000000 0000000 00000001452 15017405234 0022224 0 ustar 00root root 0000000 0000000 name: Publish 📦 to PyPI
on:
push:
tags:
- "v*"
permissions:
contents: read
jobs:
build-n-publish:
name: Build and publish 📦 to PyPI
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Python 3.11
uses: actions/setup-python@v5.6.0
with:
python-version: 3.11.4
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install build
- name: Build a binary wheel and a source tarball
run: >-
python -m build .
- name: Publish 📦 to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
password: ${{ secrets.pypi_prod_token }}
pyatmo-9.2.1/.github/workflows/publish-to-test-pypi.yml 0000664 0000000 0000000 00000001613 15017405234 0023200 0 ustar 00root root 0000000 0000000 name: Publish 📦 to TestPyPI
on:
push:
branches:
- development
jobs:
build-n-publish:
name: Build and publish 📦 to TestPyPI
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4
with:
ref: development
fetch-depth: 0
- name: Set up Python 3.11
uses: actions/setup-python@v5.6.0
with:
python-version: 3.11.4
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install build
- name: Build a binary wheel and a source tarball
run: >-
python -m build .
- name: Publish 📦 to Test PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
password: ${{ secrets.PYPI_TEST_TOKEN }}
repository-url: https://test.pypi.org/legacy/
pyatmo-9.2.1/.github/workflows/pythonpackage.yml 0000664 0000000 0000000 00000004346 15017405234 0022021 0 ustar 00root root 0000000 0000000 name: Python package
on:
push:
branches:
- '*'
pull_request:
branches:
- master
- development
permissions:
contents: read
jobs:
black:
runs-on: ubuntu-latest
strategy:
max-parallel: 1
matrix:
python-version: [3.11.4]
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5.6.0
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install black
- name: Check with black
run: |
black --check --diff src/pyatmo/ tests/
linter:
runs-on: ubuntu-latest
strategy:
max-parallel: 4
matrix:
python-version: [3.11.4]
steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5.6.0
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install ruff
- name: Lint with ruff
run: |
ruff check src/pyatmo tests/
typechecker:
runs-on: ubuntu-latest
strategy:
max-parallel: 1
matrix:
python-version: [3.11.4]
steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5.6.0
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip tox-gh-actions
- name: Typecheck with mypy
run: |
tox -e mypy
build:
runs-on: ubuntu-latest
strategy:
max-parallel: 4
matrix:
python-version: [3.11.4, 3.12.5]
steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5.6.0
with:
python-version: ${{ matrix.python-version }}
- name: Run tests with tox
run: |
pip install tox tox-gh-actions
tox -e py311,py312
pyatmo-9.2.1/.github/workflows/release_gh.yml 0000664 0000000 0000000 00000002544 15017405234 0021260 0 ustar 00root root 0000000 0000000 # This is a basic workflow to help you get started with Actions
name: Create Github Release
# Controls when the action will run. Triggers the workflow on push or pull request
# events but only for the development branch
on:
push:
# Sequence of patterns matched against refs/tags
tags:
- 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
# This workflow contains a single job called "build"
build:
# The type of runner that the job will run on
runs-on: ubuntu-latest
permissions:
contents: write
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- uses: actions/checkout@v4
with:
fetch-depth: 0
# Runs a single command using the runners shell
- name: Create a Release
uses: actions/create-release@v1.1.4
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
# The name of the tag. This should come from the webhook payload, `github.GITHUB_REF` when a user pushes a new tag
tag_name: ${{ github.ref }}
# The name of the release. For example, `Release v1.0.1`
release_name: Release ${{ github.ref }}
pyatmo-9.2.1/.gitignore 0000664 0000000 0000000 00000013144 15017405234 0015030 0 ustar 00root root 0000000 0000000
build/
dist/
**/pyatmo.egg-info/
*.pyc
.DS_Store
access.token
cov.xml
venv/
.venv
# Created by https://www.gitignore.io/api/python,pycharm
# Edit at https://www.gitignore.io/?templates=python,pycharm
### PyCharm ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
# Generated files
.idea/**/contentModel.xml
# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
# Gradle
.idea/**/gradle.xml
.idea/**/libraries
# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr
# CMake
cmake-build-*/
# Mongo Explorer plugin
.idea/**/mongoSettings.xml
# File-based project format
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Editor-based Rest Client
.idea/httpRequests
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser
### PyCharm Patch ###
# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
# *.iml
# modules.xml
# .idea/misc.xml
# *.ipr
# Sonarlint plugin
.idea/**/sonarlint/
# SonarQube Plugin
.idea/**/sonarIssues.xml
# Markdown Navigator plugin
.idea/**/markdown-navigator.xml
.idea/**/markdown-navigator/
### Python ###
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
pip-wheel-metadata/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
.pytest_cache/
# Translations
*.mo
*.pot
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# pyenv
.python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
Pipfile.lock
# celery beat schedule file
celerybeat-schedule
# SageMath parsed files
*.sage.py
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# Mr Developer
.mr.developer.cfg
.project
.pydevproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# End of https://www.gitignore.io/api/python,pycharm
# Created by https://www.gitignore.io/api/code
# Edit at https://www.gitignore.io/?templates=code
### Code ###
.vscode/*
# End of https://www.gitignore.io/api/code
# Created by https://www.gitignore.io/api/jetbrains
# Edit at https://www.gitignore.io/?templates=jetbrains
### JetBrains ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
# Generated files
.idea/**/contentModel.xml
# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
# Gradle
.idea/**/gradle.xml
.idea/**/libraries
# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr
# CMake
cmake-build-*/
# Mongo Explorer plugin
.idea/**/mongoSettings.xml
# File-based project format
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Editor-based Rest Client
.idea/httpRequests
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser
### JetBrains Patch ###
# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
# *.iml
# modules.xml
# .idea/misc.xml
# *.ipr
# Sonarlint plugin
.idea/**/sonarlint/
# SonarQube Plugin
.idea/**/sonarIssues.xml
# Markdown Navigator plugin
.idea/**/markdown-navigator.xml
.idea/**/markdown-navigator/
# End of https://www.gitignore.io/api/jetbrains
.idea
__version__.py
pyatmo-9.2.1/.pre-commit-config.yaml 0000664 0000000 0000000 00000002361 15017405234 0017320 0 ustar 00root root 0000000 0000000 # Note: don't use this config for your own repositories. Instead, see
# "Version control integration" in README.md.
default_stages: [pre-commit, pre-push]
exclude: ^(fixtures/)
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.11.9
hooks:
- id: ruff
args:
- --fix
- repo: https://github.com/psf/black
rev: 25.1.0
hooks:
- id: black
language_version: python3
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0 # Use the ref you want to point at
hooks:
- id: check-ast
- id: no-commit-to-branch
args: [--branch, master, --branch, devel]
- id: forbid-new-submodules
- id: check-merge-conflict
- id: detect-private-key
- id: end-of-file-fixer
- id: mixed-line-ending
args: [--fix=lf]
- id: trailing-whitespace
- id: debug-statements
- id: check-toml
- id: pretty-format-json
args: [--autofix]
exclude: ^(\.devcontainer|\.vscode)/
# on commit-msg, it needs 'pre-commit install -t commit-msg'*
- repo: https://github.com/compilerla/conventional-pre-commit
rev: v4.2.0
hooks:
- id: conventional-pre-commit
stages: [commit-msg]
args: []
pyatmo-9.2.1/.tool-versions 0000664 0000000 0000000 00000000016 15017405234 0015656 0 ustar 00root root 0000000 0000000 python 3.11.4
pyatmo-9.2.1/.vscode/ 0000775 0000000 0000000 00000000000 15017405234 0014376 5 ustar 00root root 0000000 0000000 pyatmo-9.2.1/.vscode/tasks.json 0000664 0000000 0000000 00000003743 15017405234 0016425 0 ustar 00root root 0000000 0000000 {
"version": "2.0.0",
"tasks": [
{
"label": "Pytest",
"detail": "Run test suite with pytest",
"type": "shell",
"command": "pytest tests",
"dependsOn": [
"Install all Test Requirements"
],
"group": {
"kind": "test",
"isDefault": true
},
"presentation": {
"reveal": "always",
"panel": "new"
},
"problemMatcher": []
},
{
"label": "Pylint",
"detail": "Run pylint code analysis",
"type": "shell",
"command": "pylint pyatmo",
"dependsOn": [
"Install all Requirements"
],
"group": {
"kind": "test",
"isDefault": true
},
"presentation": {
"reveal": "always",
"panel": "new"
},
"problemMatcher": []
},
{
"label": "Code Coverage",
"detail": "Generate code coverage report",
"type": "shell",
"command": "pytest ./tests --cov=pyatmo --cov-report term-missing",
"group": {
"kind": "test",
"isDefault": true
},
"presentation": {
"reveal": "always",
"panel": "new"
},
"problemMatcher": []
},
{
"label": "Build wheel artifacts",
"command": "rm -r dist; python -m build",
"type": "shell",
"options": {
"cwd": "${workspaceRoot}/"
},
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": [],
"presentation": {
"reveal": "always",
"panel": "new"
}
}
]
}
pyatmo-9.2.1/CHANGELOG.md 0000664 0000000 0000000 00000025665 15017405234 0014664 0 ustar 00root root 0000000 0000000 # Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [unreleased]
### Added
-
### Changed
-
### Fixed
-
### Removed
-
## [9.2.1]
### Added
- Added SPDX license identifier [PEP 639](https://peps.python.org/pep-0639/).
### Fixed
- Removed upper bound for Python version constraint.
## [9.2.0]
### Changed
- Improved schedule handling
- Updated dev container configuration
## [9.1.0]
### Added
- Support for 3rd party zigbee roller blinds
- Support for Netatmo Indoor Camera Advance (NPC)
- Fixtures for multiple modules (NLL, NLV, NLLV, NLJ, NLIS, NLPT, NLPD, NLPO)
- Added conventional-pre-commit hook for commit-msg stage
### Changed
- Updated device type descriptions to better reflect their functionality
- Removed some unnecessary mixins from Legrand device classes
- Create RemoteControlMixin for easier device representation
- Replaced setup-cfg-fmt with pyprojectsort pre-commit hook
- Improved error handling in extract_raw_data for empty homes
- Refactored test file handling to use anyio.open_file()
- Updated pre-commit hooks to latest versions
- Updated project metadata in pyproject.toml
### Fixed
- Handling of cooling/heating control mode
- Fixed async tests to avoid blocking file access
- Fixed detection of missing homes in API responses
- Fixed async mock configuration in tests
- Fixed error handling for throttling errors
- Fixed exception class names to end with "Error" suffix
- Fixed handling of empty homes data
- Fixed test file handling to use anyio
- Fixed coverage report configuration in tox.ini
- Fixed type casting in async_update_measures method for Energy module
- Fixed error handling for missing parameters in fake_post_request
- Fixed handling of unknown device types
- Fixed handling of place data and historical data in NetatmoBase class
- Fixed handling of station ids in fix_id function
- Fixed handling of zone_id type in async_set_schedule_temperatures method
- Fixed handling of angle for display in module.py
- Fixed handling of device type and boiler status in Room class
- Fixed handling of missing parameters in test functions
- Fixed handling of file paths for fixtures
- Fixed handling of deprecated assert_called method
- Fixed handling of test cases for NLP, NLF, and NLIS Legrand modules
- Fixed handling of test cases for different weather modules
- Fixed handling of mypy configuration in tox.ini
## [9.0.0]
### Added
- Support for Pilot Wire ("fil pilote" support)
- AC Auto schedule
### Changed
- Replaced pipenv with uv and updated readme
### Removed
- Python 3.10 support
### Fixed
- Propper handling of climate schedules in heating or cooling
- Fix HVAC related setpoint evaluation
- devcontainer
## [8.1.0]
### Added
- Expose camera person status
- Add NLE support
- Add proper energy support
- Add cooler support
- Add BNS support
## [8.0.3]
### Added
- Add NLLF centralized ventilation controller
### Fixed
- Add BNSC switch capability
## [8.0.3]
### Added
- Add NLLF centralized ventilation controller
### Fixed
- Add BNSC switch capability
## [8.0.2]
### Fixed
- Duplicates in entity names (https://github.com/home-assistant/core/issues/88792)
- Add shutter capabilities to BNAB, BNAS and BNMS (https://github.com/home-assistant/core/issues/106392)
## [8.0.1]
### Added
- NLFE Legrand dimmer switch evolution
## [8.0.0]
### Added
- Bticino IP scopes
- Bticino dimmable light (BNLD)
- Start and end times to room class
### Changed
- Add power data to NLPD entities
### Removed
- deprecated code
## [7.6.0]
### Added
- Opening category for NACamDoorTag
- Schedule modification
- Bticino MyHome Server 1 scopes
- NLPD - Drivia dry contact
- BTicino module stubs (functionality will come later)
- support for Legrand garage door opener (NLJ)
- support for BTicino intelligent light (BNIL)
### Removed
- Support for Python 3.8 and 3.9
### Fixed
- Update functionality for NLP, NLC, NLT and NLG
## [7.5.0]
### Added
- Add NLAS - wireless batteryless scene switch device type
- Add BNEU, EBU, NLDD, NLAO, NLLF, NLUO, NLUP, Z3L, NLTS, NLUF
### Fixed
- Update Legrand and BTicino devices
- Fix broken temperature setter when OTM is in the setup
## [7.4.0]
### Added
- Add NLUF device stub
- Add TPSRS Somfy shutters
### Changed
- Update test fixture data to be in line with HA tests
### Fixed
- Handle unknown device types and log
- Fix misc device types and add stubs for unknown
## [7.3.0]
### Added
- Add Legrand NLUI device class
### Changed
- Minor code clean ups
### Fixed
- Handle invalid ip addressed from the API more gracefully
- Let weather station devices register home even if home does not exist
- Catch ContentTypeError error and handle more graceful
- Fix key error when battery hits very_low
- Response handling issues
## [7.2.0]
### Added
- Add NLPO Legrand contactor
- Add NLD Legrand Double On/Off dimmer remote
- Add NLFE Legrand On-Off dimmer switch
- Add BTicino device support for BNCX, BNDL, BNSL
## [7.1.1]
### Fixed
- Fix Netatmo radiator valves (NRV) set termpature
## [7.1.0] - 2022-10-03
### Added
- Adds Legrand NLIS double switches
- Adds Legrand NLPT relay/teleruptor
### Fixed
- Use dimmer type for Legrand NLF dimmers
## [7.0.1] - 2022-06-05
### Deprecated
- The following modules are deprecated and will be removed in pyatmo 8.0.0
- camera
- home_coach
- public_data
- thermostat
- weather_station
## [7.0.0] - 2022-06-05
### Added
- Adds support for Netatmo modulating thermostat
- Adds support for Netatmo doorbell
- Adds support for shutters, lights, energy meters and switches
- Adds support for 3rd party devices from different Legrand brands such as BTicinio, Bubendorff, Smarther, CX3
- Fetch favorite weather sensors
- Add support for third-party Netatmo devices (see `base_url` and `user_prefix` parameters)
### Changed
- Replace freezegun with time-machine
### Deprecated
- The following modules are deprecated and will be removed in pyatmo 8.0.0
- camera
- home_coach
- public_data
- thermostat
- weather_station
### Removed
-
### Fixed
- Use async fixture decorators
### Security
-
## [6.2.4] - 2022-01-31
### Fixed
- Crash when home does not contain valid devices
## [6.2.2] - 2021-12-29
### Fixed
- Use ID if schedule name is missing
## [6.2.1] - 2021-12-18
### Fixed
- Catch when no body is contained in the response
## [6.2.0] - 2021-11-19
### Added
- Add support for python3.20
- Introduce climate module #156
### Changed
- Use assignment expressions
## [6.1.0] - 2021-10-03
### Added
- Provide a VS Code devcontainer
### Changed
- Provide separate method for image retrival
- Minor f-string conversions
## [6.0.0] - 2021-09-10
### Changed
- Ensure camera name is not None
- Split persons by home
- BREAKING: Require home_id for person related methods
- version is now managed by setuptools scm
## [5.2.3] - 2021-07-22
### Fixed
- Ignore if API omits unimportant attributes in response
## [5.2.2] - 2021-07-21
### Fixed
- Ignore if API omits unimportant attributes in response
## [5.2.1] - 2021-07-10
### Added
- Distribute type information
### Changed
- Update type annotations
## [5.2.0] - 2021-06-30
### Changed
- [BREAKING] Fix parameter order of set person home/away methods
- Refactor camera person detection checks
## [5.1.0] - 2021-06-14
### Fixed
- Handle error when camera is not reachable more graceful
- Update selfcheck to use the new update methods
- Fix false positive errors when no climate devices are registered
### Security
- Upgrade aiohttp to 3.7.4 or later to fix vulnerability
## [4.2.3] - 2021-05-17
### Fixed
- Extraction of climate schedules was looking for the wrong attribute (Backported from [5.0.1])
## [5.0.1] - 2021-05-09
### Fixed
- Extraction of climate schedules was looking for the wrong attribute
## [5.0.0] - 2021-04-26
### Added
- Async support
### Changed
- [BREAKING] Data retrival extracted into separate update method
## [4.2.2] - 2021-01-20
### Fixed
- Fix error when camera does not return a local url
## [4.2.1] - 2020-12-03
### Changed
- Improve CI & deployment
## [4.2.0] - 2020-11-02
### Changed
- Improve CI & deployment
### Fixed
- Set station name if not contained in the backend data
### Removed
- Remove min and max from weather station
## [4.1.0] - 2020-10-07
### Fixed
- Fix crash when station name is not contained in the backend data
[unreleased]: https://github.com/jabesq-org/pyatmo/compare/v9.2.1...HEAD
[9.2.1]: https://github.com/jabesq-org/pyatmo/compare/v9.2.0...v9.2.1
[9.2.0]: https://github.com/jabesq-org/pyatmo/compare/v9.1.0...v9.2.0
[9.1.0]: https://github.com/jabesq-org/pyatmo/compare/v9.0.0...v9.1.0
[9.0.0]: https://github.com/jabesq-org/pyatmo/compare/v8.1.0...v9.0.0
[8.1.0]: https://github.com/jabesq/pyatmo/compare/v8.0.3...v8.1.0
[8.0.3]: https://github.com/jabesq/pyatmo/compare/v8.0.2...v8.0.3
[8.0.2]: https://github.com/jabesq/pyatmo/compare/v8.0.1...v8.0.2
[8.0.1]: https://github.com/jabesq/pyatmo/compare/v8.0.0...v8.0.1
[8.0.0]: https://github.com/jabesq/pyatmo/compare/v7.6.0...v8.0.0
[7.6.0]: https://github.com/jabesq/pyatmo/compare/v7.5.0...v7.6.0
[7.5.0]: https://github.com/jabesq/pyatmo/compare/v7.4.0...v7.5.0
[7.4.0]: https://github.com/jabesq/pyatmo/compare/v7.3.0...v7.4.0
[7.3.0]: https://github.com/jabesq/pyatmo/compare/v7.2.0...v7.3.0
[7.2.0]: https://github.com/jabesq/pyatmo/compare/v7.1.1...v7.2.0
[7.1.1]: https://github.com/jabesq/pyatmo/compare/v7.1.0...v7.1.1
[7.1.0]: https://github.com/jabesq/pyatmo/compare/v7.0.1...v7.1.0
[7.0.1]: https://github.com/jabesq/pyatmo/compare/v7.0.0...v7.0.1
[7.0.0]: https://github.com/jabesq/pyatmo/compare/v6.2.4...v7.0.0
[6.2.4]: https://github.com/jabesq/pyatmo/compare/v6.2.2...v6.2.4
[6.2.2]: https://github.com/jabesq/pyatmo/compare/v6.2.1...v6.2.2
[6.2.1]: https://github.com/jabesq/pyatmo/compare/v6.2.0...v6.2.1
[6.2.0]: https://github.com/jabesq/pyatmo/compare/v6.1.0...v6.2.0
[6.1.0]: https://github.com/jabesq/pyatmo/compare/v6.0.0...v6.1.0
[6.0.0]: https://github.com/jabesq/pyatmo/compare/v5.2.3...v6.0.0
[5.2.3]: https://github.com/jabesq/pyatmo/compare/v5.2.2...v5.2.3
[5.2.2]: https://github.com/jabesq/pyatmo/compare/v5.2.1...v5.2.2
[5.2.1]: https://github.com/jabesq/pyatmo/compare/v5.2.0...v5.2.1
[5.2.0]: https://github.com/jabesq/pyatmo/compare/v5.1.0...v5.2.0
[5.1.0]: https://github.com/jabesq/pyatmo/compare/v5.0.1...v5.1.0
[5.0.1]: https://github.com/jabesq/pyatmo/compare/v5.0.0...v5.0.1
[5.0.0]: https://github.com/jabesq/pyatmo/compare/v4.2.2...v5.0.0
[4.2.3]: https://github.com/jabesq/pyatmo/compare/v4.2.2...v4.2.3
[4.2.2]: https://github.com/jabesq/pyatmo/compare/v4.2.1...v4.2.2
[4.2.1]: https://github.com/jabesq/pyatmo/compare/v4.2.0...v4.2.1
[4.2.0]: https://github.com/jabesq/pyatmo/compare/v4.1.0...v4.2.0
[4.1.0]: https://github.com/jabesq/pyatmo/compare/v4.0.0...v4.1.0
[4.0.0]: https://github.com/jabesq/pyatmo/compare/v3.3.1...v4.0.0
[3.3.1]: https://github.com/jabesq/pyatmo/releases/tag/v3.3.1
pyatmo-9.2.1/CODEOWNERS 0000664 0000000 0000000 00000000337 15017405234 0014433 0 ustar 00root root 0000000 0000000 # These owners will be the default owners for everything in
# the repo. Unless a later match takes precedence,
# @jabesq and @cgtobi will be requested for
# review when someone opens a pull request.
* @jabesq @cgtobi
pyatmo-9.2.1/CODE_OF_CONDUCT.md 0000664 0000000 0000000 00000012122 15017405234 0015632 0 ustar 00root root 0000000 0000000 # Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
overall community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or
advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series
of actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within
the community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.
pyatmo-9.2.1/LICENSE.txt 0000664 0000000 0000000 00000002054 15017405234 0014661 0 ustar 00root root 0000000 0000000 MIT License
Copyright (c) 2018 Hugo DUPRAS
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
pyatmo-9.2.1/README.md 0000664 0000000 0000000 00000004622 15017405234 0014320 0 ustar 00root root 0000000 0000000 # pyatmo
[](https://github.com/ambv/black)
[](https://github.com/jabesq/pyatmo/actions?workflow=Python+package)
[](https://pypi.python.org/pypi/pyatmo)
[](https://github.com/jabesq/pyatmo/blob/master/LICENSE.txt)
> **Warning:**
> Due to personal reasons, I am currently unable to dedicate sufficient time to effectively manage this repository. Consequently, no attention will be given to existing or forthcoming issues until further notice. **However**, I want to assure you that I will continue to merge any pull requests that are submitted, provided they successfully pass the continuous integration tests and do not exhibit any glaring issues.
>
> I apologize for any inconvenience this may cause, and I sincerely hope to have the capacity to allocate more time to this repository in the near future. Your understanding is greatly appreciated.
>
> *Hugo DUPRAS (jabesq)*
---
Simple API to access Netatmo devices and data like weather station or camera data from Python 3.
For more detailed information see [dev.netatmo.com](http://dev.netatmo.com)
This project has no relation with the Netatmo company.
## Install
To install pyatmo simply run:
pip install pyatmo
Depending on your permissions you might be required to use sudo.
Once installed you can simply add `pyatmo` to your Python 3 scripts by including:
import pyatmo
## Note
The module requires a valid user account and a registered application.
Be aware that the module may stop working if Netatmo decides to change their API.
## Development
Prerequisits:
uv
python >=3.11
Clone the repo, install dependencies and install pre-commit hooks:
git clone
cd pyatmo
uv sync
pre-commit install
## Testing
To run the full suite simply run the following command from within the virtual environment:
pytest
or
python -m pytest tests/
To generate code coverage xml (e.g. for use in VSCode) run
python -m pytest --cov-report xml:cov.xml --cov pyatmo --cov-append tests/
Another way to run the tests is by using `tox`. This runs the tests against the installed package and multiple versions of python.
tox
or by specifying a python version
tox -e py310
pyatmo-9.2.1/fixtures/ 0000775 0000000 0000000 00000000000 15017405234 0014706 5 ustar 00root root 0000000 0000000 pyatmo-9.2.1/fixtures/archive/ 0000775 0000000 0000000 00000000000 15017405234 0016327 5 ustar 00root root 0000000 0000000 pyatmo-9.2.1/fixtures/archive/camera_data_empty.json 0000664 0000000 0000000 00000000130 15017405234 0022653 0 ustar 00root root 0000000 0000000 {
"status": "ok",
"time_exec": 0.03621506690979,
"time_server": 1560626960
} pyatmo-9.2.1/fixtures/archive/camera_data_events_until.json 0000664 0000000 0000000 00000010566 15017405234 0024252 0 ustar 00root root 0000000 0000000 {
"body": {
"events_list": [
{
"id": "a1b2c3d4e5f6abcdef123461",
"type": "person",
"time": 1560706232,
"camera_id": "12:34:56:00:f1:62",
"device_id": "12:34:56:00:f1:62",
"person_id": "91827374-7e04-5298-83ad-a0cb8372dff1",
"video_status": "deleted",
"is_arrival": true,
"message": "John Doe gesehen"
},
{
"id": "a1b2c3d4e5f6abcdef123462",
"type": "person_away",
"time": 1560706237,
"camera_id": "12:34:56:00:f1:62",
"device_id": "12:34:56:00:f1:62",
"person_id": "91827374-7e04-5298-83ad-a0cb8372dff1",
"message": "John Doe hat das Haus verlassen",
"sub_message": "John Doe gilt als „Abwesend“, da das mit diesem Profil verbundene Telefon den Bereich des Hauses verlassen hat."
},
{
"id": "a1b2c3d4e5f6abcdef123463",
"type": "person",
"time": 1560706241,
"camera_id": "12:34:56:00:f1:62",
"device_id": "12:34:56:00:f1:62",
"person_id": "91827375-7e04-5298-83ae-a0cb8372dff2",
"snapshot": {
"id": "19b13efa945ec892c6da2a8c",
"version": 1,
"key": "1704853cfc9571bd10618591dc9035e5bc0fa3203f44739c49a5b26d2f7ad67f",
"url": "https://netatmocameraimage.blob.core.windows.net/production/5ecfa94c6da5e5bc0fa3203f3cfdc903489219b13e2a8c548547b26d2f7ad6717039c49ac9571bd10618591f"
},
"video_id": "f914-aa7da416643-4744-82f9-4e7d4440b",
"video_status": "available",
"is_arrival": false,
"message": "Jane Doe gesehen"
},
{
"id": "a1b2c3d4e5f6abcdef123464",
"type": "wifi_status",
"time": 1560706271,
"camera_id": "12:34:56:00:8b:a2",
"device_id": "12:34:56:00:8b:a2",
"sub_type": 1,
"message": "Hall:WLAN-Verbindung erfolgreich hergestellt"
},
{
"id": "a1b2c3d4e5f6abcdef123465",
"type": "outdoor",
"time": 1560706283,
"camera_id": "12:34:56:00:a5:a4",
"device_id": "12:34:56:00:a5:a4",
"video_id": "string",
"video_status": "available",
"event_list": [
{
"type": "string",
"time": 1560706283,
"offset": 0,
"id": "c81bcf7b-2cfg-4ac9-8455-487ed00c0001",
"message": "Animal détecté",
"snapshot": {
"id": "5715e16849c75xxxx00000000xxxxx",
"version": 1,
"key": "7ac578d05030d0e170643a787ee0a29663dxxx00000xxxxx00000",
"url": "https://netatmocameraimage.blob.core.windows.net/production/1aa"
},
"vignette": {
"id": "5715e16849c75xxxx00000000xxxxx",
"version": 1,
"key": "7ac578d05030d0e170643a787ee0a29663dxxx00000xxxxx00000",
"url": "https://netatmocameraimage.blob.core.windows.net/production/1aa00000"
}
},
{
"type": "string",
"time": 1560706283,
"offset": 0,
"id": "c81bcf7b-2cfg-4ac9-8455-487ed00c0002",
"message": "Animal détecté",
"snapshot": {
"filename": "vod\/af74631d-8311-42dc-825b-82e3abeaab09\/events\/c53b-aze7a.jpg"
},
"vignette": {
"filename": "vod\/af74631d-8311-42dc-825b-82e3abeaab09\/events\/c5.jpg"
}
}
]
}
]
},
"status": "ok",
"time_exec": 0.03666909215079,
"time_server": 15607062321
} pyatmo-9.2.1/fixtures/archive/camera_home_data.json 0000664 0000000 0000000 00000040022 15017405234 0022451 0 ustar 00root root 0000000 0000000 {
"body": {
"homes": [
{
"id": "91763b24c43d3e344f424e8b",
"name": "MYHOME",
"persons": [
{
"id": "91827374-7e04-5298-83ad-a0cb8372dff1",
"last_seen": 1557071156,
"out_of_sight": true,
"face": {
"id": "d74fad765b9100ef480720a9",
"version": 1,
"key": "a4a95c24b808a89f8d1730fb69ecdf2bb8b72039d2c69928b029d67fc40cb2d7",
"url": "https://netatmocameraimage.blob.core.windows.net/production/d74fad765b9100ef480720a9a4a95c24b808a89f8d1730fb69ecdf2bb8b72039d2c69928b029d67fc40cb2d7"
},
"pseudo": "John Doe"
},
{
"id": "91827375-7e04-5298-83ae-a0cb8372dff2",
"last_seen": 1560600726,
"out_of_sight": true,
"face": {
"id": "d74fad765b9100ef480720a9",
"version": 3,
"key": "a4a95c24b808a89f8d1730039d2c69928b029d67fc40cb2d7fb69ecdf2bb8b72",
"url": "https://netatmocameraimage.blob.core.windows.net/production/d74fad765b9100ef480720a9a4a95c24b808a89f8d1730039d2c69928b029d67fc40cb2d7fb69ecdf2bb8b72"
},
"pseudo": "Jane Doe"
},
{
"id": "91827376-7e04-5298-83af-a0cb8372dff3",
"last_seen": 1560626666,
"out_of_sight": false,
"face": {
"id": "d74fad765b9100ef480720a9",
"version": 1,
"key": "a4a95c2d1730fb69ecdf2bb8b72039d2c69928b029d67fc40cb2d74b808a89f8",
"url": "https://netatmocameraimage.blob.core.windows.net/production/d74fad765b9100ef480720a9a4a95c2d1730fb69ecdf2bb8b72039d2c69928b029d67fc40cb2d74b808a89f8"
},
"pseudo": "Richard Doe"
},
{
"id": "91827376-7e04-5298-83af-a0cb8372dff4",
"last_seen": 1560621666,
"out_of_sight": true,
"face": {
"id": "d0ef44fad765b980720710a9",
"version": 1,
"key": "ab029da89f84a95c2d1730fb67fc40cb2d74b80869ecdf2bb8b72039d2c69928",
"url": "https://netatmocameraimage.blob.core.windows.net/production/d0ef44fad765b980720710a9ab029da89f84a95c2d1730fb67fc40cb2d74b80869ecdf2bb8b72039d2c69928"
}
}
],
"place": {
"city": "Frankfurt",
"country": "DE",
"timezone": "Europe/Berlin"
},
"cameras": [
{
"id": "12:34:56:00:f1:62",
"type": "NACamera",
"status": "on",
"vpn_url": "https://prodvpn-eu-2.netatmo.net/restricted/10.255.248.91/6d278460699e56180d47ab47169efb31/MpEylTU2MDYzNjRVD-LJxUnIndumKzLboeAwMDqTTg,,",
"is_local": true,
"sd_status": "on",
"alim_status": "on",
"name": "Hall",
"modules": [
{
"id": "12:34:56:00:f2:f1",
"type": "NIS",
"battery_percent": 84,
"rf": 68,
"status": "no_news",
"monitoring": "on",
"alim_source": "battery",
"tamper_detection_enabled": true,
"name": "Welcome's Siren"
}
],
"use_pin_code": false,
"last_setup": 1544828430
},
{
"id": "12:34:56:00:a5:a4",
"type": "NOC",
"status": "on",
"vpn_url": "https://prodvpn-eu-2.netatmo.net/restricted/10.255.248.91/6d278460699e56180d47ab47169efb31/MpEylTU2MDYzNjRVD-LJxUnIndumKzLboeAwMDqTTw,,",
"is_local": true,
"sd_status": "on",
"alim_status": "on",
"name": "Garden",
"last_setup": 1563737661,
"light_mode_status": "auto"
}
],
"smokedetectors": [
{
"id": "12:34:56:00:8b:a2",
"type": "NSD",
"last_setup": 1567261859,
"name": "Hall"
},
{
"id": "12:34:56:00:8b:ac",
"type": "NSD",
"last_setup": 1567262759,
"name": "Kitchen"
}
],
"events": [
{
"id": "a1b2c3d4e5f6abcdef123456",
"type": "person",
"time": 1560604700,
"camera_id": "12:34:56:00:f1:62",
"device_id": "12:34:56:00:f1:62",
"person_id": "91827374-7e04-5298-83ad-a0cb8372dff1",
"video_status": "deleted",
"is_arrival": false,
"message": "John Doe gesehen"
},
{
"id": "a1b2c3d4e5f6abcdef123457",
"type": "person_away",
"time": 1560602400,
"camera_id": "12:34:56:00:f1:62",
"device_id": "12:34:56:00:f1:62",
"person_id": "91827374-7e04-5298-83ad-a0cb8372dff1",
"message": "John Doe hat das Haus verlassen",
"sub_message": "John Doe gilt als abwesend, da das mit diesem Profil verbundene Telefon den Bereich des Hauses verlassen hat."
},
{
"id": "a1b2c3d4e5f6abcdef123458",
"type": "person",
"time": 1560601200,
"camera_id": "12:34:56:00:f1:62",
"device_id": "12:34:56:00:f1:62",
"person_id": "91827374-7e04-5298-83ad-a0cb8372dff1",
"video_status": "deleted",
"is_arrival": false,
"message": "John Doe gesehen"
},
{
"id": "a1b2c3d4e5f6abcdef123459",
"type": "person",
"time": 1560600100,
"camera_id": "12:34:56:00:f1:62",
"device_id": "12:34:56:00:f1:62",
"person_id": "91827375-7e04-5298-83ae-a0cb8372dff2",
"snapshot": {
"id": "d74fad765b9100ef480720a9",
"version": 1,
"key": "a4a95c24b808a89f8d1730039d2c69928b029d67fc40cb2d7fb69ecdf2bb8b72",
"url": "https://netatmocameraimage.blob.core.windows.net/production/d74fad765b9100ef480720a9a4a95c24b808a89f8d1730039d2c69928b029d67fc40cb2d7fb69ecdf2bb8b72"
},
"video_id": "12345678-36bc-4b9a-9762-5194e707ed51",
"video_status": "available",
"is_arrival": false,
"message": "Jane Doe gesehen"
},
{
"id": "a1b2c3d4e5f6abcdef12345a",
"type": "person",
"time": 1560603600,
"camera_id": "12:34:56:00:f1:62",
"device_id": "12:34:56:00:f1:62",
"person_id": "91827375-7e04-5298-83ae-a0cb8372dff3",
"snapshot": {
"id": "532dde8d17554c022ab071b8",
"version": 1,
"key": "9fbe490fffacf45b8416241946541b031a004a09b6747feb6c38c3ccbc456b28",
"url": "https://netatmocameraimage.blob.core.windows.net/production/532dde8d17554c022ab071b89fbe490fffacf45b8416241946541b031a004a09b6747feb6c38c3ccbc456b28"
},
"video_id": "12345678-1234-46cb-ad8f-23d893874099",
"video_status": "available",
"is_arrival": false,
"message": "Bewegung erkannt"
},
{
"id": "a1b2c3d4e5f6abcdef12345b",
"type": "movement",
"time": 1560506200,
"camera_id": "12:34:56:00:f1:62",
"device_id": "12:34:56:00:f1:62",
"category": "human",
"snapshot": {
"id": "532dde8d17554c022ab071b9",
"version": 1,
"key": "8fbe490fffacf45b8416241946541b031a004a09b6747feb6c38c3ccbc456b28",
"url": "https://netatmocameraimage.blob.core.windows.net/production/532dde8d17554c022ab071b98fbe490fffacf45b8416241946541b031a004a09b6747feb6c38c3ccbc456b28"
},
"vignette": {
"id": "5dc021b5dea854bd2321707a",
"version": 1,
"key": "58c5a05bd6bd908f6bf368865ef7355231c44215f8eb7ae458c919b2c67b4944",
"url": "https://netatmocameraimage.blob.core.windows.net/production/5dc021b5dea854bd2321707a58c5a05bd6bd908f6bf368865ef7355231c44215f8eb7ae458c919b2c67b4944"
},
"video_id": "12345678-1234-46cb-ad8f-23d89387409a",
"video_status": "available",
"message": "Bewegung erkannt"
},
{
"id": "a1b2c3d4e5f6abcdef12345c",
"type": "sound_test",
"time": 1560506210,
"camera_id": "12:34:56:00:8b:a2",
"device_id": "12:34:56:00:8b:a2",
"sub_type": 0,
"message": "Hall: Alarmton erfolgreich getestet"
},
{
"id": "a1b2c3d4e5f6abcdef12345d",
"type": "wifi_status",
"time": 1560506220,
"camera_id": "12:34:56:00:8b:a2",
"device_id": "12:34:56:00:8b:a2",
"sub_type": 1,
"message": "Hall:WLAN-Verbindung erfolgreich hergestellt"
},
{
"id": "a1b2c3d4e5f6abcdef12345e",
"type": "outdoor",
"time": 1560643100,
"camera_id": "12:34:56:00:a5:a4",
"device_id": "12:34:56:00:a5:a4",
"video_id": "string",
"video_status": "available",
"event_list": [
{
"type": "string",
"time": 1560643100,
"offset": 0,
"id": "c81bcf7b-2cfg-4ac9-8455-487ed00c0000",
"message": "Animal détecté",
"snapshot": {
"id": "5715e16849c75xxxx00000000xxxxx",
"version": 1,
"key": "7ac578d05030d0e170643a787ee0a29663dxxx00000xxxxx00000",
"url": "https://netatmocameraimage.blob.core.windows.net/production/1aa"
},
"vignette": {
"id": "5715e16849c75xxxx00000000xxxxx",
"version": 1,
"key": "7ac578d05030d0e170643a787ee0a29663dxxx00000xxxxx00000",
"url": "https://netatmocameraimage.blob.core.windows.net/production/1aa00000"
}
},
{
"type": "string",
"time": 1560506222,
"offset": 0,
"id": "c81bcf7b-2cfg-4ac9-8455-487ed00c0000",
"message": "Animal détecté",
"snapshot": {
"filename": "vod\/af74631d-8311-42dc-825b-82e3abeaab09\/events\/c53b-aze7a.jpg"
},
"vignette": {
"filename": "vod\/af74631d-8311-42dc-825b-82e3abeaab09\/events\/c5.jpg"
}
}
]
}
]
},
{
"id": "91763b24c43d3e344f424e8c",
"persons": [],
"place": {
"city": "Frankfurt",
"country": "DE",
"timezone": "Europe/Berlin"
},
"cameras": [
{
"id": "12:34:56:00:a5:a5",
"type": "NOC",
"status": "on",
"vpn_url": "https://prodvpn-eu-2.netatmo.net/restricted/10.255.248.91/6d278460699e56180d47ab47169efb31/MpEylTU2MDYzNjRVD-LJxUnIndumKzLboeAwMDqTTz,,",
"is_local": true,
"sd_status": "on",
"alim_status": "on",
"name": "Street",
"last_setup": 1563737561,
"light_mode_status": "auto"
},
{
"id": "12:34:56:00:a5:a6",
"type": "NOC",
"status": "on",
"vpn_url": "https://prodvpn-eu-2.netatmo.net/restricted/10.255.248.91/6d278460699e56180d47ab47169efb31/MpEylTU2MDYzNjRVD-LJxUnIndumKzLboeAwMDqTTz,,",
"is_local": true,
"sd_status": "on",
"alim_status": "on",
"last_setup": 1563737561,
"light_mode_status": "auto"
}
],
"smokedetectors": []
},
{
"id": "91763b24c43d3e344f424e8d",
"persons": [],
"place": {
"city": "Frankfurt",
"country": "DE",
"timezone": "Europe/Berlin"
},
"cameras": [],
"smokedetectors": []
}
],
"user": {
"reg_locale": "de-DE",
"lang": "de-DE",
"country": "DE",
"mail": "john@doe.com"
},
"global_info": {
"show_tags": true
}
},
"status": "ok",
"time_exec": 0.03621506690979,
"time_server": 1560626960
} pyatmo-9.2.1/fixtures/archive/camera_home_data_disconnected.json 0000664 0000000 0000000 00000022163 15017405234 0025201 0 ustar 00root root 0000000 0000000 {
"body": {
"homes": [
{
"id": "91763b24c43d3e344f424e8b",
"name": "MYHOME",
"persons": [
{
"id": "91827374-7e04-5298-83ad-a0cb8372dff1",
"last_seen": 1557071156,
"out_of_sight": true,
"face": {
"id": "d74fad765b9100ef480720a9",
"version": 1,
"key": "a4a95c24b808a89f8d1730fb69ecdf2bb8b72039d2c69928b029d67fc40cb2d7",
"url": "https://netatmocameraimage.blob.core.windows.net/production/d74fad765b9100ef480720a9a4a95c24b808a89f8d1730fb69ecdf2bb8b72039d2c69928b029d67fc40cb2d7"
},
"pseudo": "John Doe"
},
{
"id": "91827375-7e04-5298-83ae-a0cb8372dff2",
"last_seen": 1560600726,
"out_of_sight": true,
"face": {
"id": "d74fad765b9100ef480720a9",
"version": 3,
"key": "a4a95c24b808a89f8d1730039d2c69928b029d67fc40cb2d7fb69ecdf2bb8b72",
"url": "https://netatmocameraimage.blob.core.windows.net/production/d74fad765b9100ef480720a9a4a95c24b808a89f8d1730039d2c69928b029d67fc40cb2d7fb69ecdf2bb8b72"
},
"pseudo": "Jane Doe"
},
{
"id": "91827376-7e04-5298-83af-a0cb8372dff3",
"last_seen": 1560626666,
"out_of_sight": false,
"face": {
"id": "d74fad765b9100ef480720a9",
"version": 1,
"key": "a4a95c2d1730fb69ecdf2bb8b72039d2c69928b029d67fc40cb2d74b808a89f8",
"url": "https://netatmocameraimage.blob.core.windows.net/production/d74fad765b9100ef480720a9a4a95c2d1730fb69ecdf2bb8b72039d2c69928b029d67fc40cb2d74b808a89f8"
},
"pseudo": "Richard Doe"
},
{
"id": "91827376-7e04-5298-83af-a0cb8372dff4",
"last_seen": 1560621666,
"out_of_sight": true,
"face": {
"id": "d0ef44fad765b980720710a9",
"version": 1,
"key": "ab029da89f84a95c2d1730fb67fc40cb2d74b80869ecdf2bb8b72039d2c69928",
"url": "https://netatmocameraimage.blob.core.windows.net/production/d0ef44fad765b980720710a9ab029da89f84a95c2d1730fb67fc40cb2d74b80869ecdf2bb8b72039d2c69928"
}
}
],
"place": {
"city": "Frankfurt",
"country": "DE",
"timezone": "Europe/Berlin"
},
"cameras": [
{
"id": "12:34:56:00:f1:62",
"type": "NACamera",
"status": "disconnected",
"sd_status": "on",
"alim_status": "on",
"name": "Hall",
"use_pin_code": false,
"last_setup": 1544828430
}
],
"smokedetectors": [],
"events": [
{
"id": "a1b2c3d4e5f6abcdef123456",
"type": "person",
"time": 1560604700,
"camera_id": "12:34:56:00:f1:62",
"device_id": "12:34:56:00:f1:62",
"person_id": "91827374-7e04-5298-83ad-a0cb8372dff1",
"video_status": "deleted",
"is_arrival": false,
"message": "John Doe gesehen"
},
{
"id": "a1b2c3d4e5f6abcdef123457",
"type": "person_away",
"time": 1560602400,
"camera_id": "12:34:56:00:f1:62",
"device_id": "12:34:56:00:f1:62",
"person_id": "91827374-7e04-5298-83ad-a0cb8372dff1",
"message": "John Doe hat das Haus verlassen",
"sub_message": "John Doe gilt als abwesend, da das mit diesem Profil verbundene Telefon den Bereich des Hauses verlassen hat."
},
{
"id": "a1b2c3d4e5f6abcdef123458",
"type": "person",
"time": 1560601200,
"camera_id": "12:34:56:00:f1:62",
"device_id": "12:34:56:00:f1:62",
"person_id": "91827374-7e04-5298-83ad-a0cb8372dff1",
"video_status": "deleted",
"is_arrival": false,
"message": "John Doe gesehen"
},
{
"id": "a1b2c3d4e5f6abcdef123459",
"type": "person",
"time": 1560600100,
"camera_id": "12:34:56:00:f1:62",
"device_id": "12:34:56:00:f1:62",
"person_id": "91827375-7e04-5298-83ae-a0cb8372dff2",
"snapshot": {
"id": "d74fad765b9100ef480720a9",
"version": 1,
"key": "a4a95c24b808a89f8d1730039d2c69928b029d67fc40cb2d7fb69ecdf2bb8b72",
"url": "https://netatmocameraimage.blob.core.windows.net/production/d74fad765b9100ef480720a9a4a95c24b808a89f8d1730039d2c69928b029d67fc40cb2d7fb69ecdf2bb8b72"
},
"video_id": "12345678-36bc-4b9a-9762-5194e707ed51",
"video_status": "available",
"is_arrival": false,
"message": "Jane Doe gesehen"
},
{
"id": "a1b2c3d4e5f6abcdef12345a",
"type": "person",
"time": 1560603600,
"camera_id": "12:34:56:00:f1:62",
"device_id": "12:34:56:00:f1:62",
"person_id": "91827375-7e04-5298-83ae-a0cb8372dff3",
"snapshot": {
"id": "532dde8d17554c022ab071b8",
"version": 1,
"key": "9fbe490fffacf45b8416241946541b031a004a09b6747feb6c38c3ccbc456b28",
"url": "https://netatmocameraimage.blob.core.windows.net/production/532dde8d17554c022ab071b89fbe490fffacf45b8416241946541b031a004a09b6747feb6c38c3ccbc456b28"
},
"video_id": "12345678-1234-46cb-ad8f-23d893874099",
"video_status": "available",
"is_arrival": false,
"message": "Bewegung erkannt"
},
{
"id": "a1b2c3d4e5f6abcdef12345b",
"type": "movement",
"time": 1560506200,
"camera_id": "12:34:56:00:f1:62",
"device_id": "12:34:56:00:f1:62",
"category": "human",
"snapshot": {
"id": "532dde8d17554c022ab071b9",
"version": 1,
"key": "8fbe490fffacf45b8416241946541b031a004a09b6747feb6c38c3ccbc456b28",
"url": "https://netatmocameraimage.blob.core.windows.net/production/532dde8d17554c022ab071b98fbe490fffacf45b8416241946541b031a004a09b6747feb6c38c3ccbc456b28"
},
"vignette": {
"id": "5dc021b5dea854bd2321707a",
"version": 1,
"key": "58c5a05bd6bd908f6bf368865ef7355231c44215f8eb7ae458c919b2c67b4944",
"url": "https://netatmocameraimage.blob.core.windows.net/production/5dc021b5dea854bd2321707a58c5a05bd6bd908f6bf368865ef7355231c44215f8eb7ae458c919b2c67b4944"
},
"video_id": "12345678-1234-46cb-ad8f-23d89387409a",
"video_status": "available",
"message": "Bewegung erkannt"
}
]
}
],
"user": {
"reg_locale": "de-DE",
"lang": "de-DE",
"country": "DE",
"mail": "john@doe.com"
},
"global_info": {
"show_tags": true
}
},
"status": "ok",
"time_exec": 0.03621506690979,
"time_server": 1560626960
} pyatmo-9.2.1/fixtures/archive/camera_home_data_no_homes.json 0000664 0000000 0000000 00000000540 15017405234 0024341 0 ustar 00root root 0000000 0000000 {
"body": {
"homes": [],
"user": {
"reg_locale": "de-DE",
"lang": "de-DE",
"country": "DE",
"mail": "john@doe.com"
},
"global_info": {
"show_tags": true
}
},
"status": "ok",
"time_exec": 0.03621506690979,
"time_server": 1560626960
} pyatmo-9.2.1/fixtures/archive/camera_image_sample.jpg 0000664 0000000 0000000 00000001237 15017405234 0022767 0 ustar 00root root 0000000 0000000 ÿØÿà JFIF ÿÛ C
$.' ",#(7),01444'9=82<.342ÿÛ C
2!!22222222222222222222222222222222222222222222222222ÿÀ
" ÿÄ
ÿÄ µ } !1AQa"q2‘¡#B±ÁRÑð$3br‚
%&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚáâãäåæçèéêñòóôõö÷øùúÿÄ
ÿÄ µ w !1AQaq"2B‘¡±Á #3RðbrÑ
$4á%ñ&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz‚ƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚâãäåæçèéêòóôõö÷øùúÿÚ ? Åñ´fˆz¥È*òû£µsæ(²x¯ñŸøNµNå±þB¹WfÞÜž§½ ÿÙ pyatmo-9.2.1/fixtures/archive/camera_ping.json 0000664 0000000 0000000 00000000163 15017405234 0021467 0 ustar 00root root 0000000 0000000 {
"local_url": "http://192.168.0.123/678460a0d47e5618699fb31169e2b47d",
"product_name": "Welcome Netatmo"
} pyatmo-9.2.1/fixtures/archive/camera_set_state_error.json 0000664 0000000 0000000 00000000146 15017405234 0023737 0 ustar 00root root 0000000 0000000 {
"error": {
"code": 21,
"message": "Invalid device_id, 12:34:56:00:f1:ff"
}
} pyatmo-9.2.1/fixtures/archive/camera_set_state_error_already_on.json 0000664 0000000 0000000 00000000560 15017405234 0026134 0 ustar 00root root 0000000 0000000 {
"status": "ok",
"time_server": 1582932399,
"body": {
"home": {
"id": "91763b24c43d3e344f424e8b"
},
"errors": [
{
"code": 23,
"message": "Already on",
"id": "12:34:56:00:f1:62",
"command": "command/changestatus"
}
]
}
} pyatmo-9.2.1/fixtures/archive/camera_set_state_error_wrong_parameter.json 0000664 0000000 0000000 00000000175 15017405234 0027215 0 ustar 00root root 0000000 0000000 {
"error": {
"code": 21,
"message": "cannot set property floodlight for module 12:34:56:00:f1:62"
}
} pyatmo-9.2.1/fixtures/archive/camera_set_state_ok.json 0000664 0000000 0000000 00000000065 15017405234 0023217 0 ustar 00root root 0000000 0000000 {
"status": "ok",
"time_server": 1582932411
} pyatmo-9.2.1/fixtures/archive/error_scope.json 0000664 0000000 0000000 00000000122 15017405234 0021537 0 ustar 00root root 0000000 0000000 {"error":{"code":13,"message":"Application does not have the good scope rights"}}
pyatmo-9.2.1/fixtures/archive/home_coach_no_devices.json 0000664 0000000 0000000 00000000737 15017405234 0023514 0 ustar 00root root 0000000 0000000 {
"body": {
"devices": [],
"user": {
"mail": "john@doe.com",
"administrative": {
"lang": "de-DE",
"reg_locale": "de-DE",
"country": "DE",
"unit": 0,
"windunit": 0,
"pressureunit": 0,
"feel_like_algo": 0
}
}
},
"status": "ok",
"time_exec": 0.05824708938598633,
"time_server": 1565377059
} pyatmo-9.2.1/fixtures/archive/home_coach_simple.json 0000664 0000000 0000000 00000015364 15017405234 0022671 0 ustar 00root root 0000000 0000000 {
"body": {
"devices": [
{
"_id": "12:34:56:26:69:0c",
"cipher_id": "enc:16:1UqwQlYV5AY2pfyEi5H47dmmFOOL3mCUo+KAkchL4A2CLI5u0e45Xr5jeAswO+XO",
"date_setup": 1544560184,
"last_setup": 1544560184,
"type": "NHC",
"last_status_store": 1558268332,
"firmware": 45,
"last_upgrade": 1544560186,
"wifi_status": 58,
"reachable": false,
"co2_calibrating": false,
"station_name": "Bedroom",
"data_type": [
"Temperature",
"CO2",
"Humidity",
"Noise",
"Pressure",
"health_idx"
],
"place": {
"city": "Frankfurt",
"country": "DE",
"timezone": "Europe/Berlin",
"location": [
52.516263,
13.377726
]
}
},
{
"_id": "12:34:56:25:cf:a8",
"cipher_id": "enc:16:A+Jm0yFWBwUyKinFDutPZK7I2PuHN1fqaE9oB/KF+McbFs3oN9CKpR/dYbqL4om2",
"date_setup": 1544562192,
"last_setup": 1544562192,
"type": "NHC",
"last_status_store": 1559198922,
"firmware": 45,
"last_upgrade": 1544562194,
"wifi_status": 41,
"reachable": true,
"co2_calibrating": false,
"station_name": "Kitchen",
"data_type": [
"Temperature",
"CO2",
"Humidity",
"Noise",
"Pressure",
"health_idx"
],
"place": {
"city": "Frankfurt",
"country": "DE",
"timezone": "Europe/Berlin",
"location": [
52.516263,
13.377726
]
}
},
{
"_id": "12:34:56:26:65:14",
"cipher_id": "enc:16:7kK6ZzG4L7NgfZZ6+dMvNxw4l6vXu+88SEJkCUklNdPa4KYIHmsfa1moOilEK61i",
"date_setup": 1544564061,
"last_setup": 1544564061,
"type": "NHC",
"last_status_store": 1559067159,
"firmware": 45,
"last_upgrade": 1544564302,
"wifi_status": 66,
"reachable": true,
"co2_calibrating": false,
"station_name": "Livingroom",
"data_type": [
"Temperature",
"CO2",
"Humidity",
"Noise",
"Pressure",
"health_idx"
],
"place": {
"city": "Frankfurt",
"country": "DE",
"timezone": "Europe/Berlin",
"location": [
52.516263,
13.377726
]
}
},
{
"_id": "12:34:56:3e:c5:46",
"station_name": "Parents Bedroom",
"date_setup": 1570732241,
"last_setup": 1570732241,
"type": "NHC",
"last_status_store": 1572073818,
"module_name": "Indoor",
"firmware": 45,
"wifi_status": 67,
"reachable": true,
"co2_calibrating": false,
"data_type": [
"Temperature",
"CO2",
"Humidity",
"Noise",
"Pressure",
"health_idx"
],
"place": {
"city": "Frankfurt",
"country": "DE",
"timezone": "Europe/Berlin",
"location": [
52.516263,
13.377726
]
},
"dashboard_data": {
"time_utc": 1572073816,
"Temperature": 20.3,
"CO2": 494,
"Humidity": 63,
"Noise": 42,
"Pressure": 1014.5,
"AbsolutePressure": 1004.1,
"health_idx": 1,
"min_temp": 20.3,
"max_temp": 21.6,
"date_max_temp": 1572059333,
"date_min_temp": 1572073816
}
},
{
"_id": "12:34:56:26:68:92",
"station_name": "Baby Bedroom",
"date_setup": 1571342643,
"last_setup": 1571342643,
"type": "NHC",
"last_status_store": 1572073995,
"module_name": "Indoor",
"firmware": 45,
"wifi_status": 68,
"reachable": true,
"co2_calibrating": false,
"data_type": [
"Temperature",
"CO2",
"Humidity",
"Noise",
"Pressure",
"health_idx"
],
"place": {
"city": "Frankfurt",
"country": "DE",
"timezone": "Europe/Berlin",
"location": [
52.516263,
13.377726
]
},
"dashboard_data": {
"time_utc": 1572073994,
"Temperature": 21.6,
"CO2": 1053,
"Humidity": 66,
"Noise": 45,
"Pressure": 1021.4,
"AbsolutePressure": 1011,
"health_idx": 1,
"min_temp": 20.9,
"max_temp": 21.6,
"date_max_temp": 1572073690,
"date_min_temp": 1572064254
}
}
],
"user": {
"mail": "john@doe.com",
"administrative": {
"lang": "de-DE",
"reg_locale": "de-DE",
"country": "DE",
"unit": 0,
"windunit": 0,
"pressureunit": 0,
"feel_like_algo": 0
}
}
},
"status": "ok",
"time_exec": 0.095954179763794,
"time_server": 1559463229
} pyatmo-9.2.1/fixtures/archive/home_data_empty.json 0000664 0000000 0000000 00000000151 15017405234 0022356 0 ustar 00root root 0000000 0000000 {
"body": {},
"status": "ok",
"time_exec": 0.056135892868042,
"time_server": 1559171003
} pyatmo-9.2.1/fixtures/archive/home_data_no_devices.json 0000664 0000000 0000000 00000001511 15017405234 0023337 0 ustar 00root root 0000000 0000000 {
"body": {
"homes": [
{
"id": "91763b24c43d3e344f424e8c",
"altitude": 112,
"coordinates": [
52.516263,
13.377726
],
"country": "DE",
"timezone": "Europe/Berlin",
"therm_setpoint_default_duration": 180,
"therm_mode": "schedule"
}
],
"user": {
"email": "john@doe.com",
"language": "de-DE",
"locale": "de-DE",
"feel_like_algorithm": 0,
"unit_pressure": 0,
"unit_system": 0,
"unit_wind": 0,
"id": "91763b24c43d3e344f424e8b"
}
},
"status": "ok",
"time_exec": 0.056135892868042,
"time_server": 1559171003
} pyatmo-9.2.1/fixtures/archive/home_data_no_homes.json 0000664 0000000 0000000 00000000661 15017405234 0023035 0 ustar 00root root 0000000 0000000 {
"body": {
"homes": [],
"user": {
"email": "john@doe.com",
"language": "de-DE",
"locale": "de-DE",
"feel_like_algorithm": 0,
"unit_pressure": 0,
"unit_system": 0,
"unit_wind": 0,
"id": "91763b24c43d3e344f424e8b"
}
},
"status": "ok",
"time_exec": 0.056135892868042,
"time_server": 1559171003
} pyatmo-9.2.1/fixtures/archive/home_data_nohomename.json 0000664 0000000 0000000 00000037167 15017405234 0023367 0 ustar 00root root 0000000 0000000 {
"body": {
"homes": [
{
"id": "91763b24c43d3e344f424e8b",
"altitude": 112,
"coordinates": [
52.516263,
13.377726
],
"country": "DE",
"timezone": "Europe/Berlin",
"rooms": [
{
"id": "2746182631",
"name": "Livingroom",
"type": "livingroom",
"module_ids": [
"12:34:56:00:01:ae"
]
},
{
"id": "3688132631",
"name": "Hall",
"type": "custom",
"module_ids": [
"12:34:56:00:f1:62"
]
}
],
"modules": [
{
"id": "12:34:56:00:fa:d0",
"type": "NAPlug",
"name": "Thermostat",
"setup_date": 1494963356,
"modules_bridged": [
"12:34:56:00:01:ae"
]
},
{
"id": "12:34:56:00:01:ae",
"type": "NATherm1",
"name": "Livingroom",
"setup_date": 1494963356,
"room_id": "2746182631",
"bridge": "12:34:56:00:fa:d0"
},
{
"id": "12:34:56:00:f1:62",
"type": "NACamera",
"name": "Hall",
"setup_date": 1544828430,
"room_id": "3688132631"
}
],
"therm_schedules": [
{
"zones": [
{
"type": 0,
"name": "Comfort",
"rooms_temp": [
{
"temp": 21,
"room_id": "2746182631"
}
],
"id": 0
},
{
"type": 1,
"name": "Night",
"rooms_temp": [
{
"temp": 17,
"room_id": "2746182631"
}
],
"id": 1
},
{
"type": 5,
"name": "Eco",
"rooms_temp": [
{
"temp": 17,
"room_id": "2746182631"
}
],
"id": 4
}
],
"timetable": [
{
"zone_id": 1,
"m_offset": 0
},
{
"zone_id": 0,
"m_offset": 360
},
{
"zone_id": 4,
"m_offset": 420
},
{
"zone_id": 0,
"m_offset": 960
},
{
"zone_id": 1,
"m_offset": 1410
},
{
"zone_id": 0,
"m_offset": 1800
},
{
"zone_id": 4,
"m_offset": 1860
},
{
"zone_id": 0,
"m_offset": 2400
},
{
"zone_id": 1,
"m_offset": 2850
},
{
"zone_id": 0,
"m_offset": 3240
},
{
"zone_id": 4,
"m_offset": 3300
},
{
"zone_id": 0,
"m_offset": 3840
},
{
"zone_id": 1,
"m_offset": 4290
},
{
"zone_id": 0,
"m_offset": 4680
},
{
"zone_id": 4,
"m_offset": 4740
},
{
"zone_id": 0,
"m_offset": 5280
},
{
"zone_id": 1,
"m_offset": 5730
},
{
"zone_id": 0,
"m_offset": 6120
},
{
"zone_id": 4,
"m_offset": 6180
},
{
"zone_id": 0,
"m_offset": 6720
},
{
"zone_id": 1,
"m_offset": 7170
},
{
"zone_id": 0,
"m_offset": 7620
},
{
"zone_id": 1,
"m_offset": 8610
},
{
"zone_id": 0,
"m_offset": 9060
},
{
"zone_id": 1,
"m_offset": 10050
}
],
"hg_temp": 7,
"away_temp": 14,
"name": "Default",
"selected": true,
"id": "591b54a2764ff4d50d8b5795",
"type": "therm"
}
],
"therm_setpoint_default_duration": 120,
"persons": [
{
"id": "91827374-7e04-5298-83ad-a0cb8372dff1",
"pseudo": "John Doe",
"url": "https://netatmocameraimage.blob.core.windows.net/production/d74fad765b9100ef480720a9a4a95c24b808a89f8d1730fb69ecdf2bb8b72039d2c69928b029d67fc40cb2d7"
},
{
"id": "91827375-7e04-5298-83ae-a0cb8372dff2",
"pseudo": "Jane Doe",
"url": "https://netatmocameraimage.blob.core.windows.net/production/d74fad765b9100ef480720a9a4a95c24b808a89f8d1730039d2c69928b029d67fc40cb2d7fb69ecdf2bb8b72"
},
{
"id": "91827376-7e04-5298-83af-a0cb8372dff3",
"pseudo": "Richard Doe",
"url": "https://netatmocameraimage.blob.core.windows.net/production/d74fad765b9100ef480720a9a4a95c2d1730fb69ecdf2bb8b72039d2c69928b029d67fc40cb2d74b808a89f8"
}
],
"schedules": [
{
"zones": [
{
"type": 0,
"name": "Komfort",
"rooms_temp": [
{
"temp": 21,
"room_id": "2746182631"
}
],
"id": 0,
"rooms": [
{
"id": "2746182631",
"therm_setpoint_temperature": 21
}
]
},
{
"type": 1,
"name": "Nacht",
"rooms_temp": [
{
"temp": 17,
"room_id": "2746182631"
}
],
"id": 1,
"rooms": [
{
"id": "2746182631",
"therm_setpoint_temperature": 17
}
]
},
{
"type": 5,
"name": "Eco",
"rooms_temp": [
{
"temp": 17,
"room_id": "2746182631"
}
],
"id": 4,
"rooms": [
{
"id": "2746182631",
"therm_setpoint_temperature": 17
}
]
}
],
"timetable": [
{
"zone_id": 1,
"m_offset": 0
},
{
"zone_id": 0,
"m_offset": 360
},
{
"zone_id": 4,
"m_offset": 420
},
{
"zone_id": 0,
"m_offset": 960
},
{
"zone_id": 1,
"m_offset": 1410
},
{
"zone_id": 0,
"m_offset": 1800
},
{
"zone_id": 4,
"m_offset": 1860
},
{
"zone_id": 0,
"m_offset": 2400
},
{
"zone_id": 1,
"m_offset": 2850
},
{
"zone_id": 0,
"m_offset": 3240
},
{
"zone_id": 4,
"m_offset": 3300
},
{
"zone_id": 0,
"m_offset": 3840
},
{
"zone_id": 1,
"m_offset": 4290
},
{
"zone_id": 0,
"m_offset": 4680
},
{
"zone_id": 4,
"m_offset": 4740
},
{
"zone_id": 0,
"m_offset": 5280
},
{
"zone_id": 1,
"m_offset": 5730
},
{
"zone_id": 0,
"m_offset": 6120
},
{
"zone_id": 4,
"m_offset": 6180
},
{
"zone_id": 0,
"m_offset": 6720
},
{
"zone_id": 1,
"m_offset": 7170
},
{
"zone_id": 0,
"m_offset": 7620
},
{
"zone_id": 1,
"m_offset": 8610
},
{
"zone_id": 0,
"m_offset": 9060
},
{
"zone_id": 1,
"m_offset": 10050
}
],
"hg_temp": 7,
"away_temp": 14,
"name": "Default",
"id": "591b54a2764ff4d50d8b5795",
"selected": true,
"type": "therm"
}
],
"therm_mode": "schedule"
}
],
"user": {
"email": "john@doe.com",
"language": "de-DE",
"locale": "de-DE",
"feel_like_algorithm": 0,
"unit_pressure": 0,
"unit_system": 0,
"unit_wind": 0,
"id": "91763b24c43d3e344f424e8b"
}
},
"status": "ok",
"time_exec": 0.056135892868042,
"time_server": 1559171003
} pyatmo-9.2.1/fixtures/archive/home_data_simple.json 0000664 0000000 0000000 00000055627 15017405234 0022533 0 ustar 00root root 0000000 0000000 {
"body": {
"homes": [
{
"id": "91763b24c43d3e344f424e8b",
"name": "MYHOME",
"altitude": 112,
"coordinates": [
52.516263,
13.377726
],
"country": "DE",
"timezone": "Europe/Berlin",
"rooms": [
{
"id": "2746182631",
"name": "Livingroom",
"type": "livingroom",
"module_ids": [
"12:34:56:00:01:ae"
]
},
{
"id": "3688132631",
"name": "Hall",
"type": "custom",
"module_ids": [
"12:34:56:00:f1:62"
]
},
{
"id": "2833524037",
"name": "Entrada",
"type": "lobby",
"module_ids": [
"12:34:56:03:a5:54"
]
},
{
"id": "2940411577",
"name": "Cocina",
"type": "kitchen",
"module_ids": [
"12:34:56:03:a0:ac"
]
}
],
"modules": [
{
"id": "12:34:56:00:fa:d0",
"type": "NAPlug",
"name": "Thermostat",
"setup_date": 1494963356,
"modules_bridged": [
"12:34:56:00:01:ae",
"12:34:56:03:a0:ac",
"12:34:56:03:a5:54"
]
},
{
"id": "12:34:56:00:01:ae",
"type": "NATherm1",
"name": "Livingroom",
"setup_date": 1494963356,
"room_id": "2746182631",
"bridge": "12:34:56:00:fa:d0"
},
{
"id": "12:34:56:03:a5:54",
"type": "NRV",
"name": "Valve1",
"setup_date": 1554549767,
"room_id": "2833524037",
"bridge": "12:34:56:00:fa:d0"
},
{
"id": "12:34:56:03:a0:ac",
"type": "NRV",
"name": "Valve2",
"setup_date": 1554554444,
"room_id": "2940411577",
"bridge": "12:34:56:00:fa:d0"
},
{
"id": "12:34:56:00:f1:62",
"type": "NACamera",
"name": "Hall",
"setup_date": 1544828430,
"room_id": "3688132631"
}
],
"therm_schedules": [
{
"zones": [
{
"type": 0,
"name": "Comfort",
"rooms_temp": [
{
"temp": 21,
"room_id": "2746182631"
}
],
"id": 0
},
{
"type": 1,
"name": "Night",
"rooms_temp": [
{
"temp": 17,
"room_id": "2746182631"
}
],
"id": 1
},
{
"type": 5,
"name": "Eco",
"rooms_temp": [
{
"temp": 17,
"room_id": "2746182631"
}
],
"id": 4
}
],
"timetable": [
{
"zone_id": 1,
"m_offset": 0
},
{
"zone_id": 0,
"m_offset": 360
},
{
"zone_id": 4,
"m_offset": 420
},
{
"zone_id": 0,
"m_offset": 960
},
{
"zone_id": 1,
"m_offset": 1410
},
{
"zone_id": 0,
"m_offset": 1800
},
{
"zone_id": 4,
"m_offset": 1860
},
{
"zone_id": 0,
"m_offset": 2400
},
{
"zone_id": 1,
"m_offset": 2850
},
{
"zone_id": 0,
"m_offset": 3240
},
{
"zone_id": 4,
"m_offset": 3300
},
{
"zone_id": 0,
"m_offset": 3840
},
{
"zone_id": 1,
"m_offset": 4290
},
{
"zone_id": 0,
"m_offset": 4680
},
{
"zone_id": 4,
"m_offset": 4740
},
{
"zone_id": 0,
"m_offset": 5280
},
{
"zone_id": 1,
"m_offset": 5730
},
{
"zone_id": 0,
"m_offset": 6120
},
{
"zone_id": 4,
"m_offset": 6180
},
{
"zone_id": 0,
"m_offset": 6720
},
{
"zone_id": 1,
"m_offset": 7170
},
{
"zone_id": 0,
"m_offset": 7620
},
{
"zone_id": 1,
"m_offset": 8610
},
{
"zone_id": 0,
"m_offset": 9060
},
{
"zone_id": 1,
"m_offset": 10050
}
],
"hg_temp": 7,
"away_temp": 14,
"name": "Default",
"selected": true,
"id": "591b54a2764ff4d50d8b5795",
"type": "therm"
},
{
"zones": [
{
"type": 0,
"name": "Comfort",
"rooms_temp": [
{
"temp": 21,
"room_id": "2746182631"
}
],
"id": 0
},
{
"type": 1,
"name": "Night",
"rooms_temp": [
{
"temp": 17,
"room_id": "2746182631"
}
],
"id": 1
},
{
"type": 5,
"name": "Eco",
"rooms_temp": [
{
"temp": 17,
"room_id": "2746182631"
}
],
"id": 4
}
],
"timetable": [
{
"zone_id": 1,
"m_offset": 0
},
{
"zone_id": 0,
"m_offset": 360
},
{
"zone_id": 4,
"m_offset": 420
},
{
"zone_id": 0,
"m_offset": 960
},
{
"zone_id": 1,
"m_offset": 1410
},
{
"zone_id": 0,
"m_offset": 1800
},
{
"zone_id": 4,
"m_offset": 1860
},
{
"zone_id": 0,
"m_offset": 2400
},
{
"zone_id": 1,
"m_offset": 2850
},
{
"zone_id": 0,
"m_offset": 3240
},
{
"zone_id": 4,
"m_offset": 3300
},
{
"zone_id": 0,
"m_offset": 3840
},
{
"zone_id": 1,
"m_offset": 4290
},
{
"zone_id": 0,
"m_offset": 4680
},
{
"zone_id": 4,
"m_offset": 4740
},
{
"zone_id": 0,
"m_offset": 5280
},
{
"zone_id": 1,
"m_offset": 5730
},
{
"zone_id": 0,
"m_offset": 6120
},
{
"zone_id": 4,
"m_offset": 6180
},
{
"zone_id": 0,
"m_offset": 6720
},
{
"zone_id": 1,
"m_offset": 7170
},
{
"zone_id": 0,
"m_offset": 7620
},
{
"zone_id": 1,
"m_offset": 8610
},
{
"zone_id": 0,
"m_offset": 9060
},
{
"zone_id": 1,
"m_offset": 10050
}
],
"hg_temp": 7,
"away_temp": 14,
"name": "Winter",
"id": "b1b54a2f45795764f59d50d8",
"type": "therm"
}
],
"therm_setpoint_default_duration": 120,
"persons": [
{
"id": "91827374-7e04-5298-83ad-a0cb8372dff1",
"pseudo": "John Doe",
"url": "https://netatmocameraimage.blob.core.windows.net/production/d74fad765b9100ef480720a9a4a95c24b808a89f8d1730fb69ecdf2bb8b72039d2c69928b029d67fc40cb2d7"
},
{
"id": "91827375-7e04-5298-83ae-a0cb8372dff2",
"pseudo": "Jane Doe",
"url": "https://netatmocameraimage.blob.core.windows.net/production/d74fad765b9100ef480720a9a4a95c24b808a89f8d1730039d2c69928b029d67fc40cb2d7fb69ecdf2bb8b72"
},
{
"id": "91827376-7e04-5298-83af-a0cb8372dff3",
"pseudo": "Richard Doe",
"url": "https://netatmocameraimage.blob.core.windows.net/production/d74fad765b9100ef480720a9a4a95c2d1730fb69ecdf2bb8b72039d2c69928b029d67fc40cb2d74b808a89f8"
}
],
"schedules": [
{
"zones": [
{
"type": 0,
"name": "Komfort",
"rooms_temp": [
{
"temp": 21,
"room_id": "2746182631"
}
],
"id": 0,
"rooms": [
{
"id": "2746182631",
"therm_setpoint_temperature": 21
}
]
},
{
"type": 1,
"name": "Nacht",
"rooms_temp": [
{
"temp": 17,
"room_id": "2746182631"
}
],
"id": 1,
"rooms": [
{
"id": "2746182631",
"therm_setpoint_temperature": 17
}
]
},
{
"type": 5,
"name": "Eco",
"rooms_temp": [
{
"temp": 17,
"room_id": "2746182631"
}
],
"id": 4,
"rooms": [
{
"id": "2746182631",
"therm_setpoint_temperature": 17
}
]
}
],
"timetable": [
{
"zone_id": 1,
"m_offset": 0
},
{
"zone_id": 0,
"m_offset": 360
},
{
"zone_id": 4,
"m_offset": 420
},
{
"zone_id": 0,
"m_offset": 960
},
{
"zone_id": 1,
"m_offset": 1410
},
{
"zone_id": 0,
"m_offset": 1800
},
{
"zone_id": 4,
"m_offset": 1860
},
{
"zone_id": 0,
"m_offset": 2400
},
{
"zone_id": 1,
"m_offset": 2850
},
{
"zone_id": 0,
"m_offset": 3240
},
{
"zone_id": 4,
"m_offset": 3300
},
{
"zone_id": 0,
"m_offset": 3840
},
{
"zone_id": 1,
"m_offset": 4290
},
{
"zone_id": 0,
"m_offset": 4680
},
{
"zone_id": 4,
"m_offset": 4740
},
{
"zone_id": 0,
"m_offset": 5280
},
{
"zone_id": 1,
"m_offset": 5730
},
{
"zone_id": 0,
"m_offset": 6120
},
{
"zone_id": 4,
"m_offset": 6180
},
{
"zone_id": 0,
"m_offset": 6720
},
{
"zone_id": 1,
"m_offset": 7170
},
{
"zone_id": 0,
"m_offset": 7620
},
{
"zone_id": 1,
"m_offset": 8610
},
{
"zone_id": 0,
"m_offset": 9060
},
{
"zone_id": 1,
"m_offset": 10050
}
],
"hg_temp": 7,
"away_temp": 14,
"name": "Default",
"id": "591b54a2764ff4d50d8b5795",
"selected": true,
"type": "therm"
}
],
"therm_mode": "schedule"
},
{
"id": "91763b24c43d3e344f424e8c",
"altitude": 112,
"coordinates": [
52.516263,
13.377726
],
"country": "DE",
"timezone": "Europe/Berlin",
"therm_setpoint_default_duration": 180,
"therm_mode": "schedule"
}
],
"user": {
"email": "john@doe.com",
"language": "de-DE",
"locale": "de-DE",
"feel_like_algorithm": 0,
"unit_pressure": 0,
"unit_system": 0,
"unit_wind": 0,
"id": "91763b24c43d3e344f424e8b"
}
},
"status": "ok",
"time_exec": 0.056135892868042,
"time_server": 1559171003
} pyatmo-9.2.1/fixtures/archive/home_status_empty.json 0000664 0000000 0000000 00000000105 15017405234 0022767 0 ustar 00root root 0000000 0000000 {
"status": "ok",
"time_server": 1559292039,
"body": {}
} pyatmo-9.2.1/fixtures/archive/home_status_error_and_data.json 0000664 0000000 0000000 00000007470 15017405234 0024611 0 ustar 00root root 0000000 0000000 {
"status": "ok",
"time_server": 1559292039,
"body": {
"home": {
"modules": [
{
"id": "12:34:56:00:fa:d0",
"type": "NAPlug",
"firmware_revision": 174,
"rf_strength": 107,
"wifi_strength": 42
},
{
"id": "12:34:56:00:01:ae",
"reachable": true,
"type": "NATherm1",
"firmware_revision": 65,
"rf_strength": 58,
"battery_level": 3793,
"boiler_valve_comfort_boost": false,
"boiler_status": false,
"anticipating": false,
"bridge": "12:34:56:00:fa:d0",
"battery_state": "high"
},
{
"id": "12:34:56:03:a5:54",
"reachable": true,
"type": "NRV",
"firmware_revision": 79,
"rf_strength": 51,
"battery_level": 3025,
"bridge": "12:34:56:00:fa:d0",
"battery_state": "full"
},
{
"id": "12:34:56:03:a0:ac",
"reachable": true,
"type": "NRV",
"firmware_revision": 79,
"rf_strength": 59,
"battery_level": 3029,
"bridge": "12:34:56:00:fa:d0",
"battery_state": "full"
}
],
"rooms": [
{
"id": "2746182631",
"reachable": true,
"therm_measured_temperature": 19.8,
"therm_setpoint_temperature": 12,
"therm_setpoint_mode": "away",
"therm_setpoint_start_time": 1559229567,
"therm_setpoint_end_time": 0
},
{
"id": "2940411577",
"reachable": true,
"therm_measured_temperature": 27,
"heating_power_request": 0,
"therm_setpoint_temperature": 7,
"therm_setpoint_mode": "hg",
"therm_setpoint_start_time": 0,
"therm_setpoint_end_time": 0,
"anticipating": false,
"open_window": false
},
{
"id": "2833524037",
"reachable": true,
"therm_measured_temperature": 24.5,
"heating_power_request": 0,
"therm_setpoint_temperature": 7,
"therm_setpoint_mode": "hg",
"therm_setpoint_start_time": 0,
"therm_setpoint_end_time": 0,
"anticipating": false,
"open_window": false
}
],
"id": "91763b24c43d3e344f424e8b",
"persons": [
{
"id": "91827374-7e04-5298-83ad-a0cb8372dff1",
"last_seen": 1557071156,
"out_of_sight": true
},
{
"id": "91827375-7e04-5298-83ae-a0cb8372dff2",
"last_seen": 1559282761,
"out_of_sight": false
},
{
"id": "91827376-7e04-5298-83af-a0cb8372dff3",
"last_seen": 1559224132,
"out_of_sight": true
}
]
},
"errors": [
{
"code": 6,
"id": "12:34:56:00:f1:62"
}
]
}
} pyatmo-9.2.1/fixtures/archive/home_status_error_invalid_id.json 0000664 0000000 0000000 00000000114 15017405234 0025144 0 ustar 00root root 0000000 0000000 {
"error": {
"code": 21,
"message": "Invalid id"
}
} pyatmo-9.2.1/fixtures/archive/home_status_error_missing_home_id.json 0000664 0000000 0000000 00000000121 15017405234 0026175 0 ustar 00root root 0000000 0000000 {
"error": {
"code": 10,
"message": "Missing home_id"
}
} pyatmo-9.2.1/fixtures/archive/home_status_error_missing_parameters.json 0000664 0000000 0000000 00000000124 15017405234 0026737 0 ustar 00root root 0000000 0000000 {
"error": {
"code": 10,
"message": "Missing parameters"
}
} pyatmo-9.2.1/fixtures/archive/home_status_error_mode_not_authorized.json 0000664 0000000 0000000 00000000125 15017405234 0027106 0 ustar 00root root 0000000 0000000 {
"error": {
"code": 21,
"message": "mode not authorized"
}
} pyatmo-9.2.1/fixtures/archive/invalid_grant.json 0000664 0000000 0000000 00000000040 15017405234 0022035 0 ustar 00root root 0000000 0000000 {
"error": "invalid_grant"
} pyatmo-9.2.1/fixtures/archive/oauth2_token.json 0000664 0000000 0000000 00000000636 15017405234 0021631 0 ustar 00root root 0000000 0000000 {
"access_token": "91763b24c43d3e344f424e8b|880b55a08c758e87ff8755a00c6b8a12",
"refresh_token": "91763b24c43d3e344f424e8b|87ff8755a00c6b8a120b55a08c758e93",
"scope": [
"read_station",
"read_camera",
"access_camera",
"read_thermostat",
"write_thermostat",
"read_presence",
"access_presence"
],
"expires_in": 10800,
"expire_in": 10800
} pyatmo-9.2.1/fixtures/archive/public_data_error_mongo.json 0000664 0000000 0000000 00000000263 15017405234 0024102 0 ustar 00root root 0000000 0000000 {
"error": {
"message": "failed to connect to server [localhost:27020] on first connect [MongoError: connect ECONNREFUSED 127.0.0.1:27020]",
"code": 0
}
}
pyatmo-9.2.1/fixtures/archive/public_data_simple.json 0000664 0000000 0000000 00000026314 15017405234 0023050 0 ustar 00root root 0000000 0000000 {
"status": "ok",
"time_server": 1560248397,
"time_exec": 0,
"body": [
{
"_id": "70:ee:50:36:94:7c",
"place": {
"location": [
8.791382999999996,
50.2136394
],
"timezone": "Europe/Berlin",
"country": "DE",
"altitude": 132
},
"mark": 14,
"measures": {
"02:00:00:36:f2:94": {
"res": {
"1560248022": [
21.4,
62
]
},
"type": [
"temperature",
"humidity"
]
},
"70:ee:50:36:94:7c": {
"res": {
"1560248030": [
1010.6
]
},
"type": [
"pressure"
]
},
"05:00:00:05:33:84": {
"rain_60min": 0.2,
"rain_24h": 12.322000000000001,
"rain_live": 0.5,
"rain_timeutc": 1560248022
}
},
"modules": [
"05:00:00:05:33:84",
"02:00:00:36:f2:94"
],
"module_types": {
"05:00:00:05:33:84": "NAModule3",
"02:00:00:36:f2:94": "NAModule1"
}
},
{
"_id": "70:ee:50:1f:68:9e",
"place": {
"location": [
8.795445200000017,
50.2130169
],
"timezone": "Europe/Berlin",
"country": "DE",
"altitude": 125
},
"mark": 14,
"measures": {
"02:00:00:1f:82:28": {
"res": {
"1560248312": [
21.1,
69
]
},
"type": [
"temperature",
"humidity"
]
},
"70:ee:50:1f:68:9e": {
"res": {
"1560248344": [
1007.3
]
},
"type": [
"pressure"
]
},
"05:00:00:02:bb:6e": {
"rain_60min": 0,
"rain_24h": 9.999,
"rain_live": 0,
"rain_timeutc": 1560248344
}
},
"modules": [
"02:00:00:1f:82:28",
"05:00:00:02:bb:6e"
],
"module_types": {
"02:00:00:1f:82:28": "NAModule1",
"05:00:00:02:bb:6e": "NAModule3"
}
},
{
"_id": "70:ee:50:27:25:b0",
"place": {
"location": [
8.7807159,
50.1946167
],
"timezone": "Europe/Berlin",
"country": "DE",
"altitude": 112
},
"mark": 14,
"measures": {
"02:00:00:27:19:b2": {
"res": {
"1560247889": [
23.2,
60
]
},
"type": [
"temperature",
"humidity"
]
},
"70:ee:50:27:25:b0": {
"res": {
"1560247907": [
1012.8
]
},
"type": [
"pressure"
]
},
"05:00:00:03:5d:2e": {
"rain_60min": 0,
"rain_24h": 11.716000000000001,
"rain_live": 0,
"rain_timeutc": 1560247896
}
},
"modules": [
"02:00:00:27:19:b2",
"05:00:00:03:5d:2e"
],
"module_types": {
"02:00:00:27:19:b2": "NAModule1",
"05:00:00:03:5d:2e": "NAModule3"
}
},
{
"_id": "70:ee:50:04:ed:7a",
"place": {
"location": [
8.785034,
50.192169
],
"timezone": "Europe/Berlin",
"country": "DE",
"altitude": 112
},
"mark": 14,
"measures": {
"02:00:00:04:c2:2e": {
"res": {
"1560248137": [
19.8,
76
]
},
"type": [
"temperature",
"humidity"
]
},
"70:ee:50:04:ed:7a": {
"res": {
"1560248152": [
1005.4
]
},
"type": [
"pressure"
]
}
},
"modules": [
"02:00:00:04:c2:2e"
],
"module_types": {
"02:00:00:04:c2:2e": "NAModule1"
}
},
{
"_id": "70:ee:50:27:9f:2c",
"place": {
"location": [
8.785342,
50.193573
],
"timezone": "Europe/Berlin",
"country": "DE",
"altitude": 116
},
"mark": 1,
"measures": {
"02:00:00:27:aa:70": {
"res": {
"1560247821": [
25.5,
56
]
},
"type": [
"temperature",
"humidity"
]
},
"70:ee:50:27:9f:2c": {
"res": {
"1560247853": [
1010.6
]
},
"type": [
"pressure"
]
}
},
"modules": [
"02:00:00:27:aa:70"
],
"module_types": {
"02:00:00:27:aa:70": "NAModule1"
}
},
{
"_id": "70:ee:50:01:20:fa",
"place": {
"location": [
8.7953,
50.195241
],
"timezone": "Europe/Berlin",
"country": "DE",
"altitude": 119
},
"mark": 1,
"measures": {
"02:00:00:00:f7:ba": {
"res": {
"1560247831": [
27.4,
58
]
},
"type": [
"temperature",
"humidity"
]
},
"70:ee:50:01:20:fa": {
"res": {
"1560247876": [
1014.4
]
},
"type": [
"pressure"
]
}
},
"modules": [
"02:00:00:00:f7:ba"
],
"module_types": {
"02:00:00:00:f7:ba": "NAModule1"
}
},
{
"_id": "70:ee:50:3c:02:78",
"place": {
"location": [
8.795953681700666,
50.19530139868166
],
"timezone": "Europe/Berlin",
"country": "DE",
"altitude": 119
},
"mark": 7,
"measures": {
"02:00:00:3c:21:f2": {
"res": {
"1560248225": [
23.3,
58
]
},
"type": [
"temperature",
"humidity"
]
},
"70:ee:50:3c:02:78": {
"res": {
"1560248270": [
1011.7
]
},
"type": [
"pressure"
]
}
},
"modules": [
"02:00:00:3c:21:f2"
],
"module_types": {
"02:00:00:3c:21:f2": "NAModule1"
}
},
{
"_id": "70:ee:50:36:a9:fc",
"place": {
"location": [
8.801164269110814,
50.19596181704958
],
"timezone": "Europe/Berlin",
"country": "DE",
"altitude": 113
},
"mark": 14,
"measures": {
"02:00:00:36:a9:50": {
"res": {
"1560248145": [
20.1,
67
]
},
"type": [
"temperature",
"humidity"
]
},
"70:ee:50:36:a9:fc": {
"res": {
"1560248191": [
1010
]
},
"type": [
"pressure"
]
},
"05:00:00:02:92:82": {
"rain_60min": 0,
"rain_24h": 11.009,
"rain_live": 0,
"rain_timeutc": 1560248184
},
"06:00:00:03:19:76": {
"wind_strength": 15,
"wind_angle": 17,
"gust_strength": 31,
"gust_angle": 217,
"wind_timeutc": 1560248190
}
},
"modules": [
"05:00:00:02:92:82",
"02:00:00:36:a9:50",
"06:00:00:03:19:76"
],
"module_types": {
"05:00:00:02:92:82": "NAModule3",
"02:00:00:36:a9:50": "NAModule1",
"06:00:00:03:19:76": "NAModule2"
}
}
]
} pyatmo-9.2.1/fixtures/archive/thermostat_data_simple.json 0000664 0000000 0000000 00000025524 15017405234 0023766 0 ustar 00root root 0000000 0000000 {
"body": {
"devices": [
{
"_id": "12:34:56:00:fa:d0",
"firmware": 174,
"last_bilan": {
"y": 2019,
"m": 4
},
"last_setup": 1494963356,
"last_status_store": 1559297986,
"place": {
"altitude": 112,
"city": "Berlin",
"country": "DE",
"improveLocProposed": true,
"location": [
52.516263,
13.377726
],
"timezone": "Europe/Berlin",
"trust_location": true
},
"plug_connected_boiler": 1,
"type": "NAPlug",
"udp_conn": true,
"wifi_status": 42,
"modules": [
{
"_id": "12:34:56:00:01:ae",
"module_name": "Livingroom",
"type": "NATherm1",
"firmware": 65,
"last_message": 1559297976,
"rf_status": 59,
"battery_vp": 3798,
"therm_orientation": 3,
"therm_relay_cmd": 0,
"anticipating": false,
"battery_percent": 53,
"event_history": {
"boiler_not_responding_events": [
{
"K": 1506103090
},
{
"K": 1514496738
},
{
"K": 1514583682
},
{
"K": 1518695843
},
{
"K": 1518813960
}
],
"boiler_responding_events": [
{
"K": 1506281109
},
{
"K": 1514552830
},
{
"K": 1514757686
},
{
"K": 1518798339
},
{
"K": 1518965265
}
]
},
"setpoint_history": [
{
"setpoint": {
"setpoint_mode": "hg"
},
"timestamp": 1559229554
},
{
"setpoint": {
"setpoint_mode": "program"
},
"timestamp": 1559229565
},
{
"setpoint": {
"setpoint_mode": "away"
},
"timestamp": 1559229567
}
],
"last_therm_seen": 1559297976,
"setpoint": {
"setpoint_mode": "away"
},
"therm_program_list": [
{
"zones": [
{
"type": 0,
"name": "Comfort",
"id": 0,
"temp": 21
},
{
"type": 1,
"name": "Night",
"id": 1,
"temp": 17
},
{
"type": 5,
"name": "Eco",
"id": 4,
"temp": 17
},
{
"type": 2,
"id": 2,
"temp": 14
},
{
"type": 3,
"id": 3,
"temp": 7
}
],
"timetable": [
{
"m_offset": 0,
"id": 1
},
{
"m_offset": 360,
"id": 0
},
{
"m_offset": 420,
"id": 4
},
{
"m_offset": 960,
"id": 0
},
{
"m_offset": 1410,
"id": 1
},
{
"m_offset": 1800,
"id": 0
},
{
"m_offset": 1860,
"id": 4
},
{
"m_offset": 2400,
"id": 0
},
{
"m_offset": 2850,
"id": 1
},
{
"m_offset": 3240,
"id": 0
},
{
"m_offset": 3300,
"id": 4
},
{
"m_offset": 3840,
"id": 0
},
{
"m_offset": 4290,
"id": 1
},
{
"m_offset": 4680,
"id": 0
},
{
"m_offset": 4740,
"id": 4
},
{
"m_offset": 5280,
"id": 0
},
{
"m_offset": 5730,
"id": 1
},
{
"m_offset": 6120,
"id": 0
},
{
"m_offset": 6180,
"id": 4
},
{
"m_offset": 6720,
"id": 0
},
{
"m_offset": 7170,
"id": 1
},
{
"m_offset": 7620,
"id": 0
},
{
"m_offset": 8610,
"id": 1
},
{
"m_offset": 9060,
"id": 0
},
{
"m_offset": 10050,
"id": 1
}
],
"name": "Default",
"program_id": "591b54a2764ff4d50d8b5795",
"selected": true
}
],
"measured": {
"time": 1559297836,
"temperature": 19.8,
"setpoint_temp": 12
}
}
],
"station_name": "Thermostat",
"last_plug_seen": 1559297986
}
],
"user": {
"mail": "john@doe.com",
"administrative": {
"lang": "de-DE",
"reg_locale": "de-DE",
"country": "DE",
"unit": 0,
"windunit": 0,
"pressureunit": 0,
"feel_like_algo": 0
}
}
},
"status": "ok",
"time_exec": 0.12061500549316,
"time_server": 1559300497
} pyatmo-9.2.1/fixtures/archive/too_many_connections.json 0000664 0000000 0000000 00000000047 15017405234 0023452 0 ustar 00root root 0000000 0000000 {
"error": "too_many_connections"
} pyatmo-9.2.1/fixtures/archive/weatherstation_data_simple.json 0000664 0000000 0000000 00000055176 15017405234 0024643 0 ustar 00root root 0000000 0000000 {
"body": {
"devices": [
{
"_id": "12:34:56:37:11:ca",
"cipher_id": "enc:16:zjiZF/q8jTScXVdDa/kvhUAIUPGeYszaD1ClEf8byAJkRjxc5oth7cAocrMUIApX",
"date_setup": 1544558432,
"last_setup": 1544558432,
"type": "NAMain",
"last_status_store": 1559413181,
"module_name": "NetatmoIndoor",
"firmware": 137,
"last_upgrade": 1544558433,
"wifi_status": 45,
"reachable": true,
"co2_calibrating": false,
"station_name": "MyStation",
"data_type": [
"Temperature",
"CO2",
"Humidity",
"Noise",
"Pressure"
],
"place": {
"altitude": 664,
"city": "Frankfurt",
"country": "DE",
"timezone": "Europe/Berlin",
"location": [
52.516263,
13.377726
]
},
"dashboard_data": {
"time_utc": 1559413171,
"Temperature": 24.6,
"CO2": 749,
"Humidity": 36,
"Noise": 37,
"Pressure": 1017.3,
"AbsolutePressure": 939.7,
"min_temp": 23.4,
"max_temp": 25.6,
"date_min_temp": 1559371924,
"date_max_temp": 1559411964,
"temp_trend": "stable",
"pressure_trend": "down"
},
"modules": [
{
"_id": "12:34:56:36:fc:de",
"type": "NAModule1",
"module_name": "NetatmoOutdoor",
"data_type": [
"Temperature",
"Humidity"
],
"last_setup": 1544558433,
"reachable": true,
"dashboard_data": {
"time_utc": 1559413157,
"Temperature": 28.6,
"Humidity": 24,
"min_temp": 16.9,
"max_temp": 30.3,
"date_min_temp": 1559365579,
"date_max_temp": 1559404698,
"temp_trend": "down"
},
"firmware": 46,
"last_message": 1559413177,
"last_seen": 1559413157,
"rf_status": 65,
"battery_vp": 5738,
"battery_percent": 87
},
{
"_id": "12:34:56:07:bb:3e",
"type": "NAModule4",
"module_name": "Kitchen",
"data_type": [
"Temperature",
"CO2",
"Humidity"
],
"last_setup": 1548956696,
"reachable": true,
"dashboard_data": {
"time_utc": 1559413125,
"Temperature": 28,
"CO2": 503,
"Humidity": 26,
"min_temp": 25,
"max_temp": 28,
"date_min_temp": 1559371577,
"date_max_temp": 1559412561,
"temp_trend": "up"
},
"firmware": 44,
"last_message": 1559413177,
"last_seen": 1559413177,
"rf_status": 73,
"battery_vp": 5687,
"battery_percent": 83
},
{
"_id": "12:34:56:07:bb:0e",
"type": "NAModule4",
"module_name": "Livingroom",
"data_type": [
"Temperature",
"CO2",
"Humidity"
],
"last_setup": 1548957209,
"reachable": true,
"dashboard_data": {
"time_utc": 1559413093,
"Temperature": 26.4,
"CO2": 451,
"Humidity": 31,
"min_temp": 25.1,
"max_temp": 26.4,
"date_min_temp": 1559365290,
"date_max_temp": 1559413093,
"temp_trend": "stable"
},
"firmware": 44,
"last_message": 1559413177,
"last_seen": 1559413093,
"rf_status": 84,
"battery_vp": 5626,
"battery_percent": 79
},
{
"_id": "12:34:56:03:1b:e4",
"type": "NAModule2",
"module_name": "Garden",
"data_type": [
"Wind"
],
"last_setup": 1549193862,
"reachable": true,
"dashboard_data": {
"time_utc": 1559413170,
"WindStrength": 4,
"WindAngle": 217,
"GustStrength": 9,
"GustAngle": 206,
"max_wind_str": 21,
"max_wind_angle": 217,
"date_max_wind_str": 1559386669
},
"firmware": 19,
"last_message": 1559413177,
"last_seen": 1559413177,
"rf_status": 59,
"battery_vp": 5689,
"battery_percent": 85
},
{
"_id": "12:34:56:05:51:20",
"type": "NAModule3",
"module_name": "Yard",
"data_type": [
"Rain"
],
"last_setup": 1549194580,
"reachable": true,
"dashboard_data": {
"time_utc": 1559413170,
"Rain": 0,
"sum_rain_24": 0,
"sum_rain_1": 0
},
"firmware": 8,
"last_message": 1559413177,
"last_seen": 1559413170,
"rf_status": 67,
"battery_vp": 5860,
"battery_percent": 93
}
]
},
{
"_id": "12 :34: 56:36:fd:3c",
"station_name": "Valley Road",
"date_setup": 1545897146,
"last_setup": 1545897146,
"type": "NAMain",
"last_status_store": 1581835369,
"firmware": 137,
"last_upgrade": 1545897125,
"wifi_status": 53,
"reachable": true,
"co2_calibrating": false,
"data_type": [
"Temperature",
"CO2",
"Humidity",
"Noise",
"Pressure"
],
"place": {
"altitude": 69,
"city": "Valley",
"country": "AU",
"timezone": "Australia/Hobart",
"location": [
148.444226,
-41.721282
]
},
"read_only": true,
"dashboard_data": {
"time_utc": 1581835330,
"Temperature": 22.4,
"CO2": 471,
"Humidity": 46,
"Noise": 47,
"Pressure": 1011.5,
"AbsolutePressure": 1002.8,
"min_temp": 18.1,
"max_temp": 22.5,
"date_max_temp": 1581829891,
"date_min_temp": 1581794878,
"temp_trend": "stable",
"pressure_trend": "stable"
},
"modules": [
{
"_id": "12 :34: 56:36:e6:c0",
"type": "NAModule1",
"module_name": "Module",
"data_type": [
"Temperature",
"Humidity"
],
"last_setup": 1545897146,
"battery_percent": 22,
"reachable": false,
"firmware": 46,
"last_message": 1572497781,
"last_seen": 1572497742,
"rf_status": 88,
"battery_vp": 4118
},
{
"_id": "12:34:56:05:25:6e",
"type": "NAModule3",
"module_name": "Rain Gauge",
"data_type": [
"Rain"
],
"last_setup": 1553997427,
"battery_percent": 82,
"reachable": true,
"firmware": 8,
"last_message": 1581835362,
"last_seen": 1581835354,
"rf_status": 78,
"battery_vp": 5594,
"dashboard_data": {
"time_utc": 1581835329,
"Rain": 0,
"sum_rain_1": 0,
"sum_rain_24": 0
}
}
]
},
{
"_id": "12:34:56:32:a7:60",
"home_name": "Ateljen",
"date_setup": 1566714693,
"last_setup": 1566714693,
"type": "NAMain",
"last_status_store": 1588481079,
"module_name": "Indoor",
"firmware": 177,
"last_upgrade": 1566714694,
"wifi_status": 50,
"reachable": true,
"co2_calibrating": false,
"data_type": [
"Temperature",
"CO2",
"Humidity",
"Noise",
"Pressure"
],
"place": {
"altitude": 93,
"city": "Gothenburg",
"country": "SE",
"timezone": "Europe/Stockholm",
"location": [
11.6136629,
57.7006827
]
},
"dashboard_data": {
"time_utc": 1588481073,
"Temperature": 18.2,
"CO2": 542,
"Humidity": 45,
"Noise": 45,
"Pressure": 1013,
"AbsolutePressure": 1001.9,
"min_temp": 18.2,
"max_temp": 19.5,
"date_max_temp": 1588456861,
"date_min_temp": 1588479561,
"temp_trend": "stable",
"pressure_trend": "up"
},
"modules": [
{
"_id": "12:34:56:32:db:06",
"type": "NAModule1",
"last_setup": 1587635819,
"data_type": [
"Temperature",
"Humidity"
],
"battery_percent": 100,
"reachable": false,
"firmware": 255,
"last_message": 0,
"last_seen": 0,
"rf_status": 255,
"battery_vp": 65535
}
]
},
{
"_id": "12:34:56:1c:68:2e",
"station_name": "Bol\u00e5s",
"date_setup": 1470935400,
"last_setup": 1470935400,
"type": "NAMain",
"last_status_store": 1588481399,
"module_name": "Inne - Nere",
"firmware": 177,
"last_upgrade": 1470935401,
"wifi_status": 13,
"reachable": true,
"co2_calibrating": false,
"data_type": [
"Temperature",
"CO2",
"Humidity",
"Noise",
"Pressure"
],
"place": {
"altitude": 93,
"city": "Gothenburg",
"country": "SE",
"timezone": "Europe/Stockholm",
"location": [
11.6136629,
57.7006827
]
},
"dashboard_data": {
"time_utc": 1588481387,
"Temperature": 20.8,
"CO2": 674,
"Humidity": 41,
"Noise": 34,
"Pressure": 1012.1,
"AbsolutePressure": 1001,
"min_temp": 20.8,
"max_temp": 22.2,
"date_max_temp": 1588456859,
"date_min_temp": 1588480176,
"temp_trend": "stable",
"pressure_trend": "up"
},
"modules": [
{
"_id": "12:34:56:02:b3:da",
"type": "NAModule3",
"module_name": "Regnm\u00e4tare",
"last_setup": 1470937706,
"data_type": [
"Rain"
],
"battery_percent": 81,
"reachable": true,
"firmware": 12,
"last_message": 1588481393,
"last_seen": 1588481386,
"rf_status": 67,
"battery_vp": 5582,
"dashboard_data": {
"time_utc": 1588481386,
"Rain": 0,
"sum_rain_1": 0,
"sum_rain_24": 0.1
}
},
{
"_id": "12:34:56:03:76:60",
"type": "NAModule4",
"module_name": "Inne - Uppe",
"last_setup": 1470938089,
"data_type": [
"Temperature",
"CO2",
"Humidity"
],
"battery_percent": 14,
"reachable": true,
"firmware": 50,
"last_message": 1588481393,
"last_seen": 1588481374,
"rf_status": 70,
"battery_vp": 4448,
"dashboard_data": {
"time_utc": 1588481374,
"Temperature": 19.6,
"CO2": 696,
"Humidity": 41,
"min_temp": 19.6,
"max_temp": 20.5,
"date_max_temp": 1588456817,
"date_min_temp": 1588481374,
"temp_trend": "stable"
}
},
{
"_id": "12:34:56:32:db:06",
"type": "NAModule1",
"module_name": "Ute",
"last_setup": 1566326027,
"data_type": [
"Temperature",
"Humidity"
],
"battery_percent": 81,
"reachable": true,
"firmware": 50,
"last_message": 1588481393,
"last_seen": 1588481380,
"rf_status": 61,
"battery_vp": 5544,
"dashboard_data": {
"time_utc": 1588481380,
"Temperature": 6.4,
"Humidity": 91,
"min_temp": 3.6,
"max_temp": 6.4,
"date_max_temp": 1588481380,
"date_min_temp": 1588471383,
"temp_trend": "up"
}
}
]
},
{
"_id": "12:34:56:1d:68:2e",
"date_setup": 1470935500,
"last_setup": 1470935500,
"type": "NAMain",
"last_status_store": 1588481399,
"module_name": "Basisstation",
"firmware": 177,
"last_upgrade": 1470935401,
"wifi_status": 13,
"reachable": true,
"co2_calibrating": false,
"data_type": [
"Temperature",
"CO2",
"Humidity",
"Noise",
"Pressure"
],
"place": {
"altitude": 93,
"city": "Gothenburg",
"country": "SE",
"timezone": "Europe/Stockholm",
"location": [
11.6136629,
57.7006827
]
},
"dashboard_data": {
"time_utc": 1588481387,
"Temperature": 20.8,
"CO2": 674,
"Humidity": 41,
"Noise": 34,
"Pressure": 1012.1,
"AbsolutePressure": 1001,
"min_temp": 20.8,
"max_temp": 22.2,
"date_max_temp": 1588456859,
"date_min_temp": 1588480176,
"temp_trend": "stable",
"pressure_trend": "up"
},
"modules": []
},
{
"_id": "12:34:56:58:c8:54",
"date_setup": 1605594014,
"last_setup": 1605594014,
"type": "NAMain",
"last_status_store": 1605878352,
"firmware": 178,
"wifi_status": 47,
"reachable": true,
"co2_calibrating": false,
"data_type": [
"Temperature",
"CO2",
"Humidity",
"Noise",
"Pressure"
],
"place": {
"altitude": 65,
"city": "Njurunda District",
"country": "SE",
"timezone": "Europe/Stockholm",
"location": [
17.123456,
62.123456
]
},
"station_name": "Njurunda (Indoor)",
"home_id": "5fb36b9ec68fd10c6467ca65",
"home_name": "Njurunda",
"dashboard_data": {
"time_utc": 1605878349,
"Temperature": 19.7,
"CO2": 993,
"Humidity": 40,
"Noise": 40,
"Pressure": 1015.6,
"AbsolutePressure": 1007.8,
"min_temp": 19.7,
"max_temp": 20.4,
"date_max_temp": 1605826917,
"date_min_temp": 1605873207,
"temp_trend": "stable",
"pressure_trend": "up"
},
"modules": [
{
"_id": "12:34:56:58:e6:38",
"type": "NAModule1",
"last_setup": 1605594034,
"data_type": [
"Temperature",
"Humidity"
],
"battery_percent": 100,
"reachable": true,
"firmware": 50,
"last_message": 1605878347,
"last_seen": 1605878328,
"rf_status": 62,
"battery_vp": 6198,
"dashboard_data": {
"time_utc": 1605878328,
"Temperature": 0.6,
"Humidity": 77,
"min_temp": -2.1,
"max_temp": 1.5,
"date_max_temp": 1605865920,
"date_min_temp": 1605826904,
"temp_trend": "down"
}
}
]
}
],
"user": {
"mail": "john@doe.com",
"administrative": {
"lang": "de-DE",
"reg_locale": "de-DE",
"country": "DE",
"unit": 0,
"windunit": 0,
"pressureunit": 0,
"feel_like_algo": 0
}
}
},
"status": "ok",
"time_exec": 0.91107702255249,
"time_server": 1559413602
} pyatmo-9.2.1/fixtures/archive/weatherstation_data_unreachable_station.json 0000664 0000000 0000000 00000024533 15017405234 0027355 0 ustar 00root root 0000000 0000000 {
"body": {
"devices": [
{
"_id": "12:34:56:37:11:ca",
"cipher_id": "enc:16:zjiZF/q8jTScXVdDa/kvhUAIUPGeYszaD1ClEf8byAJkRjxc5oth7cAocrMUIApX",
"date_setup": 1544558432,
"last_setup": 1544558432,
"type": "NAMain",
"last_status_store": 1559413181,
"module_name": "NetatmoIndoor",
"firmware": 137,
"last_upgrade": 1544558433,
"wifi_status": 45,
"reachable": true,
"co2_calibrating": false,
"station_name": "MyStation",
"data_type": [
"Temperature",
"CO2",
"Humidity",
"Noise",
"Pressure"
],
"place": {
"altitude": 664,
"city": "Frankfurt",
"country": "DE",
"timezone": "Europe/Berlin",
"location": [
52.516263,
13.377726
]
},
"dashboard_data": {
"time_utc": 1559413171,
"Temperature": 24.6,
"CO2": 749,
"Humidity": 36,
"Noise": 37,
"Pressure": 1017.3,
"AbsolutePressure": 939.7,
"min_temp": 23.4,
"max_temp": 25.6,
"date_min_temp": 1559371924,
"date_max_temp": 1559411964,
"temp_trend": "stable",
"pressure_trend": "down"
},
"modules": [
{
"_id": "12:34:56:36:fc:de",
"type": "NAModule1",
"module_name": "NetatmoOutdoor",
"data_type": [
"Temperature",
"Humidity"
],
"last_setup": 1544558433,
"reachable": true,
"dashboard_data": {
"time_utc": 1559413157,
"Temperature": 28.6,
"Humidity": 24,
"min_temp": 16.9,
"max_temp": 30.3,
"date_min_temp": 1559365579,
"date_max_temp": 1559404698,
"temp_trend": "down"
},
"firmware": 46,
"last_message": 1559413177,
"last_seen": 1559413157,
"rf_status": 65,
"battery_vp": 5738,
"battery_percent": 87
},
{
"_id": "12:34:56:07:bb:3e",
"type": "NAModule4",
"module_name": "Kitchen",
"data_type": [
"Temperature",
"CO2",
"Humidity"
],
"last_setup": 1548956696,
"reachable": true,
"dashboard_data": {
"time_utc": 1559413125,
"Temperature": 28,
"CO2": 503,
"Humidity": 26,
"min_temp": 25,
"max_temp": 28,
"date_min_temp": 1559371577,
"date_max_temp": 1559412561,
"temp_trend": "up"
},
"firmware": 44,
"last_message": 1559413177,
"last_seen": 1559413177,
"rf_status": 73,
"battery_vp": 5687,
"battery_percent": 83
},
{
"_id": "12:34:56:07:bb:0e",
"type": "NAModule4",
"module_name": "Livingroom",
"data_type": [
"Temperature",
"CO2",
"Humidity"
],
"last_setup": 1548957209,
"reachable": true,
"dashboard_data": {
"time_utc": 1559413093,
"Temperature": 26.4,
"CO2": 451,
"Humidity": 31,
"min_temp": 25.1,
"max_temp": 26.4,
"date_min_temp": 1559365290,
"date_max_temp": 1559413093,
"temp_trend": "stable"
},
"firmware": 44,
"last_message": 1559413177,
"last_seen": 1559413093,
"rf_status": 84,
"battery_vp": 5626,
"battery_percent": 79
},
{
"_id": "12:34:56:03:1b:e4",
"type": "NAModule2",
"module_name": "Garden",
"data_type": [
"Wind"
],
"last_setup": 1549193862,
"reachable": true,
"dashboard_data": {
"time_utc": 1559413170,
"WindStrength": 4,
"WindAngle": 217,
"GustStrength": 9,
"GustAngle": 206,
"max_wind_str": 21,
"max_wind_angle": 217,
"date_max_wind_str": 1559386669
},
"firmware": 19,
"last_message": 1559413177,
"last_seen": 1559413177,
"rf_status": 59,
"battery_vp": 5689,
"battery_percent": 85
},
{
"_id": "12:34:56:05:51:20",
"type": "NAModule3",
"module_name": "Yard",
"data_type": [
"Rain"
],
"last_setup": 1549194580,
"reachable": true,
"dashboard_data": {
"time_utc": 1559413170,
"Rain": 0,
"sum_rain_24": 0,
"sum_rain_1": 0
},
"firmware": 8,
"last_message": 1559413177,
"last_seen": 1559413170,
"rf_status": 67,
"battery_vp": 5860,
"battery_percent": 93
}
]
},
{
"_id": "12:34:56:00:aa:01",
"station_name": "MyRemoteStation",
"date_setup": 1499189962,
"last_setup": 1499189962,
"type": "NAMain",
"last_status_store": 1554506294,
"module_name": "Indoor",
"firmware": 132,
"last_upgrade": 1499189915,
"wifi_status": 46,
"reachable": false,
"co2_calibrating": false,
"data_type": [
"Temperature",
"CO2",
"Humidity",
"Noise",
"Pressure"
],
"place": {
"altitude": 6,
"city": "Harstad",
"country": "NO",
"timezone": "Europe/Oslo",
"location": [
59.895000,
10.620000
]
},
"modules": [
{
"_id": "12:34:56:00:aa:02",
"type": "NAModule1",
"module_name": "Outdoor",
"data_type": [
"Temperature",
"Humidity"
],
"last_setup": 1499189902,
"battery_percent": 17,
"reachable": false,
"firmware": 44,
"last_message": 1536805739,
"last_seen": 1536696388,
"rf_status": 87,
"battery_vp": 4018,
"main_device": "12:34:56:00:aa:01"
},
{
"_id": "12:34:56:00:aa:03",
"type": "NAModule2",
"module_name": "Wind Gauge",
"data_type": [
"Wind"
],
"last_setup": 1499190606,
"battery_percent": 3,
"reachable": false,
"firmware": 18,
"last_message": 1537259554,
"last_seen": 1537259554,
"rf_status": 74,
"battery_vp": 4013,
"main_device": "12:34:56:00:aa:01"
}
]
}
],
"user": {
"mail": "john@doe.com",
"administrative": {
"lang": "de-DE",
"reg_locale": "de-DE",
"country": "DE",
"unit": 0,
"windunit": 0,
"pressureunit": 0,
"feel_like_algo": 0
}
}
},
"status": "ok",
"time_exec": 0.91107702255249,
"time_server": 1559413602
} pyatmo-9.2.1/fixtures/archive/weatherstation_measure.json 0000664 0000000 0000000 00000001412 15017405234 0024002 0 ustar 00root root 0000000 0000000 {
"body": {
"1544558433": [
28.1
],
"1544558449": [
28.4
],
"1544558504": [
27
],
"1544558807": [
24
],
"1544559062": [
23.8
],
"1544559211": [
26.1
],
"1544559308": [
24.9
],
"1544559415": [
24.6
],
"1544559576": [
24.2
],
"1544559974": [
26.9
],
"1544560021": [
27.1
],
"1544560058": [
27.4
],
"1544560361": [
26
]
},
"status": "ok",
"time_exec": 0.33915495872498,
"time_server": 1560590041
} pyatmo-9.2.1/fixtures/getevents.json 0000664 0000000 0000000 00000015174 15017405234 0017615 0 ustar 00root root 0000000 0000000 {
"body": {
"home": {
"id": "91763b24c43d3e344f424e8b",
"events": [
{
"id": "11111111111111111f7763a6d",
"type": "outdoor",
"time": 1645794709,
"module_id": "12:34:56:10:b9:0e",
"video_id": "11111111-2222-3333-4444-b42f0fc4cfad",
"video_status": "available",
"subevents": [
{
"id": "11111111-2222-3333-4444-013560107fce",
"type": "human",
"time": 1645794709,
"verified": true,
"offset": 0,
"snapshot": {
"url": "https://netatmocameraimage.blob.core.windows.net/production/000000a722374"
},
"vignette": {
"url": "https://netatmocameraimage.blob.core.windows.net/production/0000009625c0f"
},
"message": "Person erfasst"
},
{
"id": "11111111-2222-3333-4444-0b0bc962df43",
"type": "vehicle",
"time": 1645794716,
"verified": true,
"offset": 15,
"snapshot": {
"url": "https://netatmocameraimage.blob.core.windows.net/production/00000033f9f96"
},
"vignette": {
"url": "https://netatmocameraimage.blob.core.windows.net/production/000000cba08af"
},
"message": "Fahrzeug erfasst"
},
{
"id": "11111111-2222-3333-4444-129e72195968",
"type": "human",
"time": 1645794716,
"verified": true,
"offset": 15,
"snapshot": {
"filename": "vod/11111/events/22222/snapshot_129e72195968.jpg"
},
"vignette": {
"filename": "vod/11111/events/22222/vignette_129e72195968.jpg"
},
"message": "Person erfasst"
},
{
"id": "11111111-2222-3333-4444-dae4d7e4f24e",
"type": "human",
"time": 1645794718,
"verified": true,
"offset": 17,
"snapshot": {
"filename": "vod/11111/events/22222/snapshot_dae4d7e4f24e.jpg"
},
"vignette": {
"filename": "vod/11111/events/22222/vignette_dae4d7e4f24e.jpg"
},
"message": "Person erfasst"
}
]
},
{
"id": "1111111111111111e7e40c353",
"type": "connection",
"time": 1645784799,
"module_id": "12:34:56:10:b9:0e",
"message": "Front verbunden"
},
{
"id": "11111111111111144e3115860",
"type": "boot",
"time": 1645784775,
"module_id": "12:34:56:10:b9:0e",
"message": "Front gestartet"
},
{
"id": "11111111111111169804049ca",
"type": "disconnection",
"time": 1645773806,
"module_id": "12:34:56:10:b9:0e",
"message": "Front getrennt"
},
{
"id": "1111111111111117cb8147ffd",
"type": "outdoor",
"time": 1645712826,
"module_id": "12:34:56:10:b9:0e",
"video_id": "11111111-2222-3333-4444-5091e1903f8d",
"video_status": "available",
"subevents": [
{
"id": "11111111-2222-3333-4444-b7d28e3ccc38",
"type": "human",
"time": 1645712826,
"verified": true,
"offset": 0,
"snapshot": {
"url": "https://netatmocameraimage.blob.core.windows.net/production/000000a0ca642"
},
"vignette": {
"url": "https://netatmocameraimage.blob.core.windows.net/production/00000031b0ed4"
},
"message": "Person erfasst"
}
]
},
{
"id": "1111111111111119df3d2de6",
"type": "person_home",
"time": 1645902000,
"module_id": "12:34:56:00:f1:62",
"message": "Home Assistant Cloud definiert John Doe und Jane Doe als \"Zu Hause\""
},
{
"id": "1111111111111112c91b3628",
"type": "person",
"time": 1645901266,
"module_id": "12:34:56:00:f1:62",
"snapshot": {
"url": "https://netatmocameraimage.blob.core.windows.net/production/0000081d4f42875d9"
},
"video_id": "11111111-2222-3333-4444-314d161525db",
"video_status": "available",
"message": "John Doe gesehen",
"person_id": "91827374-7e04-5298-83ad-a0cb8372dff1",
"out_of_sight": false
},
{
"id": "1111111111111115166b1283",
"type": "tag_open",
"time": 1645897638,
"module_id": "12:34:56:00:86:99",
"message": "Window Hall: immer noch offen"
}
]
}
},
"status": "ok",
"time_exec": 0.24369096755981445,
"time_server": 1645897231
} pyatmo-9.2.1/fixtures/gethomecoachsdata.json 0000664 0000000 0000000 00000015364 15017405234 0021255 0 ustar 00root root 0000000 0000000 {
"body": {
"devices": [
{
"_id": "12:34:56:26:69:0c",
"cipher_id": "enc:16:1UqwQlYV5AY2pfyEi5H47dmmFOOL3mCUo+KAkchL4A2CLI5u0e45Xr5jeAswO+XO",
"date_setup": 1544560184,
"last_setup": 1544560184,
"type": "NHC",
"last_status_store": 1558268332,
"firmware": 45,
"last_upgrade": 1544560186,
"wifi_status": 58,
"reachable": false,
"co2_calibrating": false,
"station_name": "Bedroom",
"data_type": [
"Temperature",
"CO2",
"Humidity",
"Noise",
"Pressure",
"health_idx"
],
"place": {
"city": "Frankfurt",
"country": "DE",
"timezone": "Europe/Berlin",
"location": [
52.516263,
13.377726
]
}
},
{
"_id": "12:34:56:25:cf:a8",
"cipher_id": "enc:16:A+Jm0yFWBwUyKinFDutPZK7I2PuHN1fqaE9oB/KF+McbFs3oN9CKpR/dYbqL4om2",
"date_setup": 1544562192,
"last_setup": 1544562192,
"type": "NHC",
"last_status_store": 1559198922,
"firmware": 45,
"last_upgrade": 1544562194,
"wifi_status": 41,
"reachable": true,
"co2_calibrating": false,
"station_name": "Kitchen",
"data_type": [
"Temperature",
"CO2",
"Humidity",
"Noise",
"Pressure",
"health_idx"
],
"place": {
"city": "Frankfurt",
"country": "DE",
"timezone": "Europe/Berlin",
"location": [
52.516263,
13.377726
]
}
},
{
"_id": "12:34:56:26:65:14",
"cipher_id": "enc:16:7kK6ZzG4L7NgfZZ6+dMvNxw4l6vXu+88SEJkCUklNdPa4KYIHmsfa1moOilEK61i",
"date_setup": 1544564061,
"last_setup": 1544564061,
"type": "NHC",
"last_status_store": 1559067159,
"firmware": 45,
"last_upgrade": 1544564302,
"wifi_status": 66,
"reachable": true,
"co2_calibrating": false,
"station_name": "Livingroom",
"data_type": [
"Temperature",
"CO2",
"Humidity",
"Noise",
"Pressure",
"health_idx"
],
"place": {
"city": "Frankfurt",
"country": "DE",
"timezone": "Europe/Berlin",
"location": [
52.516263,
13.377726
]
}
},
{
"_id": "12:34:56:3e:c5:46",
"station_name": "Parents Bedroom",
"date_setup": 1570732241,
"last_setup": 1570732241,
"type": "NHC",
"last_status_store": 1572073818,
"module_name": "Indoor",
"firmware": 45,
"wifi_status": 67,
"reachable": true,
"co2_calibrating": false,
"data_type": [
"Temperature",
"CO2",
"Humidity",
"Noise",
"Pressure",
"health_idx"
],
"place": {
"city": "Frankfurt",
"country": "DE",
"timezone": "Europe/Berlin",
"location": [
52.516263,
13.377726
]
},
"dashboard_data": {
"time_utc": 1572073816,
"Temperature": 20.3,
"CO2": 494,
"Humidity": 63,
"Noise": 42,
"Pressure": 1014.5,
"AbsolutePressure": 1004.1,
"health_idx": 1,
"min_temp": 20.3,
"max_temp": 21.6,
"date_max_temp": 1572059333,
"date_min_temp": 1572073816
}
},
{
"_id": "12:34:56:26:68:92",
"station_name": "Baby Bedroom",
"date_setup": 1571342643,
"last_setup": 1571342643,
"type": "NHC",
"last_status_store": 1572073995,
"module_name": "Indoor",
"firmware": 45,
"wifi_status": 68,
"reachable": true,
"co2_calibrating": false,
"data_type": [
"Temperature",
"CO2",
"Humidity",
"Noise",
"Pressure",
"health_idx"
],
"place": {
"city": "Frankfurt",
"country": "DE",
"timezone": "Europe/Berlin",
"location": [
52.516263,
13.377726
]
},
"dashboard_data": {
"time_utc": 1572073994,
"Temperature": 21.6,
"CO2": 1053,
"Humidity": 66,
"Noise": 45,
"Pressure": 1021.4,
"AbsolutePressure": 1011,
"health_idx": 1,
"min_temp": 20.9,
"max_temp": 21.6,
"date_max_temp": 1572073690,
"date_min_temp": 1572064254
}
}
],
"user": {
"mail": "john@doe.com",
"administrative": {
"lang": "de-DE",
"reg_locale": "de-DE",
"country": "DE",
"unit": 0,
"windunit": 0,
"pressureunit": 0,
"feel_like_algo": 0
}
}
},
"status": "ok",
"time_exec": 0.095954179763794,
"time_server": 1559463229
} 1c1d1694c91210991f1b006755f6bde04cf29a93.paxheader 0000666 0000000 0000000 00000000261 15017405234 0020266 x ustar 00root root 0000000 0000000 177 path=pyatmo-9.2.1/fixtures/getmeasure_sum_energy_buy_from_grid,sum_energy_buy_from_grid$0,sum_energy_buy_from_grid$1,sum_energy_buy_from_grid$2_12_34_56_00_00_a1_4c_da.json
1c1d1694c91210991f1b006755f6bde04cf29a93.data 0000664 0000000 0000000 00000031570 15017405234 0017133 0 ustar 00root root 0000000 0000000 {
"body": [
{
"beg_time": 1644049789,
"step_time": 3600,
"value": [
[ null,
197
,null, null],
[null,
262
,null, null],
[null,
168
,null, null],
[null,
219
,null, null],
[null,
224
,null, null],
[null,
299
,null, null],
[null,
343
,null, null],
[null,
443
,null, null],
[null,
317
,null, null],
[null,
229
,null, null],
[null,
147
,null, null],
[null,
178
,null, null],
[null,
340
,null, null],
[null,
536
,null, null],
[null,
471
,null, null],
[null,
397
,null, null],
[null,
290
,null, null],
[null,
302
,null, null],
[null,
309
,null, null],
[null,
219
,null, null],
[null,
154
,null, null],
[null,
163
,null, null],
[null,
146
,null, null],
[null,
189
,null, null],
[null,
256
,null, null],
[null,
162
,null, null],
[null,
1288
,null, null],
[null,
256
,null, null],
[null,
709
,null, null],
[null,
310
,null, null],
[null,
379
,null, null],
[null,
296
,null, null],
[null,
230
,null, null],
[null,
505
,null, null],
[null,
362
,null, null],
[null,
611
,null, null],
[null,
597
,null, null],
[null,
505
,null, null],
[null,
431
,null, null],
[null,
1538
,null, null],
[null,
265
,null, null],
[null,
187
,null, null],
[null,
162
,null, null],
[null,
150
,null, null],
[null,
155
,null, null],
[null,
147
,null, null],
[null,
211
,null, null],
[null,
211
,null, null],
[null,
272
,null, null],
[null,
271
,null, null],
[null,
331
,null, null],
[null,
180
,null, null],
[null,
184
,null, null],
[null,
182
,null, null],
[null,
232
,null, null],
[null,
288
,null, null],
[null,
266
,null, null],
[null,
256
,null, null],
[null,
249
,null, null],
[null,
372
,null, null],
[null,
379
,null, null],
[null,
585
,null, null],
[null,
387
,null, null],
[null,
277
,null, null],
[null,
223
,null, null],
[null,
202
,null, null],
[null,
163
,null, null],
[null,
143
,null, null],
[null,
158
,null, null],
[null,
145
,null, null],
[null,
232
,null, null],
[null,
231
,null, null],
[null,
160
,null, null],
[null,
261
,null, null],
[null,
376
,null, null],
[null,
216
,null, null],
[null,
202
,null, null],
[null,
295
,null, null],
[null,
310
,null, null],
[null,
235
,null, null],
[null,
188
,null, null],
[null,
269
,null, null],
[null,
250
,null, null],
[null,
334
,null, null],
[null,
434
,null, null],
[null,
353
,null, null],
[null,
279
,null, null],
[null,
266
,null, null],
[null,
226
,null, null],
[null,
179
,null, null],
[null,
149
,null, null],
[null,
146
,null, null],
[null,
143
,null, null],
[null,
136
,null, null],
[null,
173
,null, null],
[null,
221
,null, null],
[null,
190
,null, null],
[null,
177
,null, null],
[null,
290
,null, null],
[null,
352
,null, null],
[null,
252
,null, null],
[null,
284
,null, null],
[null,
173
,null, null],
[null,
165
,null, null],
[null,
144
,null, null],
[null,
175
,null, null],
[null,
268
,null, null],
[null,
363
,null, null],
[null,
544
,null, null],
[null,
515
,null, null],
[null,
525
,null, null],
[null,
431
,null, null],
[null,
225
,null, null],
[null,
183
,null, null],
[null,
178
,null, null],
[null,
155
,null, null],
[null,
170
,null, null],
[null,
156
,null, null],
[null,
169
,null, null],
[null,
226
,null, null],
[null,
255
,null, null],
[null,
273
,null, null],
[null,
466
,null, null],
[null,
406
,null, null],
[null,
333
,null, null],
[null,
194
,null, null],
[null,
234
,null, null],
[null,
271
,null, null],
[null,
238
,null, null],
[null,
221
,null, null],
[null,
205
,null, null],
[null,
258
,null, null],
[null,
430
,null, null],
[null,
446
,null, null],
[null,
390
,null, null],
[null,
306
,null, null],
[null,
223
,null, null],
[null,
165
,null, null],
[null,
154
,null, null],
[null,
147
,null, null],
[null,
155
,null, null],
[null,
140
,null, null],
[null,
153
,null, null],
[null,
228
,null, null],
[null,
237
,null, null],
[null,
201
,null, null],
[null,
183
,null, null],
[null,
194
,null, null],
[null,
135
,null, null],
[null,
206
,null, null],
[null,
215
,null, null],
[null,
147
,null, null],
[null,
159
,null, null],
[null,
185
,null, null],
[null,
168
,null, null],
[null,
257
,null, null],
[null,
262
,null, null],
[null,
141
,null, null],
[null,
151
,null, null],
[null,
157
,null, null],
[null,
133
,null, null],
[null,
147
,null, null],
[null,
135
,null, null],
[null,
139
,null, null],
[null,
136
,null, null],
[null,
127
,null, null],
[null,
169
,null, null],
[null,
259, null, null
]
]
}
],
"status": "ok",
"time_exec": 0.5533828735351562,
"time_server": 1647935044
}
3e11402ef9fbb9a2e47a347e9c1af2d87701f522.paxheader 0000666 0000000 0000000 00000000261 15017405234 0020510 x ustar 00root root 0000000 0000000 177 path=pyatmo-9.2.1/fixtures/getmeasure_sum_energy_buy_from_grid,sum_energy_buy_from_grid$0,sum_energy_buy_from_grid$1,sum_energy_buy_from_grid$2_98_76_54_32_10_00_00_69.json
3e11402ef9fbb9a2e47a347e9c1af2d87701f522.data 0000664 0000000 0000000 00000006526 15017405234 0017360 0 ustar 00root root 0000000 0000000 {
"body": [
{
"beg_time": 1721772900,
"step_time": 1800,
"value": [
[
null,
20,
null,
null
],
[
null,
19,
null,
null
],
[
null,
16,
null,
null
],
[
null,
11,
null,
null
],
[
null,
18,
null,
null
],
[
null,
14,
null,
null
],
[
null,
14,
null,
null
],
[
null,
64,
null,
null
],
[
null,
100,
null,
null
],
[
null,
58,
null,
null
],
[
null,
39,
null,
null
],
[
null,
24,
null,
null
],
[
null,
19,
null,
null
],
[
null,
19,
null,
null
],
[
null,
712,
null,
null
],
[
null,
724,
null,
null
],
[
null,
711,
null,
null
],
[
null,
498,
212,
null
],
[
null,
null,
717,
null
],
[
null,
null,
714,
null
],
[
null,
null,
714,
null
],
[
null,
null,
711,
null
],
[
null,
null,
706,
null
],
[
null,
null,
704,
null
],
[
null,
null,
706,
null
],
[
null,
null,
709,
null
],
[
null,
null,
714,
null
],
[
null,
null,
712,
null
],
[
null,
null,
238,
477
],
[
null,
null,
null,
714
],
[
null,
null,
null,
722
],
[
null,
null,
null,
713
],
[
null,
null,
null,
709
],
[
null,
null,
null,
714
],
[
null,
null,
477,
241
],
[
null,
null,
710,
null
],
[
null,
null,
710,
null
],
[
null,
null,
707,
null
],
[
null,
null,
16,
null
]
]
}
],
"status": "ok",
"time_exec": 0.025647878646850586,
"time_server": 1721852913
} pyatmo-9.2.1/fixtures/getpublicdata.json 0000664 0000000 0000000 00000015767 15017405234 0020431 0 ustar 00root root 0000000 0000000 {
"status": "ok",
"time_server": 1560248397,
"time_exec": 0,
"body": [
{
"_id": "70:ee:50:36:94:7c",
"place": {
"location": [8.791382999999996, 50.2136394],
"timezone": "Europe/Berlin",
"country": "DE",
"altitude": 132
},
"mark": 14,
"measures": {
"02:00:00:36:f2:94": {
"res": {
"1560248022": [21.4, 62]
},
"type": ["temperature", "humidity"]
},
"70:ee:50:36:94:7c": {
"res": {
"1560248030": [1010.6]
},
"type": ["pressure"]
},
"05:00:00:05:33:84": {
"rain_60min": 0.2,
"rain_24h": 12.322000000000001,
"rain_live": 0.5,
"rain_timeutc": 1560248022
}
},
"modules": ["05:00:00:05:33:84", "02:00:00:36:f2:94"],
"module_types": {
"05:00:00:05:33:84": "NAModule3",
"02:00:00:36:f2:94": "NAModule1"
}
},
{
"_id": "70:ee:50:1f:68:9e",
"place": {
"location": [8.795445200000017, 50.2130169],
"timezone": "Europe/Berlin",
"country": "DE",
"altitude": 125
},
"mark": 14,
"measures": {
"02:00:00:1f:82:28": {
"res": {
"1560248312": [21.1, 69]
},
"type": ["temperature", "humidity"]
},
"70:ee:50:1f:68:9e": {
"res": {
"1560248344": [1007.3]
},
"type": ["pressure"]
},
"05:00:00:02:bb:6e": {
"rain_60min": 0,
"rain_24h": 9.999,
"rain_live": 0,
"rain_timeutc": 1560248344
}
},
"modules": ["02:00:00:1f:82:28", "05:00:00:02:bb:6e"],
"module_types": {
"02:00:00:1f:82:28": "NAModule1",
"05:00:00:02:bb:6e": "NAModule3"
}
},
{
"_id": "70:ee:50:27:25:b0",
"place": {
"location": [8.7807159, 50.1946167],
"timezone": "Europe/Berlin",
"country": "DE",
"altitude": 112
},
"mark": 14,
"measures": {
"02:00:00:27:19:b2": {
"res": {
"1560247889": [23.2, 60]
},
"type": ["temperature", "humidity"]
},
"70:ee:50:27:25:b0": {
"res": {
"1560247907": [1012.8]
},
"type": ["pressure"]
},
"05:00:00:03:5d:2e": {
"rain_60min": 0,
"rain_24h": 11.716000000000001,
"rain_live": 0,
"rain_timeutc": 1560247896
}
},
"modules": ["02:00:00:27:19:b2", "05:00:00:03:5d:2e"],
"module_types": {
"02:00:00:27:19:b2": "NAModule1",
"05:00:00:03:5d:2e": "NAModule3"
}
},
{
"_id": "70:ee:50:04:ed:7a",
"place": {
"location": [8.785034, 50.192169],
"timezone": "Europe/Berlin",
"country": "DE",
"altitude": 112
},
"mark": 14,
"measures": {
"02:00:00:04:c2:2e": {
"res": {
"1560248137": [19.8, 76]
},
"type": ["temperature", "humidity"]
},
"70:ee:50:04:ed:7a": {
"res": {
"1560248152": [1005.4]
},
"type": ["pressure"]
}
},
"modules": ["02:00:00:04:c2:2e"],
"module_types": {
"02:00:00:04:c2:2e": "NAModule1"
}
},
{
"_id": "70:ee:50:27:9f:2c",
"place": {
"location": [8.785342, 50.193573],
"timezone": "Europe/Berlin",
"country": "DE",
"altitude": 116
},
"mark": 1,
"measures": {
"02:00:00:27:aa:70": {
"res": {
"1560247821": [25.5, 56]
},
"type": ["temperature", "humidity"]
},
"70:ee:50:27:9f:2c": {
"res": {
"1560247853": [1010.6]
},
"type": ["pressure"]
}
},
"modules": ["02:00:00:27:aa:70"],
"module_types": {
"02:00:00:27:aa:70": "NAModule1"
}
},
{
"_id": "70:ee:50:01:20:fa",
"place": {
"location": [8.7953, 50.195241],
"timezone": "Europe/Berlin",
"country": "DE",
"altitude": 119
},
"mark": 1,
"measures": {
"02:00:00:00:f7:ba": {
"res": {
"1560247831": [27.4, 58]
},
"type": ["temperature", "humidity"]
},
"70:ee:50:01:20:fa": {
"res": {
"1560247876": [1014.4]
},
"type": ["pressure"]
}
},
"modules": ["02:00:00:00:f7:ba"],
"module_types": {
"02:00:00:00:f7:ba": "NAModule1"
}
},
{
"_id": "70:ee:50:3c:02:78",
"place": {
"location": [8.795953681700666, 50.19530139868166],
"timezone": "Europe/Berlin",
"country": "DE",
"altitude": 119
},
"mark": 7,
"measures": {
"02:00:00:3c:21:f2": {
"res": {
"1560248225": [23.3, 58]
},
"type": ["temperature", "humidity"]
},
"70:ee:50:3c:02:78": {
"res": {
"1560248270": [1011.7]
},
"type": ["pressure"]
}
},
"modules": ["02:00:00:3c:21:f2"],
"module_types": {
"02:00:00:3c:21:f2": "NAModule1"
}
},
{
"_id": "70:ee:50:36:a9:fc",
"place": {
"location": [8.801164269110814, 50.19596181704958],
"timezone": "Europe/Berlin",
"country": "DE",
"altitude": 113
},
"mark": 14,
"measures": {
"02:00:00:36:a9:50": {
"res": {
"1560248145": [20.1, 67]
},
"type": ["temperature", "humidity"]
},
"70:ee:50:36:a9:fc": {
"res": {
"1560248191": [1010]
},
"type": ["pressure"]
},
"05:00:00:02:92:82": {
"rain_60min": 0,
"rain_24h": 11.009,
"rain_live": 0,
"rain_timeutc": 1560248184
},
"06:00:00:03:19:76": {
"wind_strength": 15,
"wind_angle": 17,
"gust_strength": 31,
"gust_angle": 217,
"wind_timeutc": 1560248190
}
},
"modules": [
"05:00:00:02:92:82",
"02:00:00:36:a9:50",
"06:00:00:03:19:76"
],
"module_types": {
"05:00:00:02:92:82": "NAModule3",
"02:00:00:36:a9:50": "NAModule1",
"06:00:00:03:19:76": "NAModule2"
}
}
]
}
pyatmo-9.2.1/fixtures/getstationsdata.json 0000664 0000000 0000000 00000051274 15017405234 0021010 0 ustar 00root root 0000000 0000000 {
"body": {
"devices": [
{
"_id": "12:34:56:37:11:ca",
"cipher_id": "enc:16:zjiZF/q8jTScXVdDa/kvhUAIUPGeYszaD1ClEf8byAJkRjxc5oth7cAocrMUIApX",
"date_setup": 1544558432,
"last_setup": 1544558432,
"type": "NAMain",
"last_status_store": 1559413181,
"module_name": "NetatmoIndoor",
"firmware": 137,
"last_upgrade": 1544558433,
"wifi_status": 45,
"reachable": true,
"co2_calibrating": false,
"station_name": "MyStation",
"data_type": [
"Temperature",
"CO2",
"Humidity",
"Noise",
"Pressure"
],
"place": {
"altitude": 664,
"city": "Frankfurt",
"country": "DE",
"timezone": "Europe/Berlin",
"location": [
52.516263,
13.377726
]
},
"dashboard_data": {
"time_utc": 1559413171,
"Temperature": 24.6,
"CO2": 749,
"Humidity": 36,
"Noise": 37,
"Pressure": 1017.3,
"AbsolutePressure": 939.7,
"min_temp": 23.4,
"max_temp": 25.6,
"date_min_temp": 1559371924,
"date_max_temp": 1559411964,
"temp_trend": "stable",
"pressure_trend": "down"
},
"modules": [
{
"_id": "12:34:56:36:fc:de",
"type": "NAModule1",
"module_name": "NetatmoOutdoor",
"data_type": [
"Temperature",
"Humidity"
],
"last_setup": 1544558433,
"reachable": true,
"dashboard_data": {
"time_utc": 1559413157,
"Temperature": 28.6,
"Humidity": 24,
"min_temp": 16.9,
"max_temp": 30.3,
"date_min_temp": 1559365579,
"date_max_temp": 1559404698,
"temp_trend": "down"
},
"firmware": 46,
"last_message": 1559413177,
"last_seen": 1559413157,
"rf_status": 65,
"battery_vp": 5738,
"battery_percent": 87
},
{
"_id": "12:34:56:07:bb:3e",
"type": "NAModule4",
"module_name": "Kitchen",
"data_type": [
"Temperature",
"CO2",
"Humidity"
],
"last_setup": 1548956696,
"reachable": true,
"dashboard_data": {
"time_utc": 1559413125,
"Temperature": 28,
"CO2": 503,
"Humidity": 26,
"min_temp": 25,
"max_temp": 28,
"date_min_temp": 1559371577,
"date_max_temp": 1559412561,
"temp_trend": "up"
},
"firmware": 44,
"last_message": 1559413177,
"last_seen": 1559413177,
"rf_status": 73,
"battery_vp": 5687,
"battery_percent": 83
},
{
"_id": "12:34:56:07:bb:0e",
"type": "NAModule4",
"module_name": "Livingroom",
"data_type": [
"Temperature",
"CO2",
"Humidity"
],
"last_setup": 1548957209,
"reachable": true,
"dashboard_data": {
"time_utc": 1559413093,
"Temperature": 26.4,
"CO2": 451,
"Humidity": 31,
"min_temp": 25.1,
"max_temp": 26.4,
"date_min_temp": 1559365290,
"date_max_temp": 1559413093,
"temp_trend": "stable"
},
"firmware": 44,
"last_message": 1559413177,
"last_seen": 1559413093,
"rf_status": 84,
"battery_vp": 5626,
"battery_percent": 79
},
{
"_id": "12:34:56:03:1b:e5",
"type": "NAModule2",
"module_name": "Garden",
"data_type": [
"Wind"
],
"last_setup": 1549193862,
"reachable": true,
"dashboard_data": {
"time_utc": 1559413170,
"WindStrength": 4,
"WindAngle": 217,
"GustStrength": 9,
"GustAngle": 206,
"max_wind_str": 21,
"max_wind_angle": 217,
"date_max_wind_str": 1559386669
},
"firmware": 19,
"last_message": 1559413177,
"last_seen": 1559413177,
"rf_status": 59,
"battery_vp": 5689,
"battery_percent": 85
},
{
"_id": "12:34:56:05:51:20",
"type": "NAModule3",
"module_name": "Yard",
"data_type": [
"Rain"
],
"last_setup": 1549194580,
"reachable": true,
"dashboard_data": {
"time_utc": 1559413170,
"Rain": 0,
"sum_rain_24": 0,
"sum_rain_1": 0
},
"firmware": 8,
"last_message": 1559413177,
"last_seen": 1559413170,
"rf_status": 67,
"battery_vp": 5860,
"battery_percent": 93
}
]
},
{
"_id": "12 :34: 56:36:fd:3c",
"station_name": "Valley Road",
"date_setup": 1545897146,
"last_setup": 1545897146,
"type": "NAMain",
"last_status_store": 1581835369,
"firmware": 137,
"last_upgrade": 1545897125,
"wifi_status": 53,
"reachable": true,
"co2_calibrating": false,
"data_type": [
"Temperature",
"CO2",
"Humidity",
"Noise",
"Pressure"
],
"place": {
"altitude": 69,
"city": "Valley",
"country": "AU",
"timezone": "Australia/Hobart",
"location": [
148.444226,
-41.721282
]
},
"read_only": true,
"dashboard_data": {
"time_utc": 1581835330,
"Temperature": 22.4,
"CO2": 471,
"Humidity": 46,
"Noise": 47,
"Pressure": 1011.5,
"AbsolutePressure": 1002.8,
"min_temp": 18.1,
"max_temp": 22.5,
"date_max_temp": 1581829891,
"date_min_temp": 1581794878,
"temp_trend": "stable",
"pressure_trend": "stable"
},
"modules": [
{
"_id": "12 :34: 56:36:e6:c0",
"type": "NAModule1",
"module_name": "Module",
"data_type": [
"Temperature",
"Humidity"
],
"last_setup": 1545897146,
"battery_percent": 22,
"reachable": false,
"firmware": 46,
"last_message": 1572497781,
"last_seen": 1572497742,
"rf_status": 88,
"battery_vp": 4118
},
{
"_id": "12:34:56:05:25:6e",
"type": "NAModule3",
"module_name": "Rain Gauge",
"data_type": [
"Rain"
],
"last_setup": 1553997427,
"battery_percent": 82,
"reachable": true,
"firmware": 8,
"last_message": 1581835362,
"last_seen": 1581835354,
"rf_status": 78,
"battery_vp": 5594,
"dashboard_data": {
"time_utc": 1581835329,
"Rain": 0,
"sum_rain_1": 0,
"sum_rain_24": 0
}
}
]
},
{
"_id": "12:34:56:32:a7:60",
"home_name": "Ateljen",
"date_setup": 1566714693,
"last_setup": 1566714693,
"type": "NAMain",
"last_status_store": 1588481079,
"module_name": "Indoor",
"firmware": 177,
"last_upgrade": 1566714694,
"wifi_status": 50,
"reachable": true,
"co2_calibrating": false,
"data_type": [
"Temperature",
"CO2",
"Humidity",
"Noise",
"Pressure"
],
"place": {
"altitude": 93,
"city": "Gothenburg",
"country": "SE",
"timezone": "Europe/Stockholm",
"location": [
11.6136629,
57.7006827
]
},
"dashboard_data": {
"time_utc": 1588481073,
"Temperature": 18.2,
"CO2": 542,
"Humidity": 45,
"Noise": 45,
"Pressure": 1013,
"AbsolutePressure": 1001.9,
"min_temp": 18.2,
"max_temp": 19.5,
"date_max_temp": 1588456861,
"date_min_temp": 1588479561,
"temp_trend": "stable",
"pressure_trend": "up"
},
"modules": [
{
"_id": "12:34:56:32:db:06",
"type": "NAModule1",
"last_setup": 1587635819,
"data_type": [
"Temperature",
"Humidity"
],
"battery_percent": 100,
"reachable": false,
"firmware": 255,
"last_message": 0,
"last_seen": 0,
"rf_status": 255,
"battery_vp": 65535
}
]
},
{
"_id": "12:34:56:1c:68:2e",
"station_name": "Bol\u00e5s",
"date_setup": 1470935400,
"last_setup": 1470935400,
"type": "NAMain",
"last_status_store": 1588481399,
"module_name": "Inne - Nere",
"firmware": 177,
"last_upgrade": 1470935401,
"wifi_status": 13,
"reachable": true,
"co2_calibrating": false,
"data_type": [
"Temperature",
"CO2",
"Humidity",
"Noise",
"Pressure"
],
"place": {
"altitude": 93,
"city": "Gothenburg",
"country": "SE",
"timezone": "Europe/Stockholm",
"location": [
11.6136629,
57.7006827
]
},
"dashboard_data": {
"time_utc": 1588481387,
"Temperature": 20.8,
"CO2": 674,
"Humidity": 41,
"Noise": 34,
"Pressure": 1012.1,
"AbsolutePressure": 1001,
"min_temp": 20.8,
"max_temp": 22.2,
"date_max_temp": 1588456859,
"date_min_temp": 1588480176,
"temp_trend": "stable",
"pressure_trend": "up"
},
"modules": [
{
"_id": "12:34:56:02:b3:da",
"type": "NAModule3",
"module_name": "Regnm\u00e4tare",
"last_setup": 1470937706,
"data_type": [
"Rain"
],
"battery_percent": 81,
"reachable": true,
"firmware": 12,
"last_message": 1588481393,
"last_seen": 1588481386,
"rf_status": 67,
"battery_vp": 5582,
"dashboard_data": {
"time_utc": 1588481386,
"Rain": 0,
"sum_rain_1": 0,
"sum_rain_24": 0.1
}
},
{
"_id": "12:34:56:03:76:60",
"type": "NAModule4",
"module_name": "Inne - Uppe",
"last_setup": 1470938089,
"data_type": [
"Temperature",
"CO2",
"Humidity"
],
"battery_percent": 14,
"reachable": true,
"firmware": 50,
"last_message": 1588481393,
"last_seen": 1588481374,
"rf_status": 70,
"battery_vp": 4448,
"dashboard_data": {
"time_utc": 1588481374,
"Temperature": 19.6,
"CO2": 696,
"Humidity": 41,
"min_temp": 19.6,
"max_temp": 20.5,
"date_max_temp": 1588456817,
"date_min_temp": 1588481374,
"temp_trend": "stable"
}
},
{
"_id": "12:34:56:32:db:06",
"type": "NAModule1",
"module_name": "Ute",
"last_setup": 1566326027,
"data_type": [
"Temperature",
"Humidity"
],
"battery_percent": 81,
"reachable": true,
"firmware": 50,
"last_message": 1588481393,
"last_seen": 1588481380,
"rf_status": 61,
"battery_vp": 5544,
"dashboard_data": {
"time_utc": 1588481380,
"Temperature": 6.4,
"Humidity": 91,
"min_temp": 3.6,
"max_temp": 6.4,
"date_max_temp": 1588481380,
"date_min_temp": 1588471383,
"temp_trend": "up"
}
}
]
},
{
"_id": "12:34:56:1d:68:2e",
"date_setup": 1470935500,
"last_setup": 1470935500,
"type": "NAMain",
"last_status_store": 1588481399,
"module_name": "Basisstation",
"firmware": 177,
"last_upgrade": 1470935401,
"wifi_status": 13,
"reachable": true,
"co2_calibrating": false,
"data_type": [
"Temperature",
"CO2",
"Humidity",
"Noise",
"Pressure"
],
"place": {
"altitude": 93,
"city": "Gothenburg",
"country": "SE",
"timezone": "Europe/Stockholm",
"location": [
11.6136629,
57.7006827
]
},
"dashboard_data": {
"time_utc": 1588481387,
"Temperature": 20.8,
"CO2": 674,
"Humidity": 41,
"Noise": 34,
"Pressure": 1012.1,
"AbsolutePressure": 1001,
"min_temp": 20.8,
"max_temp": 22.2,
"date_max_temp": 1588456859,
"date_min_temp": 1588480176,
"temp_trend": "stable",
"pressure_trend": "up"
},
"modules": []
},
{
"_id": "12:34:56:80:bb:26",
"station_name": "MYHOME (Palier)",
"date_setup": 1558709904,
"last_setup": 1558709904,
"type": "NAMain",
"last_status_store": 1644582700,
"module_name": "Palier",
"firmware": 181,
"last_upgrade": 1558709906,
"wifi_status": 57,
"reachable": true,
"co2_calibrating": false,
"data_type": [
"Temperature",
"CO2",
"Humidity",
"Noise",
"Pressure"
],
"place": {
"altitude": 329,
"city": "Someplace",
"country": "FR",
"timezone": "Europe/Paris",
"location": [
6.1234567,
46.123456
]
},
"home_id": "91763b24c43d3e344f424e8b",
"home_name": "MYHOME",
"dashboard_data": {
"time_utc": 1644582694,
"Temperature": 21.1,
"CO2": 1339,
"Humidity": 45,
"Noise": 35,
"Pressure": 1026.8,
"AbsolutePressure": 974.5,
"min_temp": 21,
"max_temp": 21.8,
"date_max_temp": 1644534255,
"date_min_temp": 1644550420,
"temp_trend": "stable",
"pressure_trend": "up"
},
"modules": [
{
"_id": "12:34:56:80:1c:42",
"type": "NAModule1",
"module_name": "Outdoor",
"last_setup": 1558709954,
"data_type": [
"Temperature",
"Humidity"
],
"battery_percent": 27,
"reachable": false,
"firmware": 50,
"last_message": 1644582699,
"last_seen": 1644582699,
"rf_status": 68,
"battery_vp": 4678
},
{
"_id": "12:34:56:80:c1:ea",
"type": "NAModule3",
"module_name": "Rain",
"last_setup": 1563734531,
"data_type": [
"Rain"
],
"battery_percent": 21,
"reachable": true,
"firmware": 12,
"last_message": 1644582699,
"last_seen": 1644582699,
"rf_status": 79,
"battery_vp": 4256,
"dashboard_data": {
"time_utc": 1644582686,
"Rain": 3.7,
"sum_rain_1": 0,
"sum_rain_24": 6.9
}
},
{
"_id": "12:34:56:80:44:92",
"type": "NAModule4",
"module_name": "Bedroom",
"last_setup": 1575915890,
"data_type": [
"Temperature",
"CO2",
"Humidity"
],
"battery_percent": 28,
"reachable": true,
"firmware": 51,
"last_message": 1644582699,
"last_seen": 1644582654,
"rf_status": 67,
"battery_vp": 4695,
"dashboard_data": {
"time_utc": 1644582654,
"Temperature": 19.3,
"CO2": 1076,
"Humidity": 53,
"min_temp": 19.2,
"max_temp": 19.7,
"date_max_temp": 1644534243,
"date_min_temp": 1644553418,
"temp_trend": "stable"
}
},
{
"_id": "12:34:56:80:7e:18",
"type": "NAModule4",
"module_name": "Bathroom",
"last_setup": 1575915955,
"data_type": [
"Temperature",
"CO2",
"Humidity"
],
"battery_percent": 55,
"reachable": true,
"firmware": 51,
"last_message": 1644582699,
"last_seen": 1644582654,
"rf_status": 59,
"battery_vp": 5184,
"dashboard_data": {
"time_utc": 1644582654,
"Temperature": 19.4,
"CO2": 1930,
"Humidity": 55,
"min_temp": 19.4,
"max_temp": 21.8,
"date_max_temp": 1644534224,
"date_min_temp": 1644582039,
"temp_trend": "stable"
}
},
{
"_id": "12:34:56:03:1b:e4",
"type": "NAModule2",
"module_name": "Garden",
"data_type": [
"Wind"
],
"last_setup": 1549193862,
"reachable": true,
"dashboard_data": {
"time_utc": 1559413170,
"WindStrength": 4,
"WindAngle": 217,
"GustStrength": 9,
"GustAngle": 206,
"max_wind_str": 21,
"max_wind_angle": 217,
"date_max_wind_str": 1559386669
},
"firmware": 19,
"last_message": 1559413177,
"last_seen": 1559413177,
"rf_status": 59,
"battery_vp": 5689,
"battery_percent": 85
}
]
},
{
"_id": "00:11:22:2c:be:c8",
"station_name": "Zuhause (Kinderzimmer)",
"type": "NAMain",
"last_status_store": 1649146022,
"reachable": true,
"favorite": true,
"data_type": [
"Pressure"
],
"place": {
"altitude": 127,
"city": "Wiesbaden",
"country": "DE",
"timezone": "Europe/Berlin",
"location": [
8.238054275512695,
50.07585525512695
]
},
"read_only": true,
"dashboard_data": {
"time_utc": 1649146022,
"Pressure": 1015.6,
"AbsolutePressure": 1000.4,
"pressure_trend": "stable"
},
"modules": [
{
"_id": "00:11:22:2c:ce:b6",
"type": "NAModule1",
"data_type": [
"Temperature",
"Humidity"
],
"reachable": true,
"last_message": 1649146022,
"last_seen": 1649145996,
"dashboard_data": {
"time_utc": 1649145996,
"Temperature": 7.8,
"Humidity": 87,
"min_temp": 6.5,
"max_temp": 7.8,
"date_max_temp": 1649145996,
"date_min_temp": 1649118465,
"temp_trend": "up"
}
}
]
}
],
"user": {
"mail": "john@doe.com",
"administrative": {
"lang": "de-DE",
"reg_locale": "de-DE",
"country": "DE",
"unit": 0,
"windunit": 0,
"pressureunit": 0,
"feel_like_algo": 0
}
}
},
"status": "ok",
"time_exec": 0.91107702255249,
"time_server": 1559413602
}
pyatmo-9.2.1/fixtures/home_multi_status_error_disconnected.json 0000664 0000000 0000000 00000000356 15017405234 0025305 0 ustar 00root root 0000000 0000000 {
"status":"ok",
"body":{
"errors":[
{
"code":6,
"id":"aa:aa:aa:aa:aa:aa"
}
],
"home":{
"id":"aaaaaaaaaaabbbbbbbbbbccc"
}
},
"time_server":1559292039
} pyatmo-9.2.1/fixtures/home_status_error_disconnected.json 0000664 0000000 0000000 00000000356 15017405234 0024073 0 ustar 00root root 0000000 0000000 {
"status":"ok",
"body":{
"errors":[
{
"code":6,
"id":"12:34:56:00:fa:d0"
}
],
"home":{
"id":"91763b24c43d3e344f424e8b"
}
},
"time_server":1559292039
} pyatmo-9.2.1/fixtures/home_status_error_invalid_schedule_id.json 0000664 0000000 0000000 00000000157 15017405234 0025406 0 ustar 00root root 0000000 0000000 {
"error": {
"code": 21,
"message": "schedule is not therm schedule"
}
} pyatmo-9.2.1/fixtures/home_status_error_mode_is_missing.json 0000664 0000000 0000000 00000000121 15017405234 0024567 0 ustar 00root root 0000000 0000000 {
"error": {
"code": 10,
"message": "mode is missing"
}
} pyatmo-9.2.1/fixtures/home_status_simple.json 0000664 0000000 0000000 00000010231 15017405234 0021502 0 ustar 00root root 0000000 0000000 {
"status": "ok",
"time_server": 1559292039,
"body": {
"home": {
"modules": [
{
"id": "12:34:56:00:f1:62",
"type": "NACamera",
"monitoring": "on",
"sd_status": 4,
"alim_status": 2,
"locked": false,
"vpn_url": "https://prodvpn-eu-2.netatmo.net/restricted/10.255.123.45/609e27de5699fb18147ab47d06846631/MTRPn_BeWCav5RBq4U1OMDruTW4dkQ0NuMwNDAw11g,,",
"is_local": true
},
{
"id": "12:34:56:00:fa:d0",
"type": "NAPlug",
"firmware_revision": 174,
"rf_strength": 107,
"wifi_strength": 42
},
{
"id": "12:34:56:00:01:ae",
"reachable": true,
"type": "NATherm1",
"firmware_revision": 65,
"rf_strength": 58,
"battery_level": 3780,
"boiler_valve_comfort_boost": false,
"boiler_status": true,
"anticipating": false,
"bridge": "12:34:56:00:fa:d0",
"battery_state": "high"
},
{
"id": "12:34:56:03:a5:54",
"reachable": true,
"type": "NRV",
"firmware_revision": 79,
"rf_strength": 51,
"battery_level": 3025,
"bridge": "12:34:56:00:fa:d0",
"battery_state": "full"
},
{
"id": "12:34:56:03:a0:ac",
"reachable": true,
"type": "NRV",
"firmware_revision": 79,
"rf_strength": 59,
"battery_level": 3029,
"bridge": "12:34:56:00:fa:d0",
"battery_state": "full"
}
],
"rooms": [
{
"id": "2746182631",
"reachable": true,
"therm_measured_temperature": 19.8,
"therm_setpoint_temperature": 12,
"therm_setpoint_mode": "away",
"therm_setpoint_start_time": 1559229567,
"therm_setpoint_end_time": 0
},
{
"id": "2940411577",
"reachable": true,
"therm_measured_temperature": 27,
"heating_power_request": 0,
"therm_setpoint_temperature": 7,
"therm_setpoint_mode": "hg",
"therm_setpoint_start_time": 0,
"therm_setpoint_end_time": 0,
"anticipating": false,
"open_window": false
},
{
"id": "2833524037",
"reachable": true,
"therm_measured_temperature": 24.5,
"heating_power_request": 0,
"therm_setpoint_temperature": 7,
"therm_setpoint_mode": "hg",
"therm_setpoint_start_time": 0,
"therm_setpoint_end_time": 0,
"anticipating": false,
"open_window": false
}
],
"id": "91763b24c43d3e344f424e8b",
"persons": [
{
"id": "91827374-7e04-5298-83ad-a0cb8372dff1",
"last_seen": 1557071156,
"out_of_sight": true
},
{
"id": "91827375-7e04-5298-83ae-a0cb8372dff2",
"last_seen": 1559282761,
"out_of_sight": false
},
{
"id": "91827376-7e04-5298-83af-a0cb8372dff3",
"last_seen": 1559224132,
"out_of_sight": true
}
]
}
}
} pyatmo-9.2.1/fixtures/homesdata.json 0000664 0000000 0000000 00000070475 15017405234 0017563 0 ustar 00root root 0000000 0000000 {
"body": {
"homes": [
{
"id": "91763b24c43d3e344f424e8b",
"name": "MYHOME",
"altitude": 112,
"coordinates": [
52.516263,
13.377726
],
"country": "DE",
"timezone": "Europe/Berlin",
"rooms": [
{
"id": "2746182631",
"name": "Livingroom",
"type": "livingroom",
"module_ids": [
"12:34:56:00:01:ae"
]
},
{
"id": "3688132631",
"name": "Hall",
"type": "custom",
"module_ids": [
"12:34:56:00:f1:62",
"12:34:56:00:f1:63",
"12:34:56:10:f1:66",
"12:34:56:00:e3:9b",
"0009999992",
"0009999993",
"12:34:56:00:01:01:01:b8"
]
},
{
"id": "2833524037",
"name": "Entrada",
"type": "lobby",
"module_ids": [
"12:34:56:03:a5:54",
"12:34:56:00:01:01:01:b6#1",
"12:34:56:00:01:01:01:b6#2"
]
},
{
"id": "2940411577",
"name": "Cocina",
"type": "kitchen",
"module_ids": [
"12:34:56:03:a0:ac",
"12:34:56:00:01:01:01:b7"
]
},
{
"id": "222452125",
"name": "Bureau",
"type": "electrical_cabinet",
"module_ids": [
"12:34:56:20:f5:44",
"12:34:56:20:f5:8c"
],
"modules": [
"12:34:56:20:f5:44",
"12:34:56:20:f5:8c"
],
"therm_relay": "12:34:56:20:f5:44",
"true_temperature_available": true
},
{
"id": "100007519",
"name": "Cabinet",
"type": "electrical_cabinet",
"module_ids": [
"12:34:56:00:16:0e",
"12:34:56:00:16:0e#0",
"12:34:56:00:16:0e#1",
"12:34:56:00:16:0e#2",
"12:34:56:00:16:0e#3",
"12:34:56:00:16:0e#4",
"12:34:56:00:16:0e#5",
"12:34:56:00:16:0e#6",
"12:34:56:00:16:0e#7",
"12:34:56:00:16:0e#8",
"12:34:56:00:01:01:01:b9"
]
},
{
"id": "1002003001",
"name": "Corridor",
"type": "corridor",
"module_ids": [
"10:20:30:bd:b8:1e"
]
},
{
"id": "100007520",
"name": "Toilettes",
"type": "toilets",
"module_ids": [
"00:11:22:33:00:11:45:fe"
]
},
{
"id": "2299431568",
"name": "Garage",
"type": "garage",
"module_ids": [
"12:34:56:00:01:01:01:b5"
],
"modules": [
"12:34:56:00:01:01:01:b5"
]
}
],
"modules": [
{
"id": "12:34:56:00:fa:d0",
"type": "NAPlug",
"name": "Thermostat",
"setup_date": 1494963356,
"modules_bridged": [
"12:34:56:00:01:ae",
"12:34:56:03:a0:ac",
"12:34:56:03:a5:54"
]
},
{
"id": "12:34:56:00:01:ae",
"type": "NATherm1",
"name": "Livingroom",
"setup_date": 1494963356,
"room_id": "2746182631",
"bridge": "12:34:56:00:fa:d0"
},
{
"id": "12:34:56:03:a5:54",
"type": "NRV",
"name": "Valve1",
"setup_date": 1554549767,
"room_id": "2833524037",
"bridge": "12:34:56:00:fa:d0"
},
{
"id": "12:34:56:03:a0:ac",
"type": "NRV",
"name": "Valve2",
"setup_date": 1554554444,
"room_id": "2940411577",
"bridge": "12:34:56:00:fa:d0"
},
{
"id": "12:34:56:00:f1:62",
"type": "NACamera",
"name": "Hall",
"setup_date": 1544828430,
"room_id": "3688132631",
"modules_bridged": [
"12:34:56:00:86:99",
"12:34:56:00:e3:9b"
]
},
{
"id": "12:34:56:00:f1:63",
"type": "NPC",
"name": "Hall",
"setup_date": 1544828430,
"room_id": "3688132631",
"modules_bridged": [
"12:34:56:00:86:99",
"12:34:56:00:e3:9b"
]
},
{
"id": "12:34:56:10:f1:66",
"type": "NDB",
"name": "Netatmo-Doorbell",
"setup_date": 1602691361,
"room_id": "3688132631",
"reachable": true,
"hk_device_id": "123456007df1",
"customer_id": "1000010",
"network_lock": false,
"quick_display_zone": 62
},
{
"id": "12:34:56:10:b9:0e",
"type": "NOC",
"name": "Front",
"setup_date": 1509290599,
"reachable": true,
"customer_id": "A00010",
"network_lock": false,
"use_pincode": false
},
{
"id": "12:34:56:20:f5:44",
"type": "OTH",
"name": "Modulating Relay",
"setup_date": 1607443936,
"room_id": "222452125",
"reachable": true,
"modules_bridged": [
"12:34:56:20:f5:8c"
],
"hk_device_id": "12:34:56:20:d0:c5",
"capabilities": [
{
"name": "automatism",
"available": true
}
],
"max_modules_nb": 21
},
{
"id": "12:34:56:20:f5:8c",
"type": "OTM",
"name": "Bureau Modulate",
"setup_date": 1607443939,
"room_id": "222452125",
"bridge": "12:34:56:20:f5:44"
},
{
"id": "12:34:56:30:d5:d4",
"type": "NBG",
"name": "module iDiamant",
"setup_date": 1562262465,
"room_id": "222452125",
"modules_bridged": [
"0009999992",
"0009999993"
]
},
{
"id": "0009999992",
"type": "NBR",
"name": "Entrance Blinds",
"setup_date": 1578551339,
"room_id": "3688132631",
"bridge": "12:34:56:30:d5:d4"
},
{
"id": "0009999993",
"type": "NBO",
"name": "Bubendorff blind",
"setup_date": 1594132017,
"room_id": "3688132631",
"bridge": "12:34:56:30:d5:d4"
},
{
"id": "12:34:56:80:bb:26",
"type": "NAMain",
"name": "Villa",
"setup_date": 1419453350,
"room_id": "4122897288",
"reachable": true,
"modules_bridged": [
"12:34:56:80:44:92",
"12:34:56:80:7e:18",
"12:34:56:80:1c:42",
"12:34:56:80:c1:ea"
],
"customer_id": "C00016",
"hardware_version": 251,
"public_ext_data": false,
"public_ext_counter": 0,
"alarm_config": {
"default_alarm": [
{
"db_alarm_number": 0
},
{
"db_alarm_number": 1
},
{
"db_alarm_number": 2
},
{
"db_alarm_number": 6
},
{
"db_alarm_number": 4
},
{
"db_alarm_number": 5
},
{
"db_alarm_number": 7
},
{
"db_alarm_number": 22
}
],
"personnalized": [
{
"threshold": 20,
"data_type": 1,
"direction": 0,
"db_alarm_number": 8
},
{
"threshold": 17,
"data_type": 1,
"direction": 1,
"db_alarm_number": 9
},
{
"threshold": 65,
"data_type": 4,
"direction": 0,
"db_alarm_number": 16
},
{
"threshold": 19,
"data_type": 8,
"direction": 0,
"db_alarm_number": 22
}
]
},
"module_offset": {
"12:34:56:80:bb:26": {
"a": 0.1
},
"03:00:00:03:1b:0e": {
"a": 0
}
}
},
{
"id": "12:34:56:80:1c:42",
"type": "NAModule1",
"name": "Outdoor",
"setup_date": 1448565785,
"bridge": "12:34:56:80:bb:26"
},
{
"id": "12:34:56:80:c1:ea",
"type": "NAModule3",
"name": "Rain",
"setup_date": 1591770206,
"bridge": "12:34:56:80:bb:26"
},
{
"id": "12:34:56:80:44:92",
"type": "NAModule4",
"name": "Bedroom",
"setup_date": 1484997703,
"bridge": "12:34:56:80:bb:26"
},
{
"id": "12:34:56:80:7e:18",
"type": "NAModule4",
"name": "Bathroom",
"setup_date": 1543579864,
"bridge": "12:34:56:80:bb:26"
},
{
"id": "12:34:56:03:1b:e4",
"type": "NAModule2",
"name": "Garden",
"setup_date": 1543579864,
"bridge": "12:34:56:80:bb:26"
},
{
"id": "12:34:56:80:60:40",
"type": "NLG",
"name": "Prise Control",
"setup_date": 1641841257,
"room_id": "1310352496",
"modules_bridged": [
"12:34:56:80:00:12:ac:f2",
"12:34:56:80:00:c3:69:3c",
"12:34:56:80:00:c3:69:3d",
"12:34:56:80:00:c3:69:3e",
"12:34:56:00:00:a1:4c:da",
"12:34:56:00:01:01:01:a1",
"00:11:22:33:00:11:45:fe",
"12:34:56:00:01:01:01:b1",
"12:34:56:00:01:01:01:b2",
"12:34:56:00:01:01:01:b3",
"12:34:56:00:01:01:01:b4",
"12:34:56:00:01:01:01:b5",
"12:34:56:00:01:01:01:b6",
"12:34:56:00:01:01:01:b7",
"12:34:56:00:01:01:01:b8",
"12:34:56:00:01:01:01:b9"
]
},
{
"id": "12:34:56:80:00:12:ac:f2",
"type": "NLP",
"name": "Prise",
"setup_date": 1641841262,
"room_id": "1310352496",
"bridge": "12:34:56:80:60:40"
},
{
"id": "12:34:56:80:00:c3:69:3c",
"type": "NLT",
"name": "Commande sans fil",
"setup_date": 1641841262,
"bridge": "12:34:56:80:60:40"
},
{
"id": "12:34:56:80:00:c3:69:3e",
"type": "NLD",
"name": "Entrance command",
"setup_date": 1610500885,
"room_id": "3688132631",
"bridge": "12:34:56:80:60:40"
},
{
"id": "12:34:56:80:00:c3:69:3d",
"type": "Z3V",
"name": "Entrance shutter",
"setup_date": 1578551339,
"room_id": "3688132631",
"bridge": "12:34:56:80:60:40"
},
{
"id": "12:34:56:00:86:99",
"type": "NACamDoorTag",
"name": "Window Hall",
"setup_date": 1581177375,
"bridge": "12:34:56:00:f1:62",
"category": "window"
},
{
"id": "12:34:56:00:e3:9b",
"type": "NIS",
"setup_date": 1620479901,
"bridge": "12:34:56:00:f1:62",
"name": "Sirene in hall"
},
{
"id": "12:34:56:00:16:0e",
"type": "NLE",
"name": "Écocompteur",
"setup_date": 1644496884,
"room_id": "100007519",
"modules_bridged": [
"12:34:56:00:16:0e#0",
"12:34:56:00:16:0e#1",
"12:34:56:00:16:0e#2",
"12:34:56:00:16:0e#3",
"12:34:56:00:16:0e#4",
"12:34:56:00:16:0e#5",
"12:34:56:00:16:0e#6",
"12:34:56:00:16:0e#7",
"12:34:56:00:16:0e#8"
]
},
{
"id": "12:34:56:00:16:0e#0",
"type": "NLE",
"name": "Line 1",
"setup_date": 1644496886,
"room_id": "100007519",
"bridge": "12:34:56:00:16:0e"
},
{
"id": "12:34:56:00:16:0e#1",
"type": "NLE",
"name": "Line 2",
"setup_date": 1644496886,
"room_id": "100007519",
"bridge": "12:34:56:00:16:0e"
},
{
"id": "12:34:56:00:16:0e#2",
"type": "NLE",
"name": "Line 3",
"setup_date": 1644496886,
"room_id": "100007519",
"bridge": "12:34:56:00:16:0e"
},
{
"id": "12:34:56:00:16:0e#3",
"type": "NLE",
"name": "Line 4",
"setup_date": 1644496886,
"room_id": "100007519",
"bridge": "12:34:56:00:16:0e"
},
{
"id": "12:34:56:00:16:0e#4",
"type": "NLE",
"name": "Line 5",
"setup_date": 1644496886,
"room_id": "100007519",
"bridge": "12:34:56:00:16:0e"
},
{
"id": "12:34:56:00:16:0e#5",
"type": "NLE",
"name": "Total",
"setup_date": 1644496886,
"room_id": "100007519",
"bridge": "12:34:56:00:16:0e"
},
{
"id": "12:34:56:00:16:0e#6",
"type": "NLE",
"name": "Gas",
"setup_date": 1644496886,
"room_id": "100007519",
"bridge": "12:34:56:00:16:0e"
},
{
"id": "12:34:56:00:16:0e#7",
"type": "NLE",
"name": "Hot water",
"setup_date": 1644496886,
"room_id": "100007519",
"bridge": "12:34:56:00:16:0e"
},
{
"id": "12:34:56:00:16:0e#8",
"type": "NLE",
"name": "Cold water",
"setup_date": 1644496886,
"room_id": "100007519",
"bridge": "12:34:56:00:16:0e"
},
{
"id": "12:34:56:00:00:a1:4c:da",
"type": "NLPC",
"name": "Consumption meter",
"setup_date": 1638376602,
"room_id": "100008999",
"bridge": "12:34:56:80:60:40"
},
{
"id": "10:20:30:bd:b8:1e",
"type": "BNS",
"name": "Smarther",
"setup_date": 1638022197,
"room_id": "1002003001"
},
{
"id": "00:11:22:33:00:11:45:fe",
"type": "NLF",
"on": false,
"brightness": 63,
"firmware_revision": 57,
"last_seen": 1657086939,
"power": 0,
"reachable": true,
"bridge": "12:34:56:80:60:40"
},
{
"id": "12:34:56:00:01:01:01:a1",
"type": "NLFN",
"name": "Bathroom light",
"setup_date": 1598367404,
"room_id": "1002003001",
"bridge": "12:34:56:80:60:40"
},
{
"id": "12:34:56:00:01:01:01:b1",
"type": "NLLF",
"name": "Centralized ventilation controler",
"setup_date": 1598367504,
"room_id": "1002003001",
"bridge": "12:34:56:80:60:40"
},
{
"id": "12:34:56:00:01:01:01:b2",
"type": "NLL",
"name": "NLL",
"setup_date": 1673019934,
"room_id": "1002003001",
"bridge": "12:34:56:80:60:40"
},
{
"id": "12:34:56:00:01:01:01:b3",
"type": "NLV",
"name": "NLV",
"setup_date": 1673019934,
"room_id": "1002003001",
"bridge": "12:34:56:80:60:40",
"appliance_type": "rolling_shutter"
},
{
"id": "12:34:56:00:01:01:01:b4",
"type": "NLLV",
"name": "NLLV",
"setup_date": 1673019934,
"room_id": "1002003001",
"bridge": "12:34:56:80:60:40",
"appliance_type": "rolling_shutter"
},
{
"id": "12:34:56:00:01:01:01:b5",
"type": "NLJ",
"name": "Garage door",
"setup_date": 1743159238,
"room_id": "2299431568",
"bridge": "12:34:56:80:60:40"
},
{
"id": "12:34:56:00:01:01:01:b6",
"type": "NLIS",
"setup_date": 1673019934,
"bridge": "12:34:56:80:60:40"
},
{
"id": "12:34:56:00:01:01:01:b6#1",
"type": "NLIS",
"name": "NLIS droite",
"setup_date": 1673019934,
"room_id": "2833524037",
"bridge": "12:34:56:80:60:40"
},
{
"id": "12:34:56:00:01:01:01:b6#2",
"type": "NLIS",
"name": "NLIS gauche",
"setup_date": 1673019934,
"room_id": "2833524037",
"bridge": "12:34:56:80:60:40"
},
{
"id": "12:34:56:00:01:01:01:b7",
"type": "NLPT",
"name": "NLPT",
"setup_date": 1673019934,
"room_id": "2940411577",
"bridge": "12:34:56:80:60:40"
},
{
"id": "12:34:56:00:01:01:01:b8",
"type": "NLPD",
"name": "NLPD",
"setup_date": 1673019934,
"room_id": "3688132631",
"bridge": "12:34:56:80:60:40",
"appliance_type": "other"
},
{
"id": "12:34:56:00:01:01:01:b9",
"type": "NLPO",
"name": "NLPO",
"setup_date": 1673019934,
"room_id": "100007519",
"bridge": "12:34:56:80:60:40",
"appliance_type": "other"
}
],
"schedules": [
{
"zones": [
{
"type": 0,
"name": "Comfort",
"rooms": [
{
"therm_setpoint_temperature": 21,
"id": "2746182631"
},
{
"therm_setpoint_temperature": 22,
"id": "2746182632"
}
],
"id": 0
},
{
"type": 1,
"name": "Night",
"rooms": [
{
"therm_setpoint_temperature": 17,
"id": "2746182631"
},
{
"therm_setpoint_temperature": 18,
"id": "2746182632"
}
],
"id": 1
},
{
"type": 5,
"name": "Eco",
"rooms": [
{
"therm_setpoint_temperature": 18,
"id": "2746182631"
},
{
"therm_setpoint_temperature": 19,
"id": "2746182632"
}
],
"id": 4
}
],
"timetable": [
{
"zone_id": 1,
"m_offset": 0
},
{
"zone_id": 0,
"m_offset": 360
},
{
"zone_id": 4,
"m_offset": 420
},
{
"zone_id": 0,
"m_offset": 960
},
{
"zone_id": 1,
"m_offset": 1410
},
{
"zone_id": 0,
"m_offset": 1800
},
{
"zone_id": 4,
"m_offset": 1860
},
{
"zone_id": 0,
"m_offset": 2400
},
{
"zone_id": 1,
"m_offset": 2850
},
{
"zone_id": 0,
"m_offset": 3240
},
{
"zone_id": 4,
"m_offset": 3300
},
{
"zone_id": 0,
"m_offset": 3840
},
{
"zone_id": 1,
"m_offset": 4290
},
{
"zone_id": 0,
"m_offset": 4680
},
{
"zone_id": 4,
"m_offset": 4740
},
{
"zone_id": 0,
"m_offset": 5280
},
{
"zone_id": 1,
"m_offset": 5730
},
{
"zone_id": 0,
"m_offset": 6120
},
{
"zone_id": 4,
"m_offset": 6180
},
{
"zone_id": 0,
"m_offset": 6720
},
{
"zone_id": 1,
"m_offset": 7170
},
{
"zone_id": 0,
"m_offset": 7620
},
{
"zone_id": 1,
"m_offset": 8610
},
{
"zone_id": 0,
"m_offset": 9060
},
{
"zone_id": 1,
"m_offset": 10050
}
],
"hg_temp": 7,
"away_temp": 14,
"name": "Default",
"selected": true,
"id": "591b54a2764ff4d50d8b5795",
"type": "cooling"
},
{
"zones": [
{
"type": 0,
"name": "Comfort",
"rooms": [
{
"therm_setpoint_temperature": 21,
"id": "2746182631"
},
{
"therm_setpoint_temperature": 22,
"id": "2746182632"
}
],
"id": 0
},
{
"type": 1,
"name": "Night",
"rooms": [
{
"therm_setpoint_temperature": 17,
"id": "2746182631"
},
{
"therm_setpoint_temperature": 18,
"id": "2746182632"
}
],
"id": 1
},
{
"type": 5,
"name": "Eco",
"rooms": [
{
"therm_setpoint_temperature": 18,
"id": "2746182631"
},
{
"therm_setpoint_temperature": 19,
"id": "2746182632"
}
],
"id": 4
}
],
"timetable": [
{
"zone_id": 1,
"m_offset": 0
},
{
"zone_id": 0,
"m_offset": 360
},
{
"zone_id": 4,
"m_offset": 420
},
{
"zone_id": 0,
"m_offset": 960
},
{
"zone_id": 1,
"m_offset": 1410
},
{
"zone_id": 0,
"m_offset": 1800
},
{
"zone_id": 4,
"m_offset": 1860
},
{
"zone_id": 0,
"m_offset": 2400
},
{
"zone_id": 1,
"m_offset": 2850
},
{
"zone_id": 0,
"m_offset": 3240
},
{
"zone_id": 4,
"m_offset": 3300
},
{
"zone_id": 0,
"m_offset": 3840
},
{
"zone_id": 1,
"m_offset": 4290
},
{
"zone_id": 0,
"m_offset": 4680
},
{
"zone_id": 4,
"m_offset": 4740
},
{
"zone_id": 0,
"m_offset": 5280
},
{
"zone_id": 1,
"m_offset": 5730
},
{
"zone_id": 0,
"m_offset": 6120
},
{
"zone_id": 4,
"m_offset": 6180
},
{
"zone_id": 0,
"m_offset": 6720
},
{
"zone_id": 1,
"m_offset": 7170
},
{
"zone_id": 0,
"m_offset": 7620
},
{
"zone_id": 1,
"m_offset": 8610
},
{
"zone_id": 0,
"m_offset": 9060
},
{
"zone_id": 1,
"m_offset": 10050
}
],
"hg_temp": 7,
"away_temp": 14,
"name": "Winter",
"id": "b1b54a2f45795764f59d50d8",
"type": "therm"
}
],
"therm_setpoint_default_duration": 120,
"temperature_control_mode": "cooling",
"cooling_mode": "schedule",
"persons": [
{
"id": "91827374-7e04-5298-83ad-a0cb8372dff1",
"pseudo": "John Doe",
"url": "https://netatmocameraimage.blob.core.windows.net/production/d74fad765b9100ef480720a9a4a95c24b808a89f8d1730fb69ecdf2bb8b72039d2c69928b029d67fc40cb2d7"
},
{
"id": "91827375-7e04-5298-83ae-a0cb8372dff2",
"pseudo": "Jane Doe",
"url": "https://netatmocameraimage.blob.core.windows.net/production/d74fad765b9100ef480720a9a4a95c24b808a89f8d1730039d2c69928b029d67fc40cb2d7fb69ecdf2bb8b72"
},
{
"id": "91827376-7e04-5298-83af-a0cb8372dff3",
"pseudo": "Richard Doe",
"url": "https://netatmocameraimage.blob.core.windows.net/production/d74fad765b9100ef480720a9a4a95c2d1730fb69ecdf2bb8b72039d2c69928b029d67fc40cb2d74b808a89f8"
}
],
"therm_mode": "schedule"
},
{
"id": "91763b24c43d3e344f424e8c",
"altitude": 112,
"coordinates": [
52.516263,
13.377726
],
"country": "DE",
"timezone": "Europe/Berlin",
"therm_setpoint_default_duration": 180,
"therm_mode": "schedule"
}
],
"user": {
"email": "john@doe.com",
"language": "de-DE",
"locale": "de-DE",
"feel_like_algorithm": 0,
"unit_pressure": 0,
"unit_system": 0,
"unit_wind": 0,
"all_linked": false,
"type": "netatmo",
"id": "91763b24c43d3e344f424e8b"
}
},
"status": "ok",
"time_exec": 0.056135892868042,
"time_server": 1559171003
} pyatmo-9.2.1/fixtures/homesdata_empty.json 0000664 0000000 0000000 00000000054 15017405234 0020763 0 ustar 00root root 0000000 0000000 {
"body": {
"homes": []
}
} pyatmo-9.2.1/fixtures/homesdata_emtpy_home.json 0000664 0000000 0000000 00000021773 15017405234 0022006 0 ustar 00root root 0000000 0000000 {
"body": {
"homes": [
{
"id": "111111111111111111111401",
"name": "Home with no modules",
"altitude": 9,
"coordinates": [
1.23456789,
50.0987654
],
"country": "BE",
"timezone": "Europe/Brussels",
"rooms": [
{
"id": "1111111401",
"name": "Livingroom",
"type": "livingroom"
}
],
"temperature_control_mode": "heating",
"therm_mode": "away",
"therm_setpoint_default_duration": 120,
"cooling_mode": "schedule",
"schedules": [
{
"away_temp": 14,
"hg_temp": 7,
"name": "Week",
"timetable": [
{
"zone_id": 1,
"m_offset": 0
},
{
"zone_id": 6,
"m_offset": 420
},
{
"zone_id": 4,
"m_offset": 450
},
{
"zone_id": 5,
"m_offset": 720
},
{
"zone_id": 4,
"m_offset": 780
},
{
"zone_id": 0,
"m_offset": 960
},
{
"zone_id": 1,
"m_offset": 1320
},
{
"zone_id": 6,
"m_offset": 1860
},
{
"zone_id": 4,
"m_offset": 1890
},
{
"zone_id": 5,
"m_offset": 2160
},
{
"zone_id": 4,
"m_offset": 2220
},
{
"zone_id": 0,
"m_offset": 2400
},
{
"zone_id": 1,
"m_offset": 2760
},
{
"zone_id": 6,
"m_offset": 3300
},
{
"zone_id": 4,
"m_offset": 3330
},
{
"zone_id": 5,
"m_offset": 3600
},
{
"zone_id": 4,
"m_offset": 3660
},
{
"zone_id": 0,
"m_offset": 3840
},
{
"zone_id": 1,
"m_offset": 4200
},
{
"zone_id": 6,
"m_offset": 4740
},
{
"zone_id": 4,
"m_offset": 4770
},
{
"zone_id": 5,
"m_offset": 5040
},
{
"zone_id": 4,
"m_offset": 5100
},
{
"zone_id": 0,
"m_offset": 5280
},
{
"zone_id": 1,
"m_offset": 5640
},
{
"zone_id": 6,
"m_offset": 6180
},
{
"zone_id": 4,
"m_offset": 6210
},
{
"zone_id": 5,
"m_offset": 6480
},
{
"zone_id": 4,
"m_offset": 6540
},
{
"zone_id": 0,
"m_offset": 6720
},
{
"zone_id": 1,
"m_offset": 7080
},
{
"zone_id": 6,
"m_offset": 7620
},
{
"zone_id": 5,
"m_offset": 7800
},
{
"zone_id": 0,
"m_offset": 8100
},
{
"zone_id": 1,
"m_offset": 8550
},
{
"zone_id": 6,
"m_offset": 9060
},
{
"zone_id": 5,
"m_offset": 9240
},
{
"zone_id": 0,
"m_offset": 9540
},
{
"zone_id": 1,
"m_offset": 9990
}
],
"zones": [
{
"type": 0,
"name": "Comfort",
"rooms_temp": [],
"id": 0,
"rooms": []
},
{
"type": 1,
"name": "Nacht",
"rooms_temp": [],
"id": 1,
"rooms": []
},
{
"type": 5,
"name": "Eco",
"rooms_temp": [],
"id": 4,
"rooms": []
},
{
"type": 4,
"name": "Tussenin",
"rooms_temp": [],
"id": 5,
"rooms": []
},
{
"type": 4,
"name": "Ochtend",
"rooms_temp": [],
"id": 6,
"rooms": []
}
],
"id": "700000000000000000000401",
"selected": true,
"type": "therm"
}
]
}
],
"user": {
"email": "john@doe.com",
"language": "de-DE",
"locale": "de-DE",
"feel_like_algorithm": 0,
"unit_pressure": 0,
"unit_system": 0,
"unit_wind": 0,
"id": "91763b24c43d3e344f424e8b"
}
},
"status": "ok",
"time_exec": 0.056135892868042,
"time_server": 1559171003
} pyatmo-9.2.1/fixtures/homesdata_multi.json 0000664 0000000 0000000 00000607333 15017405234 0020774 0 ustar 00root root 0000000 0000000 {
"body": {
"homes": [
{
"id": "aaaaaaaaaaabbbbbbbbbbccc",
"name": "A BIG HOME",
"altitude": 284,
"coordinates": [
26.234678,
83.234678
],
"country": "FR",
"timezone": "Europe/Paris",
"rooms": [
{
"id": "3707962039",
"name": "Cuisine",
"type": "kitchen",
"module_ids": [
"98:76:54:32:10:00:00:03",
"98:76:54:32:10:00:00:05",
"98:76:54:32:10:00:00:06",
"98:76:54:32:10:00:00:07",
"98:76:54:32:10:00:00:09",
"98:76:54:32:10:00:00:28",
"98:76:54:32:10:00:00:37",
"98:76:54:32:10:00:00:38",
"98:76:54:32:10:00:00:40",
"98:76:54:32:10:00:00:50"
]
},
{
"id": "596817675",
"name": "Vestibule",
"type": "lobby",
"module_ids": [
"98:76:54:32:10:00:00:01",
"98:76:54:32:10:00:00:02",
"98:76:54:32:10:00:00:08",
"98:76:54:32:10:00:00:13",
"98:76:54:32:10:00:00:14",
"98:76:54:32:10:00:00:15",
"98:76:54:32:10:00:00:16",
"98:76:54:32:10:00:00:27",
"98:76:54:32:10:00:00:29",
"98:76:54:32:10:00:00:32",
"98:76:54:32:10:00:00:36",
"98:76:54:32:10:00:00:39"
]
},
{
"id": "1462100035",
"name": "Salon",
"type": "livingroom",
"module_ids": [
"98:76:54:32:10:00:00:04",
"98:76:54:32:10:00:00:24#1",
"98:76:54:32:10:00:00:34",
"98:76:54:32:10:00:00:52",
"98:76:54:32:10:00:00:60",
"98:76:54:32:10:00:00:63",
"98:76:54:32:10:00:00:66",
"98:76:54:32:10:00:00:73",
"98:76:54:32:10:00:00:75"
]
},
{
"id": "3435163850",
"name": "Chambre A",
"type": "bedroom",
"module_ids": [
"98:76:54:32:10:00:00:26",
"98:76:54:32:10:00:00:51"
]
},
{
"id": "737850817",
"name": "Extérieur",
"type": "outdoor",
"module_ids": [
"98:76:54:32:10:00:00:10",
"98:76:54:32:10:00:00:41",
"98:76:54:32:10:00:00:42",
"98:76:54:32:10:00:00:53",
"98:76:54:32:10:00:00:54",
"98:76:54:32:10:00:00:55",
"98:76:54:32:10:00:00:56"
]
},
{
"id": "842662884",
"name": "Bibliothèque",
"type": "home_office",
"module_ids": [
"98:76:54:32:10:00:00:11",
"98:76:54:32:10:00:00:12",
"98:76:54:32:10:00:00:24#2",
"98:76:54:32:10:00:00:25"
]
},
{
"id": "3194154910",
"name": "Salle à manger",
"type": "dining_room",
"module_ids": [
"98:76:54:32:10:00:00:30",
"98:76:54:32:10:00:00:31",
"98:76:54:32:10:00:00:33",
"98:76:54:32:10:00:00:72"
]
},
{
"id": "2370728183",
"name": "Atelier",
"type": "custom",
"module_ids": [
"98:76:54:32:10:00:00:18",
"98:76:54:32:10:00:00:23"
]
},
{
"id": "2042969726",
"name": "Chambre B",
"type": "bedroom",
"module_ids": [
"98:76:54:32:10:00:00:19",
"98:76:54:32:10:00:00:20",
"98:76:54:32:10:00:00:46"
]
},
{
"id": "2754296835",
"name": "Placard Technique",
"type": "electrical_cabinet",
"module_ids": [
"aa:aa:aa:aa:aa:aa",
"98:76:54:32:10:00:00:22",
"98:76:54:32:10:00:00:48",
"98:76:54:32:10:00:00:59",
"98:76:54:32:10:00:00:67",
"98:76:54:32:10:00:00:68",
"98:76:54:32:10:00:00:69",
"98:76:54:32:10:00:00:77",
"98:76:54:32:10:00:00:78",
"98:76:54:32:10:00:00:79"
]
},
{
"id": "1662974901",
"name": "Dressing",
"type": "custom",
"module_ids": [
"98:76:54:32:10:00:00:21",
"98:76:54:32:10:00:00:35"
]
},
{
"id": "873035982",
"name": "Chambre C",
"type": "bedroom",
"module_ids": [
"98:76:54:32:10:00:00:17",
"98:76:54:32:10:00:00:43",
"98:76:54:32:10:00:00:76"
]
},
{
"id": "3795659199",
"name": "Chambre D",
"type": "bedroom",
"module_ids": [
"98:76:54:32:10:00:00:57"
]
},
{
"id": "2102454491",
"name": "Buanderie",
"type": "custom",
"module_ids": [
"98:76:54:32:10:00:00:45"
]
},
{
"id": "93888250",
"name": "Salle de bains Des Enfants",
"type": "bathroom",
"module_ids": [
"98:76:54:32:10:00:00:44"
]
},
{
"id": "3497055021",
"name": "Chambre Brice",
"type": "bedroom",
"module_ids": [
"98:76:54:32:10:00:00:47",
"98:76:54:32:10:00:00:74"
]
},
{
"id": "2061006239",
"name": "Pool house",
"type": "custom",
"module_ids": [
"98:76:54:32:10:00:00:58",
"98:76:54:32:10:00:00:61",
"98:76:54:32:10:00:00:62",
"98:76:54:32:10:00:00:64",
"98:76:54:32:10:00:00:65",
"98:76:54:32:10:00:00:71"
]
},
{
"id": "927970817",
"name": "Salle de bains Des Parents",
"type": "bathroom",
"module_ids": [
"98:76:54:32:10:00:00:49"
]
},
{
"id": "1641945290",
"name": "Salle de bains D’Arthur",
"type": "bathroom",
"module_ids": [
"98:76:54:32:10:00:00:70"
]
}
],
"modules": [
{
"id": "aa:aa:aa:aa:aa:aa",
"type": "NLG",
"name": "Legrand Gateway",
"setup_date": 1572624665,
"room_id": "2754296835",
"modules_bridged": [
"98:76:54:32:10:00:00:01",
"98:76:54:32:10:00:00:02",
"98:76:54:32:10:00:00:03",
"98:76:54:32:10:00:00:04",
"98:76:54:32:10:00:00:05",
"98:76:54:32:10:00:00:06",
"98:76:54:32:10:00:00:07",
"98:76:54:32:10:00:00:08",
"98:76:54:32:10:00:00:09",
"98:76:54:32:10:00:00:10",
"98:76:54:32:10:00:00:11",
"98:76:54:32:10:00:00:12",
"98:76:54:32:10:00:00:13",
"98:76:54:32:10:00:00:14",
"98:76:54:32:10:00:00:15",
"98:76:54:32:10:00:00:16",
"98:76:54:32:10:00:00:17",
"98:76:54:32:10:00:00:18",
"98:76:54:32:10:00:00:19",
"98:76:54:32:10:00:00:20",
"98:76:54:32:10:00:00:21",
"98:76:54:32:10:00:00:22",
"98:76:54:32:10:00:00:23",
"98:76:54:32:10:00:00:24",
"98:76:54:32:10:00:00:24#1",
"98:76:54:32:10:00:00:24#2",
"98:76:54:32:10:00:00:25",
"98:76:54:32:10:00:00:26",
"98:76:54:32:10:00:00:27",
"98:76:54:32:10:00:00:28",
"98:76:54:32:10:00:00:29",
"98:76:54:32:10:00:00:30",
"98:76:54:32:10:00:00:31",
"98:76:54:32:10:00:00:32",
"98:76:54:32:10:00:00:33",
"98:76:54:32:10:00:00:34",
"98:76:54:32:10:00:00:35",
"98:76:54:32:10:00:00:36",
"98:76:54:32:10:00:00:37",
"98:76:54:32:10:00:00:38",
"98:76:54:32:10:00:00:39",
"98:76:54:32:10:00:00:40",
"98:76:54:32:10:00:00:41",
"98:76:54:32:10:00:00:42",
"98:76:54:32:10:00:00:43",
"98:76:54:32:10:00:00:44",
"98:76:54:32:10:00:00:45",
"98:76:54:32:10:00:00:46",
"98:76:54:32:10:00:00:47",
"98:76:54:32:10:00:00:48",
"98:76:54:32:10:00:00:49",
"98:76:54:32:10:00:00:50",
"98:76:54:32:10:00:00:51",
"98:76:54:32:10:00:00:52",
"98:76:54:32:10:00:00:53",
"98:76:54:32:10:00:00:54",
"98:76:54:32:10:00:00:55",
"98:76:54:32:10:00:00:03#1",
"98:76:54:32:10:00:00:03#2",
"98:76:54:32:10:00:00:07#1",
"98:76:54:32:10:00:00:07#2",
"98:76:54:32:10:00:00:08#1",
"98:76:54:32:10:00:00:08#2",
"98:76:54:32:10:00:00:28#1",
"98:76:54:32:10:00:00:28#2",
"98:76:54:32:10:00:00:29#1",
"98:76:54:32:10:00:00:29#2",
"98:76:54:32:10:00:00:30#1",
"98:76:54:32:10:00:00:30#2",
"98:76:54:32:10:00:00:50#1",
"98:76:54:32:10:00:00:50#2",
"98:76:54:32:10:00:00:56",
"98:76:54:32:10:00:00:57",
"98:76:54:32:10:00:00:58",
"98:76:54:32:10:00:00:59",
"98:76:54:32:10:00:00:60",
"98:76:54:32:10:00:00:61",
"98:76:54:32:10:00:00:62",
"98:76:54:32:10:00:00:63",
"98:76:54:32:10:00:00:63#1",
"98:76:54:32:10:00:00:63#2",
"98:76:54:32:10:00:00:64",
"98:76:54:32:10:00:00:64#1",
"98:76:54:32:10:00:00:64#2",
"98:76:54:32:10:00:00:65",
"98:76:54:32:10:00:00:65#1",
"98:76:54:32:10:00:00:65#2",
"98:76:54:32:10:00:00:66",
"98:76:54:32:10:00:00:66#1",
"98:76:54:32:10:00:00:66#2",
"98:76:54:32:10:00:00:67",
"98:76:54:32:10:00:00:68",
"98:76:54:32:10:00:00:69",
"98:76:54:32:10:00:00:70",
"98:76:54:32:10:00:00:71",
"98:76:54:32:10:00:00:72",
"98:76:54:32:10:00:00:73",
"98:76:54:32:10:00:00:74",
"98:76:54:32:10:00:00:75",
"98:76:54:32:10:00:00:76",
"98:76:54:32:10:00:00:77",
"98:76:54:32:10:00:00:78",
"98:76:54:32:10:00:00:79"
]
},
{
"id": "98:76:54:32:10:00:00:01",
"type": "NLP",
"name": "Buffet",
"setup_date": 1572624686,
"room_id": "596817675",
"bridge": "aa:aa:aa:aa:aa:aa",
"appliance_type": "light"
},
{
"id": "98:76:54:32:10:00:00:02",
"type": "NLT",
"name": "Commande entrée sortie principale",
"setup_date": 1572624686,
"room_id": "596817675",
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:03",
"type": "NLD",
"name": "Boutons Cuisine Haut",
"setup_date": 1572629067,
"room_id": "3707962039",
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:04",
"type": "NLV",
"name": "volet",
"setup_date": 1572798965,
"room_id": "1462100035",
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:05",
"type": "NLM",
"name": "Verrière",
"setup_date": 1574591975,
"room_id": "3707962039",
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:06",
"type": "NLM",
"name": "ilot",
"setup_date": 1574591975,
"room_id": "3707962039",
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:07",
"type": "NLD",
"name": "Bouton Cuisine milieu",
"setup_date": 1574592863,
"room_id": "3707962039",
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:08",
"type": "NLD",
"name": "Entrée Bouton Portail et dehors",
"setup_date": 1574593140,
"room_id": "596817675",
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:09",
"type": "NLT",
"name": "Bouton pour exterieur porte fenetre",
"setup_date": 1605358560,
"room_id": "3707962039",
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:10",
"type": "NLM",
"name": "Olivier",
"setup_date": 1605359274,
"room_id": "737850817",
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:11",
"type": "NLP",
"name": "Lampadaire",
"setup_date": 1605369621,
"room_id": "842662884",
"bridge": "aa:aa:aa:aa:aa:aa",
"appliance_type": "light"
},
{
"id": "98:76:54:32:10:00:00:12",
"type": "NLT",
"name": "Bouton Bibliotheque",
"setup_date": 1607175439,
"room_id": "842662884",
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:13",
"type": "NLF",
"name": "Couloir enfants",
"setup_date": 1612299365,
"room_id": "596817675",
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:14",
"type": "NLT",
"name": "Couloir enfants 2",
"setup_date": 1612299777,
"room_id": "596817675",
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:15",
"type": "NLT",
"name": "Couloir enfants 3",
"setup_date": 1612299852,
"room_id": "596817675",
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:16",
"type": "NLT",
"name": "Couloir enfants 1",
"setup_date": 1613565493,
"room_id": "596817675",
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:17",
"type": "NLF",
"name": "Lumière C",
"setup_date": 1617390843,
"room_id": "873035982",
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:18",
"type": "NLM",
"name": "Néon",
"setup_date": 1643544945,
"room_id": "2370728183",
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:19",
"type": "NLT",
"name": "Couloir A interrupteur",
"setup_date": 1643794135,
"room_id": "2042969726",
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:20",
"type": "NLF",
"name": "Couloir A",
"setup_date": 1643794453,
"room_id": "2042969726",
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:21",
"type": "NLPT",
"name": "Dressing",
"setup_date": 1643809582,
"room_id": "1662974901",
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:22",
"type": "NLPM",
"name": "Onduleur Serveurs Mais Local Technique",
"setup_date": 1643911516,
"room_id": "2754296835",
"bridge": "aa:aa:aa:aa:aa:aa",
"appliance_type": "other"
},
{
"id": "98:76:54:32:10:00:00:23",
"type": "NLT",
"name": "Interrupteur neon",
"setup_date": 1644008400,
"room_id": "2370728183",
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:24",
"type": "NLIS",
"setup_date": 1645651106,
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:24#1",
"type": "NLIS",
"name": "Niche",
"setup_date": 1645651106,
"room_id": "1462100035",
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:24#2",
"type": "NLIS",
"name": "Escalier",
"setup_date": 1645651106,
"room_id": "842662884",
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:25",
"type": "NLT",
"name": "Bouton Escalier",
"setup_date": 1645651356,
"room_id": "842662884",
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:26",
"type": "NLPT",
"name": "Lumière Chambre E",
"setup_date": 1645657974,
"room_id": "3435163850",
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:27",
"type": "NLPT",
"name": "Entrée",
"setup_date": 1645658118,
"room_id": "596817675",
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:28",
"type": "NLD",
"name": "Bouton cuisine bas",
"setup_date": 1645659939,
"room_id": "3707962039",
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:29",
"type": "NLD",
"name": "Bouton double entrée porte",
"setup_date": 1645660346,
"room_id": "596817675",
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:30",
"type": "NLD",
"name": "Bouton double salle à manger",
"setup_date": 1645660684,
"room_id": "3194154910",
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:31",
"type": "NLF",
"name": "Placard",
"setup_date": 1645662093,
"room_id": "3194154910",
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:32",
"type": "NLT",
"name": "Bouton plafond entrée couloir",
"setup_date": 1645662629,
"room_id": "596817675",
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:33",
"type": "NLPT",
"name": "Table",
"setup_date": 1645889017,
"room_id": "3194154910",
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:34",
"type": "NLPT",
"name": "Baie Vitrée",
"setup_date": 1645889069,
"room_id": "1462100035",
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:35",
"type": "NLC",
"name": "Radiateur Dressing",
"setup_date": 1645894862,
"room_id": "1662974901",
"bridge": "aa:aa:aa:aa:aa:aa",
"appliance_type": "radiator"
},
{
"id": "98:76:54:32:10:00:00:36",
"type": "NLC",
"name": "Radiateur Entrée",
"setup_date": 1645899253,
"room_id": "596817675",
"bridge": "aa:aa:aa:aa:aa:aa",
"appliance_type": "radiator"
},
{
"id": "98:76:54:32:10:00:00:37",
"type": "NLC",
"name": "Radiateur Cuisine Dressing",
"setup_date": 1645902157,
"room_id": "3707962039",
"bridge": "aa:aa:aa:aa:aa:aa",
"appliance_type": "radiator"
},
{
"id": "98:76:54:32:10:00:00:38",
"type": "NLC",
"name": "Radiateur Cuisine Entrée",
"setup_date": 1645902199,
"room_id": "3707962039",
"bridge": "aa:aa:aa:aa:aa:aa",
"appliance_type": "radiator"
},
{
"id": "98:76:54:32:10:00:00:39",
"type": "NLT",
"name": "Commande sans fil couloir enfant pour entrée",
"setup_date": 1646074736,
"room_id": "596817675",
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:40",
"type": "NLPT",
"name": "Couloir Parents",
"setup_date": 1646568523,
"room_id": "3707962039",
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:41",
"type": "NLPT",
"name": "Jardin",
"setup_date": 1646568567,
"room_id": "737850817",
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:42",
"type": "NLPT",
"name": "Facade",
"setup_date": 1646568594,
"room_id": "737850817",
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:43",
"type": "NLC",
"name": "Radiateur FF",
"setup_date": 1646581781,
"room_id": "873035982",
"bridge": "aa:aa:aa:aa:aa:aa",
"appliance_type": "radiator"
},
{
"id": "98:76:54:32:10:00:00:44",
"type": "NLC",
"name": "Radiateur Salle De Bain Enfants",
"setup_date": 1646828219,
"room_id": "93888250",
"bridge": "aa:aa:aa:aa:aa:aa",
"appliance_type": "radiator"
},
{
"id": "98:76:54:32:10:00:00:45",
"type": "NLC",
"name": "Radiateur Buanderie",
"setup_date": 1646828251,
"room_id": "2102454491",
"bridge": "aa:aa:aa:aa:aa:aa",
"appliance_type": "radiator"
},
{
"id": "98:76:54:32:10:00:00:46",
"type": "NLC",
"name": "Radiateur A",
"setup_date": 1646828278,
"room_id": "2042969726",
"bridge": "aa:aa:aa:aa:aa:aa",
"appliance_type": "radiator"
},
{
"id": "98:76:54:32:10:00:00:47",
"type": "NLC",
"name": "Radiateur B",
"setup_date": 1646828308,
"room_id": "3497055021",
"bridge": "aa:aa:aa:aa:aa:aa",
"appliance_type": "radiator"
},
{
"id": "98:76:54:32:10:00:00:48",
"type": "NLM",
"name": "Cam Porte",
"setup_date": 1653579677,
"room_id": "2754296835",
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:49",
"type": "NLC",
"name": "Radiateur Sèche Serviette E",
"setup_date": 1667205824,
"room_id": "927970817",
"bridge": "aa:aa:aa:aa:aa:aa",
"appliance_type": "radiator"
},
{
"id": "98:76:54:32:10:00:00:50",
"type": "NLAO",
"name": "Porte vitree sans pile",
"setup_date": 1668001531,
"room_id": "3707962039",
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:51",
"type": "NLC",
"name": "Radiateur E",
"setup_date": 1668339519,
"room_id": "3435163850",
"bridge": "aa:aa:aa:aa:aa:aa",
"appliance_type": "radiator"
},
{
"id": "98:76:54:32:10:00:00:52",
"type": "NLM",
"name": "Meurtrières",
"setup_date": 1671560972,
"room_id": "1462100035",
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:53",
"type": "NLPT",
"name": "Parking",
"setup_date": 1672948768,
"room_id": "737850817",
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:54",
"type": "NLM",
"name": "Barbecue",
"setup_date": 1672948768,
"room_id": "737850817",
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:55",
"type": "NLAO",
"name": "Bouton sans pile cuisine ete",
"setup_date": 1672949735,
"room_id": "737850817",
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:03#1",
"type": "NLD",
"setup_date": 1673873611,
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:03#2",
"type": "NLD",
"setup_date": 1673873611,
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:07#1",
"type": "NLD",
"setup_date": 1673873611,
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:07#2",
"type": "NLD",
"setup_date": 1673873611,
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:08#1",
"type": "NLD",
"setup_date": 1673873611,
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:08#2",
"type": "NLD",
"setup_date": 1673873611,
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:28#1",
"type": "NLD",
"setup_date": 1673873611,
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:28#2",
"type": "NLD",
"setup_date": 1673873611,
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:29#1",
"type": "NLD",
"setup_date": 1673873611,
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:29#2",
"type": "NLD",
"setup_date": 1673873611,
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:30#1",
"type": "NLD",
"setup_date": 1673873611,
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:30#2",
"type": "NLD",
"setup_date": 1673873611,
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:50#1",
"type": "NLAO",
"setup_date": 1673873611,
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:50#2",
"type": "NLAO",
"setup_date": 1673873611,
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:56",
"type": "NLM",
"name": "Piscine",
"setup_date": 1691244631,
"room_id": "737850817",
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:57",
"type": "NLC",
"name": "Radiateur DD",
"setup_date": 1692093769,
"room_id": "3795659199",
"bridge": "aa:aa:aa:aa:aa:aa",
"appliance_type": "radiator"
},
{
"id": "98:76:54:32:10:00:00:58",
"type": "NLM",
"name": "Salle de bain",
"setup_date": 1692094781,
"room_id": "2061006239",
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:59",
"type": "NLP",
"name": "Prise Pool House Relais Zigbee",
"setup_date": 1692095384,
"room_id": "2754296835",
"bridge": "aa:aa:aa:aa:aa:aa",
"appliance_type": "router"
},
{
"id": "98:76:54:32:10:00:00:60",
"type": "NLPT",
"name": "Plafonnier",
"setup_date": 1692095856,
"room_id": "1462100035",
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:61",
"type": "NLPT",
"name": "Terrasse Piscine",
"setup_date": 1693848343,
"room_id": "2061006239",
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:62",
"type": "NLPT",
"name": "Lumière",
"setup_date": 1693848357,
"room_id": "2061006239",
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:63",
"type": "NLD",
"name": "Salon Commande Double Haut",
"setup_date": 1694336106,
"room_id": "1462100035",
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:63#1",
"type": "NLD",
"setup_date": 1694336106,
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:63#2",
"type": "NLD",
"setup_date": 1694336106,
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:64",
"type": "NLD",
"name": "Commande Pool House Gauche",
"setup_date": 1694336110,
"room_id": "2061006239",
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:64#1",
"type": "NLD",
"setup_date": 1694336110,
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:64#2",
"type": "NLD",
"setup_date": 1694336110,
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:65",
"type": "NLD",
"name": "Commande Pool House Droite",
"setup_date": 1694336143,
"room_id": "2061006239",
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:65#1",
"type": "NLD",
"setup_date": 1694336143,
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:65#2",
"type": "NLD",
"setup_date": 1694336143,
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:66",
"type": "NLD",
"name": "Commande Double Bas",
"setup_date": 1698577707,
"room_id": "1462100035",
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:66#1",
"type": "NLD",
"setup_date": 1698577707,
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:66#2",
"type": "NLD",
"setup_date": 1698577707,
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:67",
"type": "NLPO",
"name": "Cumulus Parents",
"setup_date": 1699128857,
"room_id": "2754296835",
"bridge": "aa:aa:aa:aa:aa:aa",
"appliance_type": "water_heater"
},
{
"id": "98:76:54:32:10:00:00:68",
"type": "NLPO",
"name": "Cumulus DD",
"setup_date": 1699132798,
"room_id": "2754296835",
"bridge": "aa:aa:aa:aa:aa:aa",
"appliance_type": "water_heater"
},
{
"id": "98:76:54:32:10:00:00:69",
"type": "NLPC",
"name": "Compteur Filtration Local Technique",
"setup_date": 1711797163,
"room_id": "2754296835",
"bridge": "00:04:74:22:52:38"
},
{
"id": "98:76:54:32:10:00:00:70",
"type": "NLC",
"name": "Radiateur Sèche Serviette A",
"setup_date": 1702133314,
"room_id": "1641945290",
"bridge": "aa:aa:aa:aa:aa:aa",
"appliance_type": "radiator"
},
{
"id": "98:76:54:32:10:00:00:71",
"type": "NLPO",
"name": "Cumulus Pool House",
"setup_date": 1702135239,
"room_id": "2061006239",
"bridge": "aa:aa:aa:aa:aa:aa",
"appliance_type": "water_heater"
},
{
"id": "98:76:54:32:10:00:00:72",
"type": "NLC",
"name": "Radiateur Sol Salle À Manger",
"setup_date": 1707332251,
"room_id": "3194154910",
"bridge": "aa:aa:aa:aa:aa:aa",
"appliance_type": "radiator_without_pilot_wire"
},
{
"id": "98:76:54:32:10:00:00:73",
"type": "NLC",
"name": "Radiateur Sol Salon",
"setup_date": 1707332251,
"room_id": "1462100035",
"bridge": "aa:aa:aa:aa:aa:aa",
"appliance_type": "radiator_without_pilot_wire"
},
{
"id": "98:76:54:32:10:00:00:74",
"type": "NLP",
"name": "Setup PC B",
"setup_date": 1707332620,
"room_id": "3497055021",
"bridge": "aa:aa:aa:aa:aa:aa",
"appliance_type": "router"
},
{
"id": "98:76:54:32:10:00:00:75",
"type": "NLPM",
"name": "Setup TV Apple TV Switch Salon",
"setup_date": 1707333771,
"room_id": "1462100035",
"bridge": "aa:aa:aa:aa:aa:aa",
"appliance_type": "multimedia"
},
{
"id": "98:76:54:32:10:00:00:76",
"type": "NLP",
"name": "Mesure PC Switch C",
"setup_date": 1707335636,
"room_id": "873035982",
"bridge": "aa:aa:aa:aa:aa:aa",
"appliance_type": "router"
},
{
"id": "98:76:54:32:10:00:00:77",
"type": "NLPC",
"name": "Compteur Plaque Sèche-Linge PC Buanderie Plan Cuisine",
"setup_date": 1707339526,
"room_id": "2754296835",
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:78",
"type": "NLPC",
"name": "Compteur Congel Micro-onde Frigo PC WC",
"setup_date": 1708185348,
"room_id": "2754296835",
"bridge": "aa:aa:aa:aa:aa:aa"
},
{
"id": "98:76:54:32:10:00:00:79",
"type": "NLPC",
"name": "Compteur Lave-linge Four Lave Lave-Vaisselle PC TV Chambre ",
"setup_date": 1708185369,
"room_id": "2754296835",
"bridge": "aa:aa:aa:aa:aa:aa"
}
],
"temperature_control_mode": "heating",
"therm_mode": "schedule",
"therm_setpoint_default_duration": 180,
"schedules": [
{
"timetable": [
{
"zone_id": 1,
"m_offset": 0
},
{
"zone_id": 0,
"m_offset": 360
},
{
"zone_id": 1,
"m_offset": 510
},
{
"zone_id": 5,
"m_offset": 960
},
{
"zone_id": 1,
"m_offset": 1200
},
{
"zone_id": 2,
"m_offset": 1260
},
{
"zone_id": 1,
"m_offset": 1380
},
{
"zone_id": 0,
"m_offset": 1800
},
{
"zone_id": 1,
"m_offset": 1950
},
{
"zone_id": 5,
"m_offset": 2400
},
{
"zone_id": 1,
"m_offset": 2640
},
{
"zone_id": 2,
"m_offset": 2700
},
{
"zone_id": 1,
"m_offset": 2820
},
{
"zone_id": 0,
"m_offset": 3240
},
{
"zone_id": 1,
"m_offset": 3390
},
{
"zone_id": 5,
"m_offset": 3840
},
{
"zone_id": 1,
"m_offset": 4080
},
{
"zone_id": 2,
"m_offset": 4140
},
{
"zone_id": 1,
"m_offset": 4260
},
{
"zone_id": 0,
"m_offset": 4680
},
{
"zone_id": 1,
"m_offset": 4830
},
{
"zone_id": 5,
"m_offset": 5280
},
{
"zone_id": 1,
"m_offset": 5520
},
{
"zone_id": 2,
"m_offset": 5580
},
{
"zone_id": 1,
"m_offset": 5700
},
{
"zone_id": 0,
"m_offset": 6120
},
{
"zone_id": 1,
"m_offset": 6270
},
{
"zone_id": 5,
"m_offset": 6720
},
{
"zone_id": 1,
"m_offset": 6960
},
{
"zone_id": 2,
"m_offset": 7020
},
{
"zone_id": 1,
"m_offset": 7140
},
{
"zone_id": 0,
"m_offset": 7560
},
{
"zone_id": 1,
"m_offset": 7710
},
{
"zone_id": 5,
"m_offset": 8160
},
{
"zone_id": 1,
"m_offset": 8400
},
{
"zone_id": 2,
"m_offset": 8460
},
{
"zone_id": 1,
"m_offset": 8580
},
{
"zone_id": 0,
"m_offset": 9000
},
{
"zone_id": 1,
"m_offset": 9150
},
{
"zone_id": 5,
"m_offset": 9600
},
{
"zone_id": 1,
"m_offset": 9840
},
{
"zone_id": 2,
"m_offset": 9900
},
{
"zone_id": 1,
"m_offset": 10020
}
],
"zones": [
{
"name": "Comfort",
"id": 0,
"type": 0,
"rooms_temp": [
{
"room_id": "3707962039",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "2042969726",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "3497055021",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "3435163850",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "873035982",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "1662974901",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "93888250",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "596817675",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "3795659199",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "927970817",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "1641945290",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "2102454491",
"therm_setpoint_fp": "comfort"
}
],
"rooms": [
{
"id": "3707962039",
"therm_setpoint_fp": "comfort"
},
{
"id": "2042969726",
"therm_setpoint_fp": "comfort"
},
{
"id": "3497055021",
"therm_setpoint_fp": "comfort"
},
{
"id": "3435163850",
"therm_setpoint_fp": "comfort"
},
{
"id": "873035982",
"therm_setpoint_fp": "comfort"
},
{
"id": "1662974901",
"therm_setpoint_fp": "comfort"
},
{
"id": "93888250",
"therm_setpoint_fp": "comfort"
},
{
"id": "596817675",
"therm_setpoint_fp": "comfort"
},
{
"id": "3795659199",
"therm_setpoint_fp": "comfort"
},
{
"id": "927970817",
"therm_setpoint_fp": "comfort"
},
{
"id": "1641945290",
"therm_setpoint_fp": "comfort"
},
{
"id": "2102454491",
"therm_setpoint_fp": "comfort"
}
]
},
{
"name": "Comfort+",
"id": 3,
"type": 8,
"rooms_temp": [
{
"room_id": "3707962039",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "2042969726",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "3497055021",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "3435163850",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "873035982",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "1662974901",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "93888250",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "596817675",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "3795659199",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "927970817",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "1641945290",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "2102454491",
"therm_setpoint_fp": "comfort"
}
],
"rooms": [
{
"id": "3707962039",
"therm_setpoint_fp": "comfort"
},
{
"id": "2042969726",
"therm_setpoint_fp": "comfort"
},
{
"id": "3497055021",
"therm_setpoint_fp": "comfort"
},
{
"id": "3435163850",
"therm_setpoint_fp": "comfort"
},
{
"id": "873035982",
"therm_setpoint_fp": "comfort"
},
{
"id": "1662974901",
"therm_setpoint_fp": "comfort"
},
{
"id": "93888250",
"therm_setpoint_fp": "comfort"
},
{
"id": "596817675",
"therm_setpoint_fp": "comfort"
},
{
"id": "3795659199",
"therm_setpoint_fp": "comfort"
},
{
"id": "927970817",
"therm_setpoint_fp": "comfort"
},
{
"id": "1641945290",
"therm_setpoint_fp": "comfort"
},
{
"id": "2102454491",
"therm_setpoint_fp": "comfort"
}
]
},
{
"name": "Éco",
"id": 4,
"type": 5,
"rooms_temp": [
{
"room_id": "3707962039",
"therm_setpoint_fp": "away"
},
{
"room_id": "2042969726",
"therm_setpoint_fp": "away"
},
{
"room_id": "3497055021",
"therm_setpoint_fp": "away"
},
{
"room_id": "3435163850",
"therm_setpoint_fp": "away"
},
{
"room_id": "873035982",
"therm_setpoint_fp": "away"
},
{
"room_id": "1662974901",
"therm_setpoint_fp": "away"
},
{
"room_id": "93888250",
"therm_setpoint_fp": "away"
},
{
"room_id": "596817675",
"therm_setpoint_fp": "away"
},
{
"room_id": "3795659199",
"therm_setpoint_fp": "away"
},
{
"room_id": "927970817",
"therm_setpoint_fp": "away"
},
{
"room_id": "1641945290",
"therm_setpoint_fp": "away"
},
{
"room_id": "2102454491",
"therm_setpoint_fp": "away"
}
],
"modules": [],
"rooms": [
{
"id": "3707962039",
"therm_setpoint_fp": "away"
},
{
"id": "2042969726",
"therm_setpoint_fp": "away"
},
{
"id": "3497055021",
"therm_setpoint_fp": "away"
},
{
"id": "3435163850",
"therm_setpoint_fp": "away"
},
{
"id": "873035982",
"therm_setpoint_fp": "away"
},
{
"id": "1662974901",
"therm_setpoint_fp": "away"
},
{
"id": "93888250",
"therm_setpoint_fp": "away"
},
{
"id": "596817675",
"therm_setpoint_fp": "away"
},
{
"id": "3795659199",
"therm_setpoint_fp": "away"
},
{
"id": "927970817",
"therm_setpoint_fp": "away"
},
{
"id": "1641945290",
"therm_setpoint_fp": "away"
},
{
"id": "2102454491",
"therm_setpoint_fp": "away"
}
]
},
{
"name": "Nuit",
"id": 1,
"type": 1,
"rooms_temp": [
{
"room_id": "3707962039",
"therm_setpoint_fp": "away"
},
{
"room_id": "2042969726",
"therm_setpoint_fp": "away"
},
{
"room_id": "3497055021",
"therm_setpoint_fp": "away"
},
{
"room_id": "3435163850",
"therm_setpoint_fp": "away"
},
{
"room_id": "873035982",
"therm_setpoint_fp": "away"
},
{
"room_id": "1662974901",
"therm_setpoint_fp": "away"
},
{
"room_id": "93888250",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "596817675",
"therm_setpoint_fp": "away"
},
{
"room_id": "3795659199",
"therm_setpoint_fp": "away"
},
{
"room_id": "927970817",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "1641945290",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "2102454491",
"therm_setpoint_fp": "away"
}
],
"modules": [],
"rooms": [
{
"id": "3707962039",
"therm_setpoint_fp": "away"
},
{
"id": "2042969726",
"therm_setpoint_fp": "away"
},
{
"id": "3497055021",
"therm_setpoint_fp": "away"
},
{
"id": "3435163850",
"therm_setpoint_fp": "away"
},
{
"id": "873035982",
"therm_setpoint_fp": "away"
},
{
"id": "1662974901",
"therm_setpoint_fp": "away"
},
{
"id": "93888250",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "596817675",
"therm_setpoint_fp": "away"
},
{
"id": "3795659199",
"therm_setpoint_fp": "away"
},
{
"id": "927970817",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "1641945290",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "2102454491",
"therm_setpoint_fp": "away"
}
]
},
{
"name": "Confort sauf chambres parents",
"id": 5,
"type": 4,
"rooms_temp": [
{
"room_id": "1641945290",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "1662974901",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "2042969726",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "3435163850",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "3497055021",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "3707962039",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "3795659199",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "596817675",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "873035982",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "927970817",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "93888250",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "2102454491",
"therm_setpoint_fp": "comfort"
}
],
"modules": [],
"rooms": [
{
"id": "1641945290",
"therm_setpoint_fp": "comfort"
},
{
"id": "1662974901",
"therm_setpoint_fp": "comfort"
},
{
"id": "2042969726",
"therm_setpoint_fp": "comfort"
},
{
"id": "3435163850",
"therm_setpoint_fp": "comfort"
},
{
"id": "3497055021",
"therm_setpoint_fp": "comfort"
},
{
"id": "3707962039",
"therm_setpoint_fp": "comfort"
},
{
"id": "3795659199",
"therm_setpoint_fp": "comfort"
},
{
"id": "596817675",
"therm_setpoint_fp": "comfort"
},
{
"id": "873035982",
"therm_setpoint_fp": "comfort"
},
{
"id": "927970817",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "93888250",
"therm_setpoint_fp": "comfort"
},
{
"id": "2102454491",
"therm_setpoint_fp": "comfort"
}
]
},
{
"name": "Chambre parents only",
"id": 2,
"type": 4,
"rooms_temp": [
{
"room_id": "1641945290",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "1662974901",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "2042969726",
"therm_setpoint_fp": "away"
},
{
"room_id": "3435163850",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "3497055021",
"therm_setpoint_fp": "away"
},
{
"room_id": "3707962039",
"therm_setpoint_fp": "away"
},
{
"room_id": "3795659199",
"therm_setpoint_fp": "away"
},
{
"room_id": "596817675",
"therm_setpoint_fp": "away"
},
{
"room_id": "873035982",
"therm_setpoint_fp": "away"
},
{
"room_id": "927970817",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "93888250",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "2102454491",
"therm_setpoint_fp": "comfort"
}
],
"modules": [],
"rooms": [
{
"id": "1641945290",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "1662974901",
"therm_setpoint_fp": "comfort"
},
{
"id": "2042969726",
"therm_setpoint_fp": "away"
},
{
"id": "3435163850",
"therm_setpoint_fp": "comfort"
},
{
"id": "3497055021",
"therm_setpoint_fp": "away"
},
{
"id": "3707962039",
"therm_setpoint_fp": "away"
},
{
"id": "3795659199",
"therm_setpoint_fp": "away"
},
{
"id": "596817675",
"therm_setpoint_fp": "away"
},
{
"id": "873035982",
"therm_setpoint_fp": "away"
},
{
"id": "927970817",
"therm_setpoint_fp": "comfort"
},
{
"id": "93888250",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "2102454491",
"therm_setpoint_fp": "comfort"
}
]
}
],
"name": "Planning Hiver",
"default": false,
"away_temp": 12,
"hg_temp": 7,
"id": "61fa621cdd99943657260882",
"type": "therm",
"selected": true
},
{
"timetable": [
{
"zone_id": 2,
"m_offset": 0
}
],
"zones": [
{
"name": "Comfort",
"id": 0,
"type": 0,
"rooms_temp": [
{
"room_id": "3707962039",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "2042969726",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "3497055021",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "3435163850",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "873035982",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "1662974901",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "93888250",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "596817675",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "3795659199",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "927970817",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "1641945290",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "2102454491",
"therm_setpoint_fp": "comfort"
}
],
"rooms": [
{
"id": "3707962039",
"therm_setpoint_fp": "comfort"
},
{
"id": "2042969726",
"therm_setpoint_fp": "comfort"
},
{
"id": "3497055021",
"therm_setpoint_fp": "comfort"
},
{
"id": "3435163850",
"therm_setpoint_fp": "comfort"
},
{
"id": "873035982",
"therm_setpoint_fp": "comfort"
},
{
"id": "1662974901",
"therm_setpoint_fp": "comfort"
},
{
"id": "93888250",
"therm_setpoint_fp": "comfort"
},
{
"id": "596817675",
"therm_setpoint_fp": "comfort"
},
{
"id": "3795659199",
"therm_setpoint_fp": "comfort"
},
{
"id": "927970817",
"therm_setpoint_fp": "comfort"
},
{
"id": "1641945290",
"therm_setpoint_fp": "comfort"
},
{
"id": "2102454491",
"therm_setpoint_fp": "comfort"
}
]
},
{
"name": "Comfort+",
"id": 3,
"type": 8,
"rooms_temp": [
{
"room_id": "3707962039",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "2042969726",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "3497055021",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "3435163850",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "873035982",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "1662974901",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "93888250",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "596817675",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "3795659199",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "927970817",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "1641945290",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "2102454491",
"therm_setpoint_fp": "comfort"
}
],
"rooms": [
{
"id": "3707962039",
"therm_setpoint_fp": "comfort"
},
{
"id": "2042969726",
"therm_setpoint_fp": "comfort"
},
{
"id": "3497055021",
"therm_setpoint_fp": "comfort"
},
{
"id": "3435163850",
"therm_setpoint_fp": "comfort"
},
{
"id": "873035982",
"therm_setpoint_fp": "comfort"
},
{
"id": "1662974901",
"therm_setpoint_fp": "comfort"
},
{
"id": "93888250",
"therm_setpoint_fp": "comfort"
},
{
"id": "596817675",
"therm_setpoint_fp": "comfort"
},
{
"id": "3795659199",
"therm_setpoint_fp": "comfort"
},
{
"id": "927970817",
"therm_setpoint_fp": "comfort"
},
{
"id": "1641945290",
"therm_setpoint_fp": "comfort"
},
{
"id": "2102454491",
"therm_setpoint_fp": "comfort"
}
]
},
{
"name": "Éco",
"id": 4,
"type": 5,
"rooms_temp": [
{
"room_id": "3707962039",
"therm_setpoint_fp": "away"
},
{
"room_id": "2042969726",
"therm_setpoint_fp": "away"
},
{
"room_id": "3497055021",
"therm_setpoint_fp": "away"
},
{
"room_id": "3435163850",
"therm_setpoint_fp": "away"
},
{
"room_id": "873035982",
"therm_setpoint_fp": "away"
},
{
"room_id": "1662974901",
"therm_setpoint_fp": "away"
},
{
"room_id": "93888250",
"therm_setpoint_fp": "away"
},
{
"room_id": "596817675",
"therm_setpoint_fp": "away"
},
{
"room_id": "3795659199",
"therm_setpoint_fp": "away"
},
{
"room_id": "927970817",
"therm_setpoint_fp": "away"
},
{
"room_id": "1641945290",
"therm_setpoint_fp": "away"
},
{
"room_id": "2102454491",
"therm_setpoint_fp": "away"
}
],
"modules": [],
"rooms": [
{
"id": "3707962039",
"therm_setpoint_fp": "away"
},
{
"id": "2042969726",
"therm_setpoint_fp": "away"
},
{
"id": "3497055021",
"therm_setpoint_fp": "away"
},
{
"id": "3435163850",
"therm_setpoint_fp": "away"
},
{
"id": "873035982",
"therm_setpoint_fp": "away"
},
{
"id": "1662974901",
"therm_setpoint_fp": "away"
},
{
"id": "93888250",
"therm_setpoint_fp": "away"
},
{
"id": "596817675",
"therm_setpoint_fp": "away"
},
{
"id": "3795659199",
"therm_setpoint_fp": "away"
},
{
"id": "927970817",
"therm_setpoint_fp": "away"
},
{
"id": "1641945290",
"therm_setpoint_fp": "away"
},
{
"id": "2102454491",
"therm_setpoint_fp": "away"
}
]
},
{
"name": "Nuit",
"id": 1,
"type": 1,
"rooms_temp": [
{
"room_id": "3707962039",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "2042969726",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "3497055021",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "3435163850",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "873035982",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "1662974901",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "93888250",
"therm_setpoint_fp": "away"
},
{
"room_id": "596817675",
"therm_setpoint_fp": "away"
},
{
"room_id": "3795659199",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "927970817",
"therm_setpoint_fp": "away"
},
{
"room_id": "1641945290",
"therm_setpoint_fp": "away"
},
{
"room_id": "2102454491",
"therm_setpoint_fp": "frost_guard"
}
],
"modules": [],
"rooms": [
{
"id": "3707962039",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "2042969726",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "3497055021",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "3435163850",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "873035982",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "1662974901",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "93888250",
"therm_setpoint_fp": "away"
},
{
"id": "596817675",
"therm_setpoint_fp": "away"
},
{
"id": "3795659199",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "927970817",
"therm_setpoint_fp": "away"
},
{
"id": "1641945290",
"therm_setpoint_fp": "away"
},
{
"id": "2102454491",
"therm_setpoint_fp": "frost_guard"
}
]
},
{
"name": "Off",
"id": 2,
"type": 4,
"rooms_temp": [
{
"room_id": "3707962039",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "2042969726",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "3497055021",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "3435163850",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "873035982",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "1662974901",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "93888250",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "596817675",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "3795659199",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "927970817",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "1641945290",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "2102454491",
"therm_setpoint_fp": "frost_guard"
}
],
"modules": [],
"rooms": [
{
"id": "3707962039",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "2042969726",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "3497055021",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "3435163850",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "873035982",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "1662974901",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "93888250",
"therm_setpoint_fp": "comfort"
},
{
"id": "596817675",
"therm_setpoint_fp": "comfort"
},
{
"id": "3795659199",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "927970817",
"therm_setpoint_fp": "comfort"
},
{
"id": "1641945290",
"therm_setpoint_fp": "comfort"
},
{
"id": "2102454491",
"therm_setpoint_fp": "frost_guard"
}
]
}
],
"name": "Planning ete",
"default": false,
"away_temp": 12,
"hg_temp": 7,
"id": "625a76ceec2cce72075ac55a",
"type": "therm"
},
{
"timetable": [
{
"zone_id": 0,
"m_offset": 0
}
],
"zones": [
{
"name": "Comfort",
"id": 0,
"type": 0,
"rooms_temp": [
{
"room_id": "3707962039",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "2042969726",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "3497055021",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "3435163850",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "873035982",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "1662974901",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "93888250",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "596817675",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "3795659199",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "927970817",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "1641945290",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "2102454491",
"therm_setpoint_fp": "comfort"
}
],
"modules": [],
"rooms": [
{
"id": "3707962039",
"therm_setpoint_fp": "comfort"
},
{
"id": "2042969726",
"therm_setpoint_fp": "comfort"
},
{
"id": "3497055021",
"therm_setpoint_fp": "comfort"
},
{
"id": "3435163850",
"therm_setpoint_fp": "comfort"
},
{
"id": "873035982",
"therm_setpoint_fp": "comfort"
},
{
"id": "1662974901",
"therm_setpoint_fp": "comfort"
},
{
"id": "93888250",
"therm_setpoint_fp": "comfort"
},
{
"id": "596817675",
"therm_setpoint_fp": "comfort"
},
{
"id": "3795659199",
"therm_setpoint_fp": "comfort"
},
{
"id": "927970817",
"therm_setpoint_fp": "comfort"
},
{
"id": "1641945290",
"therm_setpoint_fp": "comfort"
},
{
"id": "2102454491",
"therm_setpoint_fp": "comfort"
}
]
},
{
"name": "Night",
"id": 1,
"type": 1,
"rooms_temp": [
{
"room_id": "3707962039",
"therm_setpoint_fp": "away"
},
{
"room_id": "2042969726",
"therm_setpoint_fp": "away"
},
{
"room_id": "3497055021",
"therm_setpoint_fp": "away"
},
{
"room_id": "3435163850",
"therm_setpoint_fp": "away"
},
{
"room_id": "873035982",
"therm_setpoint_fp": "away"
},
{
"room_id": "1662974901",
"therm_setpoint_fp": "away"
},
{
"room_id": "93888250",
"therm_setpoint_fp": "away"
},
{
"room_id": "596817675",
"therm_setpoint_fp": "away"
},
{
"room_id": "3795659199",
"therm_setpoint_fp": "away"
},
{
"room_id": "927970817",
"therm_setpoint_fp": "away"
},
{
"room_id": "1641945290",
"therm_setpoint_fp": "away"
},
{
"room_id": "2102454491",
"therm_setpoint_fp": "away"
}
],
"modules": [],
"rooms": [
{
"id": "3707962039",
"therm_setpoint_fp": "away"
},
{
"id": "2042969726",
"therm_setpoint_fp": "away"
},
{
"id": "3497055021",
"therm_setpoint_fp": "away"
},
{
"id": "3435163850",
"therm_setpoint_fp": "away"
},
{
"id": "873035982",
"therm_setpoint_fp": "away"
},
{
"id": "1662974901",
"therm_setpoint_fp": "away"
},
{
"id": "93888250",
"therm_setpoint_fp": "away"
},
{
"id": "596817675",
"therm_setpoint_fp": "away"
},
{
"id": "3795659199",
"therm_setpoint_fp": "away"
},
{
"id": "927970817",
"therm_setpoint_fp": "away"
},
{
"id": "1641945290",
"therm_setpoint_fp": "away"
},
{
"id": "2102454491",
"therm_setpoint_fp": "away"
}
]
},
{
"name": "Comfort+",
"id": 3,
"type": 8,
"rooms_temp": [
{
"room_id": "3707962039",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "2042969726",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "3497055021",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "3435163850",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "873035982",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "1662974901",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "93888250",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "596817675",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "3795659199",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "927970817",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "1641945290",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "2102454491",
"therm_setpoint_fp": "comfort"
}
],
"modules": [],
"rooms": [
{
"id": "3707962039",
"therm_setpoint_fp": "comfort"
},
{
"id": "2042969726",
"therm_setpoint_fp": "comfort"
},
{
"id": "3497055021",
"therm_setpoint_fp": "comfort"
},
{
"id": "3435163850",
"therm_setpoint_fp": "comfort"
},
{
"id": "873035982",
"therm_setpoint_fp": "comfort"
},
{
"id": "1662974901",
"therm_setpoint_fp": "comfort"
},
{
"id": "93888250",
"therm_setpoint_fp": "comfort"
},
{
"id": "596817675",
"therm_setpoint_fp": "comfort"
},
{
"id": "3795659199",
"therm_setpoint_fp": "comfort"
},
{
"id": "927970817",
"therm_setpoint_fp": "comfort"
},
{
"id": "1641945290",
"therm_setpoint_fp": "comfort"
},
{
"id": "2102454491",
"therm_setpoint_fp": "comfort"
}
]
},
{
"name": "Eco",
"id": 4,
"type": 5,
"rooms_temp": [
{
"room_id": "3707962039",
"therm_setpoint_fp": "away"
},
{
"room_id": "2042969726",
"therm_setpoint_fp": "away"
},
{
"room_id": "3497055021",
"therm_setpoint_fp": "away"
},
{
"room_id": "3435163850",
"therm_setpoint_fp": "away"
},
{
"room_id": "873035982",
"therm_setpoint_fp": "away"
},
{
"room_id": "1662974901",
"therm_setpoint_fp": "away"
},
{
"room_id": "93888250",
"therm_setpoint_fp": "away"
},
{
"room_id": "596817675",
"therm_setpoint_fp": "away"
},
{
"room_id": "3795659199",
"therm_setpoint_fp": "away"
},
{
"room_id": "927970817",
"therm_setpoint_fp": "away"
},
{
"room_id": "1641945290",
"therm_setpoint_fp": "away"
},
{
"room_id": "2102454491",
"therm_setpoint_fp": "away"
}
],
"modules": [],
"rooms": [
{
"id": "3707962039",
"therm_setpoint_fp": "away"
},
{
"id": "2042969726",
"therm_setpoint_fp": "away"
},
{
"id": "3497055021",
"therm_setpoint_fp": "away"
},
{
"id": "3435163850",
"therm_setpoint_fp": "away"
},
{
"id": "873035982",
"therm_setpoint_fp": "away"
},
{
"id": "1662974901",
"therm_setpoint_fp": "away"
},
{
"id": "93888250",
"therm_setpoint_fp": "away"
},
{
"id": "596817675",
"therm_setpoint_fp": "away"
},
{
"id": "3795659199",
"therm_setpoint_fp": "away"
},
{
"id": "927970817",
"therm_setpoint_fp": "away"
},
{
"id": "1641945290",
"therm_setpoint_fp": "away"
},
{
"id": "2102454491",
"therm_setpoint_fp": "away"
}
]
}
],
"name": "Full",
"default": false,
"away_temp": 12,
"hg_temp": 7,
"id": "63a44ba0735ffc27410f2331",
"type": "therm"
},
{
"timetable": [
{
"zone_id": 4,
"m_offset": 0
},
{
"zone_id": 0,
"m_offset": 300
},
{
"zone_id": 4,
"m_offset": 420
},
{
"zone_id": 0,
"m_offset": 855
},
{
"zone_id": 4,
"m_offset": 1140
},
{
"zone_id": 0,
"m_offset": 1740
},
{
"zone_id": 4,
"m_offset": 1860
},
{
"zone_id": 0,
"m_offset": 2295
},
{
"zone_id": 4,
"m_offset": 2580
},
{
"zone_id": 0,
"m_offset": 3180
},
{
"zone_id": 4,
"m_offset": 3300
},
{
"zone_id": 0,
"m_offset": 3735
},
{
"zone_id": 4,
"m_offset": 4020
},
{
"zone_id": 0,
"m_offset": 4620
},
{
"zone_id": 4,
"m_offset": 4740
},
{
"zone_id": 0,
"m_offset": 5175
},
{
"zone_id": 4,
"m_offset": 5460
},
{
"zone_id": 0,
"m_offset": 6060
},
{
"zone_id": 4,
"m_offset": 6180
},
{
"zone_id": 0,
"m_offset": 6615
},
{
"zone_id": 4,
"m_offset": 6900
},
{
"zone_id": 0,
"m_offset": 7500
},
{
"zone_id": 4,
"m_offset": 7620
},
{
"zone_id": 0,
"m_offset": 8055
},
{
"zone_id": 4,
"m_offset": 8340
},
{
"zone_id": 0,
"m_offset": 8940
},
{
"zone_id": 4,
"m_offset": 9060
},
{
"zone_id": 0,
"m_offset": 9495
},
{
"zone_id": 4,
"m_offset": 9780
}
],
"zones": [
{
"name": "Comfort",
"id": 0,
"type": 0,
"rooms_temp": [
{
"room_id": "3707962039",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "2042969726",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "3497055021",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "3435163850",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "873035982",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "1662974901",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "93888250",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "596817675",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "3795659199",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "927970817",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "1641945290",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "2102454491",
"therm_setpoint_fp": "comfort"
}
],
"rooms": [
{
"id": "3707962039",
"therm_setpoint_fp": "comfort"
},
{
"id": "2042969726",
"therm_setpoint_fp": "comfort"
},
{
"id": "3497055021",
"therm_setpoint_fp": "comfort"
},
{
"id": "3435163850",
"therm_setpoint_fp": "comfort"
},
{
"id": "873035982",
"therm_setpoint_fp": "comfort"
},
{
"id": "1662974901",
"therm_setpoint_fp": "comfort"
},
{
"id": "93888250",
"therm_setpoint_fp": "comfort"
},
{
"id": "596817675",
"therm_setpoint_fp": "comfort"
},
{
"id": "3795659199",
"therm_setpoint_fp": "comfort"
},
{
"id": "927970817",
"therm_setpoint_fp": "comfort"
},
{
"id": "1641945290",
"therm_setpoint_fp": "comfort"
},
{
"id": "2102454491",
"therm_setpoint_fp": "comfort"
}
]
},
{
"name": "Comfort+",
"id": 3,
"type": 8,
"rooms_temp": [
{
"room_id": "3707962039",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "2042969726",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "3497055021",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "3435163850",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "873035982",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "1662974901",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "93888250",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "596817675",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "3795659199",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "927970817",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "1641945290",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "2102454491",
"therm_setpoint_fp": "comfort"
}
],
"rooms": [
{
"id": "3707962039",
"therm_setpoint_fp": "comfort"
},
{
"id": "2042969726",
"therm_setpoint_fp": "comfort"
},
{
"id": "3497055021",
"therm_setpoint_fp": "comfort"
},
{
"id": "3435163850",
"therm_setpoint_fp": "comfort"
},
{
"id": "873035982",
"therm_setpoint_fp": "comfort"
},
{
"id": "1662974901",
"therm_setpoint_fp": "comfort"
},
{
"id": "93888250",
"therm_setpoint_fp": "comfort"
},
{
"id": "596817675",
"therm_setpoint_fp": "comfort"
},
{
"id": "3795659199",
"therm_setpoint_fp": "comfort"
},
{
"id": "927970817",
"therm_setpoint_fp": "comfort"
},
{
"id": "1641945290",
"therm_setpoint_fp": "comfort"
},
{
"id": "2102454491",
"therm_setpoint_fp": "comfort"
}
]
},
{
"name": "Éco",
"id": 4,
"type": 5,
"rooms_temp": [
{
"room_id": "3707962039",
"therm_setpoint_fp": "away"
},
{
"room_id": "2042969726",
"therm_setpoint_fp": "away"
},
{
"room_id": "3497055021",
"therm_setpoint_fp": "away"
},
{
"room_id": "3435163850",
"therm_setpoint_fp": "away"
},
{
"room_id": "873035982",
"therm_setpoint_fp": "away"
},
{
"room_id": "1662974901",
"therm_setpoint_fp": "away"
},
{
"room_id": "93888250",
"therm_setpoint_fp": "away"
},
{
"room_id": "596817675",
"therm_setpoint_fp": "away"
},
{
"room_id": "3795659199",
"therm_setpoint_fp": "away"
},
{
"room_id": "927970817",
"therm_setpoint_fp": "away"
},
{
"room_id": "1641945290",
"therm_setpoint_fp": "away"
},
{
"room_id": "2102454491",
"therm_setpoint_fp": "away"
}
],
"modules": [],
"rooms": [
{
"id": "3707962039",
"therm_setpoint_fp": "away"
},
{
"id": "2042969726",
"therm_setpoint_fp": "away"
},
{
"id": "3497055021",
"therm_setpoint_fp": "away"
},
{
"id": "3435163850",
"therm_setpoint_fp": "away"
},
{
"id": "873035982",
"therm_setpoint_fp": "away"
},
{
"id": "1662974901",
"therm_setpoint_fp": "away"
},
{
"id": "93888250",
"therm_setpoint_fp": "away"
},
{
"id": "596817675",
"therm_setpoint_fp": "away"
},
{
"id": "3795659199",
"therm_setpoint_fp": "away"
},
{
"id": "927970817",
"therm_setpoint_fp": "away"
},
{
"id": "1641945290",
"therm_setpoint_fp": "away"
},
{
"id": "2102454491",
"therm_setpoint_fp": "away"
}
]
},
{
"name": "Nuit",
"id": 1,
"type": 1,
"rooms_temp": [
{
"room_id": "3707962039",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "2042969726",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "3497055021",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "3435163850",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "873035982",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "1662974901",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "93888250",
"therm_setpoint_fp": "away"
},
{
"room_id": "596817675",
"therm_setpoint_fp": "away"
},
{
"room_id": "3795659199",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "927970817",
"therm_setpoint_fp": "away"
},
{
"room_id": "1641945290",
"therm_setpoint_fp": "away"
},
{
"room_id": "2102454491",
"therm_setpoint_fp": "frost_guard"
}
],
"modules": [],
"rooms": [
{
"id": "3707962039",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "2042969726",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "3497055021",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "3435163850",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "873035982",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "1662974901",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "93888250",
"therm_setpoint_fp": "away"
},
{
"id": "596817675",
"therm_setpoint_fp": "away"
},
{
"id": "3795659199",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "927970817",
"therm_setpoint_fp": "away"
},
{
"id": "1641945290",
"therm_setpoint_fp": "away"
},
{
"id": "2102454491",
"therm_setpoint_fp": "frost_guard"
}
]
}
],
"name": "Planning Hiver frileux",
"default": false,
"away_temp": 12,
"hg_temp": 7,
"id": "63c5b63b766611525b0b1e4d",
"type": "therm"
},
{
"timetable": [
{
"zone_id": 1,
"m_offset": 0
},
{
"zone_id": 0,
"m_offset": 300
},
{
"zone_id": 4,
"m_offset": 420
},
{
"zone_id": 0,
"m_offset": 1020
},
{
"zone_id": 1,
"m_offset": 1140
},
{
"zone_id": 0,
"m_offset": 1740
},
{
"zone_id": 4,
"m_offset": 1860
},
{
"zone_id": 0,
"m_offset": 2460
},
{
"zone_id": 1,
"m_offset": 2580
},
{
"zone_id": 0,
"m_offset": 3180
},
{
"zone_id": 4,
"m_offset": 3300
},
{
"zone_id": 0,
"m_offset": 3900
},
{
"zone_id": 1,
"m_offset": 4020
},
{
"zone_id": 0,
"m_offset": 4620
},
{
"zone_id": 4,
"m_offset": 4740
},
{
"zone_id": 0,
"m_offset": 5340
},
{
"zone_id": 1,
"m_offset": 5460
},
{
"zone_id": 0,
"m_offset": 6060
},
{
"zone_id": 4,
"m_offset": 6180
},
{
"zone_id": 0,
"m_offset": 6780
},
{
"zone_id": 1,
"m_offset": 6900
},
{
"zone_id": 0,
"m_offset": 7560
},
{
"zone_id": 4,
"m_offset": 7680
},
{
"zone_id": 0,
"m_offset": 8220
},
{
"zone_id": 1,
"m_offset": 8340
},
{
"zone_id": 0,
"m_offset": 9000
},
{
"zone_id": 4,
"m_offset": 9120
},
{
"zone_id": 0,
"m_offset": 9660
},
{
"zone_id": 1,
"m_offset": 9780
}
],
"zones": [
{
"name": "Comfort+",
"id": 3,
"type": 8,
"rooms_temp": [
{
"room_id": "3707962039",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "2042969726",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "3497055021",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "3435163850",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "873035982",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "1662974901",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "93888250",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "596817675",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "3795659199",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "927970817",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "1641945290",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "2102454491",
"therm_setpoint_fp": "comfort"
}
],
"rooms": [
{
"id": "3707962039",
"therm_setpoint_fp": "comfort"
},
{
"id": "2042969726",
"therm_setpoint_fp": "comfort"
},
{
"id": "3497055021",
"therm_setpoint_fp": "comfort"
},
{
"id": "3435163850",
"therm_setpoint_fp": "comfort"
},
{
"id": "873035982",
"therm_setpoint_fp": "comfort"
},
{
"id": "1662974901",
"therm_setpoint_fp": "comfort"
},
{
"id": "93888250",
"therm_setpoint_fp": "comfort"
},
{
"id": "596817675",
"therm_setpoint_fp": "comfort"
},
{
"id": "3795659199",
"therm_setpoint_fp": "comfort"
},
{
"id": "927970817",
"therm_setpoint_fp": "comfort"
},
{
"id": "1641945290",
"therm_setpoint_fp": "comfort"
},
{
"id": "2102454491",
"therm_setpoint_fp": "comfort"
}
]
},
{
"name": "Nuit",
"id": 1,
"type": 1,
"rooms_temp": [
{
"room_id": "3707962039",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "2042969726",
"therm_setpoint_fp": "away"
},
{
"room_id": "3497055021",
"therm_setpoint_fp": "away"
},
{
"room_id": "3435163850",
"therm_setpoint_fp": "away"
},
{
"room_id": "873035982",
"therm_setpoint_fp": "away"
},
{
"room_id": "1662974901",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "93888250",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "596817675",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "3795659199",
"therm_setpoint_fp": "away"
},
{
"room_id": "927970817",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "1641945290",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "2102454491",
"therm_setpoint_fp": "frost_guard"
}
],
"modules": [],
"rooms": [
{
"id": "3707962039",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "2042969726",
"therm_setpoint_fp": "away"
},
{
"id": "3497055021",
"therm_setpoint_fp": "away"
},
{
"id": "3435163850",
"therm_setpoint_fp": "away"
},
{
"id": "873035982",
"therm_setpoint_fp": "away"
},
{
"id": "1662974901",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "93888250",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "596817675",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "3795659199",
"therm_setpoint_fp": "away"
},
{
"id": "927970817",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "1641945290",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "2102454491",
"therm_setpoint_fp": "frost_guard"
}
]
},
{
"name": "Confort",
"id": 0,
"type": 0,
"rooms_temp": [
{
"room_id": "3707962039",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "2042969726",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "3497055021",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "3435163850",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "873035982",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "1662974901",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "93888250",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "596817675",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "3795659199",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "927970817",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "1641945290",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "2102454491",
"therm_setpoint_fp": "frost_guard"
}
],
"modules": [],
"rooms": [
{
"id": "3707962039",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "2042969726",
"therm_setpoint_fp": "comfort"
},
{
"id": "3497055021",
"therm_setpoint_fp": "comfort"
},
{
"id": "3435163850",
"therm_setpoint_fp": "comfort"
},
{
"id": "873035982",
"therm_setpoint_fp": "comfort"
},
{
"id": "1662974901",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "93888250",
"therm_setpoint_fp": "comfort"
},
{
"id": "596817675",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "3795659199",
"therm_setpoint_fp": "comfort"
},
{
"id": "927970817",
"therm_setpoint_fp": "comfort"
},
{
"id": "1641945290",
"therm_setpoint_fp": "comfort"
},
{
"id": "2102454491",
"therm_setpoint_fp": "frost_guard"
}
]
},
{
"name": "Éco",
"id": 4,
"type": 5,
"rooms_temp": [
{
"room_id": "3707962039",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "2042969726",
"therm_setpoint_fp": "away"
},
{
"room_id": "3497055021",
"therm_setpoint_fp": "away"
},
{
"room_id": "3435163850",
"therm_setpoint_fp": "away"
},
{
"room_id": "873035982",
"therm_setpoint_fp": "away"
},
{
"room_id": "1662974901",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "93888250",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "596817675",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "3795659199",
"therm_setpoint_fp": "away"
},
{
"room_id": "927970817",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "1641945290",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "2102454491",
"therm_setpoint_fp": "frost_guard"
}
],
"modules": [],
"rooms": [
{
"id": "3707962039",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "2042969726",
"therm_setpoint_fp": "away"
},
{
"id": "3497055021",
"therm_setpoint_fp": "away"
},
{
"id": "3435163850",
"therm_setpoint_fp": "away"
},
{
"id": "873035982",
"therm_setpoint_fp": "away"
},
{
"id": "1662974901",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "93888250",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "596817675",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "3795659199",
"therm_setpoint_fp": "away"
},
{
"id": "927970817",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "1641945290",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "2102454491",
"therm_setpoint_fp": "frost_guard"
}
]
}
],
"name": "Chambres et SDB",
"default": false,
"away_temp": 12,
"hg_temp": 7,
"id": "6413ac548decf9f28b0efc4e",
"type": "therm"
},
{
"timetable": [
{
"zone_id": 5,
"m_offset": 0
},
{
"zone_id": 2,
"m_offset": 360
},
{
"zone_id": 5,
"m_offset": 450
},
{
"zone_id": 2,
"m_offset": 1020
},
{
"zone_id": 5,
"m_offset": 1080
},
{
"zone_id": 2,
"m_offset": 1800
},
{
"zone_id": 5,
"m_offset": 1890
},
{
"zone_id": 2,
"m_offset": 2460
},
{
"zone_id": 5,
"m_offset": 2520
},
{
"zone_id": 2,
"m_offset": 3240
},
{
"zone_id": 5,
"m_offset": 3330
},
{
"zone_id": 2,
"m_offset": 3900
},
{
"zone_id": 5,
"m_offset": 3960
},
{
"zone_id": 2,
"m_offset": 4680
},
{
"zone_id": 5,
"m_offset": 4770
},
{
"zone_id": 2,
"m_offset": 5340
},
{
"zone_id": 5,
"m_offset": 5400
},
{
"zone_id": 2,
"m_offset": 6120
},
{
"zone_id": 5,
"m_offset": 6210
},
{
"zone_id": 2,
"m_offset": 6780
},
{
"zone_id": 5,
"m_offset": 6840
},
{
"zone_id": 2,
"m_offset": 7680
},
{
"zone_id": 5,
"m_offset": 7740
},
{
"zone_id": 2,
"m_offset": 8220
},
{
"zone_id": 5,
"m_offset": 8280
},
{
"zone_id": 2,
"m_offset": 9120
},
{
"zone_id": 5,
"m_offset": 9180
},
{
"zone_id": 2,
"m_offset": 9660
},
{
"zone_id": 5,
"m_offset": 9720
}
],
"zones": [
{
"name": "Comfort",
"id": 0,
"type": 0,
"rooms_temp": [
{
"room_id": "3707962039",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "2042969726",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "3497055021",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "3435163850",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "873035982",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "1662974901",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "93888250",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "596817675",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "3795659199",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "927970817",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "1641945290",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "2102454491",
"therm_setpoint_fp": "comfort"
}
],
"modules": [],
"rooms": [
{
"id": "3707962039",
"therm_setpoint_fp": "comfort"
},
{
"id": "2042969726",
"therm_setpoint_fp": "comfort"
},
{
"id": "3497055021",
"therm_setpoint_fp": "comfort"
},
{
"id": "3435163850",
"therm_setpoint_fp": "comfort"
},
{
"id": "873035982",
"therm_setpoint_fp": "comfort"
},
{
"id": "1662974901",
"therm_setpoint_fp": "comfort"
},
{
"id": "93888250",
"therm_setpoint_fp": "comfort"
},
{
"id": "596817675",
"therm_setpoint_fp": "comfort"
},
{
"id": "3795659199",
"therm_setpoint_fp": "comfort"
},
{
"id": "927970817",
"therm_setpoint_fp": "comfort"
},
{
"id": "1641945290",
"therm_setpoint_fp": "comfort"
},
{
"id": "2102454491",
"therm_setpoint_fp": "comfort"
}
]
},
{
"name": "Night",
"id": 1,
"type": 1,
"rooms_temp": [
{
"room_id": "3707962039",
"therm_setpoint_fp": "away"
},
{
"room_id": "2042969726",
"therm_setpoint_fp": "away"
},
{
"room_id": "3497055021",
"therm_setpoint_fp": "away"
},
{
"room_id": "3435163850",
"therm_setpoint_fp": "away"
},
{
"room_id": "873035982",
"therm_setpoint_fp": "away"
},
{
"room_id": "1662974901",
"therm_setpoint_fp": "away"
},
{
"room_id": "93888250",
"therm_setpoint_fp": "away"
},
{
"room_id": "596817675",
"therm_setpoint_fp": "away"
},
{
"room_id": "3795659199",
"therm_setpoint_fp": "away"
},
{
"room_id": "927970817",
"therm_setpoint_fp": "away"
},
{
"room_id": "1641945290",
"therm_setpoint_fp": "away"
},
{
"room_id": "2102454491",
"therm_setpoint_fp": "away"
}
],
"modules": [],
"rooms": [
{
"id": "3707962039",
"therm_setpoint_fp": "away"
},
{
"id": "2042969726",
"therm_setpoint_fp": "away"
},
{
"id": "3497055021",
"therm_setpoint_fp": "away"
},
{
"id": "3435163850",
"therm_setpoint_fp": "away"
},
{
"id": "873035982",
"therm_setpoint_fp": "away"
},
{
"id": "1662974901",
"therm_setpoint_fp": "away"
},
{
"id": "93888250",
"therm_setpoint_fp": "away"
},
{
"id": "596817675",
"therm_setpoint_fp": "away"
},
{
"id": "3795659199",
"therm_setpoint_fp": "away"
},
{
"id": "927970817",
"therm_setpoint_fp": "away"
},
{
"id": "1641945290",
"therm_setpoint_fp": "away"
},
{
"id": "2102454491",
"therm_setpoint_fp": "away"
}
]
},
{
"name": "Comfort+",
"id": 3,
"type": 8,
"rooms_temp": [
{
"room_id": "3707962039",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "2042969726",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "3497055021",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "3435163850",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "873035982",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "1662974901",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "93888250",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "596817675",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "3795659199",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "927970817",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "1641945290",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "2102454491",
"therm_setpoint_fp": "comfort"
}
],
"modules": [],
"rooms": [
{
"id": "3707962039",
"therm_setpoint_fp": "comfort"
},
{
"id": "2042969726",
"therm_setpoint_fp": "comfort"
},
{
"id": "3497055021",
"therm_setpoint_fp": "comfort"
},
{
"id": "3435163850",
"therm_setpoint_fp": "comfort"
},
{
"id": "873035982",
"therm_setpoint_fp": "comfort"
},
{
"id": "1662974901",
"therm_setpoint_fp": "comfort"
},
{
"id": "93888250",
"therm_setpoint_fp": "comfort"
},
{
"id": "596817675",
"therm_setpoint_fp": "comfort"
},
{
"id": "3795659199",
"therm_setpoint_fp": "comfort"
},
{
"id": "927970817",
"therm_setpoint_fp": "comfort"
},
{
"id": "1641945290",
"therm_setpoint_fp": "comfort"
},
{
"id": "2102454491",
"therm_setpoint_fp": "comfort"
}
]
},
{
"name": "Eco",
"id": 4,
"type": 5,
"rooms_temp": [
{
"room_id": "3707962039",
"therm_setpoint_fp": "away"
},
{
"room_id": "2042969726",
"therm_setpoint_fp": "away"
},
{
"room_id": "3497055021",
"therm_setpoint_fp": "away"
},
{
"room_id": "3435163850",
"therm_setpoint_fp": "away"
},
{
"room_id": "873035982",
"therm_setpoint_fp": "away"
},
{
"room_id": "1662974901",
"therm_setpoint_fp": "away"
},
{
"room_id": "93888250",
"therm_setpoint_fp": "away"
},
{
"room_id": "596817675",
"therm_setpoint_fp": "away"
},
{
"room_id": "3795659199",
"therm_setpoint_fp": "away"
},
{
"room_id": "927970817",
"therm_setpoint_fp": "away"
},
{
"room_id": "1641945290",
"therm_setpoint_fp": "away"
},
{
"room_id": "2102454491",
"therm_setpoint_fp": "away"
}
],
"modules": [],
"rooms": [
{
"id": "3707962039",
"therm_setpoint_fp": "away"
},
{
"id": "2042969726",
"therm_setpoint_fp": "away"
},
{
"id": "3497055021",
"therm_setpoint_fp": "away"
},
{
"id": "3435163850",
"therm_setpoint_fp": "away"
},
{
"id": "873035982",
"therm_setpoint_fp": "away"
},
{
"id": "1662974901",
"therm_setpoint_fp": "away"
},
{
"id": "93888250",
"therm_setpoint_fp": "away"
},
{
"id": "596817675",
"therm_setpoint_fp": "away"
},
{
"id": "3795659199",
"therm_setpoint_fp": "away"
},
{
"id": "927970817",
"therm_setpoint_fp": "away"
},
{
"id": "1641945290",
"therm_setpoint_fp": "away"
},
{
"id": "2102454491",
"therm_setpoint_fp": "away"
}
]
},
{
"name": "SDB seulement",
"id": 2,
"type": 4,
"rooms_temp": [
{
"room_id": "3707962039",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "2042969726",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "3497055021",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "3435163850",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "873035982",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "1662974901",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "93888250",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "596817675",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "3795659199",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "927970817",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "1641945290",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "2102454491",
"therm_setpoint_fp": "frost_guard"
}
],
"modules": [],
"rooms": [
{
"id": "3707962039",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "2042969726",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "3497055021",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "3435163850",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "873035982",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "1662974901",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "93888250",
"therm_setpoint_fp": "comfort"
},
{
"id": "596817675",
"therm_setpoint_fp": "comfort"
},
{
"id": "3795659199",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "927970817",
"therm_setpoint_fp": "comfort"
},
{
"id": "1641945290",
"therm_setpoint_fp": "comfort"
},
{
"id": "2102454491",
"therm_setpoint_fp": "frost_guard"
}
]
},
{
"name": "Tout Off",
"id": 5,
"type": 4,
"rooms_temp": [
{
"room_id": "3707962039",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "2042969726",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "3497055021",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "3435163850",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "873035982",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "1662974901",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "93888250",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "596817675",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "3795659199",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "927970817",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "1641945290",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "2102454491",
"therm_setpoint_fp": "frost_guard"
}
],
"modules": [],
"rooms": [
{
"id": "3707962039",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "2042969726",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "3497055021",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "3435163850",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "873035982",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "1662974901",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "93888250",
"therm_setpoint_fp": "comfort"
},
{
"id": "596817675",
"therm_setpoint_fp": "comfort"
},
{
"id": "3795659199",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "927970817",
"therm_setpoint_fp": "comfort"
},
{
"id": "1641945290",
"therm_setpoint_fp": "comfort"
},
{
"id": "2102454491",
"therm_setpoint_fp": "frost_guard"
}
]
},
{
"name": "Chambres Confort and All Off",
"id": 6,
"type": 4,
"rooms_temp": [
{
"room_id": "1662974901",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "2042969726",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "3435163850",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "3497055021",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "3707962039",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "3795659199",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "596817675",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "873035982",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "93888250",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "927970817",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "1641945290",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "2102454491",
"therm_setpoint_fp": "frost_guard"
}
],
"modules": [],
"rooms": [
{
"id": "1662974901",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "2042969726",
"therm_setpoint_fp": "comfort"
},
{
"id": "3435163850",
"therm_setpoint_fp": "comfort"
},
{
"id": "3497055021",
"therm_setpoint_fp": "comfort"
},
{
"id": "3707962039",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "3795659199",
"therm_setpoint_fp": "comfort"
},
{
"id": "596817675",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "873035982",
"therm_setpoint_fp": "comfort"
},
{
"id": "93888250",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "927970817",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "1641945290",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "2102454491",
"therm_setpoint_fp": "frost_guard"
}
]
},
{
"name": "Chambres Eco and all Off",
"id": 7,
"type": 4,
"rooms_temp": [
{
"room_id": "1662974901",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "2042969726",
"therm_setpoint_fp": "away"
},
{
"room_id": "3435163850",
"therm_setpoint_fp": "away"
},
{
"room_id": "3497055021",
"therm_setpoint_fp": "away"
},
{
"room_id": "3707962039",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "3795659199",
"therm_setpoint_fp": "away"
},
{
"room_id": "596817675",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "873035982",
"therm_setpoint_fp": "away"
},
{
"room_id": "93888250",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "927970817",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "1641945290",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "2102454491",
"therm_setpoint_fp": "comfort"
}
],
"modules": [],
"rooms": [
{
"id": "1662974901",
"therm_setpoint_fp": "comfort"
},
{
"id": "2042969726",
"therm_setpoint_fp": "away"
},
{
"id": "3435163850",
"therm_setpoint_fp": "away"
},
{
"id": "3497055021",
"therm_setpoint_fp": "away"
},
{
"id": "3707962039",
"therm_setpoint_fp": "comfort"
},
{
"id": "3795659199",
"therm_setpoint_fp": "away"
},
{
"id": "596817675",
"therm_setpoint_fp": "comfort"
},
{
"id": "873035982",
"therm_setpoint_fp": "away"
},
{
"id": "93888250",
"therm_setpoint_fp": "comfort"
},
{
"id": "927970817",
"therm_setpoint_fp": "comfort"
},
{
"id": "1641945290",
"therm_setpoint_fp": "comfort"
},
{
"id": "2102454491",
"therm_setpoint_fp": "comfort"
}
]
},
{
"name": "Chambres Eco SDB Confort All OFF",
"id": 8,
"type": 4,
"rooms_temp": [
{
"room_id": "1662974901",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "2042969726",
"therm_setpoint_fp": "away"
},
{
"room_id": "3435163850",
"therm_setpoint_fp": "away"
},
{
"room_id": "3497055021",
"therm_setpoint_fp": "away"
},
{
"room_id": "3707962039",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "3795659199",
"therm_setpoint_fp": "away"
},
{
"room_id": "596817675",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "873035982",
"therm_setpoint_fp": "away"
},
{
"room_id": "93888250",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "927970817",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "1641945290",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "2102454491",
"therm_setpoint_fp": "frost_guard"
}
],
"modules": [],
"rooms": [
{
"id": "1662974901",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "2042969726",
"therm_setpoint_fp": "away"
},
{
"id": "3435163850",
"therm_setpoint_fp": "away"
},
{
"id": "3497055021",
"therm_setpoint_fp": "away"
},
{
"id": "3707962039",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "3795659199",
"therm_setpoint_fp": "away"
},
{
"id": "596817675",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "873035982",
"therm_setpoint_fp": "away"
},
{
"id": "93888250",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "927970817",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "1641945290",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "2102454491",
"therm_setpoint_fp": "frost_guard"
}
]
},
{
"name": "Chambres & SDB Confort All OFF",
"id": 9,
"type": 4,
"rooms_temp": [
{
"room_id": "1662974901",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "2042969726",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "3435163850",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "3497055021",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "3707962039",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "3795659199",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "596817675",
"therm_setpoint_fp": "frost_guard"
},
{
"room_id": "873035982",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "93888250",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "927970817",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "1641945290",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "2102454491",
"therm_setpoint_fp": "frost_guard"
}
],
"modules": [],
"rooms": [
{
"id": "1662974901",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "2042969726",
"therm_setpoint_fp": "comfort"
},
{
"id": "3435163850",
"therm_setpoint_fp": "comfort"
},
{
"id": "3497055021",
"therm_setpoint_fp": "comfort"
},
{
"id": "3707962039",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "3795659199",
"therm_setpoint_fp": "comfort"
},
{
"id": "596817675",
"therm_setpoint_fp": "frost_guard"
},
{
"id": "873035982",
"therm_setpoint_fp": "comfort"
},
{
"id": "93888250",
"therm_setpoint_fp": "comfort"
},
{
"id": "927970817",
"therm_setpoint_fp": "comfort"
},
{
"id": "1641945290",
"therm_setpoint_fp": "comfort"
},
{
"id": "2102454491",
"therm_setpoint_fp": "frost_guard"
}
]
}
],
"name": "SDM seulement",
"default": false,
"away_temp": 12,
"hg_temp": 7,
"id": "65428fdc7349fc4e49034381",
"type": "therm"
},
{
"timetable": [
{
"zone_id": 1,
"m_offset": 300
},
{
"zone_id": 3,
"m_offset": 540
},
{
"zone_id": 2,
"m_offset": 960
},
{
"zone_id": 0,
"m_offset": 1020
},
{
"zone_id": 1,
"m_offset": 1740
},
{
"zone_id": 3,
"m_offset": 1980
},
{
"zone_id": 2,
"m_offset": 2400
},
{
"zone_id": 0,
"m_offset": 2460
},
{
"zone_id": 1,
"m_offset": 3180
},
{
"zone_id": 3,
"m_offset": 3420
},
{
"zone_id": 2,
"m_offset": 3840
},
{
"zone_id": 0,
"m_offset": 3900
},
{
"zone_id": 1,
"m_offset": 4620
},
{
"zone_id": 3,
"m_offset": 4860
},
{
"zone_id": 2,
"m_offset": 5280
},
{
"zone_id": 0,
"m_offset": 5340
},
{
"zone_id": 1,
"m_offset": 6060
},
{
"zone_id": 3,
"m_offset": 6300
},
{
"zone_id": 2,
"m_offset": 6720
},
{
"zone_id": 0,
"m_offset": 6780
},
{
"zone_id": 1,
"m_offset": 7500
},
{
"zone_id": 3,
"m_offset": 7740
},
{
"zone_id": 2,
"m_offset": 8160
},
{
"zone_id": 0,
"m_offset": 8220
},
{
"zone_id": 1,
"m_offset": 8940
},
{
"zone_id": 3,
"m_offset": 9180
},
{
"zone_id": 2,
"m_offset": 9600
},
{
"zone_id": 0,
"m_offset": 9660
}
],
"zones": [
{
"id": 0,
"modules": [
{
"id": "98:76:54:32:10:00:00:67",
"bridge": "aa:aa:aa:aa:aa:aa",
"on": false
}
]
},
{
"id": 1,
"modules": [
{
"id": "98:76:54:32:10:00:00:67",
"bridge": "aa:aa:aa:aa:aa:aa",
"on": true
}
]
},
{
"id": 2,
"modules": [
{
"id": "98:76:54:32:10:00:00:67",
"bridge": "aa:aa:aa:aa:aa:aa",
"on": true
}
]
},
{
"id": 3,
"modules": [
{
"id": "98:76:54:32:10:00:00:67",
"bridge": "aa:aa:aa:aa:aa:aa",
"on": false
}
]
}
],
"name": "Planning d'actions",
"default": false,
"timetable_sunrise": [],
"timetable_sunset": [],
"id": "64fa4a1266404bbb130f4b71",
"type": "event",
"selected": true
},
{
"timetable": [],
"zones": [],
"name": "Hiver",
"default": false,
"timetable_sunrise": [],
"timetable_sunset": [],
"id": "65c3f82f61e0a3ec5401640f",
"type": "event"
},
{
"timetable": [
{
"zone_id": 0,
"m_offset": 0
},
{
"zone_id": 1,
"m_offset": 130
},
{
"zone_id": 0,
"m_offset": 430
},
{
"zone_id": 1,
"m_offset": 850
},
{
"zone_id": 0,
"m_offset": 1030
},
{
"zone_id": 1,
"m_offset": 1570
},
{
"zone_id": 0,
"m_offset": 1870
},
{
"zone_id": 1,
"m_offset": 2290
},
{
"zone_id": 0,
"m_offset": 2470
},
{
"zone_id": 1,
"m_offset": 3010
},
{
"zone_id": 0,
"m_offset": 3310
},
{
"zone_id": 1,
"m_offset": 3730
},
{
"zone_id": 0,
"m_offset": 3910
},
{
"zone_id": 1,
"m_offset": 4450
},
{
"zone_id": 0,
"m_offset": 4750
},
{
"zone_id": 1,
"m_offset": 5170
},
{
"zone_id": 0,
"m_offset": 5350
},
{
"zone_id": 1,
"m_offset": 5890
},
{
"zone_id": 0,
"m_offset": 6190
},
{
"zone_id": 1,
"m_offset": 6610
},
{
"zone_id": 0,
"m_offset": 6790
},
{
"zone_id": 1,
"m_offset": 7330
},
{
"zone_id": 0,
"m_offset": 7630
},
{
"zone_id": 1,
"m_offset": 8050
},
{
"zone_id": 0,
"m_offset": 8230
},
{
"zone_id": 1,
"m_offset": 8770
},
{
"zone_id": 0,
"m_offset": 9070
},
{
"zone_id": 1,
"m_offset": 9490
},
{
"zone_id": 0,
"m_offset": 9670
}
],
"zones": [
{
"id": 0,
"price": 0.27,
"price_type": "peak"
},
{
"id": 1,
"price": 0.2068,
"price_type": "off_peak"
}
],
"name": "electricity",
"default": false,
"tariff": "edf_tarif_bleu",
"tariff_option": "peak_and_off_peak",
"power_threshold": 36,
"contract_power_unit": "kW",
"id": "60ce3d057a24d640444c4f1c",
"type": "electricity",
"selected": true
}
]
},
{
"id": "eeeeeeeeeffffffffffaaaaa",
"name": "A SECOND HOME",
"altitude": 200,
"coordinates": [
34.345576,
89.667112
],
"country": "FR",
"timezone": "Europe/Paris",
"rooms": [
{
"id": "1468717414",
"name": "Cave",
"type": "garage",
"module_ids": [
"12:34:56:78:90:00:00:09",
"12:34:56:78:90:00:00:20",
"12:34:56:78:90:00:00:33"
]
},
{
"id": "738709350",
"name": "Salon",
"type": "livingroom",
"module_ids": [
"bb:bb:bb:bb:bb:bb",
"12:34:56:78:90:00:00:01",
"12:34:56:78:90:00:00:02",
"12:34:56:78:90:00:00:03",
"12:34:56:78:90:00:00:04",
"12:34:56:78:90:00:00:05",
"12:34:56:78:90:00:00:06",
"12:34:56:78:90:00:00:07",
"12:34:56:78:90:00:00:08",
"12:34:56:78:90:00:00:10",
"12:34:56:78:90:00:00:23",
"12:34:56:78:90:00:00:24",
"12:34:56:78:90:00:00:29",
"12:34:56:78:90:00:00:30"
]
},
{
"id": "3098890768",
"name": "Entrée",
"type": "lobby",
"module_ids": [
"12:34:56:78:90:00:00:11"
]
},
{
"id": "70754041",
"name": "Salle de bains",
"type": "bathroom",
"module_ids": [
"12:34:56:78:90:00:00:12",
"12:34:56:78:90:00:00:26"
]
},
{
"id": "1761556353",
"name": "Nouveaux toilettes",
"type": "toilets",
"module_ids": [
"12:34:56:78:90:00:00:13"
]
},
{
"id": "968846272",
"name": "Anciens Toilettes",
"type": "toilets",
"module_ids": [
"12:34:56:78:90:00:00:14"
]
},
{
"id": "4008422910",
"name": "Palier",
"type": "corridor",
"module_ids": [
"12:34:56:78:90:00:00:15",
"12:34:56:78:90:00:00:18",
"12:34:56:78:90:00:00:31"
]
},
{
"id": "2640531479",
"name": "Chambre parents",
"type": "bedroom",
"module_ids": [
"12:34:56:78:90:00:00:16",
"12:34:56:78:90:00:00:27"
]
},
{
"id": "2667868658",
"name": "Chambre Older",
"type": "bedroom",
"module_ids": [
"12:34:56:78:90:00:00:17",
"12:34:56:78:90:00:00:22"
]
},
{
"id": "3783425301",
"name": "Chambre Enfants",
"type": "bedroom",
"module_ids": [
"12:34:56:78:90:00:00:19",
"12:34:56:78:90:00:00:28"
]
},
{
"id": "68319658",
"name": "Chambre Old",
"type": "bedroom",
"module_ids": [
"12:34:56:78:90:00:00:25"
]
},
{
"id": "1156588698",
"name": "Jardin",
"type": "outdoor",
"module_ids": [
"12:34:56:78:90:00:00:21"
]
},
{
"id": "1229033409",
"name": "Grenier",
"type": "custom",
"module_ids": [
"12:34:56:78:90:00:00:32",
"12:34:56:78:90:00:00:34"
]
}
],
"modules": [
{
"id": "bb:bb:bb:bb:bb:bb",
"type": "NLG",
"name": "Legrand Gateway",
"setup_date": 1692558574,
"room_id": "738709350",
"modules_bridged": [
"12:34:56:78:90:00:00:01",
"12:34:56:78:90:00:00:02",
"12:34:56:78:90:00:00:03",
"12:34:56:78:90:00:00:04",
"12:34:56:78:90:00:00:05",
"12:34:56:78:90:00:00:06",
"12:34:56:78:90:00:00:07",
"12:34:56:78:90:00:00:08",
"12:34:56:78:90:00:00:09",
"12:34:56:78:90:00:00:10",
"12:34:56:78:90:00:00:11",
"12:34:56:78:90:00:00:12",
"12:34:56:78:90:00:00:13",
"12:34:56:78:90:00:00:14",
"12:34:56:78:90:00:00:15",
"12:34:56:78:90:00:00:16",
"12:34:56:78:90:00:00:17",
"12:34:56:78:90:00:00:18",
"12:34:56:78:90:00:00:19",
"12:34:56:78:90:00:00:20",
"12:34:56:78:90:00:00:21",
"12:34:56:78:90:00:00:22",
"12:34:56:78:90:00:00:23",
"12:34:56:78:90:00:00:24",
"12:34:56:78:90:00:00:25",
"12:34:56:78:90:00:00:26",
"12:34:56:78:90:00:00:27",
"12:34:56:78:90:00:00:28",
"12:34:56:78:90:00:00:29",
"12:34:56:78:90:00:00:30",
"12:34:56:78:90:00:00:31",
"12:34:56:78:90:00:00:32",
"12:34:56:78:90:00:00:33",
"12:34:56:78:90:00:00:34"
]
},
{
"id": "12:34:56:78:90:00:00:01",
"type": "NLAO",
"name": "Commande On/Off (Sans-Fil, Sans Pile) 1",
"setup_date": 1692558628,
"room_id": "738709350",
"bridge": "bb:bb:bb:bb:bb:bb"
},
{
"id": "12:34:56:78:90:00:00:02",
"type": "NLAO",
"name": "Commande On/Off (Sans-Fil, Sans Pile) 2",
"setup_date": 1692558628,
"room_id": "738709350",
"bridge": "bb:bb:bb:bb:bb:bb"
},
{
"id": "12:34:56:78:90:00:00:03",
"type": "NLAO",
"name": "Commande On/Off (Sans-Fil, Sans Pile) 3",
"setup_date": 1692558628,
"room_id": "738709350",
"bridge": "bb:bb:bb:bb:bb:bb"
},
{
"id": "12:34:56:78:90:00:00:04",
"type": "NLAO",
"name": "Commande On/Off (Sans-Fil, Sans Pile) 4",
"setup_date": 1692558628,
"room_id": "738709350",
"bridge": "bb:bb:bb:bb:bb:bb"
},
{
"id": "12:34:56:78:90:00:00:05",
"type": "NLAO",
"name": "Commande On/Off (Sans-Fil, Sans Pile) 5",
"setup_date": 1692558628,
"room_id": "738709350",
"bridge": "bb:bb:bb:bb:bb:bb"
},
{
"id": "12:34:56:78:90:00:00:06",
"type": "NLAO",
"name": "Commande On/Off (Sans-Fil, Sans Pile) 6",
"setup_date": 1692558628,
"room_id": "738709350",
"bridge": "bb:bb:bb:bb:bb:bb"
},
{
"id": "12:34:56:78:90:00:00:07",
"type": "NLAO",
"name": "Commande On/Off (Sans-Fil, Sans Pile) 7",
"setup_date": 1692558628,
"room_id": "738709350",
"bridge": "bb:bb:bb:bb:bb:bb"
},
{
"id": "12:34:56:78:90:00:00:08",
"type": "NLAO",
"name": "Commande On/Off (Sans-Fil, Sans Pile) 8",
"setup_date": 1692558628,
"room_id": "738709350",
"bridge": "bb:bb:bb:bb:bb:bb"
},
{
"id": "12:34:56:78:90:00:00:09",
"type": "NLPO",
"name": "OL Cumulus",
"setup_date": 1692558628,
"room_id": "1468717414",
"bridge": "bb:bb:bb:bb:bb:bb",
"appliance_type": "water_heater"
},
{
"id": "12:34:56:78:90:00:00:10",
"type": "NLPT",
"name": "OL Lumière Cuisine",
"setup_date": 1692558628,
"room_id": "738709350",
"bridge": "bb:bb:bb:bb:bb:bb"
},
{
"id": "12:34:56:78:90:00:00:11",
"type": "NLPT",
"name": "OL Escalier",
"setup_date": 1692558628,
"room_id": "3098890768",
"bridge": "bb:bb:bb:bb:bb:bb"
},
{
"id": "12:34:56:78:90:00:00:12",
"type": "NLPT",
"name": "OL Éclairage Salle de bain",
"setup_date": 1692558628,
"room_id": "70754041",
"bridge": "bb:bb:bb:bb:bb:bb"
},
{
"id": "12:34:56:78:90:00:00:13",
"type": "NLPT",
"name": "OL Lumière nouveaux toilettes",
"setup_date": 1692558628,
"room_id": "1761556353",
"bridge": "bb:bb:bb:bb:bb:bb"
},
{
"id": "12:34:56:78:90:00:00:14",
"type": "NLPT",
"name": "OL Lumière anciens toilettes",
"setup_date": 1692558628,
"room_id": "968846272",
"bridge": "bb:bb:bb:bb:bb:bb"
},
{
"id": "12:34:56:78:90:00:00:15",
"type": "NLPT",
"name": "OL Lumière palier salle de bain",
"setup_date": 1692558628,
"room_id": "4008422910",
"bridge": "bb:bb:bb:bb:bb:bb"
},
{
"id": "12:34:56:78:90:00:00:16",
"type": "NLPT",
"name": "OL Lumière chambre A",
"setup_date": 1692558628,
"room_id": "2640531479",
"bridge": "bb:bb:bb:bb:bb:bb"
},
{
"id": "12:34:56:78:90:00:00:17",
"type": "NLPT",
"name": "OL Lumière Chambre Older",
"setup_date": 1692558628,
"room_id": "2667868658",
"bridge": "bb:bb:bb:bb:bb:bb"
},
{
"id": "12:34:56:78:90:00:00:18",
"type": "NLPT",
"name": "OL Lumière Palier",
"setup_date": 1692558628,
"room_id": "4008422910",
"bridge": "bb:bb:bb:bb:bb:bb"
},
{
"id": "12:34:56:78:90:00:00:19",
"type": "NLPT",
"name": "OL Lumière enfants",
"setup_date": 1692558628,
"room_id": "3783425301",
"bridge": "bb:bb:bb:bb:bb:bb"
},
{
"id": "12:34:56:78:90:00:00:20",
"type": "NLM",
"name": "OL Lumière Cave",
"setup_date": 1692643741,
"room_id": "1468717414",
"bridge": "bb:bb:bb:bb:bb:bb"
},
{
"id": "12:34:56:78:90:00:00:21",
"type": "NLM",
"name": "OL Lumière Jardin",
"setup_date": 1692643763,
"room_id": "1156588698",
"bridge": "bb:bb:bb:bb:bb:bb"
},
{
"id": "12:34:56:78:90:00:00:22",
"type": "NLC",
"name": "OL Radiateur Chambre Older",
"setup_date": 1692644489,
"room_id": "2667868658",
"bridge": "bb:bb:bb:bb:bb:bb",
"appliance_type": "radiator"
},
{
"id": "12:34:56:78:90:00:00:23",
"type": "NLC",
"name": "OL Radiateur Salon Fenêtre",
"setup_date": 1692644493,
"room_id": "738709350",
"bridge": "bb:bb:bb:bb:bb:bb",
"appliance_type": "radiator"
},
{
"id": "12:34:56:78:90:00:00:24",
"type": "NLC",
"name": "OL Radiateur Salon Porte",
"setup_date": 1692644497,
"room_id": "738709350",
"bridge": "bb:bb:bb:bb:bb:bb",
"appliance_type": "radiator"
},
{
"id": "12:34:56:78:90:00:00:25",
"type": "NLC",
"name": "OL Radiateur Chambre Old",
"setup_date": 1692644501,
"room_id": "68319658",
"bridge": "bb:bb:bb:bb:bb:bb",
"appliance_type": "radiator"
},
{
"id": "12:34:56:78:90:00:00:26",
"type": "NLC",
"name": "OL Radiateur Serviette",
"setup_date": 1692644506,
"room_id": "70754041",
"bridge": "bb:bb:bb:bb:bb:bb",
"appliance_type": "radiator"
},
{
"id": "12:34:56:78:90:00:00:27",
"type": "NLC",
"name": "OL Radiateur Chambre A",
"setup_date": 1692644509,
"room_id": "2640531479",
"bridge": "bb:bb:bb:bb:bb:bb",
"appliance_type": "radiator"
},
{
"id": "12:34:56:78:90:00:00:28",
"type": "NLC",
"name": "OL Radiateur Chambre E",
"setup_date": 1693159267,
"room_id": "3783425301",
"bridge": "bb:bb:bb:bb:bb:bb",
"appliance_type": "radiator"
},
{
"id": "12:34:56:78:90:00:00:29",
"type": "NLPT",
"name": "OL Salle à manger",
"setup_date": 1696921179,
"room_id": "738709350",
"bridge": "bb:bb:bb:bb:bb:bb"
},
{
"id": "12:34:56:78:90:00:00:30",
"type": "NLPT",
"name": "OL Plan de travail",
"setup_date": 1696921199,
"room_id": "738709350",
"bridge": "bb:bb:bb:bb:bb:bb"
},
{
"id": "12:34:56:78:90:00:00:31",
"type": "NLAO",
"name": "Commande On/Off (Sans-Fil, Sans Pile) 9",
"setup_date": 1696922170,
"room_id": "4008422910",
"bridge": "bb:bb:bb:bb:bb:bb"
},
{
"id": "12:34:56:78:90:00:00:32",
"type": "NLPT",
"name": "OL Lumière Grenier",
"setup_date": 1696949709,
"room_id": "1229033409",
"bridge": "bb:bb:bb:bb:bb:bb"
},
{
"id": "12:34:56:78:90:00:00:33",
"type": "NLAO",
"name": "Commande Cave",
"setup_date": 1696949890,
"room_id": "1468717414",
"bridge": "bb:bb:bb:bb:bb:bb"
},
{
"id": "12:34:56:78:90:00:00:34",
"type": "NLAO",
"name": "Commande Grenier",
"setup_date": 1696951661,
"room_id": "1229033409",
"bridge": "bb:bb:bb:bb:bb:bb"
}
],
"temperature_control_mode": "heating",
"therm_mode": "hg",
"therm_setpoint_default_duration": 180,
"schedules": [
{
"timetable": [
{
"zone_id": 1,
"m_offset": 0
},
{
"zone_id": 0,
"m_offset": 420
},
{
"zone_id": 4,
"m_offset": 480
},
{
"zone_id": 0,
"m_offset": 1140
},
{
"zone_id": 1,
"m_offset": 1320
},
{
"zone_id": 0,
"m_offset": 1860
},
{
"zone_id": 4,
"m_offset": 1920
},
{
"zone_id": 0,
"m_offset": 2580
},
{
"zone_id": 1,
"m_offset": 2760
},
{
"zone_id": 0,
"m_offset": 3300
},
{
"zone_id": 4,
"m_offset": 3360
},
{
"zone_id": 0,
"m_offset": 4020
},
{
"zone_id": 1,
"m_offset": 4200
},
{
"zone_id": 0,
"m_offset": 4740
},
{
"zone_id": 4,
"m_offset": 4800
},
{
"zone_id": 0,
"m_offset": 5460
},
{
"zone_id": 1,
"m_offset": 5640
},
{
"zone_id": 0,
"m_offset": 6180
},
{
"zone_id": 4,
"m_offset": 6240
},
{
"zone_id": 0,
"m_offset": 6900
},
{
"zone_id": 1,
"m_offset": 7080
},
{
"zone_id": 0,
"m_offset": 7620
},
{
"zone_id": 4,
"m_offset": 7800
},
{
"zone_id": 0,
"m_offset": 8220
},
{
"zone_id": 1,
"m_offset": 8520
},
{
"zone_id": 0,
"m_offset": 9060
},
{
"zone_id": 4,
"m_offset": 9240
},
{
"zone_id": 0,
"m_offset": 9660
},
{
"zone_id": 1,
"m_offset": 9960
}
],
"zones": [
{
"name": "Comfort",
"id": 0,
"type": 0,
"rooms_temp": [
{
"room_id": "738709350",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "70754041",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "2640531479",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "2667868658",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "3783425301",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "68319658",
"therm_setpoint_fp": "comfort"
}
],
"modules": [],
"rooms": [
{
"id": "738709350",
"therm_setpoint_fp": "comfort"
},
{
"id": "70754041",
"therm_setpoint_fp": "comfort"
},
{
"id": "2640531479",
"therm_setpoint_fp": "comfort"
},
{
"id": "2667868658",
"therm_setpoint_fp": "comfort"
},
{
"id": "3783425301",
"therm_setpoint_fp": "comfort"
},
{
"id": "68319658",
"therm_setpoint_fp": "comfort"
}
]
},
{
"name": "Night",
"id": 1,
"type": 1,
"rooms_temp": [
{
"room_id": "738709350",
"therm_setpoint_fp": "away"
},
{
"room_id": "70754041",
"therm_setpoint_fp": "away"
},
{
"room_id": "2640531479",
"therm_setpoint_fp": "away"
},
{
"room_id": "2667868658",
"therm_setpoint_fp": "away"
},
{
"room_id": "3783425301",
"therm_setpoint_fp": "away"
},
{
"room_id": "68319658",
"therm_setpoint_fp": "away"
}
],
"modules": [],
"rooms": [
{
"id": "738709350",
"therm_setpoint_fp": "away"
},
{
"id": "70754041",
"therm_setpoint_fp": "away"
},
{
"id": "2640531479",
"therm_setpoint_fp": "away"
},
{
"id": "2667868658",
"therm_setpoint_fp": "away"
},
{
"id": "3783425301",
"therm_setpoint_fp": "away"
},
{
"id": "68319658",
"therm_setpoint_fp": "away"
}
]
},
{
"name": "Comfort+",
"id": 3,
"type": 8,
"rooms_temp": [
{
"room_id": "738709350",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "70754041",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "2640531479",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "2667868658",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "3783425301",
"therm_setpoint_fp": "comfort"
},
{
"room_id": "68319658",
"therm_setpoint_fp": "comfort"
}
],
"modules": [],
"rooms": [
{
"id": "738709350",
"therm_setpoint_fp": "comfort"
},
{
"id": "70754041",
"therm_setpoint_fp": "comfort"
},
{
"id": "2640531479",
"therm_setpoint_fp": "comfort"
},
{
"id": "2667868658",
"therm_setpoint_fp": "comfort"
},
{
"id": "3783425301",
"therm_setpoint_fp": "comfort"
},
{
"id": "68319658",
"therm_setpoint_fp": "comfort"
}
]
},
{
"name": "Eco",
"id": 4,
"type": 5,
"rooms_temp": [
{
"room_id": "738709350",
"therm_setpoint_fp": "away"
},
{
"room_id": "70754041",
"therm_setpoint_fp": "away"
},
{
"room_id": "2640531479",
"therm_setpoint_fp": "away"
},
{
"room_id": "2667868658",
"therm_setpoint_fp": "away"
},
{
"room_id": "3783425301",
"therm_setpoint_fp": "away"
},
{
"room_id": "68319658",
"therm_setpoint_fp": "away"
}
],
"modules": [],
"rooms": [
{
"id": "738709350",
"therm_setpoint_fp": "away"
},
{
"id": "70754041",
"therm_setpoint_fp": "away"
},
{
"id": "2640531479",
"therm_setpoint_fp": "away"
},
{
"id": "2667868658",
"therm_setpoint_fp": "away"
},
{
"id": "3783425301",
"therm_setpoint_fp": "away"
},
{
"id": "68319658",
"therm_setpoint_fp": "away"
}
]
}
],
"name": "Mon planning de chauffe",
"default": false,
"away_temp": 12,
"hg_temp": 7,
"id": "64e3b6102853d9405304b27a",
"type": "therm",
"selected": true
},
{
"timetable": [],
"zones": [],
"name": "Planning d'actions",
"default": false,
"timetable_sunrise": [],
"timetable_sunset": [],
"id": "64ee68e2c8419b37790c5050",
"type": "event",
"selected": true
},
{
"timetable": [
{
"zone_id": 0,
"m_offset": 0
}
],
"zones": [
{
"id": 0,
"price": 0.2516,
"price_type": "basic"
}
],
"name": "electricity",
"default": false,
"tariff": "edf_tarif_bleu",
"tariff_option": "basic",
"power_threshold": 9,
"contract_power_unit": "kVA",
"id": "64e28390bc6d555f2d05c684",
"type": "electricity",
"selected": true
}
]
}
],
"user": {
"email": "john.doe@doe.com",
"language": "fr-FR",
"locale": "fr-FR",
"feel_like_algorithm": 0,
"unit_pressure": 0,
"unit_system": 0,
"unit_wind": 0,
"id": "111111111112222222333333"
}
},
"status": "ok",
"time_exec": 0.07427000999450684,
"time_server": 1709762264
} pyatmo-9.2.1/fixtures/homestatus_91763b24c43d3e344f424e8b.json 0000664 0000000 0000000 00000035615 15017405234 0023230 0 ustar 00root root 0000000 0000000 {
"status": "ok",
"time_server": 1559292039,
"body": {
"home": {
"modules": [
{
"id": "12:34:56:80:bb:26",
"type": "NAMain",
"firmware_revision": 202,
"wifi_state": "full",
"wifi_strength": 45,
"ts": 1702884705,
"temperature": 18.9,
"co2": 498,
"humidity": 33,
"noise": 47,
"pressure": 1034.8,
"absolute_pressure": 956.1
},
{
"id": "12:34:56:80:1c:42",
"type": "NAModule1",
"battery_state": "full",
"battery_level": 6690,
"firmware_revision": 53,
"rf_state": "full",
"rf_strength": 42,
"last_seen": 1702884800,
"reachable": true,
"bridge": "70:ee:50:37:11:ca",
"ts": 1702884697,
"temperature": 5.8,
"humidity": 65
},
{
"id": "12:34:56:00:f1:62",
"type": "NACamera",
"monitoring": "on",
"sd_status": 4,
"alim_status": 2,
"locked": false,
"vpn_url": "https://prodvpn-eu-2.netatmo.net/restricted/10.255.123.45/609e27de5699fb18147ab47d06846631/MTRPn_BeWCav5RBq4U1OMDruTW4dkQ0NuMwNDAw11g,,",
"is_local": true
},
{
"id": "12:34:56:00:f1:63",
"type": "NPC",
"monitoring": "on",
"sd_status": 4,
"alim_status": 2,
"locked": false,
"vpn_url": "https://prodvpn-eu-2.netatmo.net/restricted/10.255.123.45/9fb1814609e27de5697ab47d06846631/MTRPn_BeWCav5RBq4U1OMDruTW4dkQ0NuMwNDAw11g,,",
"is_local": true
},
{
"id": "12:34:56:00:fa:d0",
"type": "NAPlug",
"firmware_revision": 174,
"rf_strength": 107,
"wifi_strength": 42
},
{
"id": "12:34:56:00:01:ae",
"reachable": true,
"type": "NATherm1",
"firmware_revision": 65,
"rf_strength": 58,
"battery_level": 3793,
"boiler_valve_comfort_boost": false,
"boiler_status": false,
"anticipating": false,
"bridge": "12:34:56:00:fa:d0",
"battery_state": "high"
},
{
"id": "12:34:56:03:a5:54",
"reachable": true,
"type": "NRV",
"firmware_revision": 79,
"rf_strength": 51,
"battery_level": 3025,
"bridge": "12:34:56:00:fa:d0",
"battery_state": "full"
},
{
"id": "12:34:56:03:a0:ac",
"reachable": true,
"type": "NRV",
"firmware_revision": 79,
"rf_strength": 59,
"battery_level": 3029,
"bridge": "12:34:56:00:fa:d0",
"battery_state": "full"
},
{
"type": "NDB",
"last_ftp_event": {
"type": 3,
"time": 1631444443,
"id": 3
},
"id": "12:34:56:10:f1:66",
"websocket_connected": true,
"vpn_url": "https://prodvpn-eu-6.netatmo.net/10.20.30.40/1111111111111/2222222222222,,",
"is_local": false,
"alim_status": 2,
"connection": "wifi",
"firmware_name": "2.18.0",
"firmware_revision": 2018000,
"homekit_status": "configured",
"max_peers_reached": false,
"sd_status": 4,
"wifi_strength": 66,
"wifi_state": "medium"
},
{
"type": "NOC",
"firmware_revision": 3002000,
"monitoring": "on",
"sd_status": 4,
"connection": "wifi",
"homekit_status": "upgradable",
"floodlight": "auto",
"timelapse_available": true,
"id": "12:34:56:10:b9:0e",
"vpn_url": "https://prodvpn-eu-6.netatmo.net/10.20.30.41/333333333333/444444444444,,",
"is_local": false,
"network_lock": false,
"firmware_name": "3.2.0",
"wifi_strength": 62,
"alim_status": 2,
"locked": false,
"wifi_state": "high"
},
{
"boiler_control": "onoff",
"dhw_control": "none",
"firmware_revision": 22,
"hardware_version": 222,
"id": "12:34:56:20:f5:44",
"outdoor_temperature": 8.2,
"sequence_id": 19764,
"type": "OTH",
"wifi_strength": 57
},
{
"battery_level": 4176,
"boiler_status": false,
"boiler_valve_comfort_boost": false,
"firmware_revision": 6,
"id": "12:34:56:20:f5:8c",
"last_message": 1637684297,
"last_seen": 1637684297,
"radio_id": 2,
"reachable": true,
"rf_strength": 64,
"type": "OTM",
"bridge": "12:34:56:20:f5:44",
"battery_state": "full"
},
{
"id": "12:34:56:30:d5:d4",
"type": "NBG",
"firmware_revision": 39,
"wifi_strength": 65,
"reachable": true
},
{
"id": "0009999992",
"type": "NBR",
"current_position": 0,
"target_position": 0,
"target_position_step": 100,
"firmware_revision": 16,
"rf_strength": 0,
"last_seen": 1638353156,
"reachable": true,
"bridge": "12:34:56:30:d5:d4"
},
{
"id": "0009999993",
"type": "NBO",
"current_position": 0,
"target_position": 0,
"target_position:step": 100,
"firmware_revision": 22,
"rf_strength": 0,
"last_seen": 1671395511,
"reachable": true,
"bridge": "12:34:56:30:d5:d4"
},
{
"id": "12:34:56:00:86:99",
"type": "NACamDoorTag",
"battery_state": "high",
"battery_level": 5240,
"firmware_revision": 58,
"rf_state": "full",
"rf_strength": 58,
"last_seen": 1642698124,
"last_activity": 1627757310,
"reachable": false,
"bridge": "12:34:56:00:f1:62",
"status": "no_news"
},
{
"id": "12:34:56:00:e3:9b",
"type": "NIS",
"battery_state": "low",
"battery_level": 5438,
"firmware_revision": 209,
"rf_state": "medium",
"rf_strength": 62,
"last_seen": 1644569790,
"reachable": true,
"bridge": "12:34:56:00:f1:62",
"status": "no_sound",
"monitoring": "off"
},
{
"id": "12:34:56:80:60:40",
"type": "NLG",
"offload": false,
"firmware_revision": 211,
"last_seen": 1644567372,
"wifi_strength": 51,
"reachable": true
},
{
"id": "12:34:56:80:00:12:ac:f2",
"type": "NLP",
"on": true,
"offload": false,
"firmware_revision": 62,
"last_seen": 1644569425,
"power": 0,
"reachable": true,
"bridge": "12:34:56:80:60:40"
},
{
"id": "12:34:56:80:00:c3:69:3c",
"type": "NLT",
"battery_state": "full",
"battery_level": 3300,
"firmware_revision": 42,
"last_seen": 0,
"reachable": false,
"bridge": "12:34:56:80:60:40"
},
{
"id": "12:34:56:80:00:c3:69:3e",
"type": "NLD",
"battery_state": "medium",
"battery_level": 2500,
"firmware_revision": 56,
"last_seen": 0,
"reachable": true,
"bridge": "12:34:56:80:60:40"
},
{
"id": "12:34:56:80:00:c3:69:3d",
"type": "Z3V",
"current_position": 0,
"target_position": 0,
"target_position_step": 100,
"firmware_revision": 16,
"last_seen": 1638353156,
"reachable": true,
"bridge": "12:34:56:80:60:40"
},
{
"id": "12:34:56:00:16:0e",
"type": "NLE",
"firmware_revision": 14,
"wifi_strength": 38
},
{
"id": "12:34:56:00:16:0e#0",
"type": "NLE",
"bridge": "12:34:56:00:16:0e"
},
{
"id": "12:34:56:00:16:0e#1",
"type": "NLE",
"bridge": "12:34:56:00:16:0e"
},
{
"id": "12:34:56:00:16:0e#2",
"type": "NLE",
"bridge": "12:34:56:00:16:0e"
},
{
"id": "12:34:56:00:16:0e#3",
"type": "NLE",
"bridge": "12:34:56:00:16:0e"
},
{
"id": "12:34:56:00:16:0e#4",
"type": "NLE",
"bridge": "12:34:56:00:16:0e"
},
{
"id": "12:34:56:00:16:0e#5",
"type": "NLE",
"bridge": "12:34:56:00:16:0e"
},
{
"id": "12:34:56:00:16:0e#6",
"type": "NLE",
"bridge": "12:34:56:00:16:0e"
},
{
"id": "12:34:56:00:16:0e#7",
"type": "NLE",
"bridge": "12:34:56:00:16:0e"
},
{
"id": "12:34:56:00:16:0e#8",
"type": "NLE",
"bridge": "12:34:56:00:16:0e"
},
{
"id": "12:34:56:00:00:a1:4c:da",
"type": "NLPC",
"firmware_revision": 62,
"last_seen": 1646511241,
"power": 476,
"reachable": true,
"bridge": "12:34:56:80:60:40"
},
{
"id": "10:20:30:bd:b8:1e",
"type": "BNS",
"firmware_revision": 32,
"wifi_strength": 49,
"boiler_valve_comfort_boost": false,
"boiler_status": true,
"cooler_status": false
},
{
"id": "00:11:22:33:00:11:45:fe",
"type": "NLF",
"on": false,
"brightness": 63,
"firmware_revision": 57,
"last_seen": 1657086939,
"power": 0,
"reachable": true,
"bridge": "12:34:56:80:60:40"
},
{
"id": "12:34:56:00:01:01:01:b1",
"type": "NLLF",
"firmware_revision": 60,
"last_seen": 1657086949,
"power": 11,
"reachable": true,
"bridge": "12:34:56:80:60:40",
"fan_speed": 1
},
{
"firmware_revision": 53,
"id": "12:34:56:00:01:01:01:b2",
"last_seen": 1657086949,
"on": false,
"power": 0,
"reachable": true,
"type": "NLL",
"bridge": "12:34:56:80:60:40"
},
{
"current_position": 0,
"firmware_revision": 47,
"id": "12:34:56:00:01:01:01:b3",
"last_seen": 1746730909,
"reachable": true,
"target_position": 0,
"target_position:step": 100,
"type": "NLV",
"bridge": "12:34:56:80:60:40"
},
{
"current_position": 0,
"firmware_revision": 53,
"id": "12:34:56:00:01:01:01:b4",
"last_seen": 1746730664,
"reachable": true,
"target_position": 10,
"target_position:step": 1,
"type": "NLLV",
"bridge": "12:34:56:80:60:40"
},
{
"id": "12:34:56:00:01:01:01:b5",
"type": "NLJ",
"target_position": 100,
"target_position:step": 1,
"firmware_revision": 7,
"last_seen": 1746736151,
"reachable": true,
"bridge": "12:34:56:80:60:40"
},
{
"id": "12:34:56:00:01:01:01:b6",
"type": "NLIS",
"firmware_revision": 20,
"last_seen": 1746731520,
"reachable": true,
"bridge": "12:34:56:80:60:40"
},
{
"id": "12:34:56:00:01:01:01:b6#2",
"type": "NLIS",
"on": false,
"power": 0,
"bridge": "12:34:56:80:60:40"
},
{
"id": "12:34:56:00:01:01:01:b6#1",
"type": "NLIS",
"on": false,
"power": 0,
"bridge": "12:34:56:80:60:40"
},
{
"id": "12:34:56:00:01:01:01:b7",
"type": "NLPT",
"on": true,
"firmware_revision": 77,
"last_seen": 1746731885,
"power": 0,
"reachable": true,
"bridge": "12:34:56:80:60:40"
},
{
"id": "12:34:56:00:01:01:01:b8",
"type": "NLPD",
"on": true,
"offload": false,
"firmware_revision": 66,
"last_seen": 1746731949,
"power": 0,
"reachable": true,
"bridge": "12:34:56:80:60:40"
},
{
"id": "12:34:56:00:01:01:01:b9",
"type": "NLPO",
"on": false,
"contactor_mode": "off",
"offload": false,
"firmware_revision": 74,
"last_seen": 1746731968,
"power": 0,
"reachable": true,
"bridge": "12:34:56:80:60:40"
}
],
"rooms": [
{
"id": "2746182631",
"reachable": true,
"therm_measured_temperature": 19.8,
"therm_setpoint_temperature": 12,
"therm_setpoint_mode": "away",
"therm_setpoint_start_time": 1559229567,
"therm_setpoint_end_time": 0
},
{
"id": "2940411577",
"reachable": true,
"therm_measured_temperature": 27,
"heating_power_request": 0,
"therm_setpoint_temperature": 7,
"therm_setpoint_mode": "hg",
"therm_setpoint_start_time": 0,
"therm_setpoint_end_time": 0,
"anticipating": false,
"open_window": false
},
{
"id": "2833524037",
"reachable": true,
"therm_measured_temperature": 24.5,
"heating_power_request": 0,
"therm_setpoint_temperature": 7,
"therm_setpoint_mode": "hg",
"therm_setpoint_start_time": 0,
"therm_setpoint_end_time": 0,
"anticipating": false,
"open_window": false
},
{
"id": "1002003001",
"reachable": true,
"anticipating": false,
"heating_power_request": 0,
"open_window": false,
"humidity": 67,
"therm_measured_temperature": 22,
"therm_setpoint_temperature": 22,
"therm_setpoint_start_time": 1647462737,
"therm_setpoint_end_time": null,
"therm_setpoint_mode": "home"
}
],
"id": "91763b24c43d3e344f424e8b",
"persons": [
{
"id": "91827374-7e04-5298-83ad-a0cb8372dff1",
"last_seen": 1557071156,
"out_of_sight": true
},
{
"id": "91827375-7e04-5298-83ae-a0cb8372dff2",
"last_seen": 1559282761,
"out_of_sight": false
},
{
"id": "91827376-7e04-5298-83af-a0cb8372dff3",
"last_seen": 1559224132,
"out_of_sight": true
}
]
}
}
} pyatmo-9.2.1/fixtures/homestatus_91763b24c43d3e344f424e8c.json 0000664 0000000 0000000 00000001006 15017405234 0023214 0 ustar 00root root 0000000 0000000 {
"status": "ok",
"time_server": 1642952130,
"body": {
"home": {
"persons": [
{
"id": "abcdef12-1111-0000-0000-000111222333",
"last_seen": 1489050910,
"out_of_sight": true
},
{
"id": "abcdef12-2222-0000-0000-000111222333",
"last_seen": 1489078776,
"out_of_sight": true
}
]
}
}
} pyatmo-9.2.1/fixtures/ping.json 0000664 0000000 0000000 00000000163 15017405234 0016536 0 ustar 00root root 0000000 0000000 {
"local_url": "http://192.168.0.123/678460a0d47e5618699fb31169e2b47d",
"product_name": "Welcome Netatmo"
} pyatmo-9.2.1/fixtures/status_ok.json 0000664 0000000 0000000 00000000131 15017405234 0017610 0 ustar 00root root 0000000 0000000 {
"status": "ok",
"time_exec": 0.020781993865967,
"time_server": 1559162635
} pyatmo-9.2.1/fixtures/sync_schedule_591b54a2764ff4d50d8b5795.json 0000664 0000000 0000000 00000006133 15017405234 0023672 0 ustar 00root root 0000000 0000000 {
"away_temp": 14,
"hg_temp": 7,
"timetable": [
{
"m_offset": 0,
"zone_id": 1
},
{
"m_offset": 360,
"zone_id": 0
},
{
"m_offset": 420,
"zone_id": 4
},
{
"m_offset": 960,
"zone_id": 0
},
{
"m_offset": 1410,
"zone_id": 1
},
{
"m_offset": 1800,
"zone_id": 0
},
{
"m_offset": 1860,
"zone_id": 4
},
{
"m_offset": 2400,
"zone_id": 0
},
{
"m_offset": 2850,
"zone_id": 1
},
{
"m_offset": 3240,
"zone_id": 0
},
{
"m_offset": 3300,
"zone_id": 4
},
{
"m_offset": 3840,
"zone_id": 0
},
{
"m_offset": 4290,
"zone_id": 1
},
{
"m_offset": 4680,
"zone_id": 0
},
{
"m_offset": 4740,
"zone_id": 4
},
{
"m_offset": 5280,
"zone_id": 0
},
{
"m_offset": 5730,
"zone_id": 1
},
{
"m_offset": 6120,
"zone_id": 0
},
{
"m_offset": 6180,
"zone_id": 4
},
{
"m_offset": 6720,
"zone_id": 0
},
{
"m_offset": 7170,
"zone_id": 1
},
{
"m_offset": 7620,
"zone_id": 0
},
{
"m_offset": 8610,
"zone_id": 1
},
{
"m_offset": 9060,
"zone_id": 0
},
{
"m_offset": 10050,
"zone_id": 1
}
],
"zones": [
{
"id": 0,
"name": "Comfort",
"type": 0,
"rooms": [
{
"id": "2746182631",
"therm_setpoint_temperature": 21
},
{
"id": "2746182632",
"therm_setpoint_temperature": 22
}
]
},
{
"id": 1,
"name": "Night",
"type": 1,
"rooms": [
{
"id": "2746182631",
"therm_setpoint_temperature": 15
},
{
"id": "2746182632",
"therm_setpoint_temperature": 18
}
]
},
{
"id": 4,
"name": "Eco",
"type": 5,
"rooms": [
{
"id": "2746182631",
"therm_setpoint_temperature": 18
},
{
"id": "2746182632",
"therm_setpoint_temperature": 19
}
]
}
]
} pyatmo-9.2.1/fixtures/sync_schedule_b1b54a2f45795764f59d50d8.json 0000664 0000000 0000000 00000006133 15017405234 0023672 0 ustar 00root root 0000000 0000000 {
"away_temp": 14,
"hg_temp": 7,
"timetable": [
{
"m_offset": 0,
"zone_id": 1
},
{
"m_offset": 360,
"zone_id": 0
},
{
"m_offset": 420,
"zone_id": 4
},
{
"m_offset": 960,
"zone_id": 0
},
{
"m_offset": 1410,
"zone_id": 1
},
{
"m_offset": 1800,
"zone_id": 0
},
{
"m_offset": 1860,
"zone_id": 4
},
{
"m_offset": 2400,
"zone_id": 0
},
{
"m_offset": 2850,
"zone_id": 1
},
{
"m_offset": 3240,
"zone_id": 0
},
{
"m_offset": 3300,
"zone_id": 4
},
{
"m_offset": 3840,
"zone_id": 0
},
{
"m_offset": 4290,
"zone_id": 1
},
{
"m_offset": 4680,
"zone_id": 0
},
{
"m_offset": 4740,
"zone_id": 4
},
{
"m_offset": 5280,
"zone_id": 0
},
{
"m_offset": 5730,
"zone_id": 1
},
{
"m_offset": 6120,
"zone_id": 0
},
{
"m_offset": 6180,
"zone_id": 4
},
{
"m_offset": 6720,
"zone_id": 0
},
{
"m_offset": 7170,
"zone_id": 1
},
{
"m_offset": 7620,
"zone_id": 0
},
{
"m_offset": 8610,
"zone_id": 1
},
{
"m_offset": 9060,
"zone_id": 0
},
{
"m_offset": 10050,
"zone_id": 1
}
],
"zones": [
{
"id": 0,
"name": "Comfort",
"type": 0,
"rooms": [
{
"id": "2746182631",
"therm_setpoint_temperature": 21
},
{
"id": "2746182632",
"therm_setpoint_temperature": 22
}
]
},
{
"id": 1,
"name": "Night",
"type": 1,
"rooms": [
{
"id": "2746182631",
"therm_setpoint_temperature": 14
},
{
"id": "2746182632",
"therm_setpoint_temperature": 18
}
]
},
{
"id": 4,
"name": "Eco",
"type": 5,
"rooms": [
{
"id": "2746182631",
"therm_setpoint_temperature": 18
},
{
"id": "2746182632",
"therm_setpoint_temperature": 19
}
]
}
]
} pyatmo-9.2.1/pyproject.toml 0000664 0000000 0000000 00000007046 15017405234 0015760 0 ustar 00root root 0000000 0000000 [build-system]
build-backend = "setuptools.build_meta"
requires = [
"setuptools>=77",
"setuptools_scm>=8",
]
[project]
name = "pyatmo"
description = "Simple API to access Netatmo weather station data from any Python 3 script. Designed for Home Assistant (but not only)"
readme = "README.md"
authors = [
{ email = "jabesq@gmail.com", name = "Hugo Dupras" },
]
maintainers = [
{ email = "cgtobi@gmail.com", name = "Tobias Sauerwein" },
{ email = "jabesq@gmail.com", name = "Hugo Dupras" },
]
license = "MIT"
license-files = ["LICENSE.txt"]
requires-python = ">=3.11"
dependencies = [
"aiohttp>=3.7.4,<4.0.0",
"oauthlib~=3.1",
"requests-oauthlib>=1.3,<3.0",
"requests~=2.24",
]
classifiers = [
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: Implementation :: CPython",
"Programming Language :: Python :: Implementation :: PyPy",
"Topic :: Home Automation",
]
dynamic = ["version"]
[project.urls]
Changelog = "https://github.com/jabesq-org/pyatmo/blob/development/CHANGELOG.md"
Homepage = "https://github.com/jabesq-org/pyatmo"
Issues = "https://github.com/jabesq-org/pyatmo/issues"
Repository = "https://github.com/jabesq-org/pyatmo.git"
[tool.mypy]
explicit_package_bases = true
namespace_packages = true
show_error_context = true
show_error_codes = true
pretty = true
check_untyped_defs = true
strict_equality = true
implicit_optional=true
warn_redundant_casts = true
warn_unused_ignores = true
warn_unreachable = true
warn_no_return = true
disallow_incomplete_defs = true
[tool.pytest.ini_options]
asyncio_default_fixture_loop_scope = "function"
asyncio_mode = "auto"
minversion = "8.0"
[tool.ruff]
fix = true
line-length = 88
[tool.ruff.lint]
select = [ "ALL" ]
ignore = [
"D202", # blank-line-after-function (D202)
"D203", # incorrect-blank-line-before-class (D203)
"D213", # multi-line-summary-second-line (D213)
"DTZ005", # call-datetime-now-without-tzinfo (DTZ005)
"DTZ006", # call-datetime-fromtimestamp (DTZ006)
"E501", # line-too-long (E501)
"FBT001", # Boolean-typed positional argument in function definition (FBT001)
"FBT002", # Boolean default positional argument in function definition (FBT002)
"FBT003", # Boolean positional value in function call (FBT003)
"PLR0913", # Too many arguments in function definition (PLR0913)
"PLW2901", # redefined-loop-name (PLW2901)
]
[tool.ruff.lint.flake8-pytest-style]
fixture-parentheses = false
[tool.ruff.lint.flake8-tidy-imports.banned-api.pytz]
msg = "use zoneinfo instead"
[tool.ruff.lint.isort]
combine-as-imports = true
force-sort-within-sections = true
split-on-trailing-comma = false
[tool.ruff.lint.mccabe]
max-complexity = 12
[tool.ruff.lint.per-file-ignores]
"tests/*" = [
"ANN001",
"ANN002",
"ANN003",
"ANN201",
"ANN202",
"ANN204",
"D10",
"DTZ001",
"N802",
"PLR2004",
"S101",
"S105",
]
[tool.setuptools_scm]
local_scheme = "no-local-version"
[tool.uv]
dev-dependencies = [
"anyio>=4.3.0",
"black>=24.8.0",
"codespell>=2.3.0",
"docutils>=0.21.2",
"mypy>=1.11.2",
"pre-commit>=3.8.0",
"pytest-asyncio>=0.24.0",
"pytest-cov>=5.0.0",
"pytest-mock>=3.14.0",
"pytest>=8.3.3",
"requests-mock>=1.12.1",
"ruff>=0.6.4",
"time-machine>=2.15.0",
"tox-uv>=1.25.0",
"twine>=6.1.0",
]
pyatmo-9.2.1/src/ 0000775 0000000 0000000 00000000000 15017405234 0013624 5 ustar 00root root 0000000 0000000 pyatmo-9.2.1/src/pyatmo/ 0000775 0000000 0000000 00000000000 15017405234 0015135 5 ustar 00root root 0000000 0000000 pyatmo-9.2.1/src/pyatmo/__init__.py 0000664 0000000 0000000 00000001503 15017405234 0017245 0 ustar 00root root 0000000 0000000 """Expose submodules."""
from pyatmo import const, modules
from pyatmo.account import AsyncAccount
from pyatmo.auth import AbstractAsyncAuth
from pyatmo.exceptions import (
ApiError,
ApiHomeReachabilityError,
ApiThrottlingError,
InvalidHomeError,
InvalidRoomError,
InvalidScheduleError,
NoDeviceError,
NoScheduleError,
)
from pyatmo.home import Home
from pyatmo.modules import Module
from pyatmo.modules.device_types import DeviceType
from pyatmo.room import Room
__all__ = [
"AbstractAsyncAuth",
"ApiError",
"ApiHomeReachabilityError",
"ApiThrottlingError",
"AsyncAccount",
"DeviceType",
"Home",
"InvalidHomeError",
"InvalidRoomError",
"InvalidScheduleError",
"Module",
"NoDeviceError",
"NoScheduleError",
"Room",
"const",
"modules",
]
pyatmo-9.2.1/src/pyatmo/account.py 0000664 0000000 0000000 00000025305 15017405234 0017150 0 ustar 00root root 0000000 0000000 """Support for a Netatmo account."""
from __future__ import annotations
import logging
from typing import TYPE_CHECKING, Any, cast
from uuid import uuid4
from pyatmo import modules
from pyatmo.const import (
GETEVENTS_ENDPOINT,
GETHOMECOACHDATA_ENDPOINT,
GETHOMESDATA_ENDPOINT,
GETHOMESTATUS_ENDPOINT,
GETPUBLIC_DATA_ENDPOINT,
GETSTATIONDATA_ENDPOINT,
HOME,
SETSTATE_ENDPOINT,
RawData,
)
from pyatmo.helpers import extract_raw_data
from pyatmo.home import Home
from pyatmo.modules.module import Energy, MeasureInterval, Module
if TYPE_CHECKING:
from pyatmo.auth import AbstractAsyncAuth
LOG = logging.getLogger(__name__)
class AsyncAccount:
"""Async class of a Netatmo account."""
def __init__(
self,
auth: AbstractAsyncAuth,
favorite_stations: bool = True,
) -> None:
"""Initialize the Netatmo account."""
self.auth: AbstractAsyncAuth = auth
self.user: str | None = None
self.all_homes_id: dict[str, str] = {}
self.homes: dict[str, Home] = {}
self.raw_data: RawData = {}
self.favorite_stations: bool = favorite_stations
self.public_weather_areas: dict[str, modules.PublicWeatherArea] = {}
self.modules: dict[str, Module] = {}
def __repr__(self) -> str:
"""Return the representation."""
return (
f"{self.__class__.__name__}(user={self.user}, home_ids={self.homes.keys()}"
)
def process_topology(self, disabled_homes_ids: list[str] | None = None) -> None:
"""Process topology information from /homesdata."""
if disabled_homes_ids is None:
disabled_homes_ids = []
for home in self.raw_data["homes"]:
home_id = home.get("id", "Unknown")
home_name = home.get("name", "Unknown")
self.all_homes_id[home_id] = home_name
if home_id in disabled_homes_ids:
if home_id in self.homes:
del self.homes[home_id]
continue
if home_id in self.homes:
self.homes[home_id].update_topology(home)
else:
self.homes[home_id] = Home(self.auth, raw_data=home)
async def async_update_topology(
self,
disabled_homes_ids: list[str] | None = None,
) -> None:
"""Retrieve topology data from /homesdata."""
resp = await self.auth.async_post_api_request(
endpoint=GETHOMESDATA_ENDPOINT,
)
self.raw_data = extract_raw_data(await resp.json(), "homes")
self.user = self.raw_data.get("user", {}).get("email")
self.process_topology(disabled_homes_ids=disabled_homes_ids)
async def async_update_status(self, home_id: str) -> None:
"""Retrieve status data from /homestatus."""
resp = await self.auth.async_post_api_request(
endpoint=GETHOMESTATUS_ENDPOINT,
params={"home_id": home_id},
)
raw_data = extract_raw_data(await resp.json(), HOME)
await self.homes[home_id].update(raw_data, do_raise_for_reachability_error=True)
async def async_update_events(self, home_id: str) -> None:
"""Retrieve events from /getevents."""
resp = await self.auth.async_post_api_request(
endpoint=GETEVENTS_ENDPOINT,
params={"home_id": home_id},
)
raw_data = extract_raw_data(await resp.json(), HOME)
await self.homes[home_id].update(raw_data)
async def async_update_weather_stations(self) -> None:
"""Retrieve status data from /getstationsdata."""
params = {"get_favorites": ("true" if self.favorite_stations else "false")}
await self._async_update_data(
GETSTATIONDATA_ENDPOINT,
params=params,
)
async def async_update_air_care(self) -> None:
"""Retrieve status data from /gethomecoachsdata."""
await self._async_update_data(GETHOMECOACHDATA_ENDPOINT)
async def async_update_measures(
self,
home_id: str,
module_id: str,
start_time: int | None = None,
end_time: int | None = None,
interval: MeasureInterval = MeasureInterval.HOUR,
days: int = 7,
) -> None:
"""Retrieve measures data from /getmeasure."""
module = self.homes[home_id].modules[module_id]
if module.has_feature("historical_data"):
module = cast("Energy", module)
await module.async_update_measures(
start_time=start_time,
end_time=end_time,
interval=interval,
days=days,
)
def register_public_weather_area(
self,
lat_ne: str,
lon_ne: str,
lat_sw: str,
lon_sw: str,
required_data_type: str | None = None,
filtering: bool = False,
*,
area_id: str = str(uuid4()),
) -> str:
"""Register public weather area to monitor."""
self.public_weather_areas[area_id] = modules.PublicWeatherArea(
lat_ne,
lon_ne,
lat_sw,
lon_sw,
required_data_type,
filtering,
)
return area_id
async def async_update_public_weather(self, area_id: str) -> None:
"""Retrieve status data from /getpublicdata."""
params = {
"lat_ne": self.public_weather_areas[area_id].location.lat_ne,
"lon_ne": self.public_weather_areas[area_id].location.lon_ne,
"lat_sw": self.public_weather_areas[area_id].location.lat_sw,
"lon_sw": self.public_weather_areas[area_id].location.lon_sw,
"filtering": (
"true" if self.public_weather_areas[area_id].filtering else "false"
),
}
await self._async_update_data(
GETPUBLIC_DATA_ENDPOINT,
tag="body",
params=params,
area_id=area_id,
)
async def _async_update_data(
self,
endpoint: str,
params: dict[str, Any] | None = None,
tag: str = "devices",
area_id: str | None = None,
) -> None:
"""Retrieve status data from ."""
resp = await self.auth.async_post_api_request(endpoint=endpoint, params=params)
raw_data = extract_raw_data(await resp.json(), tag)
await self.update_devices(raw_data, area_id)
async def async_set_state(self, home_id: str, data: dict[str, Any]) -> None:
"""Modify device state by passing JSON specific to the device."""
LOG.debug("Setting state: %s", data)
post_params = {
"json": {
HOME: {
"id": home_id,
**data,
},
},
}
resp = await self.auth.async_post_api_request(
endpoint=SETSTATE_ENDPOINT,
params=post_params,
)
LOG.debug("Response: %s", resp)
async def update_devices(
self,
raw_data: RawData,
area_id: str | None = None,
) -> None:
"""Update device states."""
for device_data in raw_data.get("devices", {}):
if home_id := device_data.get(
"home_id",
self.find_home_of_device(device_data),
):
if home_id not in self.homes:
modules_data = []
for module_data in device_data.get("modules", []):
module_data["home_id"] = home_id
module_data["id"] = module_data["_id"]
module_data["name"] = module_data.get("module_name")
modules_data.append(normalize_weather_attributes(module_data))
modules_data.append(normalize_weather_attributes(device_data))
self.homes[home_id] = Home(
self.auth,
raw_data={
"id": home_id,
"name": device_data.get("home_name", "Unknown"),
"modules": modules_data,
},
)
await self.homes[home_id].update(
{HOME: {"modules": [normalize_weather_attributes(device_data)]}},
)
else:
LOG.debug("No home %s (%s) found.", home_id, home_id)
for module_data in device_data.get("modules", []):
module_data["home_id"] = home_id
await self.update_devices({"devices": [module_data]})
if (
device_data["type"] == "NHC"
or self.find_home_of_device(device_data) is None
):
device_data["name"] = device_data.get(
"station_name",
device_data.get("module_name", "Unknown"),
)
device_data = normalize_weather_attributes(device_data)
if device_data["id"] not in self.modules:
self.modules[device_data["id"]] = getattr(
modules,
device_data["type"],
)(
home=self,
module=device_data,
)
await self.modules[device_data["id"]].update(device_data)
if device_data.get("modules", []):
self.modules[device_data["id"]].modules = [
module["_id"] for module in device_data["modules"]
]
if area_id is not None:
self.public_weather_areas[area_id].update(raw_data)
def find_home_of_device(self, device_data: dict[str, Any]) -> str | None:
"""Find home_id of device."""
return next(
(
home_id
for home_id, home in self.homes.items()
if device_data["_id"] in home.modules
),
None,
)
ATTRIBUTES_TO_FIX = {
"_id": "id",
"firmware": "firmware_revision",
"wifi_status": "wifi_strength",
"rf_status": "rf_strength",
"Temperature": "temperature",
"Humidity": "humidity",
"Pressure": "pressure",
"CO2": "co2",
"AbsolutePressure": "absolute_pressure",
"Noise": "noise",
"Rain": "rain",
"WindStrength": "wind_strength",
"WindAngle": "wind_angle",
"GustStrength": "gust_strength",
"GustAngle": "gust_angle",
}
def normalize_weather_attributes(raw_data: RawData) -> dict[str, Any]:
"""Normalize weather attributes."""
result: dict[str, Any] = {}
for attribute, value in raw_data.items():
if attribute == "dashboard_data":
result.update(**normalize_weather_attributes(value))
else:
result[ATTRIBUTES_TO_FIX.get(attribute, attribute)] = value
return result
pyatmo-9.2.1/src/pyatmo/auth.py 0000664 0000000 0000000 00000015053 15017405234 0016454 0 ustar 00root root 0000000 0000000 """Support for Netatmo authentication."""
from __future__ import annotations
from abc import ABC, abstractmethod
from json import JSONDecodeError
import logging
from typing import Any
from aiohttp import (
ClientError,
ClientResponse,
ClientSession,
ClientTimeout,
ContentTypeError,
)
from pyatmo.const import (
AUTHORIZATION_HEADER,
DEFAULT_BASE_URL,
ERRORS,
FORBIDDEN_ERROR_CODE,
THROTTLING_ERROR_CODE,
WEBHOOK_URL_ADD_ENDPOINT,
WEBHOOK_URL_DROP_ENDPOINT,
)
from pyatmo.exceptions import ApiError, ApiThrottlingError
LOG = logging.getLogger(__name__)
class AbstractAsyncAuth(ABC):
"""Abstract class to make authenticated requests."""
def __init__(
self,
websession: ClientSession,
base_url: str = DEFAULT_BASE_URL,
) -> None:
"""Initialize the auth."""
self.websession = websession
self.base_url = base_url
@abstractmethod
async def async_get_access_token(self) -> str:
"""Return a valid access token."""
async def async_get_image(
self,
endpoint: str,
base_url: str | None = None,
params: dict[str, Any] | None = None,
) -> bytes:
"""Wrap async get requests."""
try:
access_token = await self.async_get_access_token()
except ClientError as err:
error_type = type(err).__name__
msg = f"Access token failure: {error_type} - {err}"
raise ApiError(msg) from err
headers = {AUTHORIZATION_HEADER: f"Bearer {access_token}"}
url = (base_url or self.base_url) + endpoint
async with self.websession.get(
url,
params=params,
headers=headers,
timeout=ClientTimeout(total=5),
) as resp:
resp_content = await resp.read()
if resp.headers.get("content-type") == "image/jpeg":
return resp_content
msg = f"{resp.status} - invalid content-type in response when accessing '{url}'"
raise ApiError(
msg,
)
async def async_post_api_request(
self,
endpoint: str,
base_url: str | None = None,
params: dict[str, Any] | None = None,
) -> ClientResponse:
"""Wrap async post requests."""
return await self.async_post_request(
url=(base_url or self.base_url) + endpoint,
params=params,
)
async def async_post_request(
self,
url: str,
params: dict[str, Any] | None = None,
) -> ClientResponse:
"""Wrap async post requests."""
access_token = await self.get_access_token()
headers = {AUTHORIZATION_HEADER: f"Bearer {access_token}"}
req_args = self.prepare_request_arguments(params)
async with self.websession.post(
url,
**req_args,
headers=headers,
timeout=ClientTimeout(total=5),
) as resp:
return await self.process_response(resp, url)
async def get_access_token(self) -> str:
"""Get access token."""
try:
return await self.async_get_access_token()
except ClientError as err:
msg = f"Access token failure: {err}"
raise ApiError(msg) from err
def prepare_request_arguments(self, params: dict | None) -> dict:
"""Prepare request arguments."""
req_args = {"data": params if params is not None else {}}
if "params" in req_args["data"]:
req_args["params"] = req_args["data"]["params"]
req_args["data"].pop("params")
if "json" in req_args["data"]:
req_args["json"] = req_args["data"]["json"]
req_args.pop("data")
return req_args
async def process_response(self, resp: ClientResponse, url: str) -> ClientResponse:
"""Process response."""
resp_status = resp.status
resp_content = await resp.read()
if not resp.ok:
LOG.debug("The Netatmo API returned %s (%s)", resp_content, resp_status)
await self.handle_error_response(resp, resp_status, url)
return await self.handle_success_response(resp, resp_content)
async def handle_error_response(
self,
resp: ClientResponse,
resp_status: int,
url: str,
) -> None:
"""Handle error response."""
try:
resp_json = await resp.json()
message = (
f"{resp_status} - "
f"{ERRORS.get(resp_status, '')} - "
f"{resp_json['error']['message']} "
f"({resp_json['error']['code']}) "
f"when accessing '{url}'",
)
if (
resp_status == FORBIDDEN_ERROR_CODE
and resp_json["error"]["code"] == THROTTLING_ERROR_CODE
):
raise ApiThrottlingError(message)
raise ApiError(message)
except (JSONDecodeError, ContentTypeError) as exc:
msg = (
f"{resp_status} - "
f"{ERRORS.get(resp_status, '')} - "
f"when accessing '{url}'"
)
raise ApiError(
msg,
) from exc
async def handle_success_response(
self,
resp: ClientResponse,
resp_content: bytes,
) -> ClientResponse:
"""Handle success response."""
try:
if "application/json" in resp.headers.get("content-type", []):
return resp
if resp_content not in [b"", b"None"]:
return resp
except (TypeError, AttributeError):
LOG.debug("Invalid response %s", resp)
return resp
async def async_addwebhook(self, webhook_url: str) -> None:
"""Register webhook."""
try:
resp = await self.async_post_api_request(
endpoint=WEBHOOK_URL_ADD_ENDPOINT,
params={"url": webhook_url},
)
except TimeoutError as exc:
msg = "Webhook registration timed out"
raise ApiError(msg) from exc
else:
LOG.debug("addwebhook: %s", resp)
async def async_dropwebhook(self) -> None:
"""Unregister webhook."""
try:
resp = await self.async_post_api_request(
endpoint=WEBHOOK_URL_DROP_ENDPOINT,
params={"app_types": "app_security"},
)
except TimeoutError as exc:
msg = "Webhook registration timed out"
raise ApiError(msg) from exc
else:
LOG.debug("dropwebhook: %s", resp)
pyatmo-9.2.1/src/pyatmo/const.py 0000664 0000000 0000000 00000007741 15017405234 0016646 0 ustar 00root root 0000000 0000000 """Common constants."""
from __future__ import annotations
from typing import Any
ERRORS: dict[int, str] = {
400: "Bad request",
401: "Unauthorized",
403: "Forbidden",
404: "Not found",
406: "Not Acceptable",
500: "Internal Server Error",
502: "Bad Gateway",
503: "Service Unavailable",
}
# Special types
RawData = dict[str, Any]
DEFAULT_BASE_URL: str = "https://api.netatmo.com/"
# Endpoints
AUTH_REQ_ENDPOINT = "oauth2/token"
AUTH_URL_ENDPOINT = "oauth2/authorize"
WEBHOOK_URL_ADD_ENDPOINT = "api/addwebhook"
WEBHOOK_URL_DROP_ENDPOINT = "api/dropwebhook"
GETHOMESDATA_ENDPOINT = "api/homesdata"
GETHOMESTATUS_ENDPOINT = "api/homestatus"
GETEVENTS_ENDPOINT = "api/getevents"
SETTHERMMODE_ENDPOINT = "api/setthermmode"
SETROOMTHERMPOINT_ENDPOINT = "api/setroomthermpoint"
GETROOMMEASURE_ENDPOINT = "api/getroommeasure"
SWITCHHOMESCHEDULE_ENDPOINT = "api/switchhomeschedule"
SYNCHOMESCHEDULE_ENDPOINT = "api/synchomeschedule"
GETHOMEDATA_ENDPOINT = "api/gethomedata"
GETCAMERAPICTURE_ENDPOINT = "api/getcamerapicture"
GETEVENTSUNTIL_ENDPOINT = "api/geteventsuntil"
SETPERSONSAWAY_ENDPOINT = "api/setpersonsaway"
SETPERSONSHOME_ENDPOINT = "api/setpersonshome"
SETSTATE_ENDPOINT = "api/setstate"
GETHOMECOACHDATA_ENDPOINT = "api/gethomecoachsdata"
GETMEASURE_ENDPOINT = "api/getmeasure"
GETSTATIONDATA_ENDPOINT = "api/getstationsdata"
GETPUBLIC_DATA_ENDPOINT = "api/getpublicdata"
AUTHORIZATION_HEADER = "Authorization"
# Possible scops
ALL_SCOPES: list[str] = [
"access_camera", # Netatmo camera products
"access_doorbell", # Netatmo Smart Video Doorbell
"access_presence", # Netatmo Smart Outdoor Camera
"read_bubendorff", # Bubbendorf shutters
"read_bfi", # BTicino IP
"read_camera", # Netatmo camera products
"read_carbonmonoxidedetector", # Netatmo CO sensor
"read_doorbell", # Netatmo Smart Video Doorbell
"read_homecoach", # Netatmo Smart Indoor Air Quality Monitor
"read_magellan", # Legrand Wiring device or Electrical panel products
"read_mhs1", # Bticino MyHome Server 1 modules
"read_mx", # BTicino Classe 300 EOS
"read_presence", # Netatmo Smart Outdoor Camera
"read_smarther", # Smarther with Netatmo thermostat
"read_smokedetector", # Smart Smoke Alarm information and events
"read_station", # Netatmo weather station
"read_thermostat", # Netatmo climate products
"write_bubendorff", # Bubbendorf shutters
"write_bfi", # BTicino IP
"write_camera", # Netatmo camera products
"write_magellan", # Legrand Wiring device or Electrical panel products
"write_mhs1", # Bticino MyHome Server 1 modules
"write_mx", # BTicino Classe 300 EOS
"write_presence", # Netatmo Smart Outdoor Camera
"write_smarther", # Smarther products
"write_thermostat", # Netatmo climate products
]
EVENTS = "events"
SCHEDULES = "schedules"
MANUAL = "manual"
MAX = "max"
HOME = "home"
FROSTGUARD = "hg"
SCHEDULE = "schedule"
OFF = "off"
AWAY = "away"
HEATING = "heating"
COOLING = "cooling"
IDLE = "idle"
PILOT_WIRE_COMFORT = "comfort"
PILOT_WIRE_AWAY = "away"
PILOT_WIRE_FROST_GUARD = "frost_guard"
PILOT_WIRE_STAND_BY = "stand_by"
PILOT_WIRE_COMFORT_1 = "comfort_1" # => doc unclear and contradictory: it is in the json schema but no in the doc
PILOT_WIRE_COMFORT_2 = "comfort_2" # => same
STATION_TEMPERATURE_TYPE = "temperature"
STATION_PRESSURE_TYPE = "pressure"
STATION_HUMIDITY_TYPE = "humidity"
ACCESSORY_RAIN_LIVE_TYPE = "rain_live"
ACCESSORY_RAIN_60MIN_TYPE = "rain_60min"
ACCESSORY_RAIN_24H_TYPE = "rain_24h"
ACCESSORY_RAIN_TIME_TYPE = "rain_timeutc"
ACCESSORY_WIND_STRENGTH_TYPE = "wind_strength"
ACCESSORY_WIND_ANGLE_TYPE = "wind_angle"
ACCESSORY_WIND_TIME_TYPE = "wind_timeutc"
ACCESSORY_GUST_STRENGTH_TYPE = "gust_strength"
ACCESSORY_GUST_ANGLE_TYPE = "gust_angle"
# 2 days of dynamic historical data stored
MAX_HISTORY_TIME_FRAME = 24 * 2 * 3600
UNKNOWN = "unknown"
# Error codes
THROTTLING_ERROR_CODE = 26
FORBIDDEN_ERROR_CODE = 403
# Location constants
GPS_COORDINATES_COUNT = 2
pyatmo-9.2.1/src/pyatmo/enums.py 0000664 0000000 0000000 00000001022 15017405234 0016631 0 ustar 00root root 0000000 0000000 """Enums for the pyatmo package."""
from enum import StrEnum
class ScheduleType(StrEnum):
"""Enum representing the type of a schedule."""
THERM = "therm"
COOLING = "cooling"
ELECTRICITY = "electricity"
EVENT = "event"
AUTO = "auto"
class TemperatureControlMode(StrEnum):
"""Temperature control mode."""
HEATING = "heating"
COOLING = "cooling"
SCHEDULE_TYPE_MAPPING = {
TemperatureControlMode.HEATING: ScheduleType.THERM,
TemperatureControlMode.COOLING: ScheduleType.COOLING,
}
pyatmo-9.2.1/src/pyatmo/event.py 0000664 0000000 0000000 00000005324 15017405234 0016634 0 ustar 00root root 0000000 0000000 """Module to represent a Netatmo event."""
from __future__ import annotations
from dataclasses import dataclass
from enum import Enum
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from pyatmo.const import RawData
EVENT_ATTRIBUTES_MAP = {"id": "entity_id", "type": "event_type", "time": "event_time"}
class EventTypes(Enum):
"""Event types."""
movement = "movement"
person = "person"
person_away = "person_away"
connection = "connection"
disconnection = "disconnection"
new_module = "new_module"
module_connect = "module_connect"
module_disconnect = "module_disconnect"
module_low_battery = "module_low_battery"
module_end_update = "module_end_update"
on = "on"
off = "off"
sd = "sd"
alim = "alim"
boot = "boot"
outdoor = "outdoor"
daily_summary = "daily_summary"
tag_big_move = "tag_big_move"
tag_small_move = "tag_small_move"
tag_uninstalled = "tag_uninstalled"
tag_open = "tag_open"
hush = "hush"
smoke = "smoke"
tampered = "tampered"
wifi_status = "wifi_status"
battery_status = "battery_status"
detection_chamber_status = "detection_chamber_status"
sound_test = "sound_test"
siren_sounding = "siren_sounding"
siren_tampered = "siren_tampered"
incoming_call = "incoming_call"
accepted_call = "accepted_call"
missed_call = "missed_call"
co_detected = "co_detected"
class VideoStatus(Enum):
"""Video states."""
available = "available"
deleted = "deleted"
@dataclass
class Snapshot:
"""Class to represent a Netatmo event snapshot."""
snapshot_id: str
version: int
key: str
url: str
@dataclass
class Event:
"""Class to represent a Netatmo events."""
entity_id: str
event_type: EventTypes
event_time: int
message: str | None = None
camera_id: str | None = None
device_id: str | None = None
module_id: str | None = None
person_id: str | None = None
video_id: str | None = None
sub_type: int | None = None
snapshot: Snapshot | None = None
vignette: Snapshot | None = None
video_status: VideoStatus | None = None
is_arrival: bool | None = None
subevents: list[Event] | None = None
def __init__(self, home_id: str, raw_data: RawData) -> None:
"""Initialize a Netatmo event instance."""
self.home_id = home_id
self._init_attributes(raw_data)
def _init_attributes(self, raw_data: RawData) -> None:
"""Initialize attributes of the instance."""
for attrib, value in raw_data.items():
if attrib == "subevents":
value = [Event(self.home_id, event) for event in value]
setattr(self, EVENT_ATTRIBUTES_MAP.get(attrib, attrib), value)
pyatmo-9.2.1/src/pyatmo/exceptions.py 0000664 0000000 0000000 00000001467 15017405234 0017700 0 ustar 00root root 0000000 0000000 """Exceptions for pyatmo."""
class NoScheduleError(Exception):
"""Raised when no schedule is found."""
class InvalidScheduleError(Exception):
"""Raised when an invalid schedule is encountered."""
class InvalidHomeError(Exception):
"""Raised when an invalid home is encountered."""
class InvalidRoomError(Exception):
"""Raised when an invalid room is encountered."""
class NoDeviceError(Exception):
"""Raised when no device is found."""
class ApiError(Exception):
"""Raised when an API error is encountered."""
class ApiThrottlingError(ApiError):
"""Raised when an API error is encountered."""
class ApiHomeReachabilityError(ApiError):
"""Raised when an API error is encountered."""
class InvalidStateError(Exception):
"""Raised when an invalid state is encountered."""
pyatmo-9.2.1/src/pyatmo/helpers.py 0000664 0000000 0000000 00000003433 15017405234 0017154 0 ustar 00root root 0000000 0000000 """Collection of helper functions."""
from __future__ import annotations
import logging
from typing import TYPE_CHECKING, cast
from pyatmo.exceptions import NoDeviceError
if TYPE_CHECKING:
from pyatmo.const import RawData
LOG: logging.Logger = logging.getLogger(__name__)
def fix_id(raw_data: list[RawData | str]) -> list[RawData | str]:
"""Fix known errors in station ids like superfluous spaces."""
if not raw_data:
return raw_data
for station in raw_data:
if not isinstance(station, dict):
continue
if station.get("_id") is None:
continue
station["_id"] = cast("dict", station)["_id"].replace(" ", "")
for module in station.get("modules", {}):
module["_id"] = module["_id"].replace(" ", "")
return raw_data
def extract_raw_data(resp: RawData, tag: str) -> RawData:
"""Extract raw data from server response."""
if tag == "body":
return {"public": resp["body"], "errors": []}
if resp is None or "body" not in resp or tag not in resp["body"]:
LOG.debug("Server response (tag: %s): %s", tag, resp)
msg = "No device found, errors in response"
raise NoDeviceError(msg)
if tag == "homes":
homes = fix_id(resp["body"].get(tag))
if not homes:
LOG.debug("Server response (tag: %s): %s", tag, resp)
msg = "No homes found"
raise NoDeviceError(msg)
return {
tag: homes,
"errors": resp["body"].get("errors", []),
}
if not (raw_data := fix_id(resp["body"].get(tag))):
LOG.debug("Server response (tag: %s): %s", tag, resp)
msg = "No device data available"
raise NoDeviceError(msg)
return {tag: raw_data, "errors": resp["body"].get("errors", [])}
pyatmo-9.2.1/src/pyatmo/home.py 0000664 0000000 0000000 00000035621 15017405234 0016446 0 ustar 00root root 0000000 0000000 """Module to represent a Netatmo home."""
from __future__ import annotations
import logging
from typing import TYPE_CHECKING, Any, cast
from pyatmo import modules
from pyatmo.const import (
EVENTS,
SCHEDULES,
SETPERSONSAWAY_ENDPOINT,
SETPERSONSHOME_ENDPOINT,
SETSTATE_ENDPOINT,
SETTHERMMODE_ENDPOINT,
SWITCHHOMESCHEDULE_ENDPOINT,
SYNCHOMESCHEDULE_ENDPOINT,
RawData,
)
from pyatmo.enums import SCHEDULE_TYPE_MAPPING, TemperatureControlMode
from pyatmo.event import Event
from pyatmo.exceptions import (
ApiHomeReachabilityError,
InvalidScheduleError,
InvalidStateError,
NoScheduleError,
)
from pyatmo.person import Person
from pyatmo.room import Room
from pyatmo.schedule import Schedule
if TYPE_CHECKING:
from aiohttp import ClientResponse
from pyatmo.auth import AbstractAsyncAuth
from pyatmo.modules import Module
from pyatmo.modules.netatmo import NACamera
LOG = logging.getLogger(__name__)
class Home:
"""Class to represent a Netatmo home."""
auth: AbstractAsyncAuth
entity_id: str
name: str
rooms: dict[str, Room]
modules: dict[str, Module]
schedules: dict[str, Schedule]
persons: dict[str, Person]
events: dict[str, Event]
temperature_control_mode: TemperatureControlMode | None = None
therm_mode: str | None = None
therm_setpoint_default_duration: int | None = None
cooling_mode: str | None = None
def __init__(self, auth: AbstractAsyncAuth, raw_data: RawData) -> None:
"""Initialize a Netatmo home instance."""
self.auth = auth
self.entity_id = raw_data["id"]
self.name = raw_data.get("name", "Unknown")
self.modules = {
module["id"]: self.get_module(module)
for module in raw_data.get("modules", [])
}
self.rooms = {
room["id"]: Room(
home=self,
room=room,
all_modules=self.modules,
)
for room in raw_data.get("rooms", [])
}
self.schedules = {
s["id"]: Schedule(home=self, raw_data=s)
for s in raw_data.get(SCHEDULES, [])
}
self.persons = {
s["id"]: Person(home=self, raw_data=s) for s in raw_data.get("persons", [])
}
self.events = {}
self.temperature_control_mode = get_temperature_control_mode(
raw_data.get("temperature_control_mode"),
)
self.therm_mode = raw_data.get("therm_mode")
self.therm_setpoint_default_duration = raw_data.get(
"therm_setpoint_default_duration",
)
self.cooling_mode = raw_data.get("cooling_mode")
def get_module(self, module: dict) -> Module:
"""Return module."""
try:
return getattr(modules, module["type"])(
home=self,
module=module,
)
except AttributeError:
LOG.info("Unknown device type %s", module["type"])
return modules.NLunknown(
home=self,
module=module,
)
def update_topology(self, raw_data: RawData) -> None:
"""Update topology."""
self.name = raw_data.get("name", "Unknown")
raw_modules = raw_data.get("modules", [])
self.temperature_control_mode = get_temperature_control_mode(
raw_data.get("temperature_control_mode"),
)
self.therm_mode = raw_data.get("therm_mode")
self.therm_setpoint_default_duration = raw_data.get(
"therm_setpoint_default_duration",
)
self.cooling_mode = raw_data.get("cooling_mode")
for module in raw_modules:
if (module_id := module["id"]) not in self.modules:
self.modules[module_id] = self.get_module(module)
else:
self.modules[module_id].update_topology(module)
# Drop module if has been removed
for module in self.modules.keys() - {m["id"] for m in raw_modules}:
self.modules.pop(module)
raw_rooms = raw_data.get("rooms", [])
for room in raw_rooms:
if (room_id := room["id"]) not in self.rooms:
self.rooms[room_id] = Room(
home=self,
room=room,
all_modules=self.modules,
)
else:
self.rooms[room_id].update_topology(room)
# Drop room if has been removed
for room in self.rooms.keys() - {m["id"] for m in raw_rooms}:
self.rooms.pop(room)
raw_schedules = raw_data.get("schedules", [])
for schedule in raw_schedules:
if (schedule_id := schedule["id"]) not in self.schedules:
self.schedules[schedule_id] = Schedule(home=self, raw_data=schedule)
else:
self.schedules[schedule_id].update_topology(schedule)
# Drop schedule if has been removed
for schedule in self.schedules.keys() - {s["id"] for s in raw_schedules}:
self.schedules.pop(schedule)
async def update(
self,
raw_data: RawData,
do_raise_for_reachability_error: bool = False,
) -> None:
"""Update home with the latest data."""
has_error = False
for module in raw_data.get("errors", []):
has_error = True
await self.modules[module["id"]].update({})
data = raw_data["home"]
has_an_update = False
for module in data.get("modules", []):
has_an_update = True
if module["id"] not in self.modules:
self.update_topology({"modules": [module]})
await self.modules[module["id"]].update(module)
for room in data.get("rooms", []):
has_an_update = True
self.rooms[room["id"]].update(room)
for person_status in data.get("persons", []):
# if there is a person update, it means the house has been updated
has_an_update = True
if person := self.persons.get(person_status["id"]):
person.update(person_status)
self.events = {
s["id"]: Event(home_id=self.entity_id, raw_data=s)
for s in data.get(EVENTS, [])
}
if len(self.events) > 0:
has_an_update = True
has_one_module_reachable = False
for module in self.modules.values():
if module.reachable:
has_one_module_reachable = True
if hasattr(module, "events"):
module = cast("NACamera", module)
module.events = [
event
for event in self.events.values()
if event.module_id == module.entity_id
]
if (
do_raise_for_reachability_error
and has_error
and has_one_module_reachable is False
and has_an_update is False
):
msg = "No Home update could be performed, all modules unreachable and not updated"
raise ApiHomeReachabilityError(
msg,
)
def get_selected_schedule(self) -> Schedule | None:
"""Return selected schedule for given home."""
return next(
(
schedule
for schedule in self.schedules.values()
if schedule.selected
and self.temperature_control_mode
and schedule.type
== SCHEDULE_TYPE_MAPPING[self.temperature_control_mode]
),
None,
)
def get_available_schedules(self) -> list[Schedule]:
"""Return available schedules for given home."""
return [
schedule
for schedule in self.schedules.values()
if self.temperature_control_mode
and schedule.type == SCHEDULE_TYPE_MAPPING[self.temperature_control_mode]
]
def is_valid_schedule(self, schedule_id: str) -> bool:
"""Check if valid schedule."""
return schedule_id in self.schedules
def has_otm(self) -> bool:
"""Check if any room has an OTM device."""
return any("OTM" in room.device_types for room in self.rooms.values())
def has_bns(self) -> bool:
"""Check if any room has a BNS device."""
return any("BNS" in room.device_types for room in self.rooms.values())
def get_hg_temp(self) -> float | None:
"""Return frost guard temperature value for given home."""
if (schedule := self.get_selected_schedule()) is None:
return None
return schedule.hg_temp
def get_away_temp(self) -> float | None:
"""Return configured away temperature value for given home."""
if (schedule := self.get_selected_schedule()) is None:
return None
return schedule.away_temp
async def async_set_thermmode(
self,
mode: str | None,
end_time: int | None = None,
schedule_id: str | None = None,
) -> bool:
"""Set thermotat mode."""
if schedule_id is not None and not self.is_valid_schedule(schedule_id):
msg = f"{schedule_id} is not a valid schedule id."
raise NoScheduleError(msg)
if mode is None:
msg = f"{mode} is not a valid mode."
raise NoScheduleError(msg)
post_params = {"home_id": self.entity_id, "mode": mode}
if end_time is not None and mode in {"hg", "away"}:
post_params["endtime"] = str(end_time)
if schedule_id is not None and mode == "schedule":
post_params["schedule_id"] = schedule_id
LOG.debug(
"Setting home (%s) mode to %s (%s)",
self.entity_id,
mode,
schedule_id,
)
resp = await self.auth.async_post_api_request(
endpoint=SETTHERMMODE_ENDPOINT,
params=post_params,
)
return (await resp.json()).get("status") == "ok"
async def async_switch_schedule(self, schedule_id: str) -> bool:
"""Switch the schedule."""
if not self.is_valid_schedule(schedule_id):
msg = f"{schedule_id} is not a valid schedule id"
raise NoScheduleError(msg)
LOG.debug("Setting home (%s) schedule to %s", self.entity_id, schedule_id)
resp = await self.auth.async_post_api_request(
endpoint=SWITCHHOMESCHEDULE_ENDPOINT,
params={"home_id": self.entity_id, "schedule_id": schedule_id},
)
return (await resp.json()).get("status") == "ok"
async def async_set_state(self, data: dict[str, Any]) -> bool:
"""Set state using given data."""
if not is_valid_state(data):
msg = "Data for '/set_state' contains errors."
raise InvalidStateError(msg)
LOG.debug("Setting state for home (%s) according to %s", self.entity_id, data)
resp = await self.auth.async_post_api_request(
endpoint=SETSTATE_ENDPOINT,
params={"json": {"home": {"id": self.entity_id, **data}}},
)
return (await resp.json()).get("status") == "ok"
async def async_set_persons_home(
self,
person_ids: list[str] | None = None,
) -> ClientResponse:
"""Mark persons as home."""
post_params: dict[str, Any] = {"home_id": self.entity_id}
if person_ids:
post_params["person_ids[]"] = person_ids
return await self.auth.async_post_api_request(
endpoint=SETPERSONSHOME_ENDPOINT,
params=post_params,
)
async def async_set_persons_away(
self,
person_id: str | None = None,
) -> ClientResponse:
"""Mark a person as away or set the whole home to being empty."""
post_params = {"home_id": self.entity_id}
if person_id:
post_params["person_id"] = person_id
return await self.auth.async_post_api_request(
endpoint=SETPERSONSAWAY_ENDPOINT,
params=post_params,
)
async def async_set_schedule_temperatures(
self,
zone_id: str,
temps: dict[str, float],
) -> None:
"""Set the scheduled room temperature for the given schedule ID."""
selected_schedule = self.get_selected_schedule()
if selected_schedule is None:
msg = "Could not determine selected schedule."
raise NoScheduleError(msg)
for zone in (z for z in selected_schedule.zones if z.entity_id == zone_id):
for room in (r for r in zone.rooms if r.entity_id in temps):
room.therm_setpoint_temperature = temps[room.entity_id]
await self.async_sync_schedule(selected_schedule)
async def async_sync_schedule(
self,
schedule: Schedule,
) -> None:
"""Modify an existing schedule."""
if not is_valid_schedule(schedule):
msg = "Data for '/synchomeschedule' contains errors."
raise InvalidScheduleError(msg)
LOG.debug(
"Setting schedule (%s) for home (%s) to %s",
schedule.entity_id,
self.entity_id,
schedule,
)
timetable_entries = [
{
"m_offset": timetable_entry.m_offset,
"zone_id": timetable_entry.zone_id,
}
for timetable_entry in schedule.timetable
]
zones = []
for zone in schedule.zones:
new_zone = {
"id": zone.entity_id,
"name": zone.name,
"type": zone.type,
"rooms": [
{
"id": room.entity_id,
"therm_setpoint_temperature": room.therm_setpoint_temperature,
}
for room in zone.rooms
],
}
zones.append(new_zone)
request_json = {
"away_temp": schedule.away_temp,
"hg_temp": schedule.hg_temp,
"timetable": timetable_entries,
"zones": zones,
}
resp = await self.auth.async_post_api_request(
endpoint=SYNCHOMESCHEDULE_ENDPOINT,
params={
"params": {
"home_id": self.entity_id,
"schedule_id": schedule.entity_id,
"name": "Default",
},
"json": request_json,
},
)
return (await resp.json()).get("status") == "ok"
def is_valid_state(data: dict[str, Any]) -> bool:
"""Check set state data."""
return data is not None
def is_valid_schedule(schedule: Schedule) -> bool:
"""Check schedule."""
return (
isinstance(schedule, Schedule)
and hasattr(schedule, "entity_id")
and schedule.entity_id != ""
)
def get_temperature_control_mode(
temperature_control_mode: str | None,
) -> TemperatureControlMode | None:
"""Return temperature control mode."""
return (
TemperatureControlMode(temperature_control_mode)
if temperature_control_mode
else None
)
pyatmo-9.2.1/src/pyatmo/modules/ 0000775 0000000 0000000 00000000000 15017405234 0016605 5 ustar 00root root 0000000 0000000 pyatmo-9.2.1/src/pyatmo/modules/__init__.py 0000664 0000000 0000000 00000004144 15017405234 0020721 0 ustar 00root root 0000000 0000000 """Expose submodules."""
from .base_class import Place
from .bticino import (
BNAB,
BNAS,
BNCS,
BNCX,
BNDL,
BNEU,
BNFC,
BNIL,
BNLD,
BNMH,
BNMS,
BNSL,
BNTH,
BNTR,
BNXM,
)
from .idiamant import NBG, NBO, NBR, NBS
from .legrand import (
EBU,
NLAO,
NLAS,
NLC,
NLD,
NLDD,
NLE,
NLF,
NLFE,
NLFN,
NLG,
NLIS,
NLJ,
NLL,
NLLF,
NLLM,
NLLV,
NLM,
NLP,
NLPBS,
NLPC,
NLPD,
NLPM,
NLPO,
NLPS,
NLPT,
NLT,
NLTS,
NLUF,
NLUI,
NLUO,
NLUP,
NLV,
Z3L,
Z3V,
NLunknown,
)
from .module import Camera, Dimmer, Fan, Module, Shutter, Switch
from .netatmo import (
NAC,
NCO,
NDB,
NHC,
NIS,
NOC,
NPC,
NRV,
NSD,
OTH,
OTM,
Location,
NACamDoorTag,
NACamera,
NAMain,
NAModule1,
NAModule2,
NAModule3,
NAModule4,
NAPlug,
NATherm1,
PublicWeatherArea,
)
from .smarther import BNS
from .somfy import TPSRS
__all__ = [
"BNAB",
"BNAS",
"BNCS",
"BNCX",
"BNDL",
"BNEU",
"BNFC",
"BNIL",
"BNLD",
"BNMH",
"BNMS",
"BNS",
"BNSL",
"BNTH",
"BNTR",
"BNXM",
"EBU",
"NAC",
"NBG",
"NBO",
"NBR",
"NBS",
"NCO",
"NDB",
"NHC",
"NIS",
"NLAO",
"NLAS",
"NLC",
"NLD",
"NLDD",
"NLE",
"NLF",
"NLFE",
"NLFN",
"NLG",
"NLIS",
"NLJ",
"NLL",
"NLLF",
"NLLM",
"NLLV",
"NLM",
"NLP",
"NLPBS",
"NLPC",
"NLPD",
"NLPM",
"NLPO",
"NLPS",
"NLPT",
"NLT",
"NLTS",
"NLUF",
"NLUI",
"NLUO",
"NLUP",
"NLV",
"NOC",
"NPC",
"NRV",
"NSD",
"OTH",
"OTM",
"TPSRS",
"Z3L",
"Z3V",
"Camera",
"Dimmer",
"Fan",
"Location",
"Module",
"NACamDoorTag",
"NACamera",
"NAMain",
"NAModule1",
"NAModule2",
"NAModule3",
"NAModule4",
"NAPlug",
"NATherm1",
"NLunknown",
"Place",
"PublicWeatherArea",
"Shutter",
"Switch",
]
pyatmo-9.2.1/src/pyatmo/modules/base_class.py 0000664 0000000 0000000 00000014021 15017405234 0021254 0 ustar 00root root 0000000 0000000 """Base class for Netatmo entities."""
from __future__ import annotations
from abc import ABC
import bisect
from dataclasses import dataclass
import logging
from operator import itemgetter
from time import time
from typing import TYPE_CHECKING, Any
from pyatmo.const import GPS_COORDINATES_COUNT, MAX_HISTORY_TIME_FRAME, RawData
from pyatmo.event import EventTypes
from pyatmo.modules.device_types import ApplianceType, DeviceType
if TYPE_CHECKING:
from collections.abc import Callable, Iterator
from pyatmo.home import Home
from pyatmo.modules.module import ModuleT
LOG = logging.getLogger(__name__)
NETATMO_ATTRIBUTES_MAP = {
"entity_id": lambda x, y: x.get("id", y),
"modules": lambda x, y: x.get("modules_bridged", y),
"device_type": lambda x, y: DeviceType(x.get("type", y)),
"event_type": lambda x, y: EventTypes(x.get("type", y)),
"reachable": lambda x, _: x.get("reachable", False),
"monitoring": lambda x, _: x.get("monitoring", False) == "on",
"battery_level": lambda x, _: x.get("battery_vp", x.get("battery_level")),
"place": lambda x, _: Place(x.get("place")),
"target_position__step": lambda x, _: x.get("target_position:step"),
"appliance_type": lambda x, y: ApplianceType(x.get("appliance_type", y)),
}
def default(key: str, val: Any) -> Callable[[dict[str, Any], Any], Any]: # noqa: ANN401
"""Return default value."""
return lambda x, _: x.get(key, val)
def update_name(name: str, pre_fix: str) -> str:
"""Remove duplicates from string."""
if name.startswith(pre_fix):
return name
return f"{pre_fix} {name}"
class EntityBase:
"""Base class for Netatmo entities."""
entity_id: str
home: Home
bridge: str | None
history_features: set[str]
history_features_values: dict
name: str
def __init__(self, home: Home, module: ModuleT) -> None:
"""Initialize the entity."""
self.home = home
self.entity_id = module.get("id", "")
self.name = module.get("name", f"Unknown {self.entity_id}")
self.bridge = None
self.history_features = set()
self.history_features_values = {}
def has_feature(self, feature: str) -> bool:
"""Check if the entity has the given feature."""
return hasattr(self, feature) or feature in self.history_features
class NetatmoBase(EntityBase, ABC):
"""Base class for Netatmo entities."""
def __init__(self, raw_data: RawData) -> None:
"""Initialize a Netatmo entity."""
self.entity_id = raw_data["id"]
self.name = raw_data.get("name", f"Unknown {self.entity_id}")
self.history_features_values = {}
self.history_features = set()
def update_topology(self, raw_data: RawData) -> None:
"""Update topology."""
self._update_attributes(raw_data)
def _update_attributes(self, raw_data: RawData) -> None:
"""Update attributes."""
self.__dict__ = {
key: NETATMO_ATTRIBUTES_MAP.get(key, default(key, val))(raw_data, val)
for key, val in self.__dict__.items()
}
now = int(time())
for hist_feature in self.history_features:
if hist_feature in self.__dict__:
val = getattr(self, hist_feature)
if val is None:
continue
self.add_history_data(hist_feature, val, now)
def add_history_data(
self,
feature: str,
value: Any, # noqa: ANN401
time: int,
) -> None:
"""Add historical data at the given time."""
# get the feature values rolling buffer
hist_f = self.history_features_values.setdefault(feature, [])
if not hist_f or hist_f[-1][0] <= time:
hist_f.append((time, value, self.entity_id))
else:
i = bisect.bisect_left(hist_f, time, key=itemgetter(0))
if i < len(hist_f) and hist_f[i][0] == time:
hist_f[i] = (time, value, self.entity_id)
else:
hist_f.insert(i, (time, value, self.entity_id))
# keep timing history to a maximum representative time
while len(hist_f) > 0 and hist_f[-1][0] - hist_f[0][0] > MAX_HISTORY_TIME_FRAME:
hist_f.pop(0)
def get_history_data(
self,
feature: str,
from_ts: float,
to_ts: float | None = None,
) -> list[Any]:
"""Retrieve historical data."""
hist_f = self.history_features_values.get(feature, [])
if not hist_f:
return []
in_s = bisect.bisect_left(hist_f, from_ts, key=itemgetter(0))
if to_ts is None:
out_s = len(hist_f)
else:
out_s = bisect.bisect_right(hist_f, to_ts, key=itemgetter(0))
return hist_f[in_s:out_s]
@dataclass
class Location:
"""Class of Netatmo public weather location."""
latitude: float
longitude: float
def __init__(self, longitude: float, latitude: float) -> None:
"""Initialize self."""
self.latitude = latitude
self.longitude = longitude
def __iter__(self) -> Iterator[float]:
"""Iterate over latitude and longitude."""
yield self.longitude
yield self.latitude
@dataclass
class Place:
"""Class of Netatmo public weather place."""
altitude: int | None
city: str | None
country: str | None
timezone: str | None
location: Location | None
def __init__(
self,
data: dict[str, Any] | None,
) -> None:
"""Initialize self."""
if data is None:
LOG.debug("Place data is unknown")
return
if (location := data.get("location")) is None or len(
list(location),
) != GPS_COORDINATES_COUNT:
LOG.debug("Invalid location data: %s", data)
return
self.altitude = data.get("altitude")
self.city = data.get("city")
self.country = data.get("country")
self.timezone = data.get("timezone")
location_data = list(location)
self.location = Location(location_data[0], location_data[1])
pyatmo-9.2.1/src/pyatmo/modules/bticino.py 0000664 0000000 0000000 00000002215 15017405234 0020606 0 ustar 00root root 0000000 0000000 """Module to represent BTicino modules."""
from __future__ import annotations
import logging
from pyatmo.modules.module import (
DimmableMixin,
Module,
Shutter,
ShutterMixin,
Switch,
SwitchMixin,
)
LOG = logging.getLogger(__name__)
class BNDL(Module):
"""BTicino door lock."""
class BNSL(Switch):
"""BTicino staircase light."""
class BNCX(Module):
"""BTicino internal panel = gateway."""
class BNEU(Module):
"""BTicino external unit."""
class BNCS(Switch):
"""Bticino module Controlled Socket."""
class BNXM(Module):
"""BTicino X meter."""
class BNMS(Shutter):
"""BTicino motorized shade."""
class BNAS(ShutterMixin, Module):
"""BTicino automatic shutter."""
class BNAB(Shutter):
"""BTicino automatic blind."""
class BNMH(Module):
"""BTicino MyHome server."""
class BNTH(Module):
"""BTicino thermostat."""
class BNFC(Module):
"""BTicino fan coil."""
class BNTR(Module):
"""BTicino radiator thermostat."""
class BNIL(SwitchMixin, Module):
"""BTicino intelligent light."""
class BNLD(DimmableMixin, SwitchMixin, Module):
"""BTicino dimmer light."""
pyatmo-9.2.1/src/pyatmo/modules/device_types.py 0000664 0000000 0000000 00000030463 15017405234 0021650 0 ustar 00root root 0000000 0000000 """Definitions of Netatmo devices types."""
from __future__ import annotations
from enum import Enum
import logging
from typing import Literal
LOG = logging.getLogger(__name__)
class DeviceType(str, Enum):
"""Class to represent Netatmo device types."""
# Climate/Energy
NAPlug = "NAPlug" # Smart thermostat gateway
NATherm1 = "NATherm1" # Smart thermostat
NRV = "NRV" # Smart valve
NAC = "NAC" # Smart AC control
OTH = "OTH" # OpenTherm gateway
OTM = "OTM" # OpenTherm modulating thermostat
# Cameras/Security
NACamDoorTag = "NACamDoorTag" # Smart Door and Window Sensors
NACamera = "NACamera" # Smart Indoor Camera
NCO = "NCO" # Smart Carbon Monoxide Alarm
NDB = "NDB" # Smart Video Doorbell
NIS = "NIS" # Smart Indoor Siren
NOC = "NOC" # Smart Outdoor Camera (with Siren)
NPC = "NPC" # Indoor Camera Advance
NSD = "NSD" # Smart Smoke Detector
# Weather
NAMain = "NAMain" # Smart Home Weather Station
NAModule1 = "NAModule1"
NAModule2 = "NAModule2"
NAModule3 = "NAModule3"
NAModule4 = "NAModule4"
public = "public"
# Home Coach
NHC = "NHC" # Smart Indoor Air Quality Monitor
# Legrand Wiring devices and electrical panel products
NLC = "NLC" # Cable outlet
NLD = "NLD" # Remote control double on off dimmer
NLDD = "NLDD" # Dimmer
NLE = "NLE" # Connected Ecometer
NLF = "NLF" # Dimmer Light Switch
NLFE = "NLFE" # Dimmer Light Switch Evolution
NLFN = "NLFN" # light switch with neutral
NLG = "NLG" # Gateway
NLGS = "NLGS" # Gateway standalone
NLIS = "NLIS" # Double light switch
NLL = "NLL" # Italian light switch with neutral
NLLM = "NLLM" # Legrand / BTicino shutters
NLLV = "NLLV" # Legrand / BTicino shutters
NLM = "NLM" # light micro module
NLP = "NLP" # Plug
NLPBS = "NLPBS" # British standard plugs
NLPC = "NLPC" # Connected energy meter
NLPD = "NLPD" # Dry contact
NLPM = "NLPM" # mobile plug
NLPO = "NLPO" # Connected contactor
NLPS = "NLPS" # Smart Load Shedder
NLPT = "NLPT" # Connected latching relay / Telerupt
NLT = "NLT" # Remote control
NLV = "NLV" # Legrand / BTicino shutters
NLAO = "NLAO" # Legrand wireless batteryless light switch
NLUO = "NLUO" # Legrand Plug-In dimmer switch
NLUI = "NLUI" # Legrand In-Wall ON/OFF switch
NLunknown = "NLunknown" # Legrand device stub
NLUF = "NLUF" # Legrand device stub
NLAS = "NLAS" # Legrand wireless batteryless scene switch
NLUP = "NLUP" # Legrand device stub
NLLF = "NLLF" # Legrand Centralized Ventilation Control
NLTS = "NLTS" # Legrand motion sensor stub
NLJ = "NLJ" # Legrand garage door opener
# BTicino Classe 300 EOS
BNCX = "BNCX" # internal panel = gateway
BNDL = "BNDL" # door lock
BNEU = "BNEU" # external unit
BNSL = "BNSL" # staircase light
BNCS = "BNCS" # Controlled Socket
BNXM = "BNXM" # X meter
BNMS = "BNMS" # motorized shade
BNAS = "BNAS" # automatic shutter
BNAB = "BNAB" # automatic blind
BNMH = "BNMH" # MyHome server
BNTH = "BNTH" # thermostat
BNFC = "BNFC" # fan coil
BNTR = "BNTR" # radiator
BNIL = "BNIL" # intelligent light
BNLD = "BNLD" # dimmer light
# Bubbendorf shutters
NBG = "NBG" # gateway
NBO = "NBO" # orientable shutter
NBR = "NBR" # roller shutter
NBS = "NBS" # swing shutter
# Somfy
TPSRS = "TPSRS" # Somfy io shutter
# 3rd Party
BNS = "BNS" # Smarther with Netatmo
EBU = "EBU" # EBU gas meter
Z3L = "Z3L" # Zigbee 3 Light
Z3V = "Z3V" # Zigbee 3 roller shutter
# Magellan
NLDP = "NLDP" # Pocket Remote
@classmethod
def _missing_(cls, key: object) -> Literal[DeviceType.NLunknown]:
"""Handle unknown device types."""
msg = f"{key} device is unknown"
LOG.warning(msg)
return DeviceType.NLunknown
class DeviceCategory(str, Enum):
"""Class to represent Netatmo device types."""
# temporarily disable locally-disabled and locally-enabled
climate = "climate"
camera = "camera"
siren = "siren"
shutter = "shutter"
lock = "lock"
switch = "switch"
sensor = "sensor"
weather = "weather"
air_care = "air_care"
meter = "meter"
dimmer = "dimmer"
opening = "opening"
fan = "fan"
DEVICE_CATEGORY_MAP: dict[DeviceType, DeviceCategory] = {
DeviceType.NRV: DeviceCategory.climate,
DeviceType.NAC: DeviceCategory.climate,
DeviceType.NATherm1: DeviceCategory.climate,
DeviceType.OTM: DeviceCategory.climate,
DeviceType.NOC: DeviceCategory.camera,
DeviceType.NPC: DeviceCategory.camera,
DeviceType.NACamDoorTag: DeviceCategory.opening,
DeviceType.NACamera: DeviceCategory.camera,
DeviceType.NDB: DeviceCategory.camera,
DeviceType.NAMain: DeviceCategory.weather,
DeviceType.NAModule1: DeviceCategory.weather,
DeviceType.NAModule2: DeviceCategory.weather,
DeviceType.NAModule3: DeviceCategory.weather,
DeviceType.NAModule4: DeviceCategory.weather,
DeviceType.NHC: DeviceCategory.air_care,
DeviceType.NLV: DeviceCategory.shutter,
DeviceType.NLLV: DeviceCategory.shutter,
DeviceType.NLLM: DeviceCategory.shutter,
DeviceType.NBR: DeviceCategory.shutter,
DeviceType.NBO: DeviceCategory.shutter,
DeviceType.NLP: DeviceCategory.switch,
DeviceType.NLPM: DeviceCategory.switch,
DeviceType.NLPBS: DeviceCategory.switch,
DeviceType.NLIS: DeviceCategory.switch,
DeviceType.NLL: DeviceCategory.switch,
DeviceType.NLM: DeviceCategory.switch,
DeviceType.NLC: DeviceCategory.switch,
DeviceType.NLFN: DeviceCategory.dimmer,
DeviceType.NLF: DeviceCategory.dimmer,
DeviceType.NLFE: DeviceCategory.dimmer,
DeviceType.BNS: DeviceCategory.climate,
DeviceType.NLPC: DeviceCategory.meter,
DeviceType.NLE: DeviceCategory.meter,
DeviceType.Z3L: DeviceCategory.dimmer,
DeviceType.Z3V: DeviceCategory.shutter,
DeviceType.NLUP: DeviceCategory.switch,
DeviceType.NLPO: DeviceCategory.switch,
DeviceType.TPSRS: DeviceCategory.shutter,
DeviceType.NLUO: DeviceCategory.dimmer,
DeviceType.NLUI: DeviceCategory.switch,
DeviceType.NLUF: DeviceCategory.dimmer,
DeviceType.NLPS: DeviceCategory.meter,
DeviceType.NLDD: DeviceCategory.switch,
DeviceType.NLPT: DeviceCategory.switch,
DeviceType.BNMS: DeviceCategory.shutter,
DeviceType.BNAS: DeviceCategory.shutter,
DeviceType.BNAB: DeviceCategory.shutter,
DeviceType.BNTH: DeviceCategory.climate,
DeviceType.BNFC: DeviceCategory.climate,
DeviceType.BNTR: DeviceCategory.climate,
DeviceType.NLPD: DeviceCategory.switch,
DeviceType.NLJ: DeviceCategory.shutter,
DeviceType.BNIL: DeviceCategory.switch,
DeviceType.BNLD: DeviceCategory.dimmer,
DeviceType.NIS: DeviceCategory.siren,
DeviceType.BNCS: DeviceCategory.switch,
DeviceType.NLLF: DeviceCategory.fan,
}
DEVICE_DESCRIPTION_MAP: dict[DeviceType, tuple[str, str]] = {
# Netatmo Climate/Energy
DeviceType.NAPlug: ("Netatmo", "Smart Thermostat Gateway"),
DeviceType.NATherm1: ("Netatmo", "Smart Thermostat"),
DeviceType.NRV: ("Netatmo", "Smart Valve"),
DeviceType.NAC: ("Netatmo", "Smart AC Control"),
DeviceType.OTH: ("Netatmo", "OpenTherm Gateway"),
DeviceType.OTM: ("Netatmo", "OpenTherm Modulating Thermostat"),
# Netatmo Cameras/Security
DeviceType.NOC: ("Netatmo", "Smart Outdoor Camera"),
DeviceType.NPC: ("Netatmo", "Indoor Camera Advance"),
DeviceType.NACamera: ("Netatmo", "Smart Indoor Camera"),
DeviceType.NSD: ("Netatmo", "Smart Smoke Detector"),
DeviceType.NIS: ("Netatmo", "Smart Indoor Siren"),
DeviceType.NACamDoorTag: ("Netatmo", "Smart Door/Window Sensors"),
DeviceType.NDB: ("Netatmo", "Smart Video Doorbell"),
DeviceType.NCO: ("Netatmo", "Smart Carbon Monoxide Alarm"),
# Netatmo Weather
DeviceType.NAMain: ("Netatmo", "Smart Home Weather station"),
DeviceType.NAModule1: ("Netatmo", "Smart Outdoor Module"),
DeviceType.NAModule2: ("Netatmo", "Smart Anemometer"),
DeviceType.NAModule3: ("Netatmo", "Smart Rain Gauge"),
DeviceType.NAModule4: ("Netatmo", "Smart Indoor Module"),
DeviceType.public: ("Netatmo", "Public Weather station"),
# Netatmo Home Coach
DeviceType.NHC: ("Netatmo", "Smart Indoor Air Quality Monitor"),
# Legrand Wiring devices and electrical panel products
DeviceType.NLG: ("Legrand", "Gateway"),
DeviceType.NLGS: ("Legrand", "Gateway standalone"),
DeviceType.NLP: ("Legrand", "Plug"),
DeviceType.NLPM: ("Legrand", "Mobile plug"),
DeviceType.NLPBS: ("Legrand", "British standard plugs"),
DeviceType.NLF: ("Legrand", "2 wire light switch/dimmer"),
DeviceType.NLFE: ("Legrand", "2 wire light switch/dimmer evolution"),
DeviceType.NLIS: ("Legrand", "Double switch"),
DeviceType.NLFN: ("Legrand", "Light switch/dimmer with neutral"),
DeviceType.NLM: ("Legrand", "Light micro module"),
DeviceType.NLL: ("Legrand", "Italian light switch with neutral"),
DeviceType.NLLF: ("Legrand", "Centralized ventilation device"),
DeviceType.NLV: ("Legrand/BTicino", "Shutters"),
DeviceType.NLLV: ("Legrand/BTicino", "Shutters"),
DeviceType.NLLM: ("Legrand/BTicino", "Shutters"),
DeviceType.NLPO: ("Legrand", "Connected Contactor"),
DeviceType.NLPT: ("Legrand", "Connected Latching Relay"),
DeviceType.NLPC: ("Legrand", "Connected Energy Meter"),
DeviceType.NLE: ("Legrand", "Connected Ecometer"),
DeviceType.NLPS: ("Legrand", "Smart Load Shedder"),
DeviceType.NLC: ("Legrand", "Cable Outlet"),
DeviceType.NLT: ("Legrand", "Global Remote Control"),
DeviceType.NLAS: ("Legrand", "Wireless batteryless scene switch"),
DeviceType.NLD: ("Legrand", "Remote Control"),
DeviceType.NLDD: ("Legrand", "Dimmer"),
DeviceType.NLUP: ("Legrand", "Power outlet"),
DeviceType.NLUO: ("Legrand", "Plug-In dimmer switch"),
DeviceType.NLUI: ("Legrand", "In-wall switch"),
DeviceType.NLTS: ("Legrand", "Motion sensor"),
DeviceType.NLUF: ("Legrand", "In-Wall dimmer"),
DeviceType.NLJ: ("Legrand", "Garage door opener"),
# BTicino Classe 300 EOS
DeviceType.BNCX: ("BTicino", "Internal Panel"),
DeviceType.BNEU: ("BTicino", "External Unit"),
DeviceType.BNDL: ("BTicino", "Door Lock"),
DeviceType.BNSL: ("BTicino", "Staircase Light"),
DeviceType.BNMS: ("BTicino", "Motorized Shade"),
DeviceType.BNAS: ("BTicino", "Automatic Shutter"),
DeviceType.BNAB: ("BTicino", "Automatic Blind"),
DeviceType.BNMH: ("BTicino", "MyHome server 1"),
DeviceType.BNTH: ("BTicino", "Thermostat"),
DeviceType.BNFC: ("BTicino", "Fan coil"),
DeviceType.BNTR: ("BTicino", "Module towel rail"),
DeviceType.BNIL: ("BTicino", "Intelligent light"),
DeviceType.BNLD: ("BTicino", "Dimmer"),
DeviceType.BNCS: ("BTicino", "Controlled socket"),
# Bubbendorf shutters
DeviceType.NBG: ("Bubbendorf", "Gateway"),
DeviceType.NBR: ("Bubbendorf", "Roller Shutter"),
DeviceType.NBO: ("Bubbendorf", "Orientable Shutter"),
DeviceType.NBS: ("Bubbendorf", "Swing Shutter"),
# Somfy
DeviceType.TPSRS: ("Somfy", "io Shutter"),
# 3rd Party
DeviceType.BNS: ("Smarther", "Smarther with Netatmo"),
DeviceType.Z3L: ("3rd Party", "Zigbee 3 Light"),
DeviceType.Z3V: ("3rd Party", "Zigbee 3 roller shutter"),
DeviceType.EBU: ("3rd Party", "EBU gas meter"),
DeviceType.NLPD: ("Drivia", "Dry contact"),
}
class ApplianceType(str, Enum):
"""Class to represent appliance type of a module. This is only for Home + Control."""
# temporarily disable locally-disabled and locally-enabled
light = "light"
fridge_freezer = "fridge_freezer"
oven = "oven"
washing_machine = "washing_machine"
tumble_dryer = "tumble_dryer"
dishwasher = "dishwasher"
multimedia = "multimedia"
router = "router"
other = "other"
ooking = "cooking"
radiator = "radiator"
radiator_without_pilot_wire = "radiator_without_pilot_wire"
water_heater = "water_heater"
extractor_hood = "extractor_hood"
contactor = "contactor"
dryer = "dryer"
electric_charger = "electric_charger"
unknown = "unknown"
@classmethod
def _missing_(cls, key: object) -> Literal[ApplianceType.unknown]:
"""Handle unknown device types."""
msg = f"{key} appliance type is unknown"
LOG.warning(msg)
return ApplianceType.unknown
pyatmo-9.2.1/src/pyatmo/modules/idiamant.py 0000664 0000000 0000000 00000001213 15017405234 0020742 0 ustar 00root root 0000000 0000000 """Module to represent iDiamant modules."""
from __future__ import annotations
import logging
from pyatmo.modules.module import (
FirmwareMixin,
Module,
RfMixin,
ShutterMixin,
WifiMixin,
)
LOG = logging.getLogger(__name__)
class NBG(FirmwareMixin, WifiMixin, Module):
"""Class to represent a iDiamant NBG."""
class NBR(FirmwareMixin, RfMixin, ShutterMixin, Module):
"""Class to represent a iDiamant NBR."""
class NBO(FirmwareMixin, RfMixin, ShutterMixin, Module):
"""Class to represent a iDiamant NBO."""
class NBS(FirmwareMixin, RfMixin, ShutterMixin, Module):
"""Class to represent a iDiamant NBS."""
pyatmo-9.2.1/src/pyatmo/modules/legrand.py 0000664 0000000 0000000 00000007316 15017405234 0020602 0 ustar 00root root 0000000 0000000 """Module to represent Legrand modules."""
from __future__ import annotations
import logging
from typing import TYPE_CHECKING
from pyatmo.modules.module import (
BatteryMixin,
ContactorMixin,
Dimmer,
EnergyHistoryLegacyMixin,
EnergyHistoryMixin,
Fan,
FirmwareMixin,
Module,
ModuleT,
OffloadMixin,
PowerMixin,
RemoteControlMixin,
ShutterMixin,
Switch,
SwitchMixin,
WifiMixin,
)
if TYPE_CHECKING:
from pyatmo.home import Home
LOG = logging.getLogger(__name__)
class NLG(FirmwareMixin, OffloadMixin, WifiMixin, Module):
"""Legrand gateway."""
class NLT(RemoteControlMixin, BatteryMixin):
"""Legrand global remote control...but also wireless switch, like NLD."""
class NLP(OffloadMixin, Switch):
"""Legrand plug."""
class NLPM(OffloadMixin, Switch):
"""Legrand mobile plug."""
class NLPO(ContactorMixin, OffloadMixin, Switch):
"""Legrand contactor."""
class NLPT(OffloadMixin, Switch):
"""Legrand latching relay/teleruptor."""
class NLPBS(Switch):
"""Legrand british standard plug."""
class NLF(Dimmer):
"""Legrand 2 wire light switch."""
class NLFN(Dimmer):
"""Legrand light switch with neutral."""
class NLFE(Dimmer):
"""Legrand On-Off dimmer switch evolution."""
class NLM(Switch):
"""Legrand light micro module."""
class NLIS(Switch):
"""Legrand double switch."""
def __init__(self, home: Home, module: ModuleT) -> None:
"""Initialize NLIS module."""
super().__init__(home, module)
if "#" not in self.entity_id:
# This is a workaround for the fact the this module type has three entries in the API
# but one of them is not a light switch
self.device_category = None
class NLD(RemoteControlMixin, BatteryMixin):
"""Legrand Double On/Off dimmer remote. Wireless 2 button switch light."""
class NLL(Switch):
"""Legrand / BTicino italian light switch with neutral."""
class NLV(FirmwareMixin, ShutterMixin, Module):
"""Legrand / BTicino shutters."""
class NLLV(FirmwareMixin, ShutterMixin, Module):
"""Legrand / BTicino shutters."""
class NLLM(FirmwareMixin, ShutterMixin, Module):
"""Legrand / BTicino shutters."""
class NLPC(FirmwareMixin, EnergyHistoryMixin, PowerMixin, Module):
"""Legrand / BTicino connected energy meter."""
class NLE(FirmwareMixin, EnergyHistoryLegacyMixin, Module):
"""Legrand / BTicino connected ecometer. no power supported for the NLE (in the home status API)."""
class NLPS(FirmwareMixin, EnergyHistoryMixin, PowerMixin, Module):
"""Legrand / BTicino smart load shedder."""
class NLC(OffloadMixin, Switch):
"""Legrand / BTicino cable outlet."""
class NLDD(RemoteControlMixin):
"""Legrand NLDD dimmer remote control."""
class NLUP(Switch):
"""Legrand NLUP Power outlet."""
class NLAO(RemoteControlMixin):
"""Legrand wireless batteryless light switch."""
class NLUI(FirmwareMixin, SwitchMixin, Module):
"""Legrand NLUI in-wall switch."""
class NLUF(Dimmer):
"""Legrand NLUF device stub."""
class NLUO(Dimmer):
"""Legrand NLUO device stub."""
class NLLF(Fan, PowerMixin, EnergyHistoryMixin):
"""Legrand NLLF fan/ventilation device."""
class NLunknown(Module):
"""NLunknown device stub."""
class NLAS(RemoteControlMixin):
"""NLAS wireless batteryless scene switch."""
class Z3L(Dimmer):
"""Zigbee 3 Light."""
class Z3V(FirmwareMixin, ShutterMixin, Module):
"""Zigbee 3 roller shutter."""
class EBU(Module):
"""EBU gas meter."""
class NLTS(Module):
"""NLTS motion sensor."""
class NLPD(OffloadMixin, Switch):
"""NLPD dry contact."""
class NLJ(FirmwareMixin, ShutterMixin, Module):
"""Legrand garage door opener."""
pyatmo-9.2.1/src/pyatmo/modules/module.py 0000664 0000000 0000000 00000106413 15017405234 0020451 0 ustar 00root root 0000000 0000000 """Module to represent a Netatmo module."""
from __future__ import annotations
from datetime import UTC, datetime, timedelta
from enum import Enum
import logging
from operator import itemgetter
from time import time
from typing import TYPE_CHECKING, Any, LiteralString
from aiohttp import ClientConnectorError
from pyatmo.const import GETMEASURE_ENDPOINT, RawData
from pyatmo.exceptions import ApiError
from pyatmo.modules.base_class import EntityBase, NetatmoBase, Place, update_name
from pyatmo.modules.device_types import (
DEVICE_CATEGORY_MAP,
ApplianceType,
DeviceCategory,
DeviceType,
)
if TYPE_CHECKING:
from pyatmo.event import Event
from pyatmo.home import Home
LOG = logging.getLogger(__name__)
ModuleT = dict[str, Any]
# Hide from features list
ATTRIBUTE_FILTER = {
"battery_state",
"battery_level",
"battery_percent",
"date_min_temp",
"date_max_temp",
"name",
"entity_id",
"device_id",
"modules",
"firmware_revision",
"firmware_name",
"home",
"bridge",
"room_id",
"device_category",
"device_type",
"features",
"history_features",
"history_features_values",
"appliance_type",
}
def process_battery_state(data: str) -> int:
"""Process battery data and return percent (int) for display."""
mapping = {
"max": 100,
"full": 90,
"high": 75,
"medium": 50,
"low": 25,
"very_low": 10,
}
return mapping[data]
class FirmwareMixin(EntityBase):
"""Mixin for firmware data."""
def __init__(self, home: Home, module: ModuleT) -> None:
"""Initialize firmware mixin."""
super().__init__(home, module)
self.firmware_revision: int | None = None
self.firmware_name: str | None = None
class WifiMixin(EntityBase):
"""Mixin for wifi data."""
def __init__(self, home: Home, module: ModuleT) -> None:
"""Initialize wifi mixin."""
super().__init__(home, module)
self.wifi_strength: int | None = None
class RfMixin(EntityBase):
"""Mixin for rf data."""
def __init__(self, home: Home, module: ModuleT) -> None:
"""Initialize rf mixin."""
super().__init__(home, module)
self.rf_strength: int | None = None
class RainMixin(EntityBase):
"""Mixin for rain data."""
def __init__(self, home: Home, module: ModuleT) -> None:
"""Initialize rain mixin."""
super().__init__(home, module)
self.rain: float | None = None
self.sum_rain_1: float | None = None
self.sum_rain_24: float | None = None
class WindMixin(EntityBase):
"""Mixin for wind data."""
def __init__(self, home: Home, module: ModuleT) -> None:
"""Initialize wind mixin."""
super().__init__(home, module)
self.wind_strength: int | None = None
self.wind_angle: int | None = None
self.gust_strength: int | None = None
self.gust_angle: int | None = None
@property
def wind_direction(self) -> str | None:
"""Return wind direction."""
return None if self.wind_angle is None else process_angle(self.wind_angle)
@property
def gust_direction(self) -> str | None:
"""Return gust direction."""
return None if self.gust_angle is None else process_angle(self.gust_angle)
def process_angle(angle: int) -> str:
"""Process angle and return string for display."""
angle_mapping = {
(0, 30): "N",
(30, 60): "NE",
(60, 120): "E",
(120, 150): "SE",
(150, 210): "S",
(210, 240): "SW",
(240, 300): "W",
(300, 330): "NW",
(330, 360): "N",
}
for (lower, upper), direction in angle_mapping.items():
if lower <= angle < upper:
return direction
return "N" # Default case
class TemperatureMixin(EntityBase):
"""Mixin for temperature data."""
def __init__(self, home: Home, module: ModuleT) -> None:
"""Initialize temperature mixin."""
super().__init__(home, module)
self.temperature: float | None = None
self.temp_min: float | None = None
self.temp_max: float | None = None
self.temp_trend: str | None = None
self.min_temp: float | None = None
self.max_temp: float | None = None
self.date_min_temp: int | None = None
self.date_max_temp: int | None = None
class HumidityMixin(EntityBase):
"""Mixin for humidity data."""
def __init__(self, home: Home, module: ModuleT) -> None:
"""Initialize humidity mixin."""
super().__init__(home, module)
self.humidity: int | None = None
class CO2Mixin(EntityBase):
"""Mixin for CO2 data."""
def __init__(self, home: Home, module: ModuleT) -> None:
"""Initialize CO2 mixin."""
super().__init__(home, module)
self.co2: int | None = None
class HealthIndexMixin(EntityBase):
"""Mixin for health index data."""
def __init__(self, home: Home, module: ModuleT) -> None:
"""Initialize health index mixin."""
super().__init__(home, module)
self.health_idx: int | None = None
class NoiseMixin(EntityBase):
"""Mixin for noise data."""
def __init__(self, home: Home, module: ModuleT) -> None:
"""Initialize noise mixin."""
super().__init__(home, module)
self.noise: int | None = None
class PressureMixin(EntityBase):
"""Mixin for pressure data."""
def __init__(self, home: Home, module: ModuleT) -> None:
"""Initialize pressure mixin."""
super().__init__(home, module)
self.pressure: float | None = None
self.absolute_pressure: float | None = None
self.pressure_trend: str | None = None
class BoilerMixin(EntityBase):
"""Mixin for boiler data."""
def __init__(self, home: Home, module: ModuleT) -> None:
"""Initialize boiler mixin."""
super().__init__(home, module)
self.boiler_status: bool | None = None
self.boiler_valve_comfort_boost: bool | None = None
class CoolerMixin(EntityBase):
"""Mixin for cooler data."""
def __init__(self, home: Home, module: ModuleT) -> None:
"""Initialize cooler mixin."""
super().__init__(home, module)
self.cooler_status: bool | None = None
class BatteryMixin(EntityBase):
"""Mixin for battery data."""
def __init__(self, home: Home, module: ModuleT) -> None:
"""Initialize battery mixin."""
super().__init__(home, module)
self.battery_state: str | None = None
self.battery_level: int | None = None
self.battery_percent: int | None = None
@property
def battery(self) -> int:
"""Return battery percent."""
if self.battery_percent is not None:
return self.battery_percent
if self.battery_state is None:
return 0
return process_battery_state(self.battery_state)
class PlaceMixin(EntityBase):
"""Mixin for place data."""
def __init__(self, home: Home, module: ModuleT) -> None:
"""Initialize place mixin."""
super().__init__(home, module)
self.place: Place | None = None
class DimmableMixin(EntityBase):
"""Mixin for dimmable data."""
def __init__(self, home: Home, module: ModuleT) -> None:
"""Initialize dimmable mixin."""
super().__init__(home, module)
self.brightness: int | None = None
async def async_set_brightness(self, brightness: int) -> bool:
"""Set brightness."""
json_brightness = {
"modules": [
{
"id": self.entity_id,
"brightness": max(min(100, brightness), -1),
"bridge": self.bridge,
},
],
}
return await self.home.async_set_state(json_brightness)
class ApplianceTypeMixin(EntityBase):
"""Mixin for appliance type data."""
device_category: DeviceCategory | None
appliance_type: ApplianceType | None
def __init__(self, home: Home, module: ModuleT) -> None:
"""Initialize appliance type mixin."""
super().__init__(home, module)
self.appliance_type: ApplianceType | None = module.get(
"appliance_type",
ApplianceType.unknown,
)
class PowerMixin(EntityBase):
"""Mixin for power data."""
def __init__(self, home: Home, module: ModuleT) -> None:
"""Initialize power mixin."""
super().__init__(home, module)
self.power: int | None = None
self.history_features.add("power")
class EventMixin(EntityBase):
"""Mixin for event data."""
def __init__(self, home: Home, module: ModuleT) -> None:
"""Initialize event mixin."""
super().__init__(home, module)
self.events: list[Event] = []
class ContactorMixin(EntityBase):
"""Mixin for contactor data."""
def __init__(self, home: Home, module: ModuleT) -> None:
"""Initialize contactor mixin."""
super().__init__(home, module)
self.contactor_mode: str | None = None
class OffloadMixin(EntityBase):
"""Mixin for offload data."""
def __init__(self, home: Home, module: ModuleT) -> None:
"""Initialize offload mixin."""
super().__init__(home, module)
self.offload: bool | None = None
class SwitchMixin(EntityBase):
"""Mixin for switch data."""
def __init__(self, home: Home, module: ModuleT) -> None:
"""Initialize switch mixin."""
super().__init__(home, module)
self.on: bool | None = None
async def async_set_switch(self, target_position: bool) -> bool:
"""Set switch to target position."""
json_switch = {
"modules": [
{
"id": self.entity_id,
"on": target_position,
"bridge": self.bridge,
},
],
}
return await self.home.async_set_state(json_switch)
async def async_on(self) -> bool:
"""Switch on."""
return await self.async_set_switch(True)
async def async_off(self) -> bool:
"""Switch off."""
return await self.async_set_switch(False)
class FanSpeedMixin(EntityBase):
"""Mixin for fan speed data."""
def __init__(self, home: Home, module: ModuleT) -> None:
"""Initialize fan speed mixin."""
super().__init__(home, module)
self.fan_speed: int | None = None
async def async_set_fan_speed(self, speed: int) -> bool:
"""Set fan speed."""
json_fan_speed = {
"modules": [
{
"id": self.entity_id,
# fan speed is clamped between 1 and 2
# since only NLLF is such a device
# and it can only supports fan_speed 1 or 2
"fan_speed": max(min(2, speed), 1),
"bridge": self.bridge,
},
],
}
return await self.home.async_set_state(json_fan_speed)
class ShutterMixin(EntityBase):
"""Mixin for shutter data."""
__open_position = 100
__close_position = 0
__stop_position = -1
__preferred_position = -2
def __init__(self, home: Home, module: ModuleT) -> None:
"""Initialize shutter mixin."""
super().__init__(home, module)
self.current_position: int | None = None
self.target_position: int | None = None
self.target_position__step: int | None = None
async def async_set_target_position(self, target_position: int) -> bool:
"""Set shutter to target position."""
# in case of a too low value, we default to stop and not the preferred position
# We check against __preferred_position that is the lower known value
if target_position < self.__preferred_position:
target_position = self.__stop_position
json_roller_shutter = {
"modules": [
{
"id": self.entity_id,
"target_position": min(self.__open_position, target_position),
"bridge": self.bridge,
},
],
}
return await self.home.async_set_state(json_roller_shutter)
async def async_open(self) -> bool:
"""Open shutter."""
return await self.async_set_target_position(self.__open_position)
async def async_close(self) -> bool:
"""Close shutter."""
return await self.async_set_target_position(self.__close_position)
async def async_stop(self) -> bool:
"""Stop shutter."""
return await self.async_set_target_position(self.__stop_position)
async def async_move_to_preferred_position(self) -> bool:
"""Move shutter to preferred position."""
return await self.async_set_target_position(self.__preferred_position)
class CameraMixin(EntityBase):
"""Mixin for camera data."""
def __init__(self, home: Home, module: ModuleT) -> None:
"""Initialize camera mixin."""
super().__init__(home, module)
self.sd_status: int | None = None
self.vpn_url: str | None = None
self.local_url: str | None = None
self.is_local: bool | None = None
self.alim_status: int | None = None
self.device_type: DeviceType
async def async_get_live_snapshot(self) -> bytes | None:
"""Fetch live camera image."""
if not self.local_url and not self.vpn_url:
return None
resp = await self.home.auth.async_get_image(
base_url=f"{self.local_url or self.vpn_url}",
endpoint="/live/snapshot_720.jpg",
)
return resp if isinstance(resp, bytes) else None
async def async_update_camera_urls(self) -> None:
"""Update and validate the camera urls."""
if self.device_type == "NDB":
self.is_local = None
if self.vpn_url and self.is_local:
temp_local_url = await self._async_check_url(self.vpn_url)
if temp_local_url:
try:
self.local_url = await self._async_check_url(
temp_local_url,
)
except (TimeoutError, ClientConnectorError) as exc:
LOG.debug("Cannot connect to %s - reason: %s", temp_local_url, exc)
self.is_local = False
self.local_url = None
async def _async_check_url(self, url: str) -> str | None:
"""Validate camera url."""
try:
resp = await self.home.auth.async_post_api_request(
base_url=f"{url}",
endpoint="/command/ping",
)
except ApiError:
LOG.debug("Api error for camera url %s", url)
return None
if isinstance(resp, bytes):
msg = "Invalid response from camera url"
raise ApiError(msg)
resp_data = await resp.json()
return resp_data.get("local_url") if resp_data else None
class FloodlightMixin(EntityBase):
"""Mixin for floodlight data."""
def __init__(self, home: Home, module: ModuleT) -> None:
"""Initialize floodlight mixin."""
super().__init__(home, module)
self.floodlight: str | None = None
async def async_set_floodlight_state(self, state: str) -> bool:
"""Set floodlight state."""
json_floodlight_state = {
"modules": [
{
"id": self.entity_id,
"floodlight": state,
},
],
}
return await self.home.async_set_state(json_floodlight_state)
async def async_floodlight_on(self) -> bool:
"""Turn on floodlight."""
return await self.async_set_floodlight_state("on")
async def async_floodlight_off(self) -> bool:
"""Turn off floodlight."""
return await self.async_set_floodlight_state("off")
async def async_floodlight_auto(self) -> bool:
"""Set floodlight to auto mode."""
return await self.async_set_floodlight_state("auto")
class StatusMixin(EntityBase):
"""Mixin for status data."""
def __init__(self, home: Home, module: ModuleT) -> None:
"""Initialize status mixin."""
super().__init__(home, module)
self.status: str | None = None
class MonitoringMixin(EntityBase):
"""Mixin for monitoring data."""
def __init__(self, home: Home, module: ModuleT) -> None:
"""Initialize monitoring mixin."""
super().__init__(home, module)
self.monitoring: bool | None = None
async def async_set_monitoring_state(self, state: str) -> bool:
"""Set monitoring state."""
json_monitoring_state = {
"modules": [
{
"id": self.entity_id,
"monitoring": state,
},
],
}
return await self.home.async_set_state(json_monitoring_state)
async def async_monitoring_on(self) -> bool:
"""Turn on monitoring."""
return await self.async_set_monitoring_state("on")
async def async_monitoring_off(self) -> bool:
"""Turn off monitoring."""
return await self.async_set_monitoring_state("off")
class MeasureInterval(Enum):
"""Measure interval."""
HALF_HOUR = "30min"
HOUR = "1hour"
THREE_HOURS = "3hours"
DAY = "1day"
WEEK = "1week"
MONTH = "1month"
class MeasureType(Enum):
"""Measure type."""
BOILERON = "boileron"
BOILEROFF = "boileroff"
SUM_BOILER_ON = "sum_boiler_on"
SUM_BOILER_OFF = "sum_boiler_off"
SUM_ENERGY_ELEC = "sum_energy_buy_from_grid"
SUM_ENERGY_ELEC_BASIC = "sum_energy_buy_from_grid$0"
SUM_ENERGY_ELEC_PEAK = "sum_energy_buy_from_grid$1"
SUM_ENERGY_ELEC_OFF_PEAK = "sum_energy_buy_from_grid$2"
SUM_ENERGY_PRICE = "sum_energy_buy_from_grid_price"
SUM_ENERGY_PRICE_BASIC = "sum_energy_buy_from_grid_price$0"
SUM_ENERGY_PRICE_PEAK = "sum_energy_buy_from_grid_price$1"
SUM_ENERGY_PRICE_OFF_PEAK = "sum_energy_buy_from_grid_price$2"
SUM_ENERGY_ELEC_LEGACY = "sum_energy_elec"
SUM_ENERGY_ELEC_BASIC_LEGACY = "sum_energy_elec$0"
SUM_ENERGY_ELEC_PEAK_LEGACY = "sum_energy_elec$1"
SUM_ENERGY_ELEC_OFF_PEAK_LEGACY = "sum_energy_elec$2"
MEASURE_INTERVAL_TO_SECONDS = {
MeasureInterval.HALF_HOUR: 1800,
MeasureInterval.HOUR: 3600,
MeasureInterval.THREE_HOURS: 10800,
MeasureInterval.DAY: 86400,
MeasureInterval.WEEK: 604800,
MeasureInterval.MONTH: 2592000,
}
ENERGY_FILTERS = f"{MeasureType.SUM_ENERGY_ELEC.value},{MeasureType.SUM_ENERGY_ELEC_BASIC.value},{MeasureType.SUM_ENERGY_ELEC_PEAK.value},{MeasureType.SUM_ENERGY_ELEC_OFF_PEAK.value}"
ENERGY_FILTERS_LEGACY = f"{MeasureType.SUM_ENERGY_ELEC_LEGACY.value},{MeasureType.SUM_ENERGY_ELEC_BASIC_LEGACY.value},{MeasureType.SUM_ENERGY_ELEC_PEAK_LEGACY.value},{MeasureType.SUM_ENERGY_ELEC_OFF_PEAK_LEGACY.value}"
ENERGY_FILTERS_MODES = ["generic", "basic", "peak", "off_peak"]
def compute_riemann_sum(
power_data: list[tuple[int, float]],
conservative: bool = False,
) -> float:
"""Compute energy from power with a rieman sum."""
delta_energy = 0.0
if power_data and len(power_data) > 1:
# compute a rieman sum, as best as possible , trapezoidal, taking pessimistic asumption
# as we don't want to artifically go up the previous one
# (except in rare exceptions like reset, 0 , etc)
for i in range(len(power_data) - 1):
dt_h = float(power_data[i + 1][0] - power_data[i][0]) / 3600.0
if conservative:
d_p_w = 0.0
else:
d_p_w = abs(float(power_data[i + 1][1] - power_data[i][1]))
d_nrj_wh = dt_h * (
min(power_data[i + 1][1], power_data[i][1]) + 0.5 * d_p_w
)
delta_energy += d_nrj_wh
return delta_energy
class EnergyHistoryMixin(EntityBase):
"""Mixin for Energy history data."""
def __init__(self, home: Home, module: ModuleT) -> None:
"""Initialize history mixin."""
super().__init__(home, module)
self.historical_data: list[dict[str, Any]] | None = None
self.start_time: float | None = None
self.end_time: float | None = None
self.interval: MeasureInterval | None = None
self.sum_energy_elec: float = 0.0
self.sum_energy_elec_peak: float = 0.0
self.sum_energy_elec_off_peak: float = 0.0
self._anchor_for_power_adjustment: float | None = None
self.in_reset: bool = False
def reset_measures(
self,
start_power_time: datetime | None,
in_reset: bool = True,
) -> None:
"""Reset energy measures."""
self.in_reset = in_reset
self.historical_data = []
self.sum_energy_elec = 0.0
self.sum_energy_elec_peak = 0.0
self.sum_energy_elec_off_peak = 0.0
if start_power_time is None:
self._anchor_for_power_adjustment = start_power_time
else:
self._anchor_for_power_adjustment = int(start_power_time.timestamp())
def get_sum_energy_elec_power_adapted(
self,
to_ts: float | None = None,
conservative: bool = False,
) -> tuple[float, float]:
"""Compute proper energy value with adaptation from power."""
v = self.sum_energy_elec
delta_energy = 0.0
if not self.in_reset:
if to_ts is None:
to_ts = int(time())
from_ts = self._anchor_for_power_adjustment
if (
from_ts is not None
and from_ts < to_ts
and isinstance(self, PowerMixin)
and isinstance(self, NetatmoBase)
):
power_data = self.get_history_data(
"power",
from_ts=from_ts,
to_ts=to_ts,
)
if isinstance(
self,
EnergyHistoryMixin,
): # well to please the linter....
delta_energy = compute_riemann_sum(power_data, conservative)
return v, delta_energy
def _log_energy_error(
self,
start_time: float,
end_time: float,
msg: str | None = None,
body: dict | None = None,
) -> None:
LOG.debug(
"ENERGY collection error %s %s %s %s %s %s %s",
msg,
self.name,
datetime.fromtimestamp(start_time),
datetime.fromtimestamp(end_time),
start_time,
end_time,
body or "NO BODY",
)
async def async_update_measures(
self,
start_time: int | None = None,
end_time: int | None = None,
interval: MeasureInterval = MeasureInterval.HOUR,
days: int = 7,
) -> None:
"""Update historical data."""
if end_time is None:
end_time = int(datetime.now().timestamp())
if start_time is None:
end = datetime.fromtimestamp(end_time)
start_time = int((end - timedelta(days=days)).timestamp())
prev_start_time = self.start_time
prev_end_time = self.end_time
self.start_time = start_time
self.end_time = end_time
# the legrand/netatmo handling of start and endtime is very peculiar
# for 30mn/1h/3h intervals : in fact the starts is asked_start + intervals/2 !
# => so shift of 15mn, 30mn and 1h30
# for 1day : start is ALWAYS 12am (half day) of the first day of the range
# for 1week : it will be half week ALWAYS, ie on a thursday at 12am (half day)
# in fact in the case for all intervals the reported dates are "the middle" of the ranges
delta_range = MEASURE_INTERVAL_TO_SECONDS.get(interval, 0) // 2
filters, raw_data = await self._energy_api_calls(start_time, end_time, interval)
hist_good_vals = await self._get_aligned_energy_values_and_mode(
start_time,
end_time,
delta_range,
raw_data,
)
prev_sum_energy_elec = self.sum_energy_elec
self.sum_energy_elec = 0.0
self.sum_energy_elec_peak = 0.0
self.sum_energy_elec_off_peak = 0.0
# no data at all: we know nothing for the end: best guess, it is the start
self._anchor_for_power_adjustment = start_time
self.in_reset = False
if len(hist_good_vals) == 0:
# nothing has been updated or changed it can nearly be seen as an error, but the api is answering correctly
# so we probably have to reset to 0 anyway as it means there were no exisitng
# historical data for this time range
LOG.debug(
"NO VALUES energy update %s from: %s to %s, prev_sum=%s",
self.name,
datetime.fromtimestamp(start_time),
datetime.fromtimestamp(end_time),
prev_sum_energy_elec if prev_sum_energy_elec is not None else "NOTHING",
)
else:
await self._prepare_exported_historical_data(
start_time,
end_time,
delta_range,
hist_good_vals,
prev_end_time or 0.0,
prev_start_time or 0.0,
prev_sum_energy_elec or 0.0,
)
async def _prepare_exported_historical_data(
self,
start_time: float,
end_time: float,
delta_range: float,
hist_good_vals: list[tuple[int, float, list[float]]],
prev_end_time: float,
prev_start_time: float,
prev_sum_energy_elec: float | None,
) -> None:
self.historical_data = []
computed_start = 0.0
computed_end = 0.0
computed_end_for_calculus = 0.0
for cur_start_time, val, vals in hist_good_vals:
self.sum_energy_elec += val
modes = []
val_modes = []
for i, v in enumerate(vals):
if v is not None:
modes.append(ENERGY_FILTERS_MODES[i])
val_modes.append(v)
if ENERGY_FILTERS_MODES[i] == "off_peak":
self.sum_energy_elec_off_peak += v
elif ENERGY_FILTERS_MODES[i] == "peak":
self.sum_energy_elec_peak += v
c_start = cur_start_time
c_end = cur_start_time + 2 * delta_range
if computed_start == 0:
computed_start = c_start
computed_end = c_end
computed_end_for_calculus = c_end
start_time_string = f"{datetime.fromtimestamp(c_start + 1, tz=UTC).isoformat().split('+')[0]}Z"
end_time_string = (
f"{datetime.fromtimestamp(c_end, tz=UTC).isoformat().split('+')[0]}Z"
)
self.historical_data.append(
{
"duration": (2 * delta_range) // 60,
"startTime": start_time_string,
"endTime": end_time_string,
"Wh": val,
"energyMode": modes,
"WhPerModes": val_modes,
"startTimeUnix": c_start,
"endTimeUnix": c_end,
},
)
if (
prev_sum_energy_elec is not None
and prev_sum_energy_elec > self.sum_energy_elec
):
msg = (
"ENERGY GOING DOWN %s from: %s to %s "
"computed_start: %s, computed_end: %s, "
"sum=%f prev_sum=%f prev_start: %s, prev_end %s"
)
LOG.debug(
msg,
self.name,
datetime.fromtimestamp(start_time),
datetime.fromtimestamp(end_time),
datetime.fromtimestamp(computed_start),
datetime.fromtimestamp(computed_end),
self.sum_energy_elec,
prev_sum_energy_elec,
datetime.fromtimestamp(prev_start_time),
datetime.fromtimestamp(prev_end_time),
)
else:
msg = (
"Success in energy update %s from: %s to %s "
"computed_start: %s, computed_end: %s , sum=%s prev_sum=%s"
)
LOG.debug(
msg,
self.name,
datetime.fromtimestamp(start_time),
datetime.fromtimestamp(end_time),
datetime.fromtimestamp(computed_start),
datetime.fromtimestamp(computed_end),
self.sum_energy_elec,
prev_sum_energy_elec if prev_sum_energy_elec is not None else "NOTHING",
)
self._anchor_for_power_adjustment = computed_end_for_calculus
async def _get_aligned_energy_values_and_mode(
self,
start_time: float,
end_time: float,
delta_range: float,
raw_data: dict,
) -> list[Any]:
hist_good_vals = []
values_lots = raw_data
for values_lot in values_lots:
try:
start_lot_time = int(values_lot["beg_time"])
except KeyError:
self._log_energy_error(
start_time,
end_time,
msg="beg_time missing",
body=values_lots,
)
msg = (
f"Energy badly formed resp beg_time missing: {values_lots} - "
f"module: {self.name}"
)
raise ApiError(
msg,
) from None
interval_sec = values_lot.get("step_time")
if interval_sec is None:
if len(values_lot.get("value", [])) > 1:
self._log_energy_error(
start_time,
end_time,
msg="step_time missing",
body=values_lots,
)
interval_sec = 2 * delta_range
else:
interval_sec = int(interval_sec)
# align the start on the begining of the segment
cur_start_time = start_lot_time - interval_sec // 2
for val_arr in values_lot.get("value", []):
vals = []
val = 0
for v in val_arr:
if v is not None:
v = int(v)
val += v
vals.append(v)
else:
vals.append(None)
hist_good_vals.append((cur_start_time, val, vals))
cur_start_time = cur_start_time + interval_sec
return sorted(hist_good_vals, key=itemgetter(0))
def _get_energy_filers(self) -> str:
return ENERGY_FILTERS
async def _energy_api_calls(
self,
start_time: float,
end_time: float,
interval: MeasureInterval,
) -> tuple[LiteralString, Any]:
filters = self._get_energy_filers()
params = {
"device_id": self.bridge,
"module_id": self.entity_id,
"scale": interval.value,
"type": filters,
"date_begin": start_time,
"date_end": end_time,
}
resp = await self.home.auth.async_post_api_request(
endpoint=GETMEASURE_ENDPOINT,
params=params,
)
rw_dt_f = await resp.json()
rw_dt = rw_dt_f.get("body")
if rw_dt is None:
self._log_energy_error(
start_time,
end_time,
msg=f"direct from {filters}",
body=rw_dt_f,
)
msg = (
f"Energy badly formed resp: {rw_dt_f} - "
f"module: {self.name} - "
f"when accessing '{filters}'"
)
raise ApiError(msg)
raw_data = rw_dt
return filters, raw_data
class EnergyHistoryLegacyMixin(EnergyHistoryMixin):
"""Mixin for Energy history data, Using legacy APis (used for NLE)."""
def _get_energy_filers(self) -> str:
return ENERGY_FILTERS_LEGACY
class Module(NetatmoBase):
"""Class to represent a Netatmo module."""
device_type: DeviceType
device_category: DeviceCategory | None
room_id: str | None
modules: list[str] | None
reachable: bool | None
features: set[str]
def __init__(self, home: Home, module: ModuleT) -> None:
"""Initialize a Netatmo module instance."""
super().__init__(module)
self.device_type = DeviceType(module["type"])
self.home = home
self.room_id = module.get("room_id")
self.reachable = module.get("reachable")
self.bridge = module.get("bridge")
self.modules = module.get("modules_bridged")
self.device_category = DEVICE_CATEGORY_MAP.get(self.device_type)
self.features = set()
async def update(self, raw_data: RawData) -> None:
"""Update module with the latest data."""
self.update_topology(raw_data)
if (
self.bridge
and self.bridge in self.home.modules
and hasattr(self, "device_category")
and self.device_category == "weather"
):
self.name = update_name(self.name, self.home.modules[self.bridge].name)
self.update_features()
# If we have an NLE as a bridge all its bridged modules will have to be reachable
if self.device_type == DeviceType.NLE:
# if there is a bridge it means it is a leaf
if self.bridge:
self.reachable = True
elif self.modules:
# this NLE is a bridge itself : make it not available
self.reachable = False
if not self.reachable and self.modules:
# Update bridged modules and associated rooms
for module_id in self.modules:
module = self.home.modules[module_id]
await module.update(raw_data)
if module.room_id:
self.home.rooms[module.room_id].update(raw_data)
def update_features(self) -> None:
"""Update features."""
self.features.update({var for var in vars(self) if var not in ATTRIBUTE_FILTER})
if "battery_state" in vars(self) or "battery_percent" in vars(self):
self.features.add("battery")
if "wind_angle" in self.features:
self.features.add("wind_direction")
self.features.add("gust_direction")
class Camera(
FirmwareMixin,
MonitoringMixin,
EventMixin,
CameraMixin,
WifiMixin,
Module,
):
"""Class to represent a Netatmo camera."""
async def update(self, raw_data: RawData) -> None:
"""Update camera with the latest data."""
await Module.update(self, raw_data)
await self.async_update_camera_urls()
class Switch(
FirmwareMixin,
EnergyHistoryMixin,
PowerMixin,
SwitchMixin,
ApplianceTypeMixin,
Module,
):
"""Class to represent a Netatmo switch."""
class Dimmer(DimmableMixin, Switch):
"""Class to represent a Netatmo dimmer."""
class Shutter(FirmwareMixin, ShutterMixin, Module):
"""Class to represent a Netatmo shutter."""
class Fan(FirmwareMixin, FanSpeedMixin, PowerMixin, Module):
"""Class to represent a Netatmo ventilation device."""
class RemoteControlMixin(FirmwareMixin, Module):
"""Class to represent a Netatmo remote control."""
class Energy(EnergyHistoryMixin, Module):
"""Class to represent a Netatmo energy module."""
class Boiler(BoilerMixin, Module):
"""Class to represent a Netatmo boiler."""
pyatmo-9.2.1/src/pyatmo/modules/netatmo.py 0000664 0000000 0000000 00000016366 15017405234 0020642 0 ustar 00root root 0000000 0000000 """Module to represent Netatmo modules."""
from __future__ import annotations
from dataclasses import dataclass
import logging
from typing import Any
from pyatmo.const import (
ACCESSORY_GUST_ANGLE_TYPE,
ACCESSORY_GUST_STRENGTH_TYPE,
ACCESSORY_RAIN_24H_TYPE,
ACCESSORY_RAIN_60MIN_TYPE,
ACCESSORY_RAIN_LIVE_TYPE,
ACCESSORY_WIND_ANGLE_TYPE,
ACCESSORY_WIND_STRENGTH_TYPE,
STATION_HUMIDITY_TYPE,
STATION_PRESSURE_TYPE,
STATION_TEMPERATURE_TYPE,
RawData,
)
from pyatmo.modules.module import (
BatteryMixin,
BoilerMixin,
Camera,
CO2Mixin,
FirmwareMixin,
FloodlightMixin,
HealthIndexMixin,
HumidityMixin,
Module,
MonitoringMixin,
NoiseMixin,
PlaceMixin,
PressureMixin,
RainMixin,
RfMixin,
StatusMixin,
TemperatureMixin,
WifiMixin,
WindMixin,
)
LOG = logging.getLogger(__name__)
class NRV(FirmwareMixin, RfMixin, BatteryMixin, Module):
"""Class to represent a Netatmo NRV."""
class NAC(FirmwareMixin, RfMixin, BatteryMixin, Module):
"""Class to represent a Netatmo NAC."""
class NATherm1(FirmwareMixin, RfMixin, BatteryMixin, BoilerMixin, Module):
"""Class to represent a Netatmo NATherm1."""
class NAPlug(FirmwareMixin, RfMixin, WifiMixin, Module):
"""Class to represent a Netatmo NAPlug."""
class OTH(FirmwareMixin, WifiMixin, Module):
"""Class to represent a Netatmo OTH."""
class OTM(FirmwareMixin, RfMixin, BatteryMixin, BoilerMixin, Module):
"""Class to represent a Netatmo OTM."""
class NACamera(Camera):
"""Class to represent a Netatmo NACamera."""
class NPC(Camera):
"""Class to represent a Netatmo NPC."""
class NOC(FloodlightMixin, Camera):
"""Class to represent a Netatmo NOC."""
class NDB(Camera):
"""Class to represent a Netatmo NDB."""
class NAMain(
TemperatureMixin,
HumidityMixin,
CO2Mixin,
NoiseMixin,
PressureMixin,
WifiMixin,
FirmwareMixin,
PlaceMixin,
Module,
):
"""Class to represent a Netatmo NAMain."""
class NAModule1(
TemperatureMixin,
HumidityMixin,
RfMixin,
FirmwareMixin,
BatteryMixin,
PlaceMixin,
Module,
):
"""Class to represent a Netatmo NAModule1."""
class NAModule2(WindMixin, RfMixin, FirmwareMixin, BatteryMixin, PlaceMixin, Module):
"""Class to represent a Netatmo NAModule2."""
class NAModule3(RainMixin, RfMixin, FirmwareMixin, BatteryMixin, PlaceMixin, Module):
"""Class to represent a Netatmo NAModule3."""
class NAModule4(
TemperatureMixin,
CO2Mixin,
HumidityMixin,
RfMixin,
FirmwareMixin,
BatteryMixin,
PlaceMixin,
Module,
):
"""Class to represent a Netatmo NAModule4."""
class NHC(
TemperatureMixin,
HumidityMixin,
CO2Mixin,
PressureMixin,
NoiseMixin,
HealthIndexMixin,
WifiMixin,
FirmwareMixin,
PlaceMixin,
Module,
):
"""Class to represent a Netatmo NHC."""
class NACamDoorTag(StatusMixin, FirmwareMixin, BatteryMixin, RfMixin, Module):
"""Class to represent a Netatmo NACamDoorTag."""
class NIS(
StatusMixin,
MonitoringMixin,
FirmwareMixin,
BatteryMixin,
RfMixin,
Module,
):
"""Class to represent a Netatmo NIS."""
class NSD(
FirmwareMixin,
Module,
):
"""Class to represent a Netatmo NSD."""
class NCO(
FirmwareMixin,
Module,
):
"""Class to represent a Netatmo NCO."""
@dataclass
class Location:
"""Class of Netatmo public weather location."""
lat_ne: str
lon_ne: str
lat_sw: str
lon_sw: str
class PublicWeatherArea:
"""Class of Netatmo public weather data."""
location: Location
required_data_type: str | None
filtering: bool
modules: list[dict[str, Any]]
def __init__(
self,
lat_ne: str,
lon_ne: str,
lat_sw: str,
lon_sw: str,
required_data_type: str | None = None,
filtering: bool = False,
) -> None:
"""Initialize self."""
self.location = Location(
lat_ne,
lon_ne,
lat_sw,
lon_sw,
)
self.modules = []
self.required_data_type = required_data_type
self.filtering = filtering
def update(self, raw_data: RawData) -> None:
"""Update public weather area with the latest data."""
self.modules = list(raw_data.get("public", []))
def stations_in_area(self) -> int:
"""Return available number of stations in area."""
return len(self.modules)
def get_latest_rain(self) -> dict[str, Any]:
"""Return latest rain measures."""
return self.get_accessory_data(ACCESSORY_RAIN_LIVE_TYPE)
def get_60_min_rain(self) -> dict[str, Any]:
"""Return 60 min rain measures."""
return self.get_accessory_data(ACCESSORY_RAIN_60MIN_TYPE)
def get_24_h_rain(self) -> dict[str, Any]:
"""Return 24 h rain measures."""
return self.get_accessory_data(ACCESSORY_RAIN_24H_TYPE)
def get_latest_pressures(self) -> dict[str, Any]:
"""Return latest pressure measures."""
return self.get_latest_station_measures(STATION_PRESSURE_TYPE)
def get_latest_temperatures(self) -> dict[str, Any]:
"""Return latest temperature measures."""
return self.get_latest_station_measures(STATION_TEMPERATURE_TYPE)
def get_latest_humidities(self) -> dict[str, Any]:
"""Return latest humidity measures."""
return self.get_latest_station_measures(STATION_HUMIDITY_TYPE)
def get_latest_wind_strengths(self) -> dict[str, Any]:
"""Return latest wind strength measures."""
return self.get_accessory_data(ACCESSORY_WIND_STRENGTH_TYPE)
def get_latest_wind_angles(self) -> dict[str, Any]:
"""Return latest wind angle measures."""
return self.get_accessory_data(ACCESSORY_WIND_ANGLE_TYPE)
def get_latest_gust_strengths(self) -> dict[str, Any]:
"""Return latest gust strength measures."""
return self.get_accessory_data(ACCESSORY_GUST_STRENGTH_TYPE)
def get_latest_gust_angles(self) -> dict[str, Any]:
"""Return latest gust angle measures."""
return self.get_accessory_data(ACCESSORY_GUST_ANGLE_TYPE)
def get_latest_station_measures(self, data_type: str) -> dict[str, Any]:
"""Return latest station measures of a given type."""
measures: dict[str, Any] = {}
for station in self.modules:
for module in station["measures"].values():
if (
"type" in module
and data_type in module["type"]
and "res" in module
and module["res"]
):
measure_index = module["type"].index(data_type)
latest_timestamp = sorted(module["res"], reverse=True)[0]
measures[station["_id"]] = module["res"][latest_timestamp][
measure_index
]
return measures
def get_accessory_data(self, data_type: str) -> dict[str, Any]:
"""Return accessory data of a given type."""
data: dict[str, Any] = {}
for station in self.modules:
for module in station["measures"].values():
if data_type in module:
data[station["_id"]] = module[data_type]
return data
pyatmo-9.2.1/src/pyatmo/modules/smarther.py 0000664 0000000 0000000 00000000542 15017405234 0021005 0 ustar 00root root 0000000 0000000 """Module to represent Smarther modules."""
from __future__ import annotations
import logging
from pyatmo.modules.module import (
BoilerMixin,
CoolerMixin,
FirmwareMixin,
Module,
WifiMixin,
)
LOG = logging.getLogger(__name__)
class BNS(FirmwareMixin, BoilerMixin, CoolerMixin, WifiMixin, Module):
"""Smarther thermostat."""
pyatmo-9.2.1/src/pyatmo/modules/somfy.py 0000664 0000000 0000000 00000000401 15017405234 0020307 0 ustar 00root root 0000000 0000000 """Module to represent somfy modules."""
from __future__ import annotations
import logging
from pyatmo.modules.module import RfMixin, Shutter
LOG = logging.getLogger(__name__)
class TPSRS(RfMixin, Shutter):
"""Class to represent a somfy TPSRS."""
pyatmo-9.2.1/src/pyatmo/person.py 0000664 0000000 0000000 00000001733 15017405234 0017021 0 ustar 00root root 0000000 0000000 """Module to represent a Netatmo person."""
from __future__ import annotations
from dataclasses import dataclass
import logging
from typing import TYPE_CHECKING
from pyatmo.modules.base_class import NetatmoBase
if TYPE_CHECKING:
from pyatmo.const import RawData
from .home import Home
LOG = logging.getLogger(__name__)
@dataclass
class Person(NetatmoBase):
"""Class to represent a Netatmo person."""
pseudo: str | None
url: str | None
out_of_sight: bool | None = None
last_seen: int | None = None
def __init__(self, home: Home, raw_data: RawData) -> None:
"""Initialize a Netatmo person instance."""
super().__init__(raw_data)
self.home = home
self.pseudo = raw_data.get("pseudo")
self.url = raw_data.get("url")
def update(self, raw_data: RawData) -> None:
"""Update person data."""
self.out_of_sight = raw_data.get("out_of_sight")
self.last_seen = raw_data.get("last_seen")
pyatmo-9.2.1/src/pyatmo/py.typed 0000664 0000000 0000000 00000000000 15017405234 0016622 0 ustar 00root root 0000000 0000000 pyatmo-9.2.1/src/pyatmo/room.py 0000664 0000000 0000000 00000033214 15017405234 0016466 0 ustar 00root root 0000000 0000000 """Module to represent a Netatmo room."""
from __future__ import annotations
from dataclasses import dataclass
import logging
from typing import TYPE_CHECKING, Any, cast
from pyatmo.const import (
AWAY,
COOLING,
FROSTGUARD,
HEATING,
HOME,
IDLE,
MANUAL,
MAX,
OFF,
PILOT_WIRE_AWAY,
PILOT_WIRE_COMFORT,
PILOT_WIRE_COMFORT_1,
PILOT_WIRE_COMFORT_2,
PILOT_WIRE_FROST_GUARD,
PILOT_WIRE_STAND_BY,
SCHEDULE,
SETROOMTHERMPOINT_ENDPOINT,
UNKNOWN,
RawData,
)
from pyatmo.enums import TemperatureControlMode
from pyatmo.modules.base_class import NetatmoBase
from pyatmo.modules.device_types import ApplianceType, DeviceCategory, DeviceType
from pyatmo.modules.module import ApplianceTypeMixin, Boiler, PowerMixin
if TYPE_CHECKING:
from pyatmo.home import Home
from pyatmo.modules.module import Module
LOG = logging.getLogger(__name__)
MODE_MAP = {SCHEDULE: HOME}
# as for now all the below is not exposed at all through the API, don't put it in the public API, so not in const.py
NETAMO_CLIMATE_SETPOINT_MODE_TO_PILOT_WIRE = {
MANUAL: PILOT_WIRE_COMFORT,
MAX: PILOT_WIRE_COMFORT,
OFF: PILOT_WIRE_FROST_GUARD,
HOME: PILOT_WIRE_COMFORT, # HOME is equivalent to a schedule for Netatmo NLC based room
FROSTGUARD: PILOT_WIRE_FROST_GUARD,
SCHEDULE: PILOT_WIRE_COMFORT,
AWAY: PILOT_WIRE_AWAY,
}
# invert of the map above:
NETAMO_PILOT_WIRE_TO_CLIMATE_SETPOINT_MODE = {
PILOT_WIRE_COMFORT: MANUAL,
PILOT_WIRE_AWAY: MANUAL, # AWAY is like ECO for a pilot wire heater, so put manual to force it to happen
PILOT_WIRE_FROST_GUARD: FROSTGUARD,
PILOT_WIRE_STAND_BY: FROSTGUARD,
PILOT_WIRE_COMFORT_1: HOME,
PILOT_WIRE_COMFORT_2: HOME,
}
@dataclass
class Room(NetatmoBase):
"""Class to represent a Netatmo room."""
modules: dict[str, Module]
device_types: set[DeviceType]
features: set[str]
climate_type: DeviceType | None = None
humidity: int | None = None
therm_measured_temperature: float | None = None
reachable: bool | None = None
heating_power_request: int | None = None
therm_setpoint_temperature: float | None = None
therm_setpoint_mode: str | None = None
# therm_setpoint_mode: per the documentation: "The thermostat mode in which the room is.
# For a room controlled by a BNS, mode can be home, manual, max or hg/off (if heating/cooling).
# For a room controlled by a NLC, mode can be off, manual or hg."
# values can be
# "manual"
# "max"
# "off"
# "home"
# "hg"
# "schedule"
# "away"
# therm_setpoint_fp: used to set up pilot wire, ie "fil pilote" set point
# netatmo documentation:
# Usually used to control (Fil pilote (FP)) setpoint
# values:
# "comfort"
# "away"
# "frost_guard"
# "stand_by"
# "comfort_1" => documentation unclear and contradictory here, as it is in the json schema but no in the doc
# "comfort_2" => same
# but here:
therm_setpoint_fp: str | None = None
support_pilot_wire: bool = False
therm_setpoint_start_time: int | None = None
therm_setpoint_end_time: int | None = None
anticipating: bool | None = None
open_window: bool | None = None
cooling_setpoint_temperature: float | None = None
cooling_setpoint_start_time: int | None = None
cooling_setpoint_end_time: int | None = None
cooling_setpoint_mode: str | None = None
radiators_power: int | None = None
def __init__(
self,
home: Home,
room: dict[str, Any],
all_modules: dict[str, Module],
) -> None:
"""Initialize a Netatmo room instance."""
super().__init__(room)
self.home = home
self.support_pilot_wire = False
self.modules = {
m_id: m
for m_id, m in all_modules.items()
if m_id in room.get("module_ids", [])
}
self.device_types = set()
self.features = set()
self.evaluate_device_type()
def update_topology(self, raw_data: RawData) -> None:
"""Update room topology."""
self.name = raw_data.get("name", UNKNOWN)
self.modules = {
m_id: m
for m_id, m in self.home.modules.items()
if m_id in raw_data.get("module_ids", [])
}
self.evaluate_device_type()
def evaluate_device_type(self) -> None:
"""Evaluate the device type of the room."""
self.support_pilot_wire = False
for module in self.modules.values():
self.device_types.add(module.device_type)
if module.device_category is not None:
self.features.add(module.device_category.name)
if (
module.device_type == "NLC"
and isinstance(module, ApplianceTypeMixin)
and module.appliance_type == ApplianceType.radiator
):
self.support_pilot_wire = True
# Regarding to the room the cable outlet can be seen as climate control, add the climate feature
self.features.add(DeviceCategory.climate.name)
if "OTM" in self.device_types:
self.climate_type = DeviceType.OTM
elif "NATherm1" in self.device_types:
self.climate_type = DeviceType.NATherm1
elif "BNS" in self.device_types:
self.climate_type = DeviceType.BNS
self.features.add("humidity")
elif "NRV" in self.device_types:
self.climate_type = DeviceType.NRV
elif "NAC" in self.device_types:
self.climate_type = DeviceType.NAC
elif "BNTH" in self.device_types:
self.climate_type = DeviceType.BNTH
elif "NLC" in self.device_types and self.support_pilot_wire:
self.climate_type = DeviceType.NLC
def update(self, raw_data: RawData) -> None:
"""Update room data."""
self.humidity = raw_data.get("humidity")
self.radiators_power = 0
if self.climate_type == DeviceType.BNTH:
# BNTH is wired, so the room is always reachable
self.reachable = True
elif self.climate_type == DeviceType.NLC:
self.reachable = raw_data.get("reachable", False)
for module in self.modules.values():
if (
isinstance(module, ApplianceTypeMixin)
and module.device_type == DeviceType.NLC
and module.appliance_type == ApplianceType.radiator
):
if isinstance(module, PowerMixin) and module.power is not None:
self.radiators_power += module.power
if hasattr(module, "reachable"):
state = module.reachable
if state is not None:
if self.reachable is None:
self.reachable = state
else:
self.reachable = (
self.reachable or state
) # as soon as we do have one
else:
self.reachable = raw_data.get("reachable")
self.therm_measured_temperature = raw_data.get("therm_measured_temperature")
self.heating_power_request = raw_data.get("heating_power_request")
self.therm_setpoint_mode = raw_data.get("therm_setpoint_mode")
self.therm_setpoint_fp = raw_data.get("therm_setpoint_fp")
self.therm_setpoint_temperature = raw_data.get("therm_setpoint_temperature")
self.therm_setpoint_start_time = raw_data.get("therm_setpoint_start_time")
self.therm_setpoint_end_time = raw_data.get("therm_setpoint_end_time")
self.anticipating = raw_data.get("anticipating")
self.open_window = raw_data.get("open_window")
self.cooling_setpoint_temperature = raw_data.get("cooling_setpoint_temperature")
self.cooling_setpoint_start_time = raw_data.get("cooling_setpoint_start_time")
self.cooling_setpoint_end_time = raw_data.get("cooling_setpoint_end_time")
self.cooling_setpoint_mode = raw_data.get("cooling_setpoint_mode")
async def async_therm_manual(
self,
temp: float | None = None,
end_time: int | None = None,
) -> None:
"""Set room temperature set point to manual."""
await self.async_therm_set(MANUAL, temp, end_time)
async def async_therm_home(self, end_time: int | None = None) -> None:
"""Set room temperature set point to home."""
await self.async_therm_set(HOME, end_time=end_time)
async def async_therm_frostguard(self, end_time: int | None = None) -> None:
"""Set room temperature set point to frostguard."""
await self.async_therm_set(FROSTGUARD, end_time=end_time)
async def async_therm_set(
self,
mode: str | None = None,
temp: float | None = None,
end_time: int | None = None,
pilot_wire: str | None = None,
) -> None:
"""Set room temperature set point."""
if mode is None:
mode = MANUAL
mode = MODE_MAP.get(mode, mode)
if "NATherm1" in self.device_types or (
"NRV" in self.device_types
and not self.home.has_otm()
and not self.home.has_bns()
):
await self._async_set_thermpoint(mode, temp, end_time)
else:
await self._async_therm_set(mode, temp, end_time, pilot_wire)
async def _async_therm_set(
self,
mode: str | None = None,
temp: float | None = None,
end_time: int | None = None,
pilot_wire: str | None = None,
) -> bool:
"""Set room temperature set point (OTM)."""
if pilot_wire is None:
# in case both are None stop everything
if mode is None:
mode = FROSTGUARD
pilot_wire = NETAMO_CLIMATE_SETPOINT_MODE_TO_PILOT_WIRE.get(
mode,
PILOT_WIRE_FROST_GUARD,
)
# force back the proper preset mode in case of pilot wire
# to comply with netatmo model
if self.support_pilot_wire and self.climate_type == DeviceType.NLC:
mode = NETAMO_PILOT_WIRE_TO_CLIMATE_SETPOINT_MODE.get(
pilot_wire,
FROSTGUARD,
)
if pilot_wire is not None and mode is None:
mode = MANUAL
temp_mode_mapping = {
None: "therm",
TemperatureControlMode.HEATING: "therm",
TemperatureControlMode.COOLING: "cooling",
}
setpoint_mode_prefix = temp_mode_mapping.get(
self.home.temperature_control_mode,
"therm",
)
json_therm_set: dict[str, Any] = {
"rooms": [
{
"id": self.entity_id,
f"{setpoint_mode_prefix}_setpoint_mode": mode,
},
],
}
if temp:
json_therm_set["rooms"][0][
f"{setpoint_mode_prefix}_setpoint_temperature"
] = temp
if end_time:
json_therm_set["rooms"][0][
f"{setpoint_mode_prefix}_setpoint_end_time"
] = end_time
if self.support_pilot_wire and pilot_wire:
json_therm_set["rooms"][0]["therm_setpoint_fp"] = pilot_wire
return await self.home.async_set_state(json_therm_set)
async def _async_set_thermpoint(
self,
mode: str,
temp: float | None = None,
end_time: int | None = None,
) -> None:
"""Set room temperature set point (NRV, NATherm1)."""
post_params = {
"home_id": self.home.entity_id,
"room_id": self.entity_id,
"mode": mode,
}
# Temp and endtime should only be sent when mode=='manual', but netatmo api can
# handle that even when mode == 'home' and these settings don't make sense
if temp is not None:
post_params["temp"] = str(temp)
if end_time is not None:
post_params["endtime"] = str(end_time)
LOG.debug(
"Setting room (%s) temperature set point to %s until %s",
self.entity_id,
temp,
end_time,
)
await self.home.auth.async_post_api_request(
endpoint=SETROOMTHERMPOINT_ENDPOINT,
params=post_params,
)
@property
def boiler_status(self) -> bool | None:
"""Return the boiler status."""
for module in self.modules.values():
if hasattr(module, "boiler_status"):
module = cast("Boiler", module)
if (boiler_status := module.boiler_status) is not None:
return boiler_status
return None
@property
def setpoint_mode(self) -> str:
"""Return the current setpoint mode."""
return self.therm_setpoint_mode or self.cooling_setpoint_mode or UNKNOWN
@property
def setpoint_temperature(self) -> float | None:
"""Return the current setpoint temperature."""
return (
self.therm_setpoint_temperature or self.cooling_setpoint_temperature or None
)
@property
def setpoint_fp(self) -> str | None:
"""Return the current setpoint 'Fil pilote (FP)'."""
return self.therm_setpoint_fp or None
@property
def hvac_action(self) -> str:
"""Return the current HVAC action."""
if self.setpoint_mode == OFF:
return OFF
if self.boiler_status is True:
return HEATING
if self.heating_power_request is not None and self.heating_power_request > 0:
return HEATING
if self.cooling_setpoint_temperature:
return COOLING
return IDLE
pyatmo-9.2.1/src/pyatmo/schedule.py 0000664 0000000 0000000 00000006117 15017405234 0017310 0 ustar 00root root 0000000 0000000 """Module to represent a Netatmo schedule."""
from __future__ import annotations
from dataclasses import dataclass
import logging
from typing import TYPE_CHECKING
from pyatmo.enums import ScheduleType
from pyatmo.modules.base_class import NetatmoBase
from pyatmo.room import Room
if TYPE_CHECKING:
from pyatmo.const import RawData
from .home import Home
LOG = logging.getLogger(__name__)
@dataclass
class Schedule(NetatmoBase):
"""Class to represent a Netatmo schedule."""
type: ScheduleType
away_temp: float | None
hg_temp: float | None
cooling_away_temp: float | None
timetable: list[TimetableEntry]
selected: bool
default: bool
def __init__(self, home: Home, raw_data: RawData) -> None:
"""Initialize a Netatmo schedule instance."""
super().__init__(raw_data)
self.home = home
self.type = ScheduleType(raw_data.get("type", ScheduleType.THERM))
self.default = raw_data.get("default", False)
self.selected = raw_data.get("selected", False)
self.hg_temp = raw_data.get("hg_temp")
self.away_temp = raw_data.get("away_temp")
self.cooling_away_temp = raw_data.get("cooling_away_temp")
self.timetable = [
TimetableEntry(home, r) for r in raw_data.get("timetable", [])
]
self.zones = [Zone(home, r) for r in raw_data.get("zones", [])]
def update_topology(self, raw_data: RawData) -> None:
"""Update the schedule topology."""
super().update_topology(raw_data)
self.selected = raw_data.get("selected", self.selected)
self.default = raw_data.get("default", self.default)
self.hg_temp = raw_data.get("hg_temp", self.hg_temp)
self.away_temp = raw_data.get("away_temp", self.away_temp)
self.cooling_away_temp = raw_data.get(
"cooling_away_temp",
self.cooling_away_temp,
)
self.timetable = [
TimetableEntry(self.home, r) for r in raw_data.get("timetable", [])
]
self.zones = [Zone(self.home, r) for r in raw_data.get("zones", [])]
@dataclass
class TimetableEntry:
"""Class to represent a Netatmo schedule's timetable entry."""
zone_id: int | None
m_offset: int | None
def __init__(self, home: Home, raw_data: RawData) -> None:
"""Initialize a Netatmo schedule's timetable entry instance."""
self.home = home
self.zone_id = raw_data.get("zone_id", 0)
self.m_offset = raw_data.get("m_offset", 0)
@dataclass
class Zone(NetatmoBase):
"""Class to represent a Netatmo schedule's zone."""
type: int
rooms: list[Room]
def __init__(self, home: Home, raw_data: RawData) -> None:
"""Initialize a Netatmo schedule's zone instance."""
super().__init__(raw_data)
self.home = home
self.type = raw_data.get("type", 0)
def room_factory(home: Home, room_raw_data: RawData) -> Room:
room = Room(home, room_raw_data, {})
room.update(room_raw_data)
return room
self.rooms = [room_factory(home, r) for r in raw_data.get("rooms", [])]
pyatmo-9.2.1/tests/ 0000775 0000000 0000000 00000000000 15017405234 0014177 5 ustar 00root root 0000000 0000000 pyatmo-9.2.1/tests/__init__.py 0000664 0000000 0000000 00000000000 15017405234 0016276 0 ustar 00root root 0000000 0000000 pyatmo-9.2.1/tests/common.py 0000664 0000000 0000000 00000004115 15017405234 0016042 0 ustar 00root root 0000000 0000000 """Define shared test helpers."""
from __future__ import annotations
import json
import pathlib
def get_fixture_path(filename: str) -> pathlib.Path:
"""Get path of fixture."""
return pathlib.Path(__file__).parent.joinpath("../fixtures", filename)
def load_fixture(filename):
"""Load a fixture."""
return get_fixture_path(filename).read_text(encoding="utf-8")
class MockResponse:
def __init__(self, text, status):
self._text = text
self.status = status
async def json(self):
return self._text
async def read(self):
return self._text
async def __aexit__(self, exc_type, exc, traceback):
pass
async def __aenter__(self):
return self
async def fake_post_request(*_, **kwargs):
"""Return fake data."""
if "endpoint" not in kwargs:
return "{}"
endpoint = kwargs["endpoint"].split("/")[-1]
if endpoint in "snapshot_720.jpg":
return b"test stream image bytes"
if endpoint in [
"setpersonsaway",
"setpersonshome",
"setstate",
"setroomthermpoint",
"setthermmode",
"switchhomeschedule",
]:
payload = f'{{"{endpoint}": true}}'
elif endpoint == "homestatus":
home_id = kwargs.get("params", {}).get("home_id")
payload = json.loads(load_fixture(f"{endpoint}_{home_id}.json"))
elif endpoint == "getmeasure":
module_id = kwargs.get("params", {}).get("module_id", "")
measure_type = kwargs.get("params", {}).get("type", "")
payload = json.loads(
load_fixture(
f"{endpoint}_{measure_type}_{module_id.replace(':', '_')}.json",
),
)
else:
postfix = kwargs.get("POSTFIX")
if postfix is not None:
payload = json.loads(load_fixture(f"{endpoint}_{postfix}.json"))
else:
payload = json.loads(load_fixture(f"{endpoint}.json"))
return MockResponse(payload, 200)
async def fake_post_request_multi(*args, **kwargs):
kwargs["POSTFIX"] = "multi"
return await fake_post_request(*args, **kwargs)
pyatmo-9.2.1/tests/conftest.py 0000664 0000000 0000000 00000003575 15017405234 0016410 0 ustar 00root root 0000000 0000000 """Define shared fixtures."""
from contextlib import contextmanager
from unittest.mock import AsyncMock, patch
import pytest
import pyatmo
from .common import fake_post_request, fake_post_request_multi
@contextmanager
def does_not_raise():
yield
@pytest.fixture
async def async_auth():
"""AsyncAuth fixture."""
with patch("pyatmo.auth.AbstractAsyncAuth", AsyncMock()) as auth:
yield auth
@pytest.fixture
async def async_account(async_auth):
"""AsyncAccount fixture."""
account = pyatmo.AsyncAccount(async_auth)
with (
patch(
"pyatmo.auth.AbstractAsyncAuth.async_post_api_request",
fake_post_request,
),
patch(
"pyatmo.auth.AbstractAsyncAuth.async_post_request",
fake_post_request,
),
):
await account.async_update_topology()
yield account
@pytest.fixture
async def async_home(async_account):
"""AsyncClimate fixture for home_id 91763b24c43d3e344f424e8b."""
home_id = "91763b24c43d3e344f424e8b"
await async_account.async_update_status(home_id)
return async_account.homes[home_id]
@pytest.fixture
async def async_account_multi(async_auth):
"""AsyncAccount fixture."""
account = pyatmo.AsyncAccount(async_auth)
with (
patch(
"pyatmo.auth.AbstractAsyncAuth.async_post_api_request",
fake_post_request_multi,
),
patch(
"pyatmo.auth.AbstractAsyncAuth.async_post_request",
fake_post_request_multi,
),
):
await account.async_update_topology(
disabled_homes_ids=["eeeeeeeeeffffffffffaaaaa"],
)
yield account
@pytest.fixture
async def async_home_multi(async_account_multi):
"""AsyncClimate fixture for home_id 91763b24c43d3e344f424e8b."""
home_id = "aaaaaaaaaaabbbbbbbbbbccc"
return async_account_multi.homes[home_id]
pyatmo-9.2.1/tests/test_camera.py 0000664 0000000 0000000 00000011152 15017405234 0017040 0 ustar 00root root 0000000 0000000 """Define tests for camera module."""
import json
from unittest.mock import AsyncMock, patch
import anyio
from pyatmo import DeviceType
from tests.common import MockResponse
async def test_async_camera_NACamera(async_home):
"""Test Netatmo indoor camera module."""
module_id = "12:34:56:00:f1:62"
assert module_id in async_home.modules
module = async_home.modules[module_id]
await module.async_update_camera_urls()
assert module.device_type == DeviceType.NACamera
assert module.is_local
assert module.local_url == "http://192.168.0.123/678460a0d47e5618699fb31169e2b47d"
person_id = "91827374-7e04-5298-83ad-a0cb8372dff1"
assert person_id in module.home.persons
person = module.home.persons[person_id]
assert person.pseudo == "John Doe"
assert person.out_of_sight
assert person.last_seen == 1557071156
async def test_async_camera_NPC(async_home):
"""Test Netatmo indoor camera advance module."""
module_id = "12:34:56:00:f1:63"
assert module_id in async_home.modules
module = async_home.modules[module_id]
await module.async_update_camera_urls()
assert module.device_type == DeviceType.NPC
assert module.is_local
assert module.local_url == "http://192.168.0.123/678460a0d47e5618699fb31169e2b47d"
person_id = "91827374-7e04-5298-83ad-a0cb8372dff1"
assert person_id in module.home.persons
person = module.home.persons[person_id]
assert person.pseudo == "John Doe"
assert person.out_of_sight
assert person.last_seen == 1557071156
async def test_async_NOC(async_home):
"""Test basic outdoor camera functionality."""
module_id = "12:34:56:10:b9:0e"
assert module_id in async_home.modules
module = async_home.modules[module_id]
assert module.device_type == DeviceType.NOC
assert module.firmware_revision == 3002000
assert module.firmware_name == "3.2.0"
assert module.monitoring is True
assert module.alim_status == 2
assert module.is_local is False
assert module.floodlight == "auto"
async with await anyio.open_file(
"fixtures/status_ok.json",
encoding="utf-8",
) as json_file:
response = json.loads(await json_file.read())
def gen_json_data(state):
return {
"json": {
"home": {
"id": "91763b24c43d3e344f424e8b",
"modules": [
{
"id": module_id,
"floodlight": state,
},
],
},
},
}
with patch(
"pyatmo.auth.AbstractAsyncAuth.async_post_api_request",
AsyncMock(return_value=MockResponse(response, 200)),
) as mock_resp:
assert await module.async_floodlight_on()
mock_resp.assert_awaited_with(
params=gen_json_data("on"),
endpoint="api/setstate",
)
assert await module.async_floodlight_off()
mock_resp.assert_awaited_with(
params=gen_json_data("off"),
endpoint="api/setstate",
)
assert await module.async_floodlight_auto()
mock_resp.assert_awaited_with(
params=gen_json_data("auto"),
endpoint="api/setstate",
)
async def test_async_camera_monitoring(async_home):
"""Test basic camera monitoring functionality."""
module_id = "12:34:56:10:b9:0e"
assert module_id in async_home.modules
module = async_home.modules[module_id]
assert module.device_type == DeviceType.NOC
assert module.is_local is False
async with await anyio.open_file(
"fixtures/status_ok.json",
encoding="utf-8",
) as json_file:
response = json.loads(await json_file.read())
def gen_json_data(state):
return {
"json": {
"home": {
"id": "91763b24c43d3e344f424e8b",
"modules": [
{
"id": module_id,
"monitoring": state,
},
],
},
},
}
with patch(
"pyatmo.auth.AbstractAsyncAuth.async_post_api_request",
AsyncMock(return_value=MockResponse(response, 200)),
) as mock_resp:
assert await module.async_monitoring_on()
mock_resp.assert_awaited_with(
params=gen_json_data("on"),
endpoint="api/setstate",
)
assert await module.async_monitoring_off()
mock_resp.assert_awaited_with(
params=gen_json_data("off"),
endpoint="api/setstate",
)
pyatmo-9.2.1/tests/test_climate.py 0000664 0000000 0000000 00000024720 15017405234 0017233 0 ustar 00root root 0000000 0000000 """Define tests for climate module."""
import json
from unittest.mock import AsyncMock, patch
import anyio
import pytest
from pyatmo import DeviceType, NoScheduleError
from pyatmo.modules import NATherm1
from pyatmo.modules.device_types import DeviceCategory
from tests.common import MockResponse, fake_post_request
from tests.conftest import does_not_raise
async def test_async_climate_room(async_home):
"""Test room with climate devices."""
room_id = "2746182631"
assert room_id in async_home.rooms
room = async_home.rooms[room_id]
assert room.reachable is True
assert room.device_types == {DeviceType.NATherm1}
module_id = "12:34:56:00:01:ae"
assert module_id in room.modules
assert len(room.modules) == 1
async def test_async_climate_NATherm1(async_home):
"""Test NATherm1 climate device."""
module_id = "12:34:56:00:01:ae"
module = async_home.modules[module_id]
assert module.name == "Livingroom"
assert module.device_type == DeviceType.NATherm1
assert module.reachable is True
assert module.boiler_status is False
assert module.firmware_revision == 65
assert module.battery == 75
assert module.rf_strength == 58
async def test_async_climate_NRV(async_home):
"""Test NRV climate device."""
module_id = "12:34:56:03:a5:54"
module = async_home.modules[module_id]
assert module.name == "Valve1"
assert async_home.rooms[module.room_id].name == "Entrada"
assert module.device_type == DeviceType.NRV
assert module.reachable is True
assert module.rf_strength == 51
assert module.battery == 90
assert module.firmware_revision == 79
async def test_async_climate_NAPlug(async_home):
"""Test NAPlug climate device."""
module_id = "12:34:56:00:fa:d0"
assert module_id in async_home.modules
module = async_home.modules[module_id]
assert module.device_type == DeviceType.NAPlug
assert len(module.modules) == 3
assert module.rf_strength == 107
assert module.wifi_strength == 42
assert module.firmware_revision == 174
async def test_async_climate_NIS(async_home):
"""Test Netatmo siren."""
module_id = "12:34:56:00:e3:9b"
assert module_id in async_home.modules
module = async_home.modules[module_id]
assert module.device_type == DeviceType.NIS
assert module.firmware_revision == 209
assert module.status == "no_sound"
assert module.monitoring is False
async def test_async_climate_OTM(async_home):
"""Test OTM climate device."""
module_id = "12:34:56:20:f5:8c"
module = async_home.modules[module_id]
assert module.name == "Bureau Modulate"
assert module.device_type == DeviceType.OTM
assert module.reachable is True
assert module.boiler_status is False
assert module.firmware_revision == 6
assert module.battery == 90
assert module.rf_strength == 64
async def test_async_climate_OTH(async_home):
"""Test OTH climate device."""
module_id = "12:34:56:20:f5:44"
assert module_id in async_home.modules
module = async_home.modules[module_id]
assert module.device_type == DeviceType.OTH
assert len(module.modules) == 1
assert module.wifi_strength == 57
assert module.firmware_revision == 22
async def test_async_climate_BNS(async_home):
"""Test Smarther BNS climate module."""
module_id = "10:20:30:bd:b8:1e"
assert module_id in async_home.modules
module = async_home.modules[module_id]
assert module.device_type == DeviceType.BNS
assert module.name == "Smarther"
room = async_home.rooms[module.room_id]
assert room.name == "Corridor"
assert room.device_types == {
DeviceType.BNS,
}
assert room.features == {"humidity", DeviceCategory.climate}
async def test_async_climate_update(async_account):
"""Test basic climate state update."""
home_id = "91763b24c43d3e344f424e8b"
await async_account.async_update_status(home_id)
home = async_account.homes[home_id]
room_id = "2746182631"
room = home.rooms[room_id]
module_id = "12:34:56:00:01:ae"
module = home.modules[module_id]
assert room.reachable is True
assert room.humidity is None
assert module.name == "Livingroom"
assert module.device_type == DeviceType.NATherm1
assert module.reachable is True
assert module.boiler_status is False
assert module.battery == 75
assert isinstance(module, NATherm1)
async with await anyio.open_file(
"fixtures/home_status_error_disconnected.json",
encoding="utf-8",
) as json_file:
content = await json_file.read()
home_status_fixture = json.loads(content)
mock_home_status_resp = MockResponse(home_status_fixture, 200)
with patch(
"pyatmo.auth.AbstractAsyncAuth.async_post_api_request",
AsyncMock(return_value=mock_home_status_resp),
) as mock_request:
await async_account.async_update_status(home_id)
mock_request.assert_called()
assert room.reachable is None
assert module.reachable is False
async with await anyio.open_file(
"fixtures/home_status_simple.json",
encoding="utf-8",
) as json_file:
home_status_fixture = json.loads(await json_file.read())
mock_home_status_resp = MockResponse(home_status_fixture, 200)
with patch(
"pyatmo.auth.AbstractAsyncAuth.async_post_api_request",
AsyncMock(return_value=mock_home_status_resp),
) as mock_request:
await async_account.async_update_status(home_id)
mock_request.assert_called()
assert room.reachable is True
assert module.reachable is True
assert module.battery == 75
assert module.rf_strength == 58
@pytest.mark.parametrize(
("t_sched_id", "expected"),
[
("591b54a2764ff4d50d8b5795", does_not_raise()),
(
"123456789abcdefg12345678",
pytest.raises(NoScheduleError),
),
],
)
async def test_async_climate_switch_schedule(
async_home,
t_sched_id,
expected,
):
async with await anyio.open_file(
"fixtures/status_ok.json",
encoding="utf-8",
) as json_file:
response = json.loads(await json_file.read())
with (
patch(
"pyatmo.auth.AbstractAsyncAuth.async_post_api_request",
AsyncMock(return_value=MockResponse(response, 200)),
),
expected,
):
await async_home.async_switch_schedule(
schedule_id=t_sched_id,
)
@pytest.mark.parametrize(
("temp", "end_time"),
[
(
14,
None,
),
(
14,
1559162650,
),
(
None,
None,
),
(
None,
1559162650,
),
],
)
async def test_async_climate_room_therm_set(
async_home,
temp,
end_time,
):
room_id = "2746182631"
mode = "home"
expected_params = {
"home_id": "91763b24c43d3e344f424e8b",
"room_id": room_id,
"mode": mode,
}
if temp:
expected_params["temp"] = str(temp)
if end_time:
expected_params["endtime"] = str(end_time)
async with await anyio.open_file(
"fixtures/status_ok.json",
encoding="utf-8",
) as json_file:
response = json.loads(await json_file.read())
with patch(
"pyatmo.auth.AbstractAsyncAuth.async_post_api_request",
AsyncMock(return_value=MockResponse(response, 200)),
) as mock_post:
room = async_home.rooms[room_id]
await room.async_therm_set(
mode=mode,
temp=temp,
end_time=end_time,
)
mock_post.assert_awaited_once_with(
endpoint="api/setroomthermpoint",
params=expected_params,
)
@pytest.mark.parametrize(
("mode", "end_time", "schedule_id", "json_fixture", "expected", "exception"),
[
(
"away",
None,
None,
"status_ok.json",
True,
does_not_raise(),
),
(
"away",
1559162650,
None,
"status_ok.json",
True,
does_not_raise(),
),
(
"schedule",
None,
"591b54a2764ff4d50d8b5795",
"status_ok.json",
True,
does_not_raise(),
),
(
"schedule",
1559162650,
"591b54a2764ff4d50d8b5795",
"status_ok.json",
True,
does_not_raise(),
),
(
None,
None,
None,
"home_status_error_mode_is_missing.json",
False,
pytest.raises(NoScheduleError),
),
(
"away",
1559162650,
0000000,
"status_ok.json",
True,
pytest.raises(NoScheduleError),
),
(
"schedule",
None,
"blahblahblah",
"home_status_error_invalid_schedule_id.json",
False,
pytest.raises(NoScheduleError),
),
],
)
async def test_async_climate_set_thermmode(
async_home,
mode,
end_time,
schedule_id,
json_fixture,
expected,
exception,
):
async with await anyio.open_file(
f"fixtures/{json_fixture}",
encoding="utf-8",
) as json_file:
response = json.loads(await json_file.read())
with (
patch(
"pyatmo.auth.AbstractAsyncAuth.async_post_api_request",
AsyncMock(return_value=MockResponse(response, 200)),
),
exception,
):
resp = await async_home.async_set_thermmode(
mode=mode,
end_time=end_time,
schedule_id=schedule_id,
)
assert expected is resp
async def test_async_climate_empty_home(async_account):
"""Test climate setup with empty home."""
home_id = "91763b24c43d3e344f424e8c"
with patch(
"pyatmo.auth.AbstractAsyncAuth.async_post_api_request",
fake_post_request,
):
await async_account.async_update_status(home_id)
assert home_id in async_account.homes
home = async_account.homes[home_id]
assert len(home.rooms) == 0
async def test_power_wire(async_home_multi):
"""Test room with climate devices."""
room_id = "3707962039"
assert room_id in async_home_multi.rooms
room = async_home_multi.rooms[room_id]
assert room.climate_type == DeviceType.NLC
assert DeviceType.NLC in room.device_types
assert room.support_pilot_wire is True
pyatmo-9.2.1/tests/test_energy.py 0000664 0000000 0000000 00000011266 15017405234 0017107 0 ustar 00root root 0000000 0000000 """Define tests for energy module."""
import datetime as dt
import json
from unittest.mock import patch
import anyio
import pytest
import time_machine
from pyatmo import ApiHomeReachabilityError, DeviceType
from pyatmo.modules.module import EnergyHistoryMixin, MeasureInterval
from tests.common import MockResponse
async def test_async_energy_NLPC(async_home):
"""Test Legrand / BTicino connected energy meter module."""
module_id = "12:34:56:00:00:a1:4c:da"
assert module_id in async_home.modules
module = async_home.modules[module_id]
assert module.device_type == DeviceType.NLPC
assert module.power == 476
@time_machine.travel(dt.datetime(2022, 2, 12, 7, 59, 49))
async def test_historical_data_retrieval(async_account):
"""Test retrieval of historical measurements."""
home_id = "91763b24c43d3e344f424e8b"
await async_account.async_update_events(home_id=home_id)
home = async_account.homes[home_id]
module_id = "12:34:56:00:00:a1:4c:da"
assert module_id in home.modules
module = home.modules[module_id]
assert module.device_type == DeviceType.NLPC
await async_account.async_update_measures(home_id=home_id, module_id=module_id)
# changed the reference here as start and stop data was not calculated in the spirit of the netatmo api where their time data is in the fact representing the "middle" of the range and not the begining
assert module.historical_data[0] == {
"Wh": 197,
"duration": 60,
"endTime": "2022-02-05T08:59:49Z",
"endTimeUnix": 1644051589,
"energyMode": ["basic"],
"WhPerModes": [197],
"startTime": "2022-02-05T07:59:50Z",
"startTimeUnix": 1644047989,
}
assert module.historical_data[-1] == {
"Wh": 259,
"duration": 60,
"endTime": "2022-02-12T07:59:49Z",
"endTimeUnix": 1644652789,
"energyMode": ["basic"],
"WhPerModes": [259],
"startTime": "2022-02-12T06:59:50Z",
"startTimeUnix": 1644649189,
}
assert len(module.historical_data) == 168
@time_machine.travel(dt.datetime(2024, 7, 24, 22, 00, 10))
async def test_historical_data_retrieval_multi(async_account_multi):
"""Test retrieval of historical measurements."""
home_id = "aaaaaaaaaaabbbbbbbbbbccc"
home = async_account_multi.homes[home_id]
module_id = "98:76:54:32:10:00:00:69"
assert module_id in home.modules
module = home.modules[module_id]
assert module.device_type == DeviceType.NLPC
strt = int(dt.datetime.fromisoformat("2024-07-24 00:00:00").timestamp())
end_time = int(dt.datetime.fromisoformat("2024-07-24 22:27:00").timestamp())
await async_account_multi.async_update_measures(
home_id=home_id,
module_id=module_id,
interval=MeasureInterval.HALF_HOUR,
start_time=strt,
end_time=end_time,
)
assert isinstance(module, EnergyHistoryMixin)
assert module.historical_data[0] == {
"Wh": 20,
"duration": 30,
"endTime": "2024-07-23T22:30:00Z",
"endTimeUnix": 1721773800,
"energyMode": ["basic"],
"WhPerModes": [20],
"startTime": "2024-07-23T22:00:01Z",
"startTimeUnix": 1721772000,
}
assert module.historical_data[17] == {
"Wh": 710,
"WhPerModes": [498, 212],
"duration": 30,
"endTime": "2024-07-24T07:00:00Z",
"endTimeUnix": 1721804400,
"energyMode": ["basic", "peak"],
"startTime": "2024-07-24T06:30:01Z",
"startTimeUnix": 1721802600,
}
assert module.historical_data[-1] == {
"Wh": 16,
"WhPerModes": [16],
"duration": 30,
"endTime": "2024-07-24T17:30:00Z",
"endTimeUnix": 1721842200,
"energyMode": ["peak"],
"startTime": "2024-07-24T17:00:01Z",
"startTimeUnix": 1721840400,
}
assert len(module.historical_data) == 39
assert module.sum_energy_elec == 17547
assert module.sum_energy_elec_off_peak == 4290
assert module.sum_energy_elec_peak == 10177
@patch("pyatmo.auth.AbstractAsyncAuth.async_post_api_request")
async def test_disconnected_main_bridge(mock_home_status, async_account_multi):
"""Test retrieval of historical measurements."""
home_id = "aaaaaaaaaaabbbbbbbbbbccc"
async with await anyio.open_file(
"fixtures/home_multi_status_error_disconnected.json",
encoding="utf-8",
) as json_file:
content = await json_file.read()
home_status_fixture = json.loads(content)
mock_home_status_resp = MockResponse(home_status_fixture, 200)
mock_home_status.return_value = mock_home_status_resp
with pytest.raises(ApiHomeReachabilityError):
await async_account_multi.async_update_status(home_id)
pyatmo-9.2.1/tests/test_fan.py 0000664 0000000 0000000 00000000711 15017405234 0016353 0 ustar 00root root 0000000 0000000 """Define tests for fan module."""
from pyatmo import DeviceType
async def test_async_fan_NLLF(async_home):
"""Test NLLF Legrand centralized ventilation controller."""
module_id = "12:34:56:00:01:01:01:b1"
assert module_id in async_home.modules
module = async_home.modules[module_id]
assert module.device_type == DeviceType.NLLF
assert module.power == 11
assert module.firmware_revision == 60
assert module.fan_speed == 1
pyatmo-9.2.1/tests/test_home.py 0000664 0000000 0000000 00000017507 15017405234 0016552 0 ustar 00root root 0000000 0000000 """Define tests for home module."""
import json
from unittest.mock import AsyncMock, patch
import anyio
import pytest
import pyatmo
from pyatmo import DeviceType, InvalidScheduleError, NoDeviceError
from tests.common import MockResponse
async def test_async_home(async_home):
"""Test basic home setup."""
room_id = "3688132631"
room = async_home.rooms[room_id]
assert room.device_types == {
DeviceType.NDB,
DeviceType.NACamera,
DeviceType.NBR,
DeviceType.NIS,
DeviceType.NBO,
DeviceType.NPC,
DeviceType.NLPD,
}
assert len(async_home.rooms) == 9
assert len(async_home.modules) == 51
assert async_home.modules != room.modules
module_id = "12:34:56:10:f1:66"
assert module_id in async_home.modules
module = async_home.modules[module_id]
assert module.device_type == DeviceType.NDB
module_id = "12:34:56:10:b9:0e"
assert module_id in async_home.modules
module = async_home.modules[module_id]
assert module.device_type == DeviceType.NOC
assert async_home.temperature_control_mode == "cooling"
async def test_async_home_set_schedule(async_home):
"""Test home schedule."""
schedule_id = "591b54a2764ff4d50d8b5795"
selected_schedule = async_home.get_selected_schedule()
assert selected_schedule.entity_id == schedule_id
assert async_home.is_valid_schedule(schedule_id)
assert not async_home.is_valid_schedule("123")
assert async_home.get_hg_temp() == 7
assert async_home.get_away_temp() == 14
async def test_async_set_schedule_temperatures(async_home):
"""Test setting schedule temperatures."""
schedule_id = "591b54a2764ff4d50d8b5795"
schedule = async_home.get_selected_schedule()
assert schedule.entity_id == schedule_id
zone = next((zone for zone in schedule.zones if zone.entity_id == 1), None)
assert zone is not None
room = next((room for room in zone.rooms if room.entity_id == "2746182631"), None)
assert room is not None
assert room.therm_setpoint_temperature == 17
temps = {"2746182631": 15}
async with await anyio.open_file(
"fixtures/sync_schedule_591b54a2764ff4d50d8b5795.json",
encoding="utf-8",
) as fixture_file:
json_fixture = json.loads(await fixture_file.read())
with patch(
"pyatmo.auth.AbstractAsyncAuth.async_post_api_request",
AsyncMock(return_value=MockResponse({"status": "ok"}, 200)),
) as mock_resp:
await async_home.async_set_schedule_temperatures(1, temps)
mock_resp.assert_awaited_with(
endpoint="api/synchomeschedule",
params={
"params": {
"home_id": "91763b24c43d3e344f424e8b",
"schedule_id": schedule_id,
"name": "Default",
},
"json": json_fixture,
},
)
async def test_async_sync_schedule(async_home):
"""Test setting schedule temperatures."""
schedule_id = "b1b54a2f45795764f59d50d8"
schedule = async_home.schedules.get(schedule_id)
assert schedule is not None
assert schedule.entity_id == schedule_id
zone = next((zone for zone in schedule.zones if zone.entity_id == 1), None)
assert zone is not None
room = next((room for room in zone.rooms if room.entity_id == "2746182631"), None)
assert room is not None
assert room.therm_setpoint_temperature == 17
# set a new room temperature
room.therm_setpoint_temperature = 14
async with await anyio.open_file(
"fixtures/sync_schedule_b1b54a2f45795764f59d50d8.json",
encoding="utf-8",
) as fixture_file:
json_fixture = json.loads(await fixture_file.read())
with patch(
"pyatmo.auth.AbstractAsyncAuth.async_post_api_request",
AsyncMock(return_value=MockResponse({"status": "ok"}, 200)),
) as mock_resp:
await async_home.async_sync_schedule(schedule)
mock_resp.assert_awaited_with(
endpoint="api/synchomeschedule",
params={
"params": {
"home_id": "91763b24c43d3e344f424e8b",
"schedule_id": schedule_id,
"name": "Default",
},
"json": json_fixture,
},
)
async def test_async_sync_schedule_invalid_schedule(async_home):
"""Test syncing an invalid schedule."""
invalid_schedule = {"invalid": "data"}
with (
pytest.raises(InvalidScheduleError),
patch(
"pyatmo.home.is_valid_schedule",
return_value=False,
),
):
await async_home.async_sync_schedule(invalid_schedule)
async def test_async_home_data_no_body(async_auth):
"""Test home data with no body."""
async with await anyio.open_file(
"fixtures/homesdata_empty.json",
encoding="utf-8",
) as fixture_file:
json_fixture = json.loads(await fixture_file.read())
mock_request = AsyncMock(return_value=MockResponse(json_fixture, 200))
with patch(
"pyatmo.auth.AbstractAsyncAuth.async_post_api_request",
mock_request,
):
climate = pyatmo.AsyncAccount(async_auth)
with pytest.raises(NoDeviceError):
await climate.async_update_topology()
mock_request.assert_awaited_once()
async def test_async_set_persons_home(async_account):
"""Test marking a person being at home."""
home_id = "91763b24c43d3e344f424e8b"
home = async_account.homes[home_id]
person_ids = [
"91827374-7e04-5298-83ad-a0cb8372dff1",
"91827375-7e04-5298-83ae-a0cb8372dff2",
]
async with await anyio.open_file(
"fixtures/status_ok.json",
encoding="utf-8",
) as json_file:
response = json.loads(await json_file.read())
with patch(
"pyatmo.auth.AbstractAsyncAuth.async_post_api_request",
AsyncMock(return_value=MockResponse(response, 200)),
) as mock_resp:
await home.async_set_persons_home(person_ids)
mock_resp.assert_awaited_with(
params={"home_id": home_id, "person_ids[]": person_ids},
endpoint="api/setpersonshome",
)
async def test_async_set_persons_away(async_account):
"""Test marking a set of persons being away."""
home_id = "91763b24c43d3e344f424e8b"
home = async_account.homes[home_id]
async with await anyio.open_file(
"fixtures/status_ok.json",
encoding="utf-8",
) as json_file:
response = json.loads(await json_file.read())
with patch(
"pyatmo.auth.AbstractAsyncAuth.async_post_api_request",
AsyncMock(return_value=MockResponse(response, 200)),
) as mock_resp:
person_id = "91827374-7e04-5298-83ad-a0cb8372dff1"
await home.async_set_persons_away(person_id)
mock_resp.assert_awaited_with(
params={"home_id": home_id, "person_id": person_id},
endpoint="api/setpersonsaway",
)
await home.async_set_persons_away()
mock_resp.assert_awaited_with(
params={"home_id": home_id},
endpoint="api/setpersonsaway",
)
async def test_home_event_update(async_account):
"""Test basic event update."""
home_id = "91763b24c43d3e344f424e8b"
await async_account.async_update_events(home_id=home_id)
home = async_account.homes[home_id]
events = home.events
assert len(events) == 8
module_id = "12:34:56:10:b9:0e"
assert module_id in home.modules
module = home.modules[module_id]
events = module.events
assert len(events) == 5
assert events[0].event_type == "outdoor"
assert events[0].video_id == "11111111-2222-3333-4444-b42f0fc4cfad"
assert events[1].event_type == "connection"
def test_device_types_missing():
"""Test handling of missing device types."""
assert DeviceType("NOC") == DeviceType.NOC
assert DeviceType("UNKNOWN") == DeviceType.NLunknown
pyatmo-9.2.1/tests/test_shutter.py 0000664 0000000 0000000 00000006734 15017405234 0017320 0 ustar 00root root 0000000 0000000 """Define tests for shutter module."""
import json
from unittest.mock import AsyncMock, patch
import anyio
from pyatmo import DeviceType
from tests.common import MockResponse
async def test_async_shutter_NBR(async_home):
"""Test NLP Bubendorf iDiamant roller shutter."""
module_id = "0009999992"
assert module_id in async_home.modules
module = async_home.modules[module_id]
assert module.device_type == DeviceType.NBR
assert module.firmware_revision == 16
assert module.current_position == 0
async def test_async_shutter_Z3V(async_home):
"""Test NLG Legrand roller shutter 3rd party."""
module_id = "12:34:56:80:00:c3:69:3d"
assert module_id in async_home.modules
module = async_home.modules[module_id]
assert module.device_type == DeviceType.Z3V
assert module.firmware_revision == 16
assert module.current_position == 0
async def test_async_shutter_NBO(async_home):
"""Test NBO Bubendorf iDiamant roller shutter."""
module_id = "0009999993"
assert module_id in async_home.modules
module = async_home.modules[module_id]
assert module.device_type == DeviceType.NBO
assert module.firmware_revision == 22
assert module.current_position == 0
async def test_async_shutters(async_home):
"""Test basic shutter functionality."""
room_id = "3688132631"
assert room_id in async_home.rooms
module_id = "0009999992"
module = async_home.modules[module_id]
assert module.device_type == DeviceType.NBR
async with await anyio.open_file(
"fixtures/status_ok.json",
encoding="utf-8",
) as json_file:
response = json.loads(await json_file.read())
def gen_json_data(position):
return {
"json": {
"home": {
"id": "91763b24c43d3e344f424e8b",
"modules": [
{
"bridge": "12:34:56:30:d5:d4",
"id": module_id,
"target_position": position,
},
],
},
},
}
with patch(
"pyatmo.auth.AbstractAsyncAuth.async_post_api_request",
AsyncMock(return_value=MockResponse(response, 200)),
) as mock_resp:
assert await module.async_open()
mock_resp.assert_awaited_with(
params=gen_json_data(100),
endpoint="api/setstate",
)
assert await module.async_close()
mock_resp.assert_awaited_with(
params=gen_json_data(0),
endpoint="api/setstate",
)
assert await module.async_stop()
mock_resp.assert_awaited_with(
params=gen_json_data(-1),
endpoint="api/setstate",
)
assert await module.async_move_to_preferred_position()
mock_resp.assert_awaited_with(
params=gen_json_data(-2),
endpoint="api/setstate",
)
assert await module.async_set_target_position(47)
mock_resp.assert_awaited_with(
params=gen_json_data(47),
endpoint="api/setstate",
)
assert await module.async_set_target_position(-10)
mock_resp.assert_awaited_with(
params=gen_json_data(-1),
endpoint="api/setstate",
)
assert await module.async_set_target_position(101)
mock_resp.assert_awaited_with(
params=gen_json_data(100),
endpoint="api/setstate",
)
pyatmo-9.2.1/tests/test_switch.py 0000664 0000000 0000000 00000002732 15017405234 0017115 0 ustar 00root root 0000000 0000000 """Define tests for switch module."""
from pyatmo import DeviceType
from pyatmo.modules.device_types import DeviceCategory
async def test_async_switch_NLP(async_home):
"""Test NLP Legrand plug."""
module_id = "12:34:56:80:00:12:ac:f2"
assert module_id in async_home.modules
module = async_home.modules[module_id]
assert module.device_type == DeviceType.NLP
assert module.firmware_revision == 62
assert module.on
assert module.power == 0
async def test_async_switch_NLF(async_home):
"""Test NLF Legrand dimmer."""
module_id = "00:11:22:33:00:11:45:fe"
assert module_id in async_home.modules
module = async_home.modules[module_id]
assert module.device_type == DeviceType.NLF
assert module.firmware_revision == 57
assert module.on is False
assert module.brightness == 63
assert module.power == 0
async def test_async_switch_NLIS(async_home):
"""Test NLIS Legrand module."""
module_id = "12:34:56:00:01:01:01:b6"
assert module_id in async_home.modules
module = async_home.modules[module_id]
assert module.device_category is None
module_id = "12:34:56:00:01:01:01:b6#1"
assert module_id in async_home.modules
module = async_home.modules[module_id]
assert module.device_category == DeviceCategory.switch
module_id = "12:34:56:00:01:01:01:b6#2"
assert module_id in async_home.modules
module = async_home.modules[module_id]
assert module.device_category == DeviceCategory.switch
pyatmo-9.2.1/tests/test_weather.py 0000664 0000000 0000000 00000024732 15017405234 0017257 0 ustar 00root root 0000000 0000000 """Define tests for weaather module."""
import pyatmo
from pyatmo import DeviceType
from pyatmo.modules.base_class import Location, Place
async def test_async_weather_NAMain(async_home):
"""Test Netatmo weather station main module."""
module_id = "12:34:56:80:bb:26"
assert module_id in async_home.modules
module = async_home.modules[module_id]
assert module.device_type == DeviceType.NAMain
async def test_async_weather_update_main(async_account):
"""Test main weather station module."""
home_id = "91763b24c43d3e344f424e8b"
await async_account.async_update_weather_stations()
home = async_account.homes[home_id]
module_id = "12:34:56:80:bb:26"
assert module_id in home.modules
module = home.modules[module_id]
assert module.device_type == DeviceType.NAMain
assert module.name == "Villa"
assert module.modules == [
"12:34:56:80:44:92",
"12:34:56:80:7e:18",
"12:34:56:80:1c:42",
"12:34:56:80:c1:ea",
]
assert module.features == {
"temperature",
"humidity",
"co2",
"noise",
"pressure",
"absolute_pressure",
"temp_trend",
"pressure_trend",
"min_temp",
"max_temp",
"temp_max",
"temp_min",
"reachable",
"wifi_strength",
"place",
}
assert module.firmware_revision == 181
assert module.wifi_strength == 57
assert module.temperature == 21.1
assert module.humidity == 45
assert module.co2 == 1339
assert module.pressure == 1026.8
assert module.noise == 35
assert module.absolute_pressure == 974.5
assert module.place == Place(
{
"altitude": 329,
"city": "Someplace",
"country": "FR",
"location": Location(longitude=6.1234567, latitude=46.123456),
"timezone": "Europe/Paris",
},
)
async def test_async_weather_update_indoor(async_account):
"""Test indoor weather module."""
home_id = "91763b24c43d3e344f424e8b"
await async_account.async_update_weather_stations()
home = async_account.homes[home_id]
module_id = "12:34:56:80:44:92"
assert module_id in home.modules
module = home.modules[module_id]
assert module.name == "Villa Bedroom"
assert module.features == {
"temperature",
"temp_trend",
"min_temp",
"max_temp",
"temp_max",
"temp_min",
"reachable",
"rf_strength",
"co2",
"humidity",
"battery",
"place",
}
assert module.device_type == DeviceType.NAModule4
assert module.modules is None
assert module.firmware_revision == 51
assert module.rf_strength == 67
assert module.temperature == 19.3
assert module.humidity == 53
assert module.battery == 28
async def test_async_weather_update_rain(async_account):
"""Test rain module."""
home_id = "91763b24c43d3e344f424e8b"
await async_account.async_update_weather_stations()
home = async_account.homes[home_id]
module_id = "12:34:56:80:c1:ea"
assert module_id in home.modules
module = home.modules[module_id]
assert module.name == "Villa Rain"
assert module.features == {
"sum_rain_1",
"sum_rain_24",
"rain",
"reachable",
"rf_strength",
"battery",
"place",
}
assert module.device_type == DeviceType.NAModule3
assert module.modules is None
assert module.firmware_revision == 12
assert module.rf_strength == 79
assert module.rain == 3.7
async def test_async_weather_update_outdoor(async_account):
"""Test outdoor module."""
home_id = "91763b24c43d3e344f424e8b"
await async_account.async_update_weather_stations()
home = async_account.homes[home_id]
module_id = "12:34:56:80:1c:42"
assert module_id in home.modules
module = home.modules[module_id]
assert module.name == "Villa Outdoor"
assert module.features == {
"temperature",
"humidity",
"temp_trend",
"min_temp",
"max_temp",
"temp_max",
"temp_min",
"reachable",
"rf_strength",
"battery",
"place",
}
assert module.device_type == DeviceType.NAModule1
assert module.modules is None
assert module.firmware_revision == 50
assert module.rf_strength == 68
assert module.reachable is False
async def test_async_weather_update_wind(async_account):
"""Test wind module."""
home_id = "91763b24c43d3e344f424e8b"
await async_account.async_update_weather_stations()
home = async_account.homes[home_id]
module_id = "12:34:56:03:1b:e4"
assert module_id in home.modules
module = home.modules[module_id]
assert module.name == "Villa Garden"
assert module.features == {
"wind_strength",
"gust_strength",
"gust_angle",
"gust_direction",
"wind_angle",
"wind_direction",
"reachable",
"rf_strength",
"battery",
"place",
}
assert module.device_type == DeviceType.NAModule2
assert module.modules is None
assert module.firmware_revision == 19
assert module.rf_strength == 59
assert module.wind_strength == 4
assert module.wind_angle == 217
assert module.gust_strength == 9
assert module.gust_angle == 206
async def test_async_weather_favorite(async_account):
"""Test favorite weather station."""
await async_account.async_update_weather_stations()
module_id = "00:11:22:2c:be:c8"
assert module_id in async_account.modules
module = async_account.modules[module_id]
assert module.device_type == DeviceType.NAMain
assert module.name == "Zuhause (Kinderzimmer)"
assert module.modules == ["00:11:22:2c:ce:b6"]
assert module.features == {
"temperature",
"humidity",
"co2",
"noise",
"pressure",
"absolute_pressure",
"temp_trend",
"pressure_trend",
"min_temp",
"max_temp",
"temp_max",
"temp_min",
"reachable",
"wifi_strength",
"place",
}
assert module.pressure == 1015.6
assert module.absolute_pressure == 1000.4
assert module.place == Place(
{
"altitude": 127,
"city": "Wiesbaden",
"country": "DE",
"location": Location(
longitude=8.238054275512695,
latitude=50.07585525512695,
),
"timezone": "Europe/Berlin",
},
)
module_id = "00:11:22:2c:ce:b6"
assert module_id in async_account.modules
module = async_account.modules[module_id]
assert module.device_type == DeviceType.NAModule1
assert module.name == "Unknown"
assert module.modules is None
assert module.features == {
"temperature",
"humidity",
"temp_trend",
"min_temp",
"max_temp",
"temp_max",
"temp_min",
"reachable",
"rf_strength",
"battery",
"place",
}
assert module.temperature == 7.8
assert module.humidity == 87
async def test_async_air_care_update(async_account):
"""Test basic air care update."""
await async_account.async_update_air_care()
module_id = "12:34:56:26:68:92"
assert module_id in async_account.modules
module = async_account.modules[module_id]
assert module.device_type == DeviceType.NHC
assert module.name == "Baby Bedroom"
assert module.features == {
"temperature",
"humidity",
"co2",
"noise",
"pressure",
"absolute_pressure",
"temp_trend",
"pressure_trend",
"min_temp",
"max_temp",
"temp_max",
"temp_min",
"health_idx",
"reachable",
"wifi_strength",
"place",
}
assert module.modules is None
assert module.firmware_revision == 45
assert module.wifi_strength == 68
assert module.temperature == 21.6
assert module.humidity == 66
assert module.co2 == 1053
assert module.pressure == 1021.4
assert module.noise == 45
assert module.absolute_pressure == 1011
assert module.health_idx == 1
async def test_async_public_weather_update(async_account):
"""Test basic public weather update."""
lon_ne = "6.221652"
lat_ne = "46.610870"
lon_sw = "6.217828"
lat_sw = "46.596485"
area_id = async_account.register_public_weather_area(lat_ne, lon_ne, lat_sw, lon_sw)
await async_account.async_update_public_weather(area_id)
area = async_account.public_weather_areas[area_id]
assert area.location == pyatmo.modules.Location(
lat_ne,
lon_ne,
lat_sw,
lon_sw,
)
assert area.stations_in_area() == 8
assert area.get_latest_rain() == {
"70:ee:50:1f:68:9e": 0,
"70:ee:50:27:25:b0": 0,
"70:ee:50:36:94:7c": 0.5,
"70:ee:50:36:a9:fc": 0,
}
assert area.get_60_min_rain() == {
"70:ee:50:1f:68:9e": 0,
"70:ee:50:27:25:b0": 0,
"70:ee:50:36:94:7c": 0.2,
"70:ee:50:36:a9:fc": 0,
}
assert area.get_24_h_rain() == {
"70:ee:50:1f:68:9e": 9.999,
"70:ee:50:27:25:b0": 11.716000000000001,
"70:ee:50:36:94:7c": 12.322000000000001,
"70:ee:50:36:a9:fc": 11.009,
}
assert area.get_latest_pressures() == {
"70:ee:50:1f:68:9e": 1007.3,
"70:ee:50:27:25:b0": 1012.8,
"70:ee:50:36:94:7c": 1010.6,
"70:ee:50:36:a9:fc": 1010,
"70:ee:50:01:20:fa": 1014.4,
"70:ee:50:04:ed:7a": 1005.4,
"70:ee:50:27:9f:2c": 1010.6,
"70:ee:50:3c:02:78": 1011.7,
}
assert area.get_latest_temperatures() == {
"70:ee:50:1f:68:9e": 21.1,
"70:ee:50:27:25:b0": 23.2,
"70:ee:50:36:94:7c": 21.4,
"70:ee:50:36:a9:fc": 20.1,
"70:ee:50:01:20:fa": 27.4,
"70:ee:50:04:ed:7a": 19.8,
"70:ee:50:27:9f:2c": 25.5,
"70:ee:50:3c:02:78": 23.3,
}
assert area.get_latest_humidities() == {
"70:ee:50:1f:68:9e": 69,
"70:ee:50:27:25:b0": 60,
"70:ee:50:36:94:7c": 62,
"70:ee:50:36:a9:fc": 67,
"70:ee:50:01:20:fa": 58,
"70:ee:50:04:ed:7a": 76,
"70:ee:50:27:9f:2c": 56,
"70:ee:50:3c:02:78": 58,
}
assert area.get_latest_wind_strengths() == {"70:ee:50:36:a9:fc": 15}
assert area.get_latest_wind_angles() == {"70:ee:50:36:a9:fc": 17}
assert area.get_latest_gust_strengths() == {"70:ee:50:36:a9:fc": 31}
assert area.get_latest_gust_angles() == {"70:ee:50:36:a9:fc": 217}
pyatmo-9.2.1/tests/testing_main_template.py 0000664 0000000 0000000 00000001703 15017405234 0021126 0 ustar 00root root 0000000 0000000 import asyncio
from aiohttp import ClientSession
import pyatmo
from pyatmo.auth import AbstractAsyncAuth
from pyatmo.modules.module import MeasureInterval
MY_TOKEN_FROM_NETATMO = "MY_TOKEN"
class MyAuth(AbstractAsyncAuth):
async def async_get_access_token(self):
return MY_TOKEN_FROM_NETATMO
async def main():
session = ClientSession()
async_auth = MyAuth(session)
account = pyatmo.AsyncAccount(async_auth)
t = asyncio.create_task(account.async_update_topology())
home_id = "MY_HOME_ID"
module_id = "MY_MODULE_ID"
await asyncio.gather(t)
await account.async_update_status(home_id=home_id)
strt = 1709766000 + 10 * 60
end = 1709852400 + 10 * 60
await account.async_update_measures(
home_id=home_id,
module_id=module_id,
interval=MeasureInterval.HALF_HOUR,
start_time=strt,
end_time=end,
)
if __name__ == "__main__":
topology = asyncio.run(main())
pyatmo-9.2.1/tox.ini 0000664 0000000 0000000 00000001277 15017405234 0014357 0 ustar 00root root 0000000 0000000 [tox]
envlist = py311,py312,mypy
isolated_build = True
skip_missing_interpreters = True
[gh-actions]
python =
3.11: py311
3.12: py312,mypy
[testenv:py311,py312]
deps =
pytest-cov
pytest-mock
pytest-asyncio
requests-mock
time-machine
anyio
setenv =
COVERAGE_FILE = {envlogdir}/.coverage
commands =
python -m pytest --cov {envsitepackagesdir}/pyatmo {posargs}
[coverage:paths]
source =
pyatmo
.tox/*/lib/python*/site-packages/pyatmo
[coverage:run]
branch = True
omit = */__main__.py
source =
pyatmo
[coverage:report]
show_missing = True
precision = 2
fail_under = 78
[testenv:mypy]
deps =
mypy
types-requests
commands =
mypy -p pyatmo
pyatmo-9.2.1/uv.lock 0000664 0000000 0000000 00000775403 15017405234 0014361 0 ustar 00root root 0000000 0000000 version = 1
revision = 2
requires-python = ">=3.11"
[[package]]
name = "aiohappyeyeballs"
version = "2.6.1"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/26/30/f84a107a9c4331c14b2b586036f40965c128aa4fee4dda5d3d51cb14ad54/aiohappyeyeballs-2.6.1.tar.gz", hash = "sha256:c3f9d0113123803ccadfdf3f0faa505bc78e6a72d1cc4806cbd719826e943558", size = 22760, upload-time = "2025-03-12T01:42:48.764Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/0f/15/5bf3b99495fb160b63f95972b81750f18f7f4e02ad051373b669d17d44f2/aiohappyeyeballs-2.6.1-py3-none-any.whl", hash = "sha256:f349ba8f4b75cb25c99c5c2d84e997e485204d2902a9597802b0371f09331fb8", size = 15265, upload-time = "2025-03-12T01:42:47.083Z" },
]
[[package]]
name = "aiohttp"
version = "3.12.7"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "aiohappyeyeballs" },
{ name = "aiosignal" },
{ name = "attrs" },
{ name = "frozenlist" },
{ name = "multidict" },
{ name = "propcache" },
{ name = "yarl" },
]
sdist = { url = "https://files.pythonhosted.org/packages/eb/62/95588e933dfea06a3af0332990bd19f6768f8f37fa4c0fe33fe4c55cf9d0/aiohttp-3.12.7.tar.gz", hash = "sha256:08bf55b216c779eddb6e41c1841c17d7ddd12776c7d7b36051c0a292a9ca828e", size = 7806530, upload-time = "2025-06-02T16:34:10.399Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/af/19/37560cc111d6fd95ff6c4bd14445e3c629269fce406c89cc7a69a2865ecf/aiohttp-3.12.7-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:388b5947aa6931ef4ce3ed4edde6853e84980677886992cfadcf733dd06eed63", size = 707169, upload-time = "2025-06-02T16:31:39.107Z" },
{ url = "https://files.pythonhosted.org/packages/b9/18/29bbefb094f81a687473c1d31391bf8a4c48c7b5b8559c3679fc14e67597/aiohttp-3.12.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9ed5af1cce257cca27a3e920b003b3b397f63418a203064b7d804ea3b45782af", size = 479443, upload-time = "2025-06-02T16:31:41.185Z" },
{ url = "https://files.pythonhosted.org/packages/cf/7d/119f3e012c75a3fe38f86ac1d77f1452779e0e940770d5827d4e62aa5655/aiohttp-3.12.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f466ae8f9c02993b7d167be685bdbeb527cf254a3cfcc757697e0e336399d0a2", size = 467706, upload-time = "2025-06-02T16:31:43.401Z" },
{ url = "https://files.pythonhosted.org/packages/83/f1/f61d8573d648e17347ab9a112063e4363664b5b6100792467fbb26028bde/aiohttp-3.12.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2be095a420a9f9a12eff343d877ae180dd919238b539431af08cef929e874759", size = 1737902, upload-time = "2025-06-02T16:31:45.948Z" },
{ url = "https://files.pythonhosted.org/packages/4b/f8/7a8a000bc63de3c79aaa8f03b0784e29e9982276f4579c5e2e56d560e403/aiohttp-3.12.7-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:b058cf2ba6adba699960d7bc403411c8a99ab5d3e5ea3eb01473638ae7d1a30e", size = 1686569, upload-time = "2025-06-02T16:31:47.749Z" },
{ url = "https://files.pythonhosted.org/packages/5c/4e/29a5b35ca9a598f51dc7deff4e8403bf813988f30a8b250e25a8442641b7/aiohttp-3.12.7-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9b6a660163b055686dbb0acc961978fd14537eba5d9da6cbdb4dced7a8d3be1a", size = 1785359, upload-time = "2025-06-02T16:31:49.687Z" },
{ url = "https://files.pythonhosted.org/packages/f9/36/0521398a69c40ac24c659b130597e2544cde1d7dd00291b8a6206bb552d0/aiohttp-3.12.7-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d741923905f267ad5d5c8f86a56f9d2beac9f32a36c217c5d9ef65cd74fd8ca0", size = 1824408, upload-time = "2025-06-02T16:31:51.518Z" },
{ url = "https://files.pythonhosted.org/packages/c1/41/79506d76da96399b6b700acbe10b14291547a3b49a1cc7ed2c5edaa199ce/aiohttp-3.12.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:519f5454b6018158ae0e789b8f6a88726c47dd680982eb318ef3ca4dee727314", size = 1726867, upload-time = "2025-06-02T16:31:53.277Z" },
{ url = "https://files.pythonhosted.org/packages/32/d1/d59ed16962934b46c7569d04af2dc9638a38ae5812680b9d6c7ee42d770e/aiohttp-3.12.7-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e4eebfe470e22cc4b374d7e32c07e96d777a5c0fa51f3824de68e697da037ec", size = 1663943, upload-time = "2025-06-02T16:31:55.094Z" },
{ url = "https://files.pythonhosted.org/packages/15/d5/971d1b277e6a3d5b679f0c9ba076c343a5125ea2eacc51c23ea7d875d43a/aiohttp-3.12.7-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:74ff39445f94923cf595e9e6dd602ecbe66b12364e2207e61342b8834417f8da", size = 1712217, upload-time = "2025-06-02T16:31:57.336Z" },
{ url = "https://files.pythonhosted.org/packages/e1/9c/c21fd0ba87772f3d1d43cdbfcfd40fe29f37d36a5d73997a8a4d4d1485c3/aiohttp-3.12.7-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:77cb9dba16486ecfeac8076763600b9714941e0ff696e53a30e8d408d9a196ca", size = 1707375, upload-time = "2025-06-02T16:31:59.12Z" },
{ url = "https://files.pythonhosted.org/packages/85/48/bb97ef3a694df852b70e6f5c1aaf3621a3a26b35f0a0d90481f3fdb1ce8b/aiohttp-3.12.7-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:a7b3b9cbe83e3918a1918b0de274884f17b64224c1c9210a6fb0f7c10d246636", size = 1687561, upload-time = "2025-06-02T16:32:01.385Z" },
{ url = "https://files.pythonhosted.org/packages/d5/75/0b85f30ba9eb1dbdb5d3a53d3a0db29990220f69187acb24d06903686c5d/aiohttp-3.12.7-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:6055f53c70938498884e71ca966abe8e9e7558489e13a7e40b6384dee7230d1d", size = 1781163, upload-time = "2025-06-02T16:32:03.176Z" },
{ url = "https://files.pythonhosted.org/packages/92/51/6350a4c485c7d2fb794101d46085c3830485ec1c37738d8af6c9c5ed8e1a/aiohttp-3.12.7-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:8493a42d5b2a736c6804239b985feebeea1c60f8fcb46a3607d6dce3c1a42b12", size = 1801624, upload-time = "2025-06-02T16:32:05.027Z" },
{ url = "https://files.pythonhosted.org/packages/4f/dd/6a75eaaac93b5552090e42c38a576062028ce4af50f0b50ac550332d332c/aiohttp-3.12.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:372f2237cade45f563d973c2a913895f2699a892c0eb11c55c6880b6f0acf219", size = 1714679, upload-time = "2025-06-02T16:32:06.837Z" },
{ url = "https://files.pythonhosted.org/packages/de/ad/0574964387d8eed7fcd0c2fe6ef20c4affe0b265c710938d5fffdb3776b5/aiohttp-3.12.7-cp311-cp311-win32.whl", hash = "sha256:41f686749a099b507563a5c0cb4fd77367b05448a2c1758784ad506a28e9e579", size = 424709, upload-time = "2025-06-02T16:32:08.671Z" },
{ url = "https://files.pythonhosted.org/packages/4f/ab/6b82b43abb0990e4452aaef509cf1403ab50c04b5c090f92fb1b255fb319/aiohttp-3.12.7-cp311-cp311-win_amd64.whl", hash = "sha256:7a3691583470d4397aca70fbf8e0f0778b63a2c2a6a23263bdeeb68395972f29", size = 449100, upload-time = "2025-06-02T16:32:10.373Z" },
{ url = "https://files.pythonhosted.org/packages/5d/65/0bd8ccbffa33ee69db9f5c43f3f62fb8b600b607388e9a8deab8962d0523/aiohttp-3.12.7-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:9b9345918f5b5156a5712c37d1d331baf320df67547ea032a49a609b773c3606", size = 698263, upload-time = "2025-06-02T16:32:12.107Z" },
{ url = "https://files.pythonhosted.org/packages/99/64/a48a8abc4e684fb447d1f7b61e7adcb19865b91e20b50595f49b2942fbb3/aiohttp-3.12.7-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3091b4883f405dbabeb9ea821a25dec16d03a51c3e0d2752fc3ab48b652bf196", size = 472877, upload-time = "2025-06-02T16:32:14.386Z" },
{ url = "https://files.pythonhosted.org/packages/7d/e4/994bc56a7d7733e9cd1f45db8b656e78d51d7a61cefff8043ec4f7d4a23f/aiohttp-3.12.7-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:97fd97abd4cf199eff4041d0346a7dc68b60deab177f01de87283be513ffc3ab", size = 465716, upload-time = "2025-06-02T16:32:16.108Z" },
{ url = "https://files.pythonhosted.org/packages/39/b0/bddc489288a0e3b05fa05387db9caebc38577204a17db0d5428abae524ba/aiohttp-3.12.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3a5938973105cd5ff17176e8cb36bc19cac7c82ae7c58c0dbd7e023972d0c708", size = 1712513, upload-time = "2025-06-02T16:32:17.898Z" },
{ url = "https://files.pythonhosted.org/packages/4d/4a/c06d3ce0dc5f96338cc8d18da57d74608585a3751234eeef5952e4f48ade/aiohttp-3.12.7-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e506ae5c4c05d1a1e87edd64b994cea2d49385d41d32e1c6be8764f31cf2245c", size = 1695167, upload-time = "2025-06-02T16:32:20.131Z" },
{ url = "https://files.pythonhosted.org/packages/79/ec/e847fdfe2b1c1f1a2b0ba5343a9b2bd033a0545f8eaf1f7894a6614473ae/aiohttp-3.12.7-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b780b402e6361c4cfcec252580f5ecdd86cb68376520ac34748d3f8b262dd598", size = 1750261, upload-time = "2025-06-02T16:32:22.717Z" },
{ url = "https://files.pythonhosted.org/packages/2c/5e/b832ff59737d99cc5ae51b737c52976d19990ccee922ba6fe811f615e7f9/aiohttp-3.12.7-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cf981bbfb7ff2ebc1b3bfae49d2efe2c51ca1cf3d90867f47c310df65398e85e", size = 1796416, upload-time = "2025-06-02T16:32:25.15Z" },
{ url = "https://files.pythonhosted.org/packages/e0/ff/51ae87efce9b53aafd384179f58923bf178f561897cf80054a440fdf8363/aiohttp-3.12.7-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94f98e0e5a49f89b252e115844f756c04fc8050f38252a32a3dd994ce8121f10", size = 1715855, upload-time = "2025-06-02T16:32:27.236Z" },
{ url = "https://files.pythonhosted.org/packages/b1/54/5a77116498f84d2503f5588e687eccfa43a85aa2450bc195ee6e5bb75695/aiohttp-3.12.7-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:410e96cc6824fc4ced9703fb2ac2d06c6190d21fc6f5b588f62b1918628449c1", size = 1631656, upload-time = "2025-06-02T16:32:29.15Z" },
{ url = "https://files.pythonhosted.org/packages/46/34/554220592f8ade7f3cabebfb9325e95078f842140f293ced3ab977fd13ec/aiohttp-3.12.7-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:43e93987fe9df4349db8deae7c391695538c35e4ba893133c7e823234f6e4537", size = 1692718, upload-time = "2025-06-02T16:32:31.295Z" },
{ url = "https://files.pythonhosted.org/packages/ff/9d/ae7103bb8c73c3521e38ae8cde301ddc937024b1681ce134bb1ef01be7d0/aiohttp-3.12.7-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:cb3f3dcb59f3e16819a1c7d3fa32e7b87255b661c1e139a1b5940bde270704ab", size = 1714171, upload-time = "2025-06-02T16:32:33.767Z" },
{ url = "https://files.pythonhosted.org/packages/5d/4d/9b8b8f362e36392939019340321f7efcc1807bb2c4cdea8eb1019d3398ff/aiohttp-3.12.7-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:4a46fe4a4c66b2712059e48a8384eb93565fbe3251af4844860fed846ef4ca75", size = 1654822, upload-time = "2025-06-02T16:32:36.23Z" },
{ url = "https://files.pythonhosted.org/packages/48/30/0ca82df423ee346206bc167852c825cd210c11d2f1fa0064a2a55d7f60d5/aiohttp-3.12.7-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:ad01793164661af70918490ef8efc2c09df7a3c686b6c84ca90a2d69cdbc3911", size = 1734385, upload-time = "2025-06-02T16:32:38.171Z" },
{ url = "https://files.pythonhosted.org/packages/43/bd/96d12318c0f82ac8323bd4459ee26291ad220f688988077a21e538b0872c/aiohttp-3.12.7-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:e85c6833be3f49cead2e7bc79080e5c18d6dab9af32226ab5a01dc20c523e7d9", size = 1762356, upload-time = "2025-06-02T16:32:40.142Z" },
{ url = "https://files.pythonhosted.org/packages/6c/39/7a9b706bf42f293415584d60cf35e80d0558929ab70e72cb40b747f0dfc7/aiohttp-3.12.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3c9f52149d8249566e72c50c7985c2345521b3b78f84aa86f6f492cd50b14793", size = 1721970, upload-time = "2025-06-02T16:32:42.187Z" },
{ url = "https://files.pythonhosted.org/packages/19/f2/8899367a52dec8100f43036e5a792cfdbae317bf3a80549da90290083ff4/aiohttp-3.12.7-cp312-cp312-win32.whl", hash = "sha256:0e1c33ac0f6a396bcefe9c1d52c9d38a051861885a5c102ca5c8298aba0108fa", size = 419443, upload-time = "2025-06-02T16:32:44.335Z" },
{ url = "https://files.pythonhosted.org/packages/e8/34/ad5225b4edbcc23496537011d67ef1a147c03205c07340f4a50993b219b9/aiohttp-3.12.7-cp312-cp312-win_amd64.whl", hash = "sha256:b4aed5233a9d13e34e8624ecb798533aa2da97e7048cc69671b7a6d7a2efe7e8", size = 445544, upload-time = "2025-06-02T16:32:46.631Z" },
{ url = "https://files.pythonhosted.org/packages/fb/a0/c6b01de500e6a115c185bd892d41fcad47b680cc3383c3a01f1f6ab44335/aiohttp-3.12.7-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:adbb2046600a60e37a54ea9b77b0ddef280029b0a853624a8e9b2b71a037c890", size = 692665, upload-time = "2025-06-02T16:32:48.962Z" },
{ url = "https://files.pythonhosted.org/packages/c1/30/afc2b7c23fccdb1efd056bc6a9aa62077dee59448551631cb80ed3c893dd/aiohttp-3.12.7-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:76392cbadc1ccc0a8c02098b74c0240d53c644b10a81e1addbc1666dce3cd62a", size = 470331, upload-time = "2025-06-02T16:32:50.89Z" },
{ url = "https://files.pythonhosted.org/packages/35/03/61318657ba49899defd70dde622e85fa2fc69dcbafe20bc26ce10dbbcfe0/aiohttp-3.12.7-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6f04af3bf040dc8fd9b2bc0e465f5aca6fc5349fa08bd7f08142974a2ded21bf", size = 462635, upload-time = "2025-06-02T16:32:52.778Z" },
{ url = "https://files.pythonhosted.org/packages/10/1e/20ff25b33d39a604094e6d0f9e32c110d63b48a0f8394fa33fd6228ea0dd/aiohttp-3.12.7-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b19763f88f058e9c605f79cde8a800660f7e259162b80982111cc631dfc54bf0", size = 1701455, upload-time = "2025-06-02T16:32:55.209Z" },
{ url = "https://files.pythonhosted.org/packages/6a/37/43adcb8e2940b888a743acfa54e754b1932b5665a0728944928e8bda93a2/aiohttp-3.12.7-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:6600550593c440ef29ca2a14b8a52ac91b9f494d85f75294409ec6ad5637476f", size = 1682720, upload-time = "2025-06-02T16:32:57.743Z" },
{ url = "https://files.pythonhosted.org/packages/c5/b3/b4830455bcbac491904c0fbfc9e1cd70445f3ed745ba3b2b5e196964249e/aiohttp-3.12.7-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c7b83c829be3cddaf958dee8108e09b1502c215e95064d3045015298dbded54a", size = 1734788, upload-time = "2025-06-02T16:32:59.738Z" },
{ url = "https://files.pythonhosted.org/packages/97/87/21eca23f8c3f2fcf96661029533596a520a44a47707040782762bc948588/aiohttp-3.12.7-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ffa9928fd37061c8e35b85d3f1b4a256d0c3e8cbd421c1d8bd0ab45461b6a838", size = 1784163, upload-time = "2025-06-02T16:33:01.855Z" },
{ url = "https://files.pythonhosted.org/packages/ce/2f/5692c1d0bce47c733beca21e30da28a9fa9b9013c777be5537b81924ef9a/aiohttp-3.12.7-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc8086515dd1016b67db9ccebb7159234226dba99fb6a895a0c9270b644cf525", size = 1706492, upload-time = "2025-06-02T16:33:03.951Z" },
{ url = "https://files.pythonhosted.org/packages/a0/40/bb2ae33973c23cb7d96676c2c342d55a46e718906c267b05368b063420bb/aiohttp-3.12.7-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8c19b1de25703560fa64f998dfc3685040b52996056e048b3406c8e97dcfa1e3", size = 1620197, upload-time = "2025-06-02T16:33:06.69Z" },
{ url = "https://files.pythonhosted.org/packages/5e/39/45d2ca30a6275445764cfefecebcc9ec41461a3b41c3beebff33ba080fe3/aiohttp-3.12.7-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6357abdc7a2cfb113274c4f4a7f086bdca36905924953bf7a9e3f6add3aec7c5", size = 1673219, upload-time = "2025-06-02T16:33:08.9Z" },
{ url = "https://files.pythonhosted.org/packages/21/91/05864e93472dcc52e95cb33c808c212cb248069d11d730c1c726aefd42d5/aiohttp-3.12.7-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:29ff7876ff7e4a8029642334a81891cb5a842f1e405195c2946f697102756670", size = 1704882, upload-time = "2025-06-02T16:33:11.046Z" },
{ url = "https://files.pythonhosted.org/packages/3c/90/a4585fa7b8603dd5c6778d4471245c50048c13b41f95e9e855d7ce1bd6f0/aiohttp-3.12.7-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:5e7741c53d473204f89dd26f3b087a5883c742add8d6504d0d7d3ad3ff1cd1b7", size = 1647478, upload-time = "2025-06-02T16:33:13.473Z" },
{ url = "https://files.pythonhosted.org/packages/8f/37/f2f30aceb3b6977033deab11f54728e46c990950e3206dfc91677219d3e3/aiohttp-3.12.7-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:38dc536059cc0624e22273905a1df74b231ac903d73af59ee6e6e3139f05a28b", size = 1723613, upload-time = "2025-06-02T16:33:15.883Z" },
{ url = "https://files.pythonhosted.org/packages/29/92/8ef582e9c286cf285f1788fef10b95a8b9178ee68759071ff5ef3a7c2aa6/aiohttp-3.12.7-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:82a59cf086396a409d6d2350c122aada07f1f56bb529734994d37bcafc8cf101", size = 1757083, upload-time = "2025-06-02T16:33:18.553Z" },
{ url = "https://files.pythonhosted.org/packages/6d/84/e0e010286781187e3bce69ac9e2b51d3264293a9295db5791ffa084aeaf9/aiohttp-3.12.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:7cd6e299292ba085a3642cb4085b393f45bbca45c067182d15e33c2e3473283c", size = 1705975, upload-time = "2025-06-02T16:33:20.849Z" },
{ url = "https://files.pythonhosted.org/packages/ff/6a/a956e2634f9c3af533a60b2c001a484edd52fea05572d144d5efbf8c313e/aiohttp-3.12.7-cp313-cp313-win32.whl", hash = "sha256:4acec2b5de65adc469837260be8408d5f53d4c8ae60631be868e9d7eb8563167", size = 418469, upload-time = "2025-06-02T16:33:23.566Z" },
{ url = "https://files.pythonhosted.org/packages/86/7a/944963ccf6651dd593a00370423dd74fad745b439fc89502f81620cd93c9/aiohttp-3.12.7-cp313-cp313-win_amd64.whl", hash = "sha256:93317649d65cc895ba1fe5384353cb6c44638db39ebb55dabe3dade34a1b1177", size = 444406, upload-time = "2025-06-02T16:33:26.213Z" },
]
[[package]]
name = "aiosignal"
version = "1.3.2"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "frozenlist" },
]
sdist = { url = "https://files.pythonhosted.org/packages/ba/b5/6d55e80f6d8a08ce22b982eafa278d823b541c925f11ee774b0b9c43473d/aiosignal-1.3.2.tar.gz", hash = "sha256:a8c255c66fafb1e499c9351d0bf32ff2d8a0321595ebac3b93713656d2436f54", size = 19424, upload-time = "2024-12-13T17:10:40.86Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/ec/6a/bc7e17a3e87a2985d3e8f4da4cd0f481060eb78fb08596c42be62c90a4d9/aiosignal-1.3.2-py2.py3-none-any.whl", hash = "sha256:45cde58e409a301715980c2b01d0c28bdde3770d8290b5eb2173759d9acb31a5", size = 7597, upload-time = "2024-12-13T17:10:38.469Z" },
]
[[package]]
name = "anyio"
version = "4.9.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "idna" },
{ name = "sniffio" },
{ name = "typing-extensions", marker = "python_full_version < '3.13'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/95/7d/4c1bd541d4dffa1b52bd83fb8527089e097a106fc90b467a7313b105f840/anyio-4.9.0.tar.gz", hash = "sha256:673c0c244e15788651a4ff38710fea9675823028a6f08a5eda409e0c9840a028", size = 190949, upload-time = "2025-03-17T00:02:54.77Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/a1/ee/48ca1a7c89ffec8b6a0c5d02b89c305671d5ffd8d3c94acf8b8c408575bb/anyio-4.9.0-py3-none-any.whl", hash = "sha256:9f76d541cad6e36af7beb62e978876f3b41e3e04f2c1fbf0884604c0a9c4d93c", size = 100916, upload-time = "2025-03-17T00:02:52.713Z" },
]
[[package]]
name = "attrs"
version = "25.3.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/5a/b0/1367933a8532ee6ff8d63537de4f1177af4bff9f3e829baf7331f595bb24/attrs-25.3.0.tar.gz", hash = "sha256:75d7cefc7fb576747b2c81b4442d4d4a1ce0900973527c011d1030fd3bf4af1b", size = 812032, upload-time = "2025-03-13T11:10:22.779Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/77/06/bb80f5f86020c4551da315d78b3ab75e8228f89f0162f2c3a819e407941a/attrs-25.3.0-py3-none-any.whl", hash = "sha256:427318ce031701fea540783410126f03899a97ffc6f61596ad581ac2e40e3bc3", size = 63815, upload-time = "2025-03-13T11:10:21.14Z" },
]
[[package]]
name = "backports-tarfile"
version = "1.2.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/86/72/cd9b395f25e290e633655a100af28cb253e4393396264a98bd5f5951d50f/backports_tarfile-1.2.0.tar.gz", hash = "sha256:d75e02c268746e1b8144c278978b6e98e85de6ad16f8e4b0844a154557eca991", size = 86406, upload-time = "2024-05-28T17:01:54.731Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/b9/fa/123043af240e49752f1c4bd24da5053b6bd00cad78c2be53c0d1e8b975bc/backports.tarfile-1.2.0-py3-none-any.whl", hash = "sha256:77e284d754527b01fb1e6fa8a1afe577858ebe4e9dad8919e34c862cb399bc34", size = 30181, upload-time = "2024-05-28T17:01:53.112Z" },
]
[[package]]
name = "black"
version = "25.1.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "click" },
{ name = "mypy-extensions" },
{ name = "packaging" },
{ name = "pathspec" },
{ name = "platformdirs" },
]
sdist = { url = "https://files.pythonhosted.org/packages/94/49/26a7b0f3f35da4b5a65f081943b7bcd22d7002f5f0fb8098ec1ff21cb6ef/black-25.1.0.tar.gz", hash = "sha256:33496d5cd1222ad73391352b4ae8da15253c5de89b93a80b3e2c8d9a19ec2666", size = 649449, upload-time = "2025-01-29T04:15:40.373Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/7e/4f/87f596aca05c3ce5b94b8663dbfe242a12843caaa82dd3f85f1ffdc3f177/black-25.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a39337598244de4bae26475f77dda852ea00a93bd4c728e09eacd827ec929df0", size = 1614372, upload-time = "2025-01-29T05:37:11.71Z" },
{ url = "https://files.pythonhosted.org/packages/e7/d0/2c34c36190b741c59c901e56ab7f6e54dad8df05a6272a9747ecef7c6036/black-25.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:96c1c7cd856bba8e20094e36e0f948718dc688dba4a9d78c3adde52b9e6c2299", size = 1442865, upload-time = "2025-01-29T05:37:14.309Z" },
{ url = "https://files.pythonhosted.org/packages/21/d4/7518c72262468430ead45cf22bd86c883a6448b9eb43672765d69a8f1248/black-25.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bce2e264d59c91e52d8000d507eb20a9aca4a778731a08cfff7e5ac4a4bb7096", size = 1749699, upload-time = "2025-01-29T04:18:17.688Z" },
{ url = "https://files.pythonhosted.org/packages/58/db/4f5beb989b547f79096e035c4981ceb36ac2b552d0ac5f2620e941501c99/black-25.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:172b1dbff09f86ce6f4eb8edf9dede08b1fce58ba194c87d7a4f1a5aa2f5b3c2", size = 1428028, upload-time = "2025-01-29T04:18:51.711Z" },
{ url = "https://files.pythonhosted.org/packages/83/71/3fe4741df7adf015ad8dfa082dd36c94ca86bb21f25608eb247b4afb15b2/black-25.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4b60580e829091e6f9238c848ea6750efed72140b91b048770b64e74fe04908b", size = 1650988, upload-time = "2025-01-29T05:37:16.707Z" },
{ url = "https://files.pythonhosted.org/packages/13/f3/89aac8a83d73937ccd39bbe8fc6ac8860c11cfa0af5b1c96d081facac844/black-25.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1e2978f6df243b155ef5fa7e558a43037c3079093ed5d10fd84c43900f2d8ecc", size = 1453985, upload-time = "2025-01-29T05:37:18.273Z" },
{ url = "https://files.pythonhosted.org/packages/6f/22/b99efca33f1f3a1d2552c714b1e1b5ae92efac6c43e790ad539a163d1754/black-25.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3b48735872ec535027d979e8dcb20bf4f70b5ac75a8ea99f127c106a7d7aba9f", size = 1783816, upload-time = "2025-01-29T04:18:33.823Z" },
{ url = "https://files.pythonhosted.org/packages/18/7e/a27c3ad3822b6f2e0e00d63d58ff6299a99a5b3aee69fa77cd4b0076b261/black-25.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:ea0213189960bda9cf99be5b8c8ce66bb054af5e9e861249cd23471bd7b0b3ba", size = 1440860, upload-time = "2025-01-29T04:19:12.944Z" },
{ url = "https://files.pythonhosted.org/packages/98/87/0edf98916640efa5d0696e1abb0a8357b52e69e82322628f25bf14d263d1/black-25.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8f0b18a02996a836cc9c9c78e5babec10930862827b1b724ddfe98ccf2f2fe4f", size = 1650673, upload-time = "2025-01-29T05:37:20.574Z" },
{ url = "https://files.pythonhosted.org/packages/52/e5/f7bf17207cf87fa6e9b676576749c6b6ed0d70f179a3d812c997870291c3/black-25.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:afebb7098bfbc70037a053b91ae8437c3857482d3a690fefc03e9ff7aa9a5fd3", size = 1453190, upload-time = "2025-01-29T05:37:22.106Z" },
{ url = "https://files.pythonhosted.org/packages/e3/ee/adda3d46d4a9120772fae6de454c8495603c37c4c3b9c60f25b1ab6401fe/black-25.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:030b9759066a4ee5e5aca28c3c77f9c64789cdd4de8ac1df642c40b708be6171", size = 1782926, upload-time = "2025-01-29T04:18:58.564Z" },
{ url = "https://files.pythonhosted.org/packages/cc/64/94eb5f45dcb997d2082f097a3944cfc7fe87e071907f677e80788a2d7b7a/black-25.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:a22f402b410566e2d1c950708c77ebf5ebd5d0d88a6a2e87c86d9fb48afa0d18", size = 1442613, upload-time = "2025-01-29T04:19:27.63Z" },
{ url = "https://files.pythonhosted.org/packages/09/71/54e999902aed72baf26bca0d50781b01838251a462612966e9fc4891eadd/black-25.1.0-py3-none-any.whl", hash = "sha256:95e8176dae143ba9097f351d174fdaf0ccd29efb414b362ae3fd72bf0f710717", size = 207646, upload-time = "2025-01-29T04:15:38.082Z" },
]
[[package]]
name = "cachetools"
version = "6.0.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/c0/b0/f539a1ddff36644c28a61490056e5bae43bd7386d9f9c69beae2d7e7d6d1/cachetools-6.0.0.tar.gz", hash = "sha256:f225782b84438f828328fc2ad74346522f27e5b1440f4e9fd18b20ebfd1aa2cf", size = 30160, upload-time = "2025-05-23T20:01:13.076Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/6a/c3/8bb087c903c95a570015ce84e0c23ae1d79f528c349cbc141b5c4e250293/cachetools-6.0.0-py3-none-any.whl", hash = "sha256:82e73ba88f7b30228b5507dce1a1f878498fc669d972aef2dde4f3a3c24f103e", size = 10964, upload-time = "2025-05-23T20:01:11.323Z" },
]
[[package]]
name = "certifi"
version = "2025.4.26"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/e8/9e/c05b3920a3b7d20d3d3310465f50348e5b3694f4f88c6daf736eef3024c4/certifi-2025.4.26.tar.gz", hash = "sha256:0a816057ea3cdefcef70270d2c515e4506bbc954f417fa5ade2021213bb8f0c6", size = 160705, upload-time = "2025-04-26T02:12:29.51Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/4a/7e/3db2bd1b1f9e95f7cddca6d6e75e2f2bd9f51b1246e546d88addca0106bd/certifi-2025.4.26-py3-none-any.whl", hash = "sha256:30350364dfe371162649852c63336a15c70c6510c2ad5015b21c2345311805f3", size = 159618, upload-time = "2025-04-26T02:12:27.662Z" },
]
[[package]]
name = "cffi"
version = "1.17.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "pycparser" },
]
sdist = { url = "https://files.pythonhosted.org/packages/fc/97/c783634659c2920c3fc70419e3af40972dbaf758daa229a7d6ea6135c90d/cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824", size = 516621, upload-time = "2024-09-04T20:45:21.852Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/94/dd/a3f0118e688d1b1a57553da23b16bdade96d2f9bcda4d32e7d2838047ff7/cffi-1.17.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4", size = 445259, upload-time = "2024-09-04T20:43:56.123Z" },
{ url = "https://files.pythonhosted.org/packages/2e/ea/70ce63780f096e16ce8588efe039d3c4f91deb1dc01e9c73a287939c79a6/cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41", size = 469200, upload-time = "2024-09-04T20:43:57.891Z" },
{ url = "https://files.pythonhosted.org/packages/1c/a0/a4fa9f4f781bda074c3ddd57a572b060fa0df7655d2a4247bbe277200146/cffi-1.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1", size = 477235, upload-time = "2024-09-04T20:44:00.18Z" },
{ url = "https://files.pythonhosted.org/packages/62/12/ce8710b5b8affbcdd5c6e367217c242524ad17a02fe5beec3ee339f69f85/cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6", size = 459721, upload-time = "2024-09-04T20:44:01.585Z" },
{ url = "https://files.pythonhosted.org/packages/ff/6b/d45873c5e0242196f042d555526f92aa9e0c32355a1be1ff8c27f077fd37/cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d", size = 467242, upload-time = "2024-09-04T20:44:03.467Z" },
{ url = "https://files.pythonhosted.org/packages/1a/52/d9a0e523a572fbccf2955f5abe883cfa8bcc570d7faeee06336fbd50c9fc/cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6", size = 477999, upload-time = "2024-09-04T20:44:05.023Z" },
{ url = "https://files.pythonhosted.org/packages/44/74/f2a2460684a1a2d00ca799ad880d54652841a780c4c97b87754f660c7603/cffi-1.17.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f", size = 454242, upload-time = "2024-09-04T20:44:06.444Z" },
{ url = "https://files.pythonhosted.org/packages/f8/4a/34599cac7dfcd888ff54e801afe06a19c17787dfd94495ab0c8d35fe99fb/cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b", size = 478604, upload-time = "2024-09-04T20:44:08.206Z" },
{ url = "https://files.pythonhosted.org/packages/cc/b6/db007700f67d151abadf508cbfd6a1884f57eab90b1bb985c4c8c02b0f28/cffi-1.17.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36", size = 454803, upload-time = "2024-09-04T20:44:15.231Z" },
{ url = "https://files.pythonhosted.org/packages/1a/df/f8d151540d8c200eb1c6fba8cd0dfd40904f1b0682ea705c36e6c2e97ab3/cffi-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5", size = 478850, upload-time = "2024-09-04T20:44:17.188Z" },
{ url = "https://files.pythonhosted.org/packages/28/c0/b31116332a547fd2677ae5b78a2ef662dfc8023d67f41b2a83f7c2aa78b1/cffi-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff", size = 485729, upload-time = "2024-09-04T20:44:18.688Z" },
{ url = "https://files.pythonhosted.org/packages/91/2b/9a1ddfa5c7f13cab007a2c9cc295b70fbbda7cb10a286aa6810338e60ea1/cffi-1.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99", size = 471256, upload-time = "2024-09-04T20:44:20.248Z" },
{ url = "https://files.pythonhosted.org/packages/b2/d5/da47df7004cb17e4955df6a43d14b3b4ae77737dff8bf7f8f333196717bf/cffi-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93", size = 479424, upload-time = "2024-09-04T20:44:21.673Z" },
{ url = "https://files.pythonhosted.org/packages/0b/ac/2a28bcf513e93a219c8a4e8e125534f4f6db03e3179ba1c45e949b76212c/cffi-1.17.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3", size = 484568, upload-time = "2024-09-04T20:44:23.245Z" },
{ url = "https://files.pythonhosted.org/packages/d4/38/ca8a4f639065f14ae0f1d9751e70447a261f1a30fa7547a828ae08142465/cffi-1.17.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8", size = 488736, upload-time = "2024-09-04T20:44:24.757Z" },
{ url = "https://files.pythonhosted.org/packages/0e/2d/eab2e858a91fdff70533cab61dcff4a1f55ec60425832ddfdc9cd36bc8af/cffi-1.17.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3", size = 454792, upload-time = "2024-09-04T20:44:32.01Z" },
{ url = "https://files.pythonhosted.org/packages/75/b2/fbaec7c4455c604e29388d55599b99ebcc250a60050610fadde58932b7ee/cffi-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683", size = 478893, upload-time = "2024-09-04T20:44:33.606Z" },
{ url = "https://files.pythonhosted.org/packages/4f/b7/6e4a2162178bf1935c336d4da8a9352cccab4d3a5d7914065490f08c0690/cffi-1.17.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5", size = 485810, upload-time = "2024-09-04T20:44:35.191Z" },
{ url = "https://files.pythonhosted.org/packages/c7/8a/1d0e4a9c26e54746dc08c2c6c037889124d4f59dffd853a659fa545f1b40/cffi-1.17.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4", size = 471200, upload-time = "2024-09-04T20:44:36.743Z" },
{ url = "https://files.pythonhosted.org/packages/26/9f/1aab65a6c0db35f43c4d1b4f580e8df53914310afc10ae0397d29d697af4/cffi-1.17.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd", size = 479447, upload-time = "2024-09-04T20:44:38.492Z" },
{ url = "https://files.pythonhosted.org/packages/5f/e4/fb8b3dd8dc0e98edf1135ff067ae070bb32ef9d509d6cb0f538cd6f7483f/cffi-1.17.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed", size = 484358, upload-time = "2024-09-04T20:44:40.046Z" },
{ url = "https://files.pythonhosted.org/packages/f1/47/d7145bf2dc04684935d57d67dff9d6d795b2ba2796806bb109864be3a151/cffi-1.17.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9", size = 488469, upload-time = "2024-09-04T20:44:41.616Z" },
]
[[package]]
name = "cfgv"
version = "3.4.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/11/74/539e56497d9bd1d484fd863dd69cbbfa653cd2aa27abfe35653494d85e94/cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560", size = 7114, upload-time = "2023-08-12T20:38:17.776Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/c5/55/51844dd50c4fc7a33b653bfaba4c2456f06955289ca770a5dbd5fd267374/cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9", size = 7249, upload-time = "2023-08-12T20:38:16.269Z" },
]
[[package]]
name = "chardet"
version = "5.2.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/f3/0d/f7b6ab21ec75897ed80c17d79b15951a719226b9fababf1e40ea74d69079/chardet-5.2.0.tar.gz", hash = "sha256:1b3b6ff479a8c414bc3fa2c0852995695c4a026dcd6d0633b2dd092ca39c1cf7", size = 2069618, upload-time = "2023-08-01T19:23:02.662Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/38/6f/f5fbc992a329ee4e0f288c1fe0e2ad9485ed064cac731ed2fe47dcc38cbf/chardet-5.2.0-py3-none-any.whl", hash = "sha256:e1cf59446890a00105fe7b7912492ea04b6e6f06d4b742b2c788469e34c82970", size = 199385, upload-time = "2023-08-01T19:23:00.661Z" },
]
[[package]]
name = "charset-normalizer"
version = "3.4.2"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/e4/33/89c2ced2b67d1c2a61c19c6751aa8902d46ce3dacb23600a283619f5a12d/charset_normalizer-3.4.2.tar.gz", hash = "sha256:5baececa9ecba31eff645232d59845c07aa030f0c81ee70184a90d35099a0e63", size = 126367, upload-time = "2025-05-02T08:34:42.01Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/05/85/4c40d00dcc6284a1c1ad5de5e0996b06f39d8232f1031cd23c2f5c07ee86/charset_normalizer-3.4.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:be1e352acbe3c78727a16a455126d9ff83ea2dfdcbc83148d2982305a04714c2", size = 198794, upload-time = "2025-05-02T08:32:11.945Z" },
{ url = "https://files.pythonhosted.org/packages/41/d9/7a6c0b9db952598e97e93cbdfcb91bacd89b9b88c7c983250a77c008703c/charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aa88ca0b1932e93f2d961bf3addbb2db902198dca337d88c89e1559e066e7645", size = 142846, upload-time = "2025-05-02T08:32:13.946Z" },
{ url = "https://files.pythonhosted.org/packages/66/82/a37989cda2ace7e37f36c1a8ed16c58cf48965a79c2142713244bf945c89/charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d524ba3f1581b35c03cb42beebab4a13e6cdad7b36246bd22541fa585a56cccd", size = 153350, upload-time = "2025-05-02T08:32:15.873Z" },
{ url = "https://files.pythonhosted.org/packages/df/68/a576b31b694d07b53807269d05ec3f6f1093e9545e8607121995ba7a8313/charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28a1005facc94196e1fb3e82a3d442a9d9110b8434fc1ded7a24a2983c9888d8", size = 145657, upload-time = "2025-05-02T08:32:17.283Z" },
{ url = "https://files.pythonhosted.org/packages/92/9b/ad67f03d74554bed3aefd56fe836e1623a50780f7c998d00ca128924a499/charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fdb20a30fe1175ecabed17cbf7812f7b804b8a315a25f24678bcdf120a90077f", size = 147260, upload-time = "2025-05-02T08:32:18.807Z" },
{ url = "https://files.pythonhosted.org/packages/a6/e6/8aebae25e328160b20e31a7e9929b1578bbdc7f42e66f46595a432f8539e/charset_normalizer-3.4.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0f5d9ed7f254402c9e7d35d2f5972c9bbea9040e99cd2861bd77dc68263277c7", size = 149164, upload-time = "2025-05-02T08:32:20.333Z" },
{ url = "https://files.pythonhosted.org/packages/8b/f2/b3c2f07dbcc248805f10e67a0262c93308cfa149a4cd3d1fe01f593e5fd2/charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:efd387a49825780ff861998cd959767800d54f8308936b21025326de4b5a42b9", size = 144571, upload-time = "2025-05-02T08:32:21.86Z" },
{ url = "https://files.pythonhosted.org/packages/60/5b/c3f3a94bc345bc211622ea59b4bed9ae63c00920e2e8f11824aa5708e8b7/charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:f0aa37f3c979cf2546b73e8222bbfa3dc07a641585340179d768068e3455e544", size = 151952, upload-time = "2025-05-02T08:32:23.434Z" },
{ url = "https://files.pythonhosted.org/packages/e2/4d/ff460c8b474122334c2fa394a3f99a04cf11c646da895f81402ae54f5c42/charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:e70e990b2137b29dc5564715de1e12701815dacc1d056308e2b17e9095372a82", size = 155959, upload-time = "2025-05-02T08:32:24.993Z" },
{ url = "https://files.pythonhosted.org/packages/a2/2b/b964c6a2fda88611a1fe3d4c400d39c66a42d6c169c924818c848f922415/charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:0c8c57f84ccfc871a48a47321cfa49ae1df56cd1d965a09abe84066f6853b9c0", size = 153030, upload-time = "2025-05-02T08:32:26.435Z" },
{ url = "https://files.pythonhosted.org/packages/59/2e/d3b9811db26a5ebf444bc0fa4f4be5aa6d76fc6e1c0fd537b16c14e849b6/charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6b66f92b17849b85cad91259efc341dce9c1af48e2173bf38a85c6329f1033e5", size = 148015, upload-time = "2025-05-02T08:32:28.376Z" },
{ url = "https://files.pythonhosted.org/packages/90/07/c5fd7c11eafd561bb51220d600a788f1c8d77c5eef37ee49454cc5c35575/charset_normalizer-3.4.2-cp311-cp311-win32.whl", hash = "sha256:daac4765328a919a805fa5e2720f3e94767abd632ae410a9062dff5412bae65a", size = 98106, upload-time = "2025-05-02T08:32:30.281Z" },
{ url = "https://files.pythonhosted.org/packages/a8/05/5e33dbef7e2f773d672b6d79f10ec633d4a71cd96db6673625838a4fd532/charset_normalizer-3.4.2-cp311-cp311-win_amd64.whl", hash = "sha256:e53efc7c7cee4c1e70661e2e112ca46a575f90ed9ae3fef200f2a25e954f4b28", size = 105402, upload-time = "2025-05-02T08:32:32.191Z" },
{ url = "https://files.pythonhosted.org/packages/d7/a4/37f4d6035c89cac7930395a35cc0f1b872e652eaafb76a6075943754f095/charset_normalizer-3.4.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0c29de6a1a95f24b9a1aa7aefd27d2487263f00dfd55a77719b530788f75cff7", size = 199936, upload-time = "2025-05-02T08:32:33.712Z" },
{ url = "https://files.pythonhosted.org/packages/ee/8a/1a5e33b73e0d9287274f899d967907cd0bf9c343e651755d9307e0dbf2b3/charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cddf7bd982eaa998934a91f69d182aec997c6c468898efe6679af88283b498d3", size = 143790, upload-time = "2025-05-02T08:32:35.768Z" },
{ url = "https://files.pythonhosted.org/packages/66/52/59521f1d8e6ab1482164fa21409c5ef44da3e9f653c13ba71becdd98dec3/charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fcbe676a55d7445b22c10967bceaaf0ee69407fbe0ece4d032b6eb8d4565982a", size = 153924, upload-time = "2025-05-02T08:32:37.284Z" },
{ url = "https://files.pythonhosted.org/packages/86/2d/fb55fdf41964ec782febbf33cb64be480a6b8f16ded2dbe8db27a405c09f/charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d41c4d287cfc69060fa91cae9683eacffad989f1a10811995fa309df656ec214", size = 146626, upload-time = "2025-05-02T08:32:38.803Z" },
{ url = "https://files.pythonhosted.org/packages/8c/73/6ede2ec59bce19b3edf4209d70004253ec5f4e319f9a2e3f2f15601ed5f7/charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e594135de17ab3866138f496755f302b72157d115086d100c3f19370839dd3a", size = 148567, upload-time = "2025-05-02T08:32:40.251Z" },
{ url = "https://files.pythonhosted.org/packages/09/14/957d03c6dc343c04904530b6bef4e5efae5ec7d7990a7cbb868e4595ee30/charset_normalizer-3.4.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cf713fe9a71ef6fd5adf7a79670135081cd4431c2943864757f0fa3a65b1fafd", size = 150957, upload-time = "2025-05-02T08:32:41.705Z" },
{ url = "https://files.pythonhosted.org/packages/0d/c8/8174d0e5c10ccebdcb1b53cc959591c4c722a3ad92461a273e86b9f5a302/charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a370b3e078e418187da8c3674eddb9d983ec09445c99a3a263c2011993522981", size = 145408, upload-time = "2025-05-02T08:32:43.709Z" },
{ url = "https://files.pythonhosted.org/packages/58/aa/8904b84bc8084ac19dc52feb4f5952c6df03ffb460a887b42615ee1382e8/charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a955b438e62efdf7e0b7b52a64dc5c3396e2634baa62471768a64bc2adb73d5c", size = 153399, upload-time = "2025-05-02T08:32:46.197Z" },
{ url = "https://files.pythonhosted.org/packages/c2/26/89ee1f0e264d201cb65cf054aca6038c03b1a0c6b4ae998070392a3ce605/charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:7222ffd5e4de8e57e03ce2cef95a4c43c98fcb72ad86909abdfc2c17d227fc1b", size = 156815, upload-time = "2025-05-02T08:32:48.105Z" },
{ url = "https://files.pythonhosted.org/packages/fd/07/68e95b4b345bad3dbbd3a8681737b4338ff2c9df29856a6d6d23ac4c73cb/charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:bee093bf902e1d8fc0ac143c88902c3dfc8941f7ea1d6a8dd2bcb786d33db03d", size = 154537, upload-time = "2025-05-02T08:32:49.719Z" },
{ url = "https://files.pythonhosted.org/packages/77/1a/5eefc0ce04affb98af07bc05f3bac9094513c0e23b0562d64af46a06aae4/charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:dedb8adb91d11846ee08bec4c8236c8549ac721c245678282dcb06b221aab59f", size = 149565, upload-time = "2025-05-02T08:32:51.404Z" },
{ url = "https://files.pythonhosted.org/packages/37/a0/2410e5e6032a174c95e0806b1a6585eb21e12f445ebe239fac441995226a/charset_normalizer-3.4.2-cp312-cp312-win32.whl", hash = "sha256:db4c7bf0e07fc3b7d89ac2a5880a6a8062056801b83ff56d8464b70f65482b6c", size = 98357, upload-time = "2025-05-02T08:32:53.079Z" },
{ url = "https://files.pythonhosted.org/packages/6c/4f/c02d5c493967af3eda9c771ad4d2bbc8df6f99ddbeb37ceea6e8716a32bc/charset_normalizer-3.4.2-cp312-cp312-win_amd64.whl", hash = "sha256:5a9979887252a82fefd3d3ed2a8e3b937a7a809f65dcb1e068b090e165bbe99e", size = 105776, upload-time = "2025-05-02T08:32:54.573Z" },
{ url = "https://files.pythonhosted.org/packages/ea/12/a93df3366ed32db1d907d7593a94f1fe6293903e3e92967bebd6950ed12c/charset_normalizer-3.4.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:926ca93accd5d36ccdabd803392ddc3e03e6d4cd1cf17deff3b989ab8e9dbcf0", size = 199622, upload-time = "2025-05-02T08:32:56.363Z" },
{ url = "https://files.pythonhosted.org/packages/04/93/bf204e6f344c39d9937d3c13c8cd5bbfc266472e51fc8c07cb7f64fcd2de/charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eba9904b0f38a143592d9fc0e19e2df0fa2e41c3c3745554761c5f6447eedabf", size = 143435, upload-time = "2025-05-02T08:32:58.551Z" },
{ url = "https://files.pythonhosted.org/packages/22/2a/ea8a2095b0bafa6c5b5a55ffdc2f924455233ee7b91c69b7edfcc9e02284/charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3fddb7e2c84ac87ac3a947cb4e66d143ca5863ef48e4a5ecb83bd48619e4634e", size = 153653, upload-time = "2025-05-02T08:33:00.342Z" },
{ url = "https://files.pythonhosted.org/packages/b6/57/1b090ff183d13cef485dfbe272e2fe57622a76694061353c59da52c9a659/charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98f862da73774290f251b9df8d11161b6cf25b599a66baf087c1ffe340e9bfd1", size = 146231, upload-time = "2025-05-02T08:33:02.081Z" },
{ url = "https://files.pythonhosted.org/packages/e2/28/ffc026b26f441fc67bd21ab7f03b313ab3fe46714a14b516f931abe1a2d8/charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c9379d65defcab82d07b2a9dfbfc2e95bc8fe0ebb1b176a3190230a3ef0e07c", size = 148243, upload-time = "2025-05-02T08:33:04.063Z" },
{ url = "https://files.pythonhosted.org/packages/c0/0f/9abe9bd191629c33e69e47c6ef45ef99773320e9ad8e9cb08b8ab4a8d4cb/charset_normalizer-3.4.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e635b87f01ebc977342e2697d05b56632f5f879a4f15955dfe8cef2448b51691", size = 150442, upload-time = "2025-05-02T08:33:06.418Z" },
{ url = "https://files.pythonhosted.org/packages/67/7c/a123bbcedca91d5916c056407f89a7f5e8fdfce12ba825d7d6b9954a1a3c/charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:1c95a1e2902a8b722868587c0e1184ad5c55631de5afc0eb96bc4b0d738092c0", size = 145147, upload-time = "2025-05-02T08:33:08.183Z" },
{ url = "https://files.pythonhosted.org/packages/ec/fe/1ac556fa4899d967b83e9893788e86b6af4d83e4726511eaaad035e36595/charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ef8de666d6179b009dce7bcb2ad4c4a779f113f12caf8dc77f0162c29d20490b", size = 153057, upload-time = "2025-05-02T08:33:09.986Z" },
{ url = "https://files.pythonhosted.org/packages/2b/ff/acfc0b0a70b19e3e54febdd5301a98b72fa07635e56f24f60502e954c461/charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:32fc0341d72e0f73f80acb0a2c94216bd704f4f0bce10aedea38f30502b271ff", size = 156454, upload-time = "2025-05-02T08:33:11.814Z" },
{ url = "https://files.pythonhosted.org/packages/92/08/95b458ce9c740d0645feb0e96cea1f5ec946ea9c580a94adfe0b617f3573/charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:289200a18fa698949d2b39c671c2cc7a24d44096784e76614899a7ccf2574b7b", size = 154174, upload-time = "2025-05-02T08:33:13.707Z" },
{ url = "https://files.pythonhosted.org/packages/78/be/8392efc43487ac051eee6c36d5fbd63032d78f7728cb37aebcc98191f1ff/charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4a476b06fbcf359ad25d34a057b7219281286ae2477cc5ff5e3f70a246971148", size = 149166, upload-time = "2025-05-02T08:33:15.458Z" },
{ url = "https://files.pythonhosted.org/packages/44/96/392abd49b094d30b91d9fbda6a69519e95802250b777841cf3bda8fe136c/charset_normalizer-3.4.2-cp313-cp313-win32.whl", hash = "sha256:aaeeb6a479c7667fbe1099af9617c83aaca22182d6cf8c53966491a0f1b7ffb7", size = 98064, upload-time = "2025-05-02T08:33:17.06Z" },
{ url = "https://files.pythonhosted.org/packages/e9/b0/0200da600134e001d91851ddc797809e2fe0ea72de90e09bec5a2fbdaccb/charset_normalizer-3.4.2-cp313-cp313-win_amd64.whl", hash = "sha256:aa6af9e7d59f9c12b33ae4e9450619cf2488e2bbe9b44030905877f0b2324980", size = 105641, upload-time = "2025-05-02T08:33:18.753Z" },
{ url = "https://files.pythonhosted.org/packages/20/94/c5790835a017658cbfabd07f3bfb549140c3ac458cfc196323996b10095a/charset_normalizer-3.4.2-py3-none-any.whl", hash = "sha256:7f56930ab0abd1c45cd15be65cc741c28b1c9a34876ce8c17a2fa107810c0af0", size = 52626, upload-time = "2025-05-02T08:34:40.053Z" },
]
[[package]]
name = "click"
version = "8.2.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "colorama", marker = "sys_platform == 'win32'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/60/6c/8ca2efa64cf75a977a0d7fac081354553ebe483345c734fb6b6515d96bbc/click-8.2.1.tar.gz", hash = "sha256:27c491cc05d968d271d5a1db13e3b5a184636d9d930f148c50b038f0d0646202", size = 286342, upload-time = "2025-05-20T23:19:49.832Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/85/32/10bb5764d90a8eee674e9dc6f4db6a0ab47c8c4d0d83c27f7c39ac415a4d/click-8.2.1-py3-none-any.whl", hash = "sha256:61a3265b914e850b85317d0b3109c7f8cd35a670f963866005d6ef1d5175a12b", size = 102215, upload-time = "2025-05-20T23:19:47.796Z" },
]
[[package]]
name = "codespell"
version = "2.4.1"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/15/e0/709453393c0ea77d007d907dd436b3ee262e28b30995ea1aa36c6ffbccaf/codespell-2.4.1.tar.gz", hash = "sha256:299fcdcb09d23e81e35a671bbe746d5ad7e8385972e65dbb833a2eaac33c01e5", size = 344740, upload-time = "2025-01-28T18:52:39.411Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/20/01/b394922252051e97aab231d416c86da3d8a6d781eeadcdca1082867de64e/codespell-2.4.1-py3-none-any.whl", hash = "sha256:3dadafa67df7e4a3dbf51e0d7315061b80d265f9552ebd699b3dd6834b47e425", size = 344501, upload-time = "2025-01-28T18:52:37.057Z" },
]
[[package]]
name = "colorama"
version = "0.4.6"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" },
]
[[package]]
name = "coverage"
version = "7.8.2"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/ba/07/998afa4a0ecdf9b1981ae05415dad2d4e7716e1b1f00abbd91691ac09ac9/coverage-7.8.2.tar.gz", hash = "sha256:a886d531373a1f6ff9fad2a2ba4a045b68467b779ae729ee0b3b10ac20033b27", size = 812759, upload-time = "2025-05-23T11:39:57.856Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/6a/4d/1ff618ee9f134d0de5cc1661582c21a65e06823f41caf801aadf18811a8e/coverage-7.8.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b99058eef42e6a8dcd135afb068b3d53aff3921ce699e127602efff9956457a9", size = 211692, upload-time = "2025-05-23T11:38:08.485Z" },
{ url = "https://files.pythonhosted.org/packages/96/fa/c3c1b476de96f2bc7a8ca01a9f1fcb51c01c6b60a9d2c3e66194b2bdb4af/coverage-7.8.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5feb7f2c3e6ea94d3b877def0270dff0947b8d8c04cfa34a17be0a4dc1836879", size = 212115, upload-time = "2025-05-23T11:38:09.989Z" },
{ url = "https://files.pythonhosted.org/packages/f7/c2/5414c5a1b286c0f3881ae5adb49be1854ac5b7e99011501f81c8c1453065/coverage-7.8.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:670a13249b957bb9050fab12d86acef7bf8f6a879b9d1a883799276e0d4c674a", size = 244740, upload-time = "2025-05-23T11:38:11.947Z" },
{ url = "https://files.pythonhosted.org/packages/cd/46/1ae01912dfb06a642ef3dd9cf38ed4996fda8fe884dab8952da616f81a2b/coverage-7.8.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0bdc8bf760459a4a4187b452213e04d039990211f98644c7292adf1e471162b5", size = 242429, upload-time = "2025-05-23T11:38:13.955Z" },
{ url = "https://files.pythonhosted.org/packages/06/58/38c676aec594bfe2a87c7683942e5a30224791d8df99bcc8439fde140377/coverage-7.8.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:07a989c867986c2a75f158f03fdb413128aad29aca9d4dbce5fc755672d96f11", size = 244218, upload-time = "2025-05-23T11:38:15.631Z" },
{ url = "https://files.pythonhosted.org/packages/80/0c/95b1023e881ce45006d9abc250f76c6cdab7134a1c182d9713878dfefcb2/coverage-7.8.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2db10dedeb619a771ef0e2949ccba7b75e33905de959c2643a4607bef2f3fb3a", size = 243865, upload-time = "2025-05-23T11:38:17.622Z" },
{ url = "https://files.pythonhosted.org/packages/57/37/0ae95989285a39e0839c959fe854a3ae46c06610439350d1ab860bf020ac/coverage-7.8.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e6ea7dba4e92926b7b5f0990634b78ea02f208d04af520c73a7c876d5a8d36cb", size = 242038, upload-time = "2025-05-23T11:38:19.966Z" },
{ url = "https://files.pythonhosted.org/packages/4d/82/40e55f7c0eb5e97cc62cbd9d0746fd24e8caf57be5a408b87529416e0c70/coverage-7.8.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ef2f22795a7aca99fc3c84393a55a53dd18ab8c93fb431004e4d8f0774150f54", size = 242567, upload-time = "2025-05-23T11:38:21.912Z" },
{ url = "https://files.pythonhosted.org/packages/f9/35/66a51adc273433a253989f0d9cc7aa6bcdb4855382cf0858200afe578861/coverage-7.8.2-cp311-cp311-win32.whl", hash = "sha256:641988828bc18a6368fe72355df5f1703e44411adbe49bba5644b941ce6f2e3a", size = 214194, upload-time = "2025-05-23T11:38:23.571Z" },
{ url = "https://files.pythonhosted.org/packages/f6/8f/a543121f9f5f150eae092b08428cb4e6b6d2d134152c3357b77659d2a605/coverage-7.8.2-cp311-cp311-win_amd64.whl", hash = "sha256:8ab4a51cb39dc1933ba627e0875046d150e88478dbe22ce145a68393e9652975", size = 215109, upload-time = "2025-05-23T11:38:25.137Z" },
{ url = "https://files.pythonhosted.org/packages/77/65/6cc84b68d4f35186463cd7ab1da1169e9abb59870c0f6a57ea6aba95f861/coverage-7.8.2-cp311-cp311-win_arm64.whl", hash = "sha256:8966a821e2083c74d88cca5b7dcccc0a3a888a596a04c0b9668a891de3a0cc53", size = 213521, upload-time = "2025-05-23T11:38:27.123Z" },
{ url = "https://files.pythonhosted.org/packages/8d/2a/1da1ada2e3044fcd4a3254fb3576e160b8fe5b36d705c8a31f793423f763/coverage-7.8.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:e2f6fe3654468d061942591aef56686131335b7a8325684eda85dacdf311356c", size = 211876, upload-time = "2025-05-23T11:38:29.01Z" },
{ url = "https://files.pythonhosted.org/packages/70/e9/3d715ffd5b6b17a8be80cd14a8917a002530a99943cc1939ad5bb2aa74b9/coverage-7.8.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:76090fab50610798cc05241bf83b603477c40ee87acd358b66196ab0ca44ffa1", size = 212130, upload-time = "2025-05-23T11:38:30.675Z" },
{ url = "https://files.pythonhosted.org/packages/a0/02/fdce62bb3c21649abfd91fbdcf041fb99be0d728ff00f3f9d54d97ed683e/coverage-7.8.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2bd0a0a5054be160777a7920b731a0570284db5142abaaf81bcbb282b8d99279", size = 246176, upload-time = "2025-05-23T11:38:32.395Z" },
{ url = "https://files.pythonhosted.org/packages/a7/52/decbbed61e03b6ffe85cd0fea360a5e04a5a98a7423f292aae62423b8557/coverage-7.8.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:da23ce9a3d356d0affe9c7036030b5c8f14556bd970c9b224f9c8205505e3b99", size = 243068, upload-time = "2025-05-23T11:38:33.989Z" },
{ url = "https://files.pythonhosted.org/packages/38/6c/d0e9c0cce18faef79a52778219a3c6ee8e336437da8eddd4ab3dbd8fadff/coverage-7.8.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9392773cffeb8d7e042a7b15b82a414011e9d2b5fdbbd3f7e6a6b17d5e21b20", size = 245328, upload-time = "2025-05-23T11:38:35.568Z" },
{ url = "https://files.pythonhosted.org/packages/f0/70/f703b553a2f6b6c70568c7e398ed0789d47f953d67fbba36a327714a7bca/coverage-7.8.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:876cbfd0b09ce09d81585d266c07a32657beb3eaec896f39484b631555be0fe2", size = 245099, upload-time = "2025-05-23T11:38:37.627Z" },
{ url = "https://files.pythonhosted.org/packages/ec/fb/4cbb370dedae78460c3aacbdad9d249e853f3bc4ce5ff0e02b1983d03044/coverage-7.8.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:3da9b771c98977a13fbc3830f6caa85cae6c9c83911d24cb2d218e9394259c57", size = 243314, upload-time = "2025-05-23T11:38:39.238Z" },
{ url = "https://files.pythonhosted.org/packages/39/9f/1afbb2cb9c8699b8bc38afdce00a3b4644904e6a38c7bf9005386c9305ec/coverage-7.8.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:9a990f6510b3292686713bfef26d0049cd63b9c7bb17e0864f133cbfd2e6167f", size = 244489, upload-time = "2025-05-23T11:38:40.845Z" },
{ url = "https://files.pythonhosted.org/packages/79/fa/f3e7ec7d220bff14aba7a4786ae47043770cbdceeea1803083059c878837/coverage-7.8.2-cp312-cp312-win32.whl", hash = "sha256:bf8111cddd0f2b54d34e96613e7fbdd59a673f0cf5574b61134ae75b6f5a33b8", size = 214366, upload-time = "2025-05-23T11:38:43.551Z" },
{ url = "https://files.pythonhosted.org/packages/54/aa/9cbeade19b7e8e853e7ffc261df885d66bf3a782c71cba06c17df271f9e6/coverage-7.8.2-cp312-cp312-win_amd64.whl", hash = "sha256:86a323a275e9e44cdf228af9b71c5030861d4d2610886ab920d9945672a81223", size = 215165, upload-time = "2025-05-23T11:38:45.148Z" },
{ url = "https://files.pythonhosted.org/packages/c4/73/e2528bf1237d2448f882bbebaec5c3500ef07301816c5c63464b9da4d88a/coverage-7.8.2-cp312-cp312-win_arm64.whl", hash = "sha256:820157de3a589e992689ffcda8639fbabb313b323d26388d02e154164c57b07f", size = 213548, upload-time = "2025-05-23T11:38:46.74Z" },
{ url = "https://files.pythonhosted.org/packages/1a/93/eb6400a745ad3b265bac36e8077fdffcf0268bdbbb6c02b7220b624c9b31/coverage-7.8.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ea561010914ec1c26ab4188aef8b1567272ef6de096312716f90e5baa79ef8ca", size = 211898, upload-time = "2025-05-23T11:38:49.066Z" },
{ url = "https://files.pythonhosted.org/packages/1b/7c/bdbf113f92683024406a1cd226a199e4200a2001fc85d6a6e7e299e60253/coverage-7.8.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cb86337a4fcdd0e598ff2caeb513ac604d2f3da6d53df2c8e368e07ee38e277d", size = 212171, upload-time = "2025-05-23T11:38:51.207Z" },
{ url = "https://files.pythonhosted.org/packages/91/22/594513f9541a6b88eb0dba4d5da7d71596dadef6b17a12dc2c0e859818a9/coverage-7.8.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:26a4636ddb666971345541b59899e969f3b301143dd86b0ddbb570bd591f1e85", size = 245564, upload-time = "2025-05-23T11:38:52.857Z" },
{ url = "https://files.pythonhosted.org/packages/1f/f4/2860fd6abeebd9f2efcfe0fd376226938f22afc80c1943f363cd3c28421f/coverage-7.8.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5040536cf9b13fb033f76bcb5e1e5cb3b57c4807fef37db9e0ed129c6a094257", size = 242719, upload-time = "2025-05-23T11:38:54.529Z" },
{ url = "https://files.pythonhosted.org/packages/89/60/f5f50f61b6332451520e6cdc2401700c48310c64bc2dd34027a47d6ab4ca/coverage-7.8.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc67994df9bcd7e0150a47ef41278b9e0a0ea187caba72414b71dc590b99a108", size = 244634, upload-time = "2025-05-23T11:38:57.326Z" },
{ url = "https://files.pythonhosted.org/packages/3b/70/7f4e919039ab7d944276c446b603eea84da29ebcf20984fb1fdf6e602028/coverage-7.8.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6e6c86888fd076d9e0fe848af0a2142bf606044dc5ceee0aa9eddb56e26895a0", size = 244824, upload-time = "2025-05-23T11:38:59.421Z" },
{ url = "https://files.pythonhosted.org/packages/26/45/36297a4c0cea4de2b2c442fe32f60c3991056c59cdc3cdd5346fbb995c97/coverage-7.8.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:684ca9f58119b8e26bef860db33524ae0365601492e86ba0b71d513f525e7050", size = 242872, upload-time = "2025-05-23T11:39:01.049Z" },
{ url = "https://files.pythonhosted.org/packages/a4/71/e041f1b9420f7b786b1367fa2a375703889ef376e0d48de9f5723fb35f11/coverage-7.8.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8165584ddedb49204c4e18da083913bdf6a982bfb558632a79bdaadcdafd0d48", size = 244179, upload-time = "2025-05-23T11:39:02.709Z" },
{ url = "https://files.pythonhosted.org/packages/bd/db/3c2bf49bdc9de76acf2491fc03130c4ffc51469ce2f6889d2640eb563d77/coverage-7.8.2-cp313-cp313-win32.whl", hash = "sha256:34759ee2c65362163699cc917bdb2a54114dd06d19bab860725f94ef45a3d9b7", size = 214393, upload-time = "2025-05-23T11:39:05.457Z" },
{ url = "https://files.pythonhosted.org/packages/c6/dc/947e75d47ebbb4b02d8babb1fad4ad381410d5bc9da7cfca80b7565ef401/coverage-7.8.2-cp313-cp313-win_amd64.whl", hash = "sha256:2f9bc608fbafaee40eb60a9a53dbfb90f53cc66d3d32c2849dc27cf5638a21e3", size = 215194, upload-time = "2025-05-23T11:39:07.171Z" },
{ url = "https://files.pythonhosted.org/packages/90/31/a980f7df8a37eaf0dc60f932507fda9656b3a03f0abf188474a0ea188d6d/coverage-7.8.2-cp313-cp313-win_arm64.whl", hash = "sha256:9fe449ee461a3b0c7105690419d0b0aba1232f4ff6d120a9e241e58a556733f7", size = 213580, upload-time = "2025-05-23T11:39:08.862Z" },
{ url = "https://files.pythonhosted.org/packages/8a/6a/25a37dd90f6c95f59355629417ebcb74e1c34e38bb1eddf6ca9b38b0fc53/coverage-7.8.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:8369a7c8ef66bded2b6484053749ff220dbf83cba84f3398c84c51a6f748a008", size = 212734, upload-time = "2025-05-23T11:39:11.109Z" },
{ url = "https://files.pythonhosted.org/packages/36/8b/3a728b3118988725f40950931abb09cd7f43b3c740f4640a59f1db60e372/coverage-7.8.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:159b81df53a5fcbc7d45dae3adad554fdbde9829a994e15227b3f9d816d00b36", size = 212959, upload-time = "2025-05-23T11:39:12.751Z" },
{ url = "https://files.pythonhosted.org/packages/53/3c/212d94e6add3a3c3f412d664aee452045ca17a066def8b9421673e9482c4/coverage-7.8.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e6fcbbd35a96192d042c691c9e0c49ef54bd7ed865846a3c9d624c30bb67ce46", size = 257024, upload-time = "2025-05-23T11:39:15.569Z" },
{ url = "https://files.pythonhosted.org/packages/a4/40/afc03f0883b1e51bbe804707aae62e29c4e8c8bbc365c75e3e4ddeee9ead/coverage-7.8.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:05364b9cc82f138cc86128dc4e2e1251c2981a2218bfcd556fe6b0fbaa3501be", size = 252867, upload-time = "2025-05-23T11:39:17.64Z" },
{ url = "https://files.pythonhosted.org/packages/18/a2/3699190e927b9439c6ded4998941a3c1d6fa99e14cb28d8536729537e307/coverage-7.8.2-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46d532db4e5ff3979ce47d18e2fe8ecad283eeb7367726da0e5ef88e4fe64740", size = 255096, upload-time = "2025-05-23T11:39:19.328Z" },
{ url = "https://files.pythonhosted.org/packages/b4/06/16e3598b9466456b718eb3e789457d1a5b8bfb22e23b6e8bbc307df5daf0/coverage-7.8.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4000a31c34932e7e4fa0381a3d6deb43dc0c8f458e3e7ea6502e6238e10be625", size = 256276, upload-time = "2025-05-23T11:39:21.077Z" },
{ url = "https://files.pythonhosted.org/packages/a7/d5/4b5a120d5d0223050a53d2783c049c311eea1709fa9de12d1c358e18b707/coverage-7.8.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:43ff5033d657cd51f83015c3b7a443287250dc14e69910577c3e03bd2e06f27b", size = 254478, upload-time = "2025-05-23T11:39:22.838Z" },
{ url = "https://files.pythonhosted.org/packages/ba/85/f9ecdb910ecdb282b121bfcaa32fa8ee8cbd7699f83330ee13ff9bbf1a85/coverage-7.8.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:94316e13f0981cbbba132c1f9f365cac1d26716aaac130866ca812006f662199", size = 255255, upload-time = "2025-05-23T11:39:24.644Z" },
{ url = "https://files.pythonhosted.org/packages/50/63/2d624ac7d7ccd4ebbd3c6a9eba9d7fc4491a1226071360d59dd84928ccb2/coverage-7.8.2-cp313-cp313t-win32.whl", hash = "sha256:3f5673888d3676d0a745c3d0e16da338c5eea300cb1f4ada9c872981265e76d8", size = 215109, upload-time = "2025-05-23T11:39:26.722Z" },
{ url = "https://files.pythonhosted.org/packages/22/5e/7053b71462e970e869111c1853afd642212568a350eba796deefdfbd0770/coverage-7.8.2-cp313-cp313t-win_amd64.whl", hash = "sha256:2c08b05ee8d7861e45dc5a2cc4195c8c66dca5ac613144eb6ebeaff2d502e73d", size = 216268, upload-time = "2025-05-23T11:39:28.429Z" },
{ url = "https://files.pythonhosted.org/packages/07/69/afa41aa34147655543dbe96994f8a246daf94b361ccf5edfd5df62ce066a/coverage-7.8.2-cp313-cp313t-win_arm64.whl", hash = "sha256:1e1448bb72b387755e1ff3ef1268a06617afd94188164960dba8d0245a46004b", size = 214071, upload-time = "2025-05-23T11:39:30.55Z" },
{ url = "https://files.pythonhosted.org/packages/69/2f/572b29496d8234e4a7773200dd835a0d32d9e171f2d974f3fe04a9dbc271/coverage-7.8.2-pp39.pp310.pp311-none-any.whl", hash = "sha256:ec455eedf3ba0bbdf8f5a570012617eb305c63cb9f03428d39bf544cb2b94837", size = 203636, upload-time = "2025-05-23T11:39:52.002Z" },
{ url = "https://files.pythonhosted.org/packages/a0/1a/0b9c32220ad694d66062f571cc5cedfa9997b64a591e8a500bb63de1bd40/coverage-7.8.2-py3-none-any.whl", hash = "sha256:726f32ee3713f7359696331a18daf0c3b3a70bb0ae71141b9d3c52be7c595e32", size = 203623, upload-time = "2025-05-23T11:39:53.846Z" },
]
[package.optional-dependencies]
toml = [
{ name = "tomli", marker = "python_full_version <= '3.11'" },
]
[[package]]
name = "cryptography"
version = "45.0.3"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "cffi", marker = "platform_python_implementation != 'PyPy'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/13/1f/9fa001e74a1993a9cadd2333bb889e50c66327b8594ac538ab8a04f915b7/cryptography-45.0.3.tar.gz", hash = "sha256:ec21313dd335c51d7877baf2972569f40a4291b76a0ce51391523ae358d05899", size = 744738, upload-time = "2025-05-25T14:17:24.777Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/71/3d/ac361649a0bfffc105e2298b720d8b862330a767dab27c06adc2ddbef96a/cryptography-45.0.3-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d377dde61c5d67eb4311eace661c3efda46c62113ff56bf05e2d679e02aebb5b", size = 4205541, upload-time = "2025-05-25T14:16:14.333Z" },
{ url = "https://files.pythonhosted.org/packages/70/3e/c02a043750494d5c445f769e9c9f67e550d65060e0bfce52d91c1362693d/cryptography-45.0.3-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fae1e637f527750811588e4582988932c222f8251f7b7ea93739acb624e1487f", size = 4433275, upload-time = "2025-05-25T14:16:16.421Z" },
{ url = "https://files.pythonhosted.org/packages/40/7a/9af0bfd48784e80eef3eb6fd6fde96fe706b4fc156751ce1b2b965dada70/cryptography-45.0.3-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:ca932e11218bcc9ef812aa497cdf669484870ecbcf2d99b765d6c27a86000942", size = 4209173, upload-time = "2025-05-25T14:16:18.163Z" },
{ url = "https://files.pythonhosted.org/packages/31/5f/d6f8753c8708912df52e67969e80ef70b8e8897306cd9eb8b98201f8c184/cryptography-45.0.3-cp311-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:af3f92b1dc25621f5fad065288a44ac790c5798e986a34d393ab27d2b27fcff9", size = 3898150, upload-time = "2025-05-25T14:16:20.34Z" },
{ url = "https://files.pythonhosted.org/packages/8b/50/f256ab79c671fb066e47336706dc398c3b1e125f952e07d54ce82cf4011a/cryptography-45.0.3-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:2f8f8f0b73b885ddd7f3d8c2b2234a7d3ba49002b0223f58cfde1bedd9563c56", size = 4466473, upload-time = "2025-05-25T14:16:22.605Z" },
{ url = "https://files.pythonhosted.org/packages/62/e7/312428336bb2df0848d0768ab5a062e11a32d18139447a76dfc19ada8eed/cryptography-45.0.3-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:9cc80ce69032ffa528b5e16d217fa4d8d4bb7d6ba8659c1b4d74a1b0f4235fca", size = 4211890, upload-time = "2025-05-25T14:16:24.738Z" },
{ url = "https://files.pythonhosted.org/packages/e7/53/8a130e22c1e432b3c14896ec5eb7ac01fb53c6737e1d705df7e0efb647c6/cryptography-45.0.3-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:c824c9281cb628015bfc3c59335163d4ca0540d49de4582d6c2637312907e4b1", size = 4466300, upload-time = "2025-05-25T14:16:26.768Z" },
{ url = "https://files.pythonhosted.org/packages/ba/75/6bb6579688ef805fd16a053005fce93944cdade465fc92ef32bbc5c40681/cryptography-45.0.3-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:5833bb4355cb377ebd880457663a972cd044e7f49585aee39245c0d592904578", size = 4332483, upload-time = "2025-05-25T14:16:28.316Z" },
{ url = "https://files.pythonhosted.org/packages/2f/11/2538f4e1ce05c6c4f81f43c1ef2bd6de7ae5e24ee284460ff6c77e42ca77/cryptography-45.0.3-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:9bb5bf55dcb69f7067d80354d0a348368da907345a2c448b0babc4215ccd3497", size = 4573714, upload-time = "2025-05-25T14:16:30.474Z" },
{ url = "https://files.pythonhosted.org/packages/46/c7/c7d05d0e133a09fc677b8a87953815c522697bdf025e5cac13ba419e7240/cryptography-45.0.3-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c5edcb90da1843df85292ef3a313513766a78fbbb83f584a5a58fb001a5a9d57", size = 4196181, upload-time = "2025-05-25T14:16:37.934Z" },
{ url = "https://files.pythonhosted.org/packages/08/7a/6ad3aa796b18a683657cef930a986fac0045417e2dc428fd336cfc45ba52/cryptography-45.0.3-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:38deed72285c7ed699864f964a3f4cf11ab3fb38e8d39cfcd96710cd2b5bb716", size = 4423370, upload-time = "2025-05-25T14:16:39.502Z" },
{ url = "https://files.pythonhosted.org/packages/4f/58/ec1461bfcb393525f597ac6a10a63938d18775b7803324072974b41a926b/cryptography-45.0.3-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:5555365a50efe1f486eed6ac7062c33b97ccef409f5970a0b6f205a7cfab59c8", size = 4197839, upload-time = "2025-05-25T14:16:41.322Z" },
{ url = "https://files.pythonhosted.org/packages/d4/3d/5185b117c32ad4f40846f579369a80e710d6146c2baa8ce09d01612750db/cryptography-45.0.3-cp37-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:9e4253ed8f5948a3589b3caee7ad9a5bf218ffd16869c516535325fece163dcc", size = 3886324, upload-time = "2025-05-25T14:16:43.041Z" },
{ url = "https://files.pythonhosted.org/packages/67/85/caba91a57d291a2ad46e74016d1f83ac294f08128b26e2a81e9b4f2d2555/cryptography-45.0.3-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:cfd84777b4b6684955ce86156cfb5e08d75e80dc2585e10d69e47f014f0a5342", size = 4450447, upload-time = "2025-05-25T14:16:44.759Z" },
{ url = "https://files.pythonhosted.org/packages/ae/d1/164e3c9d559133a38279215c712b8ba38e77735d3412f37711b9f8f6f7e0/cryptography-45.0.3-cp37-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:a2b56de3417fd5f48773ad8e91abaa700b678dc7fe1e0c757e1ae340779acf7b", size = 4200576, upload-time = "2025-05-25T14:16:46.438Z" },
{ url = "https://files.pythonhosted.org/packages/71/7a/e002d5ce624ed46dfc32abe1deff32190f3ac47ede911789ee936f5a4255/cryptography-45.0.3-cp37-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:57a6500d459e8035e813bd8b51b671977fb149a8c95ed814989da682314d0782", size = 4450308, upload-time = "2025-05-25T14:16:48.228Z" },
{ url = "https://files.pythonhosted.org/packages/87/ad/3fbff9c28cf09b0a71e98af57d74f3662dea4a174b12acc493de00ea3f28/cryptography-45.0.3-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:f22af3c78abfbc7cbcdf2c55d23c3e022e1a462ee2481011d518c7fb9c9f3d65", size = 4325125, upload-time = "2025-05-25T14:16:49.844Z" },
{ url = "https://files.pythonhosted.org/packages/f5/b4/51417d0cc01802304c1984d76e9592f15e4801abd44ef7ba657060520bf0/cryptography-45.0.3-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:232954730c362638544758a8160c4ee1b832dc011d2c41a306ad8f7cccc5bb0b", size = 4560038, upload-time = "2025-05-25T14:16:51.398Z" },
{ url = "https://files.pythonhosted.org/packages/96/61/751ebea58c87b5be533c429f01996050a72c7283b59eee250275746632ea/cryptography-45.0.3-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:555e5e2d3a53b4fabeca32835878b2818b3f23966a4efb0d566689777c5a12c8", size = 4146964, upload-time = "2025-05-25T14:17:09.538Z" },
{ url = "https://files.pythonhosted.org/packages/8d/01/28c90601b199964de383da0b740b5156f5d71a1da25e7194fdf793d373ef/cryptography-45.0.3-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:25286aacb947286620a31f78f2ed1a32cded7be5d8b729ba3fb2c988457639e4", size = 4388103, upload-time = "2025-05-25T14:17:11.978Z" },
{ url = "https://files.pythonhosted.org/packages/3d/ec/cd892180b9e42897446ef35c62442f5b8b039c3d63a05f618aa87ec9ebb5/cryptography-45.0.3-pp311-pypy311_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:050ce5209d5072472971e6efbfc8ec5a8f9a841de5a4db0ebd9c2e392cb81972", size = 4150031, upload-time = "2025-05-25T14:17:14.131Z" },
{ url = "https://files.pythonhosted.org/packages/db/d4/22628c2dedd99289960a682439c6d3aa248dff5215123ead94ac2d82f3f5/cryptography-45.0.3-pp311-pypy311_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:dc10ec1e9f21f33420cc05214989544727e776286c1c16697178978327b95c9c", size = 4387389, upload-time = "2025-05-25T14:17:17.303Z" },
]
[[package]]
name = "distlib"
version = "0.3.9"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/0d/dd/1bec4c5ddb504ca60fc29472f3d27e8d4da1257a854e1d96742f15c1d02d/distlib-0.3.9.tar.gz", hash = "sha256:a60f20dea646b8a33f3e7772f74dc0b2d0772d2837ee1342a00645c81edf9403", size = 613923, upload-time = "2024-10-09T18:35:47.551Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/91/a1/cf2472db20f7ce4a6be1253a81cfdf85ad9c7885ffbed7047fb72c24cf87/distlib-0.3.9-py2.py3-none-any.whl", hash = "sha256:47f8c22fd27c27e25a65601af709b38e4f0a45ea4fc2e710f65755fa8caaaf87", size = 468973, upload-time = "2024-10-09T18:35:44.272Z" },
]
[[package]]
name = "docutils"
version = "0.21.2"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/ae/ed/aefcc8cd0ba62a0560c3c18c33925362d46c6075480bfa4df87b28e169a9/docutils-0.21.2.tar.gz", hash = "sha256:3a6b18732edf182daa3cd12775bbb338cf5691468f91eeeb109deff6ebfa986f", size = 2204444, upload-time = "2024-04-23T18:57:18.24Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/8f/d7/9322c609343d929e75e7e5e6255e614fcc67572cfd083959cdef3b7aad79/docutils-0.21.2-py3-none-any.whl", hash = "sha256:dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2", size = 587408, upload-time = "2024-04-23T18:57:14.835Z" },
]
[[package]]
name = "filelock"
version = "3.18.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/0a/10/c23352565a6544bdc5353e0b15fc1c563352101f30e24bf500207a54df9a/filelock-3.18.0.tar.gz", hash = "sha256:adbc88eabb99d2fec8c9c1b229b171f18afa655400173ddc653d5d01501fb9f2", size = 18075, upload-time = "2025-03-14T07:11:40.47Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/4d/36/2a115987e2d8c300a974597416d9de88f2444426de9571f4b59b2cca3acc/filelock-3.18.0-py3-none-any.whl", hash = "sha256:c401f4f8377c4464e6db25fff06205fd89bdd83b65eb0488ed1b160f780e21de", size = 16215, upload-time = "2025-03-14T07:11:39.145Z" },
]
[[package]]
name = "frozenlist"
version = "1.6.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/ee/f4/d744cba2da59b5c1d88823cf9e8a6c74e4659e2b27604ed973be2a0bf5ab/frozenlist-1.6.0.tar.gz", hash = "sha256:b99655c32c1c8e06d111e7f41c06c29a5318cb1835df23a45518e02a47c63b68", size = 42831, upload-time = "2025-04-17T22:38:53.099Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/53/b5/bc883b5296ec902115c00be161da93bf661199c465ec4c483feec6ea4c32/frozenlist-1.6.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ae8337990e7a45683548ffb2fee1af2f1ed08169284cd829cdd9a7fa7470530d", size = 160912, upload-time = "2025-04-17T22:36:17.235Z" },
{ url = "https://files.pythonhosted.org/packages/6f/93/51b058b563d0704b39c56baa222828043aafcac17fd3734bec5dbeb619b1/frozenlist-1.6.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8c952f69dd524558694818a461855f35d36cc7f5c0adddce37e962c85d06eac0", size = 124315, upload-time = "2025-04-17T22:36:18.735Z" },
{ url = "https://files.pythonhosted.org/packages/c9/e0/46cd35219428d350558b874d595e132d1c17a9471a1bd0d01d518a261e7c/frozenlist-1.6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8f5fef13136c4e2dee91bfb9a44e236fff78fc2cd9f838eddfc470c3d7d90afe", size = 122230, upload-time = "2025-04-17T22:36:20.6Z" },
{ url = "https://files.pythonhosted.org/packages/d1/0f/7ad2ce928ad06d6dd26a61812b959ded573d3e9d0ee6109d96c2be7172e9/frozenlist-1.6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:716bbba09611b4663ecbb7cd022f640759af8259e12a6ca939c0a6acd49eedba", size = 314842, upload-time = "2025-04-17T22:36:22.088Z" },
{ url = "https://files.pythonhosted.org/packages/34/76/98cbbd8a20a5c3359a2004ae5e5b216af84a150ccbad67c8f8f30fb2ea91/frozenlist-1.6.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:7b8c4dc422c1a3ffc550b465090e53b0bf4839047f3e436a34172ac67c45d595", size = 304919, upload-time = "2025-04-17T22:36:24.247Z" },
{ url = "https://files.pythonhosted.org/packages/9a/fa/258e771ce3a44348c05e6b01dffc2bc67603fba95761458c238cd09a2c77/frozenlist-1.6.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b11534872256e1666116f6587a1592ef395a98b54476addb5e8d352925cb5d4a", size = 324074, upload-time = "2025-04-17T22:36:26.291Z" },
{ url = "https://files.pythonhosted.org/packages/d5/a4/047d861fd8c538210e12b208c0479912273f991356b6bdee7ea8356b07c9/frozenlist-1.6.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1c6eceb88aaf7221f75be6ab498dc622a151f5f88d536661af3ffc486245a626", size = 321292, upload-time = "2025-04-17T22:36:27.909Z" },
{ url = "https://files.pythonhosted.org/packages/c0/25/cfec8af758b4525676cabd36efcaf7102c1348a776c0d1ad046b8a7cdc65/frozenlist-1.6.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62c828a5b195570eb4b37369fcbbd58e96c905768d53a44d13044355647838ff", size = 301569, upload-time = "2025-04-17T22:36:29.448Z" },
{ url = "https://files.pythonhosted.org/packages/87/2f/0c819372fa9f0c07b153124bf58683b8d0ca7bb73ea5ccde9b9ef1745beb/frozenlist-1.6.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e1c6bd2c6399920c9622362ce95a7d74e7f9af9bfec05fff91b8ce4b9647845a", size = 313625, upload-time = "2025-04-17T22:36:31.55Z" },
{ url = "https://files.pythonhosted.org/packages/50/5f/f0cf8b0fdedffdb76b3745aa13d5dbe404d63493cc211ce8250f2025307f/frozenlist-1.6.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:49ba23817781e22fcbd45fd9ff2b9b8cdb7b16a42a4851ab8025cae7b22e96d0", size = 312523, upload-time = "2025-04-17T22:36:33.078Z" },
{ url = "https://files.pythonhosted.org/packages/e1/6c/38c49108491272d3e84125bbabf2c2d0b304899b52f49f0539deb26ad18d/frozenlist-1.6.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:431ef6937ae0f853143e2ca67d6da76c083e8b1fe3df0e96f3802fd37626e606", size = 322657, upload-time = "2025-04-17T22:36:34.688Z" },
{ url = "https://files.pythonhosted.org/packages/bd/4b/3bd3bad5be06a9d1b04b1c22be80b5fe65b502992d62fab4bdb25d9366ee/frozenlist-1.6.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:9d124b38b3c299ca68433597ee26b7819209cb8a3a9ea761dfe9db3a04bba584", size = 303414, upload-time = "2025-04-17T22:36:36.363Z" },
{ url = "https://files.pythonhosted.org/packages/5b/89/7e225a30bef6e85dbfe22622c24afe932e9444de3b40d58b1ea589a14ef8/frozenlist-1.6.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:118e97556306402e2b010da1ef21ea70cb6d6122e580da64c056b96f524fbd6a", size = 320321, upload-time = "2025-04-17T22:36:38.16Z" },
{ url = "https://files.pythonhosted.org/packages/22/72/7e3acef4dd9e86366cb8f4d8f28e852c2b7e116927e9722b31a6f71ea4b0/frozenlist-1.6.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:fb3b309f1d4086b5533cf7bbcf3f956f0ae6469664522f1bde4feed26fba60f1", size = 323975, upload-time = "2025-04-17T22:36:40.289Z" },
{ url = "https://files.pythonhosted.org/packages/d8/85/e5da03d20507e13c66ce612c9792b76811b7a43e3320cce42d95b85ac755/frozenlist-1.6.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:54dece0d21dce4fdb188a1ffc555926adf1d1c516e493c2914d7c370e454bc9e", size = 316553, upload-time = "2025-04-17T22:36:42.045Z" },
{ url = "https://files.pythonhosted.org/packages/ac/8e/6c609cbd0580ae8a0661c408149f196aade7d325b1ae7adc930501b81acb/frozenlist-1.6.0-cp311-cp311-win32.whl", hash = "sha256:654e4ba1d0b2154ca2f096bed27461cf6160bc7f504a7f9a9ef447c293caf860", size = 115511, upload-time = "2025-04-17T22:36:44.067Z" },
{ url = "https://files.pythonhosted.org/packages/f2/13/a84804cfde6de12d44ed48ecbf777ba62b12ff09e761f76cdd1ff9e14bb1/frozenlist-1.6.0-cp311-cp311-win_amd64.whl", hash = "sha256:3e911391bffdb806001002c1f860787542f45916c3baf764264a52765d5a5603", size = 120863, upload-time = "2025-04-17T22:36:45.465Z" },
{ url = "https://files.pythonhosted.org/packages/9c/8a/289b7d0de2fbac832ea80944d809759976f661557a38bb8e77db5d9f79b7/frozenlist-1.6.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:c5b9e42ace7d95bf41e19b87cec8f262c41d3510d8ad7514ab3862ea2197bfb1", size = 160193, upload-time = "2025-04-17T22:36:47.382Z" },
{ url = "https://files.pythonhosted.org/packages/19/80/2fd17d322aec7f430549f0669f599997174f93ee17929ea5b92781ec902c/frozenlist-1.6.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ca9973735ce9f770d24d5484dcb42f68f135351c2fc81a7a9369e48cf2998a29", size = 123831, upload-time = "2025-04-17T22:36:49.401Z" },
{ url = "https://files.pythonhosted.org/packages/99/06/f5812da431273f78c6543e0b2f7de67dfd65eb0a433978b2c9c63d2205e4/frozenlist-1.6.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6ac40ec76041c67b928ca8aaffba15c2b2ee3f5ae8d0cb0617b5e63ec119ca25", size = 121862, upload-time = "2025-04-17T22:36:51.899Z" },
{ url = "https://files.pythonhosted.org/packages/d0/31/9e61c6b5fc493cf24d54881731204d27105234d09878be1a5983182cc4a5/frozenlist-1.6.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:95b7a8a3180dfb280eb044fdec562f9b461614c0ef21669aea6f1d3dac6ee576", size = 316361, upload-time = "2025-04-17T22:36:53.402Z" },
{ url = "https://files.pythonhosted.org/packages/9d/55/22ca9362d4f0222324981470fd50192be200154d51509ee6eb9baa148e96/frozenlist-1.6.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:c444d824e22da6c9291886d80c7d00c444981a72686e2b59d38b285617cb52c8", size = 307115, upload-time = "2025-04-17T22:36:55.016Z" },
{ url = "https://files.pythonhosted.org/packages/ae/39/4fff42920a57794881e7bb3898dc7f5f539261711ea411b43bba3cde8b79/frozenlist-1.6.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bb52c8166499a8150bfd38478248572c924c003cbb45fe3bcd348e5ac7c000f9", size = 322505, upload-time = "2025-04-17T22:36:57.12Z" },
{ url = "https://files.pythonhosted.org/packages/55/f2/88c41f374c1e4cf0092a5459e5f3d6a1e17ed274c98087a76487783df90c/frozenlist-1.6.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b35298b2db9c2468106278537ee529719228950a5fdda686582f68f247d1dc6e", size = 322666, upload-time = "2025-04-17T22:36:58.735Z" },
{ url = "https://files.pythonhosted.org/packages/75/51/034eeb75afdf3fd03997856195b500722c0b1a50716664cde64e28299c4b/frozenlist-1.6.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d108e2d070034f9d57210f22fefd22ea0d04609fc97c5f7f5a686b3471028590", size = 302119, upload-time = "2025-04-17T22:37:00.512Z" },
{ url = "https://files.pythonhosted.org/packages/2b/a6/564ecde55ee633270a793999ef4fd1d2c2b32b5a7eec903b1012cb7c5143/frozenlist-1.6.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e1be9111cb6756868ac242b3c2bd1f09d9aea09846e4f5c23715e7afb647103", size = 316226, upload-time = "2025-04-17T22:37:02.102Z" },
{ url = "https://files.pythonhosted.org/packages/f1/c8/6c0682c32377f402b8a6174fb16378b683cf6379ab4d2827c580892ab3c7/frozenlist-1.6.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:94bb451c664415f02f07eef4ece976a2c65dcbab9c2f1705b7031a3a75349d8c", size = 312788, upload-time = "2025-04-17T22:37:03.578Z" },
{ url = "https://files.pythonhosted.org/packages/b6/b8/10fbec38f82c5d163ca1750bfff4ede69713badf236a016781cf1f10a0f0/frozenlist-1.6.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:d1a686d0b0949182b8faddea596f3fc11f44768d1f74d4cad70213b2e139d821", size = 325914, upload-time = "2025-04-17T22:37:05.213Z" },
{ url = "https://files.pythonhosted.org/packages/62/ca/2bf4f3a1bd40cdedd301e6ecfdbb291080d5afc5f9ce350c0739f773d6b9/frozenlist-1.6.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:ea8e59105d802c5a38bdbe7362822c522230b3faba2aa35c0fa1765239b7dd70", size = 305283, upload-time = "2025-04-17T22:37:06.985Z" },
{ url = "https://files.pythonhosted.org/packages/09/64/20cc13ccf94abc2a1f482f74ad210703dc78a590d0b805af1c9aa67f76f9/frozenlist-1.6.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:abc4e880a9b920bc5020bf6a431a6bb40589d9bca3975c980495f63632e8382f", size = 319264, upload-time = "2025-04-17T22:37:08.618Z" },
{ url = "https://files.pythonhosted.org/packages/20/ff/86c6a2bbe98cfc231519f5e6d712a0898488ceac804a917ce014f32e68f6/frozenlist-1.6.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:9a79713adfe28830f27a3c62f6b5406c37376c892b05ae070906f07ae4487046", size = 326482, upload-time = "2025-04-17T22:37:10.196Z" },
{ url = "https://files.pythonhosted.org/packages/2f/da/8e381f66367d79adca245d1d71527aac774e30e291d41ef161ce2d80c38e/frozenlist-1.6.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:9a0318c2068e217a8f5e3b85e35899f5a19e97141a45bb925bb357cfe1daf770", size = 318248, upload-time = "2025-04-17T22:37:12.284Z" },
{ url = "https://files.pythonhosted.org/packages/39/24/1a1976563fb476ab6f0fa9fefaac7616a4361dbe0461324f9fd7bf425dbe/frozenlist-1.6.0-cp312-cp312-win32.whl", hash = "sha256:853ac025092a24bb3bf09ae87f9127de9fe6e0c345614ac92536577cf956dfcc", size = 115161, upload-time = "2025-04-17T22:37:13.902Z" },
{ url = "https://files.pythonhosted.org/packages/80/2e/fb4ed62a65f8cd66044706b1013f0010930d8cbb0729a2219561ea075434/frozenlist-1.6.0-cp312-cp312-win_amd64.whl", hash = "sha256:2bdfe2d7e6c9281c6e55523acd6c2bf77963cb422fdc7d142fb0cb6621b66878", size = 120548, upload-time = "2025-04-17T22:37:15.326Z" },
{ url = "https://files.pythonhosted.org/packages/6f/e5/04c7090c514d96ca00887932417f04343ab94904a56ab7f57861bf63652d/frozenlist-1.6.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:1d7fb014fe0fbfee3efd6a94fc635aeaa68e5e1720fe9e57357f2e2c6e1a647e", size = 158182, upload-time = "2025-04-17T22:37:16.837Z" },
{ url = "https://files.pythonhosted.org/packages/e9/8f/60d0555c61eec855783a6356268314d204137f5e0c53b59ae2fc28938c99/frozenlist-1.6.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:01bcaa305a0fdad12745502bfd16a1c75b14558dabae226852f9159364573117", size = 122838, upload-time = "2025-04-17T22:37:18.352Z" },
{ url = "https://files.pythonhosted.org/packages/5a/a7/d0ec890e3665b4b3b7c05dc80e477ed8dc2e2e77719368e78e2cd9fec9c8/frozenlist-1.6.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:8b314faa3051a6d45da196a2c495e922f987dc848e967d8cfeaee8a0328b1cd4", size = 120980, upload-time = "2025-04-17T22:37:19.857Z" },
{ url = "https://files.pythonhosted.org/packages/cc/19/9b355a5e7a8eba903a008579964192c3e427444752f20b2144b10bb336df/frozenlist-1.6.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da62fecac21a3ee10463d153549d8db87549a5e77eefb8c91ac84bb42bb1e4e3", size = 305463, upload-time = "2025-04-17T22:37:21.328Z" },
{ url = "https://files.pythonhosted.org/packages/9c/8d/5b4c758c2550131d66935ef2fa700ada2461c08866aef4229ae1554b93ca/frozenlist-1.6.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:d1eb89bf3454e2132e046f9599fbcf0a4483ed43b40f545551a39316d0201cd1", size = 297985, upload-time = "2025-04-17T22:37:23.55Z" },
{ url = "https://files.pythonhosted.org/packages/48/2c/537ec09e032b5865715726b2d1d9813e6589b571d34d01550c7aeaad7e53/frozenlist-1.6.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d18689b40cb3936acd971f663ccb8e2589c45db5e2c5f07e0ec6207664029a9c", size = 311188, upload-time = "2025-04-17T22:37:25.221Z" },
{ url = "https://files.pythonhosted.org/packages/31/2f/1aa74b33f74d54817055de9a4961eff798f066cdc6f67591905d4fc82a84/frozenlist-1.6.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e67ddb0749ed066b1a03fba812e2dcae791dd50e5da03be50b6a14d0c1a9ee45", size = 311874, upload-time = "2025-04-17T22:37:26.791Z" },
{ url = "https://files.pythonhosted.org/packages/bf/f0/cfec18838f13ebf4b37cfebc8649db5ea71a1b25dacd691444a10729776c/frozenlist-1.6.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fc5e64626e6682638d6e44398c9baf1d6ce6bc236d40b4b57255c9d3f9761f1f", size = 291897, upload-time = "2025-04-17T22:37:28.958Z" },
{ url = "https://files.pythonhosted.org/packages/ea/a5/deb39325cbbea6cd0a46db8ccd76150ae2fcbe60d63243d9df4a0b8c3205/frozenlist-1.6.0-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:437cfd39564744ae32ad5929e55b18ebd88817f9180e4cc05e7d53b75f79ce85", size = 305799, upload-time = "2025-04-17T22:37:30.889Z" },
{ url = "https://files.pythonhosted.org/packages/78/22/6ddec55c5243a59f605e4280f10cee8c95a449f81e40117163383829c241/frozenlist-1.6.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:62dd7df78e74d924952e2feb7357d826af8d2f307557a779d14ddf94d7311be8", size = 302804, upload-time = "2025-04-17T22:37:32.489Z" },
{ url = "https://files.pythonhosted.org/packages/5d/b7/d9ca9bab87f28855063c4d202936800219e39db9e46f9fb004d521152623/frozenlist-1.6.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:a66781d7e4cddcbbcfd64de3d41a61d6bdde370fc2e38623f30b2bd539e84a9f", size = 316404, upload-time = "2025-04-17T22:37:34.59Z" },
{ url = "https://files.pythonhosted.org/packages/a6/3a/1255305db7874d0b9eddb4fe4a27469e1fb63720f1fc6d325a5118492d18/frozenlist-1.6.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:482fe06e9a3fffbcd41950f9d890034b4a54395c60b5e61fae875d37a699813f", size = 295572, upload-time = "2025-04-17T22:37:36.337Z" },
{ url = "https://files.pythonhosted.org/packages/2a/f2/8d38eeee39a0e3a91b75867cc102159ecccf441deb6ddf67be96d3410b84/frozenlist-1.6.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:e4f9373c500dfc02feea39f7a56e4f543e670212102cc2eeb51d3a99c7ffbde6", size = 307601, upload-time = "2025-04-17T22:37:37.923Z" },
{ url = "https://files.pythonhosted.org/packages/38/04/80ec8e6b92f61ef085422d7b196822820404f940950dde5b2e367bede8bc/frozenlist-1.6.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:e69bb81de06827147b7bfbaeb284d85219fa92d9f097e32cc73675f279d70188", size = 314232, upload-time = "2025-04-17T22:37:39.669Z" },
{ url = "https://files.pythonhosted.org/packages/3a/58/93b41fb23e75f38f453ae92a2f987274c64637c450285577bd81c599b715/frozenlist-1.6.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:7613d9977d2ab4a9141dde4a149f4357e4065949674c5649f920fec86ecb393e", size = 308187, upload-time = "2025-04-17T22:37:41.662Z" },
{ url = "https://files.pythonhosted.org/packages/6a/a2/e64df5c5aa36ab3dee5a40d254f3e471bb0603c225f81664267281c46a2d/frozenlist-1.6.0-cp313-cp313-win32.whl", hash = "sha256:4def87ef6d90429f777c9d9de3961679abf938cb6b7b63d4a7eb8a268babfce4", size = 114772, upload-time = "2025-04-17T22:37:43.132Z" },
{ url = "https://files.pythonhosted.org/packages/a0/77/fead27441e749b2d574bb73d693530d59d520d4b9e9679b8e3cb779d37f2/frozenlist-1.6.0-cp313-cp313-win_amd64.whl", hash = "sha256:37a8a52c3dfff01515e9bbbee0e6063181362f9de3db2ccf9bc96189b557cbfd", size = 119847, upload-time = "2025-04-17T22:37:45.118Z" },
{ url = "https://files.pythonhosted.org/packages/df/bd/cc6d934991c1e5d9cafda83dfdc52f987c7b28343686aef2e58a9cf89f20/frozenlist-1.6.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:46138f5a0773d064ff663d273b309b696293d7a7c00a0994c5c13a5078134b64", size = 174937, upload-time = "2025-04-17T22:37:46.635Z" },
{ url = "https://files.pythonhosted.org/packages/f2/a2/daf945f335abdbfdd5993e9dc348ef4507436936ab3c26d7cfe72f4843bf/frozenlist-1.6.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:f88bc0a2b9c2a835cb888b32246c27cdab5740059fb3688852bf91e915399b91", size = 136029, upload-time = "2025-04-17T22:37:48.192Z" },
{ url = "https://files.pythonhosted.org/packages/51/65/4c3145f237a31247c3429e1c94c384d053f69b52110a0d04bfc8afc55fb2/frozenlist-1.6.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:777704c1d7655b802c7850255639672e90e81ad6fa42b99ce5ed3fbf45e338dd", size = 134831, upload-time = "2025-04-17T22:37:50.485Z" },
{ url = "https://files.pythonhosted.org/packages/77/38/03d316507d8dea84dfb99bdd515ea245628af964b2bf57759e3c9205cc5e/frozenlist-1.6.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:85ef8d41764c7de0dcdaf64f733a27352248493a85a80661f3c678acd27e31f2", size = 392981, upload-time = "2025-04-17T22:37:52.558Z" },
{ url = "https://files.pythonhosted.org/packages/37/02/46285ef9828f318ba400a51d5bb616ded38db8466836a9cfa39f3903260b/frozenlist-1.6.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:da5cb36623f2b846fb25009d9d9215322318ff1c63403075f812b3b2876c8506", size = 371999, upload-time = "2025-04-17T22:37:54.092Z" },
{ url = "https://files.pythonhosted.org/packages/0d/64/1212fea37a112c3c5c05bfb5f0a81af4836ce349e69be75af93f99644da9/frozenlist-1.6.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cbb56587a16cf0fb8acd19e90ff9924979ac1431baea8681712716a8337577b0", size = 392200, upload-time = "2025-04-17T22:37:55.951Z" },
{ url = "https://files.pythonhosted.org/packages/81/ce/9a6ea1763e3366e44a5208f76bf37c76c5da570772375e4d0be85180e588/frozenlist-1.6.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c6154c3ba59cda3f954c6333025369e42c3acd0c6e8b6ce31eb5c5b8116c07e0", size = 390134, upload-time = "2025-04-17T22:37:57.633Z" },
{ url = "https://files.pythonhosted.org/packages/bc/36/939738b0b495b2c6d0c39ba51563e453232813042a8d908b8f9544296c29/frozenlist-1.6.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2e8246877afa3f1ae5c979fe85f567d220f86a50dc6c493b9b7d8191181ae01e", size = 365208, upload-time = "2025-04-17T22:37:59.742Z" },
{ url = "https://files.pythonhosted.org/packages/b4/8b/939e62e93c63409949c25220d1ba8e88e3960f8ef6a8d9ede8f94b459d27/frozenlist-1.6.0-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b0f6cce16306d2e117cf9db71ab3a9e8878a28176aeaf0dbe35248d97b28d0c", size = 385548, upload-time = "2025-04-17T22:38:01.416Z" },
{ url = "https://files.pythonhosted.org/packages/62/38/22d2873c90102e06a7c5a3a5b82ca47e393c6079413e8a75c72bff067fa8/frozenlist-1.6.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:1b8e8cd8032ba266f91136d7105706ad57770f3522eac4a111d77ac126a25a9b", size = 391123, upload-time = "2025-04-17T22:38:03.049Z" },
{ url = "https://files.pythonhosted.org/packages/44/78/63aaaf533ee0701549500f6d819be092c6065cb5c577edb70c09df74d5d0/frozenlist-1.6.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:e2ada1d8515d3ea5378c018a5f6d14b4994d4036591a52ceaf1a1549dec8e1ad", size = 394199, upload-time = "2025-04-17T22:38:04.776Z" },
{ url = "https://files.pythonhosted.org/packages/54/45/71a6b48981d429e8fbcc08454dc99c4c2639865a646d549812883e9c9dd3/frozenlist-1.6.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:cdb2c7f071e4026c19a3e32b93a09e59b12000751fc9b0b7758da899e657d215", size = 373854, upload-time = "2025-04-17T22:38:06.576Z" },
{ url = "https://files.pythonhosted.org/packages/3f/f3/dbf2a5e11736ea81a66e37288bf9f881143a7822b288a992579ba1b4204d/frozenlist-1.6.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:03572933a1969a6d6ab509d509e5af82ef80d4a5d4e1e9f2e1cdd22c77a3f4d2", size = 395412, upload-time = "2025-04-17T22:38:08.197Z" },
{ url = "https://files.pythonhosted.org/packages/b3/f1/c63166806b331f05104d8ea385c4acd511598568b1f3e4e8297ca54f2676/frozenlist-1.6.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:77effc978947548b676c54bbd6a08992759ea6f410d4987d69feea9cd0919911", size = 394936, upload-time = "2025-04-17T22:38:10.056Z" },
{ url = "https://files.pythonhosted.org/packages/ef/ea/4f3e69e179a430473eaa1a75ff986526571215fefc6b9281cdc1f09a4eb8/frozenlist-1.6.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:a2bda8be77660ad4089caf2223fdbd6db1858462c4b85b67fbfa22102021e497", size = 391459, upload-time = "2025-04-17T22:38:11.826Z" },
{ url = "https://files.pythonhosted.org/packages/d3/c3/0fc2c97dea550df9afd072a37c1e95421652e3206bbeaa02378b24c2b480/frozenlist-1.6.0-cp313-cp313t-win32.whl", hash = "sha256:a4d96dc5bcdbd834ec6b0f91027817214216b5b30316494d2b1aebffb87c534f", size = 128797, upload-time = "2025-04-17T22:38:14.013Z" },
{ url = "https://files.pythonhosted.org/packages/ae/f5/79c9320c5656b1965634fe4be9c82b12a3305bdbc58ad9cb941131107b20/frozenlist-1.6.0-cp313-cp313t-win_amd64.whl", hash = "sha256:e18036cb4caa17ea151fd5f3d70be9d354c99eb8cf817a3ccde8a7873b074348", size = 134709, upload-time = "2025-04-17T22:38:15.551Z" },
{ url = "https://files.pythonhosted.org/packages/71/3e/b04a0adda73bd52b390d730071c0d577073d3d26740ee1bad25c3ad0f37b/frozenlist-1.6.0-py3-none-any.whl", hash = "sha256:535eec9987adb04701266b92745d6cdcef2e77669299359c3009c3404dd5d191", size = 12404, upload-time = "2025-04-17T22:38:51.668Z" },
]
[[package]]
name = "id"
version = "1.5.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "requests" },
]
sdist = { url = "https://files.pythonhosted.org/packages/22/11/102da08f88412d875fa2f1a9a469ff7ad4c874b0ca6fed0048fe385bdb3d/id-1.5.0.tar.gz", hash = "sha256:292cb8a49eacbbdbce97244f47a97b4c62540169c976552e497fd57df0734c1d", size = 15237, upload-time = "2024-12-04T19:53:05.575Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/9f/cb/18326d2d89ad3b0dd143da971e77afd1e6ca6674f1b1c3df4b6bec6279fc/id-1.5.0-py3-none-any.whl", hash = "sha256:f1434e1cef91f2cbb8a4ec64663d5a23b9ed43ef44c4c957d02583d61714c658", size = 13611, upload-time = "2024-12-04T19:53:03.02Z" },
]
[[package]]
name = "identify"
version = "2.6.12"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/a2/88/d193a27416618628a5eea64e3223acd800b40749a96ffb322a9b55a49ed1/identify-2.6.12.tar.gz", hash = "sha256:d8de45749f1efb108badef65ee8386f0f7bb19a7f26185f74de6367bffbaf0e6", size = 99254, upload-time = "2025-05-23T20:37:53.3Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/7a/cd/18f8da995b658420625f7ef13f037be53ae04ec5ad33f9b718240dcfd48c/identify-2.6.12-py2.py3-none-any.whl", hash = "sha256:ad9672d5a72e0d2ff7c5c8809b62dfa60458626352fb0eb7b55e69bdc45334a2", size = 99145, upload-time = "2025-05-23T20:37:51.495Z" },
]
[[package]]
name = "idna"
version = "3.10"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/f1/70/7703c29685631f5a7590aa73f1f1d3fa9a380e654b86af429e0934a32f7d/idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", size = 190490, upload-time = "2024-09-15T18:07:39.745Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442, upload-time = "2024-09-15T18:07:37.964Z" },
]
[[package]]
name = "importlib-metadata"
version = "8.7.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "zipp" },
]
sdist = { url = "https://files.pythonhosted.org/packages/76/66/650a33bd90f786193e4de4b3ad86ea60b53c89b669a5c7be931fac31cdb0/importlib_metadata-8.7.0.tar.gz", hash = "sha256:d13b81ad223b890aa16c5471f2ac3056cf76c5f10f82d6f9292f0b415f389000", size = 56641, upload-time = "2025-04-27T15:29:01.736Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/20/b0/36bd937216ec521246249be3bf9855081de4c5e06a0c9b4219dbeda50373/importlib_metadata-8.7.0-py3-none-any.whl", hash = "sha256:e5dd1551894c77868a30651cef00984d50e1002d06942a7101d34870c5f02afd", size = 27656, upload-time = "2025-04-27T15:29:00.214Z" },
]
[[package]]
name = "iniconfig"
version = "2.1.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/f2/97/ebf4da567aa6827c909642694d71c9fcf53e5b504f2d96afea02718862f3/iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7", size = 4793, upload-time = "2025-03-19T20:09:59.721Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/2c/e1/e6716421ea10d38022b952c159d5161ca1193197fb744506875fbb87ea7b/iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760", size = 6050, upload-time = "2025-03-19T20:10:01.071Z" },
]
[[package]]
name = "jaraco-classes"
version = "3.4.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "more-itertools" },
]
sdist = { url = "https://files.pythonhosted.org/packages/06/c0/ed4a27bc5571b99e3cff68f8a9fa5b56ff7df1c2251cc715a652ddd26402/jaraco.classes-3.4.0.tar.gz", hash = "sha256:47a024b51d0239c0dd8c8540c6c7f484be3b8fcf0b2d85c13825780d3b3f3acd", size = 11780, upload-time = "2024-03-31T07:27:36.643Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/7f/66/b15ce62552d84bbfcec9a4873ab79d993a1dd4edb922cbfccae192bd5b5f/jaraco.classes-3.4.0-py3-none-any.whl", hash = "sha256:f662826b6bed8cace05e7ff873ce0f9283b5c924470fe664fff1c2f00f581790", size = 6777, upload-time = "2024-03-31T07:27:34.792Z" },
]
[[package]]
name = "jaraco-context"
version = "6.0.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "backports-tarfile", marker = "python_full_version < '3.12'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/df/ad/f3777b81bf0b6e7bc7514a1656d3e637b2e8e15fab2ce3235730b3e7a4e6/jaraco_context-6.0.1.tar.gz", hash = "sha256:9bae4ea555cf0b14938dc0aee7c9f32ed303aa20a3b73e7dc80111628792d1b3", size = 13912, upload-time = "2024-08-20T03:39:27.358Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/ff/db/0c52c4cf5e4bd9f5d7135ec7669a3a767af21b3a308e1ed3674881e52b62/jaraco.context-6.0.1-py3-none-any.whl", hash = "sha256:f797fc481b490edb305122c9181830a3a5b76d84ef6d1aef2fb9b47ab956f9e4", size = 6825, upload-time = "2024-08-20T03:39:25.966Z" },
]
[[package]]
name = "jaraco-functools"
version = "4.1.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "more-itertools" },
]
sdist = { url = "https://files.pythonhosted.org/packages/ab/23/9894b3df5d0a6eb44611c36aec777823fc2e07740dabbd0b810e19594013/jaraco_functools-4.1.0.tar.gz", hash = "sha256:70f7e0e2ae076498e212562325e805204fc092d7b4c17e0e86c959e249701a9d", size = 19159, upload-time = "2024-09-27T19:47:09.122Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/9f/4f/24b319316142c44283d7540e76c7b5a6dbd5db623abd86bb7b3491c21018/jaraco.functools-4.1.0-py3-none-any.whl", hash = "sha256:ad159f13428bc4acbf5541ad6dec511f91573b90fba04df61dafa2a1231cf649", size = 10187, upload-time = "2024-09-27T19:47:07.14Z" },
]
[[package]]
name = "jeepney"
version = "0.9.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/7b/6f/357efd7602486741aa73ffc0617fb310a29b588ed0fd69c2399acbb85b0c/jeepney-0.9.0.tar.gz", hash = "sha256:cf0e9e845622b81e4a28df94c40345400256ec608d0e55bb8a3feaa9163f5732", size = 106758, upload-time = "2025-02-27T18:51:01.684Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/b2/a3/e137168c9c44d18eff0376253da9f1e9234d0239e0ee230d2fee6cea8e55/jeepney-0.9.0-py3-none-any.whl", hash = "sha256:97e5714520c16fc0a45695e5365a2e11b81ea79bba796e26f9f1d178cb182683", size = 49010, upload-time = "2025-02-27T18:51:00.104Z" },
]
[[package]]
name = "keyring"
version = "25.6.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "importlib-metadata", marker = "python_full_version < '3.12'" },
{ name = "jaraco-classes" },
{ name = "jaraco-context" },
{ name = "jaraco-functools" },
{ name = "jeepney", marker = "sys_platform == 'linux'" },
{ name = "pywin32-ctypes", marker = "sys_platform == 'win32'" },
{ name = "secretstorage", marker = "sys_platform == 'linux'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/70/09/d904a6e96f76ff214be59e7aa6ef7190008f52a0ab6689760a98de0bf37d/keyring-25.6.0.tar.gz", hash = "sha256:0b39998aa941431eb3d9b0d4b2460bc773b9df6fed7621c2dfb291a7e0187a66", size = 62750, upload-time = "2024-12-25T15:26:45.782Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/d3/32/da7f44bcb1105d3e88a0b74ebdca50c59121d2ddf71c9e34ba47df7f3a56/keyring-25.6.0-py3-none-any.whl", hash = "sha256:552a3f7af126ece7ed5c89753650eec89c7eaae8617d0aa4d9ad2b75111266bd", size = 39085, upload-time = "2024-12-25T15:26:44.377Z" },
]
[[package]]
name = "markdown-it-py"
version = "3.0.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "mdurl" },
]
sdist = { url = "https://files.pythonhosted.org/packages/38/71/3b932df36c1a044d397a1f92d1cf91ee0a503d91e470cbd670aa66b07ed0/markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb", size = 74596, upload-time = "2023-06-03T06:41:14.443Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/42/d7/1ec15b46af6af88f19b8e5ffea08fa375d433c998b8a7639e76935c14f1f/markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1", size = 87528, upload-time = "2023-06-03T06:41:11.019Z" },
]
[[package]]
name = "mdurl"
version = "0.1.2"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729, upload-time = "2022-08-14T12:40:10.846Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" },
]
[[package]]
name = "more-itertools"
version = "10.7.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/ce/a0/834b0cebabbfc7e311f30b46c8188790a37f89fc8d756660346fe5abfd09/more_itertools-10.7.0.tar.gz", hash = "sha256:9fddd5403be01a94b204faadcff459ec3568cf110265d3c54323e1e866ad29d3", size = 127671, upload-time = "2025-04-22T14:17:41.838Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/2b/9f/7ba6f94fc1e9ac3d2b853fdff3035fb2fa5afbed898c4a72b8a020610594/more_itertools-10.7.0-py3-none-any.whl", hash = "sha256:d43980384673cb07d2f7d2d918c616b30c659c089ee23953f601d6609c67510e", size = 65278, upload-time = "2025-04-22T14:17:40.49Z" },
]
[[package]]
name = "multidict"
version = "6.4.4"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/91/2f/a3470242707058fe856fe59241eee5635d79087100b7042a867368863a27/multidict-6.4.4.tar.gz", hash = "sha256:69ee9e6ba214b5245031b76233dd95408a0fd57fdb019ddcc1ead4790932a8e8", size = 90183, upload-time = "2025-05-19T14:16:37.381Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/19/1b/4c6e638195851524a63972c5773c7737bea7e47b1ba402186a37773acee2/multidict-6.4.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4f5f29794ac0e73d2a06ac03fd18870adc0135a9d384f4a306a951188ed02f95", size = 65515, upload-time = "2025-05-19T14:14:19.767Z" },
{ url = "https://files.pythonhosted.org/packages/25/d5/10e6bca9a44b8af3c7f920743e5fc0c2bcf8c11bf7a295d4cfe00b08fb46/multidict-6.4.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c04157266344158ebd57b7120d9b0b35812285d26d0e78193e17ef57bfe2979a", size = 38609, upload-time = "2025-05-19T14:14:21.538Z" },
{ url = "https://files.pythonhosted.org/packages/26/b4/91fead447ccff56247edc7f0535fbf140733ae25187a33621771ee598a18/multidict-6.4.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bb61ffd3ab8310d93427e460f565322c44ef12769f51f77277b4abad7b6f7223", size = 37871, upload-time = "2025-05-19T14:14:22.666Z" },
{ url = "https://files.pythonhosted.org/packages/3b/37/cbc977cae59277e99d15bbda84cc53b5e0c4929ffd91d958347200a42ad0/multidict-6.4.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5e0ba18a9afd495f17c351d08ebbc4284e9c9f7971d715f196b79636a4d0de44", size = 226661, upload-time = "2025-05-19T14:14:24.124Z" },
{ url = "https://files.pythonhosted.org/packages/15/cd/7e0b57fbd4dc2fc105169c4ecce5be1a63970f23bb4ec8c721b67e11953d/multidict-6.4.4-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:9faf1b1dcaadf9f900d23a0e6d6c8eadd6a95795a0e57fcca73acce0eb912065", size = 223422, upload-time = "2025-05-19T14:14:25.437Z" },
{ url = "https://files.pythonhosted.org/packages/f1/01/1de268da121bac9f93242e30cd3286f6a819e5f0b8896511162d6ed4bf8d/multidict-6.4.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a4d1cb1327c6082c4fce4e2a438483390964c02213bc6b8d782cf782c9b1471f", size = 235447, upload-time = "2025-05-19T14:14:26.793Z" },
{ url = "https://files.pythonhosted.org/packages/d2/8c/8b9a5e4aaaf4f2de14e86181a3a3d7b105077f668b6a06f043ec794f684c/multidict-6.4.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:941f1bec2f5dbd51feeb40aea654c2747f811ab01bdd3422a48a4e4576b7d76a", size = 231455, upload-time = "2025-05-19T14:14:28.149Z" },
{ url = "https://files.pythonhosted.org/packages/35/db/e1817dcbaa10b319c412769cf999b1016890849245d38905b73e9c286862/multidict-6.4.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e5f8a146184da7ea12910a4cec51ef85e44f6268467fb489c3caf0cd512f29c2", size = 223666, upload-time = "2025-05-19T14:14:29.584Z" },
{ url = "https://files.pythonhosted.org/packages/4a/e1/66e8579290ade8a00e0126b3d9a93029033ffd84f0e697d457ed1814d0fc/multidict-6.4.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:232b7237e57ec3c09be97206bfb83a0aa1c5d7d377faa019c68a210fa35831f1", size = 217392, upload-time = "2025-05-19T14:14:30.961Z" },
{ url = "https://files.pythonhosted.org/packages/7b/6f/f8639326069c24a48c7747c2a5485d37847e142a3f741ff3340c88060a9a/multidict-6.4.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:55ae0721c1513e5e3210bca4fc98456b980b0c2c016679d3d723119b6b202c42", size = 228969, upload-time = "2025-05-19T14:14:32.672Z" },
{ url = "https://files.pythonhosted.org/packages/d2/c3/3d58182f76b960eeade51c89fcdce450f93379340457a328e132e2f8f9ed/multidict-6.4.4-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:51d662c072579f63137919d7bb8fc250655ce79f00c82ecf11cab678f335062e", size = 217433, upload-time = "2025-05-19T14:14:34.016Z" },
{ url = "https://files.pythonhosted.org/packages/e1/4b/f31a562906f3bd375f3d0e83ce314e4a660c01b16c2923e8229b53fba5d7/multidict-6.4.4-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:0e05c39962baa0bb19a6b210e9b1422c35c093b651d64246b6c2e1a7e242d9fd", size = 225418, upload-time = "2025-05-19T14:14:35.376Z" },
{ url = "https://files.pythonhosted.org/packages/99/89/78bb95c89c496d64b5798434a3deee21996114d4d2c28dd65850bf3a691e/multidict-6.4.4-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:d5b1cc3ab8c31d9ebf0faa6e3540fb91257590da330ffe6d2393d4208e638925", size = 235042, upload-time = "2025-05-19T14:14:36.723Z" },
{ url = "https://files.pythonhosted.org/packages/74/91/8780a6e5885a8770442a8f80db86a0887c4becca0e5a2282ba2cae702bc4/multidict-6.4.4-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:93ec84488a384cd7b8a29c2c7f467137d8a73f6fe38bb810ecf29d1ade011a7c", size = 230280, upload-time = "2025-05-19T14:14:38.194Z" },
{ url = "https://files.pythonhosted.org/packages/68/c1/fcf69cabd542eb6f4b892469e033567ee6991d361d77abdc55e3a0f48349/multidict-6.4.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b308402608493638763abc95f9dc0030bbd6ac6aff784512e8ac3da73a88af08", size = 223322, upload-time = "2025-05-19T14:14:40.015Z" },
{ url = "https://files.pythonhosted.org/packages/b8/85/5b80bf4b83d8141bd763e1d99142a9cdfd0db83f0739b4797172a4508014/multidict-6.4.4-cp311-cp311-win32.whl", hash = "sha256:343892a27d1a04d6ae455ecece12904d242d299ada01633d94c4f431d68a8c49", size = 35070, upload-time = "2025-05-19T14:14:41.904Z" },
{ url = "https://files.pythonhosted.org/packages/09/66/0bed198ffd590ab86e001f7fa46b740d58cf8ff98c2f254e4a36bf8861ad/multidict-6.4.4-cp311-cp311-win_amd64.whl", hash = "sha256:73484a94f55359780c0f458bbd3c39cb9cf9c182552177d2136e828269dee529", size = 38667, upload-time = "2025-05-19T14:14:43.534Z" },
{ url = "https://files.pythonhosted.org/packages/d2/b5/5675377da23d60875fe7dae6be841787755878e315e2f517235f22f59e18/multidict-6.4.4-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:dc388f75a1c00000824bf28b7633e40854f4127ede80512b44c3cfeeea1839a2", size = 64293, upload-time = "2025-05-19T14:14:44.724Z" },
{ url = "https://files.pythonhosted.org/packages/34/a7/be384a482754bb8c95d2bbe91717bf7ccce6dc38c18569997a11f95aa554/multidict-6.4.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:98af87593a666f739d9dba5d0ae86e01b0e1a9cfcd2e30d2d361fbbbd1a9162d", size = 38096, upload-time = "2025-05-19T14:14:45.95Z" },
{ url = "https://files.pythonhosted.org/packages/66/6d/d59854bb4352306145bdfd1704d210731c1bb2c890bfee31fb7bbc1c4c7f/multidict-6.4.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:aff4cafea2d120327d55eadd6b7f1136a8e5a0ecf6fb3b6863e8aca32cd8e50a", size = 37214, upload-time = "2025-05-19T14:14:47.158Z" },
{ url = "https://files.pythonhosted.org/packages/99/e0/c29d9d462d7cfc5fc8f9bf24f9c6843b40e953c0b55e04eba2ad2cf54fba/multidict-6.4.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:169c4ba7858176b797fe551d6e99040c531c775d2d57b31bcf4de6d7a669847f", size = 224686, upload-time = "2025-05-19T14:14:48.366Z" },
{ url = "https://files.pythonhosted.org/packages/dc/4a/da99398d7fd8210d9de068f9a1b5f96dfaf67d51e3f2521f17cba4ee1012/multidict-6.4.4-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:b9eb4c59c54421a32b3273d4239865cb14ead53a606db066d7130ac80cc8ec93", size = 231061, upload-time = "2025-05-19T14:14:49.952Z" },
{ url = "https://files.pythonhosted.org/packages/21/f5/ac11add39a0f447ac89353e6ca46666847051103649831c08a2800a14455/multidict-6.4.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7cf3bd54c56aa16fdb40028d545eaa8d051402b61533c21e84046e05513d5780", size = 232412, upload-time = "2025-05-19T14:14:51.812Z" },
{ url = "https://files.pythonhosted.org/packages/d9/11/4b551e2110cded705a3c13a1d4b6a11f73891eb5a1c449f1b2b6259e58a6/multidict-6.4.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f682c42003c7264134bfe886376299db4cc0c6cd06a3295b41b347044bcb5482", size = 231563, upload-time = "2025-05-19T14:14:53.262Z" },
{ url = "https://files.pythonhosted.org/packages/4c/02/751530c19e78fe73b24c3da66618eda0aa0d7f6e7aa512e46483de6be210/multidict-6.4.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a920f9cf2abdf6e493c519492d892c362007f113c94da4c239ae88429835bad1", size = 223811, upload-time = "2025-05-19T14:14:55.232Z" },
{ url = "https://files.pythonhosted.org/packages/c7/cb/2be8a214643056289e51ca356026c7b2ce7225373e7a1f8c8715efee8988/multidict-6.4.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:530d86827a2df6504526106b4c104ba19044594f8722d3e87714e847c74a0275", size = 216524, upload-time = "2025-05-19T14:14:57.226Z" },
{ url = "https://files.pythonhosted.org/packages/19/f3/6d5011ec375c09081f5250af58de85f172bfcaafebff286d8089243c4bd4/multidict-6.4.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ecde56ea2439b96ed8a8d826b50c57364612ddac0438c39e473fafad7ae1c23b", size = 229012, upload-time = "2025-05-19T14:14:58.597Z" },
{ url = "https://files.pythonhosted.org/packages/67/9c/ca510785df5cf0eaf5b2a8132d7d04c1ce058dcf2c16233e596ce37a7f8e/multidict-6.4.4-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:dc8c9736d8574b560634775ac0def6bdc1661fc63fa27ffdfc7264c565bcb4f2", size = 226765, upload-time = "2025-05-19T14:15:00.048Z" },
{ url = "https://files.pythonhosted.org/packages/36/c8/ca86019994e92a0f11e642bda31265854e6ea7b235642f0477e8c2e25c1f/multidict-6.4.4-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:7f3d3b3c34867579ea47cbd6c1f2ce23fbfd20a273b6f9e3177e256584f1eacc", size = 222888, upload-time = "2025-05-19T14:15:01.568Z" },
{ url = "https://files.pythonhosted.org/packages/c6/67/bc25a8e8bd522935379066950ec4e2277f9b236162a73548a2576d4b9587/multidict-6.4.4-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:87a728af265e08f96b6318ebe3c0f68b9335131f461efab2fc64cc84a44aa6ed", size = 234041, upload-time = "2025-05-19T14:15:03.759Z" },
{ url = "https://files.pythonhosted.org/packages/f1/a0/70c4c2d12857fccbe607b334b7ee28b6b5326c322ca8f73ee54e70d76484/multidict-6.4.4-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:9f193eeda1857f8e8d3079a4abd258f42ef4a4bc87388452ed1e1c4d2b0c8740", size = 231046, upload-time = "2025-05-19T14:15:05.698Z" },
{ url = "https://files.pythonhosted.org/packages/c1/0f/52954601d02d39742aab01d6b92f53c1dd38b2392248154c50797b4df7f1/multidict-6.4.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:be06e73c06415199200e9a2324a11252a3d62030319919cde5e6950ffeccf72e", size = 227106, upload-time = "2025-05-19T14:15:07.124Z" },
{ url = "https://files.pythonhosted.org/packages/af/24/679d83ec4379402d28721790dce818e5d6b9f94ce1323a556fb17fa9996c/multidict-6.4.4-cp312-cp312-win32.whl", hash = "sha256:622f26ea6a7e19b7c48dd9228071f571b2fbbd57a8cd71c061e848f281550e6b", size = 35351, upload-time = "2025-05-19T14:15:08.556Z" },
{ url = "https://files.pythonhosted.org/packages/52/ef/40d98bc5f986f61565f9b345f102409534e29da86a6454eb6b7c00225a13/multidict-6.4.4-cp312-cp312-win_amd64.whl", hash = "sha256:5e2bcda30d5009996ff439e02a9f2b5c3d64a20151d34898c000a6281faa3781", size = 38791, upload-time = "2025-05-19T14:15:09.825Z" },
{ url = "https://files.pythonhosted.org/packages/df/2a/e166d2ffbf4b10131b2d5b0e458f7cee7d986661caceae0de8753042d4b2/multidict-6.4.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:82ffabefc8d84c2742ad19c37f02cde5ec2a1ee172d19944d380f920a340e4b9", size = 64123, upload-time = "2025-05-19T14:15:11.044Z" },
{ url = "https://files.pythonhosted.org/packages/8c/96/e200e379ae5b6f95cbae472e0199ea98913f03d8c9a709f42612a432932c/multidict-6.4.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:6a2f58a66fe2c22615ad26156354005391e26a2f3721c3621504cd87c1ea87bf", size = 38049, upload-time = "2025-05-19T14:15:12.902Z" },
{ url = "https://files.pythonhosted.org/packages/75/fb/47afd17b83f6a8c7fa863c6d23ac5ba6a0e6145ed8a6bcc8da20b2b2c1d2/multidict-6.4.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5883d6ee0fd9d8a48e9174df47540b7545909841ac82354c7ae4cbe9952603bd", size = 37078, upload-time = "2025-05-19T14:15:14.282Z" },
{ url = "https://files.pythonhosted.org/packages/fa/70/1af3143000eddfb19fd5ca5e78393985ed988ac493bb859800fe0914041f/multidict-6.4.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9abcf56a9511653fa1d052bfc55fbe53dbee8f34e68bd6a5a038731b0ca42d15", size = 224097, upload-time = "2025-05-19T14:15:15.566Z" },
{ url = "https://files.pythonhosted.org/packages/b1/39/d570c62b53d4fba844e0378ffbcd02ac25ca423d3235047013ba2f6f60f8/multidict-6.4.4-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:6ed5ae5605d4ad5a049fad2a28bb7193400700ce2f4ae484ab702d1e3749c3f9", size = 230768, upload-time = "2025-05-19T14:15:17.308Z" },
{ url = "https://files.pythonhosted.org/packages/fd/f8/ed88f2c4d06f752b015933055eb291d9bc184936903752c66f68fb3c95a7/multidict-6.4.4-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bbfcb60396f9bcfa63e017a180c3105b8c123a63e9d1428a36544e7d37ca9e20", size = 231331, upload-time = "2025-05-19T14:15:18.73Z" },
{ url = "https://files.pythonhosted.org/packages/9c/6f/8e07cffa32f483ab887b0d56bbd8747ac2c1acd00dc0af6fcf265f4a121e/multidict-6.4.4-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b0f1987787f5f1e2076b59692352ab29a955b09ccc433c1f6b8e8e18666f608b", size = 230169, upload-time = "2025-05-19T14:15:20.179Z" },
{ url = "https://files.pythonhosted.org/packages/e6/2b/5dcf173be15e42f330110875a2668ddfc208afc4229097312212dc9c1236/multidict-6.4.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1d0121ccce8c812047d8d43d691a1ad7641f72c4f730474878a5aeae1b8ead8c", size = 222947, upload-time = "2025-05-19T14:15:21.714Z" },
{ url = "https://files.pythonhosted.org/packages/39/75/4ddcbcebe5ebcd6faa770b629260d15840a5fc07ce8ad295a32e14993726/multidict-6.4.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:83ec4967114295b8afd120a8eec579920c882831a3e4c3331d591a8e5bfbbc0f", size = 215761, upload-time = "2025-05-19T14:15:23.242Z" },
{ url = "https://files.pythonhosted.org/packages/6a/c9/55e998ae45ff15c5608e384206aa71a11e1b7f48b64d166db400b14a3433/multidict-6.4.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:995f985e2e268deaf17867801b859a282e0448633f1310e3704b30616d269d69", size = 227605, upload-time = "2025-05-19T14:15:24.763Z" },
{ url = "https://files.pythonhosted.org/packages/04/49/c2404eac74497503c77071bd2e6f88c7e94092b8a07601536b8dbe99be50/multidict-6.4.4-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:d832c608f94b9f92a0ec8b7e949be7792a642b6e535fcf32f3e28fab69eeb046", size = 226144, upload-time = "2025-05-19T14:15:26.249Z" },
{ url = "https://files.pythonhosted.org/packages/62/c5/0cd0c3c6f18864c40846aa2252cd69d308699cb163e1c0d989ca301684da/multidict-6.4.4-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d21c1212171cf7da703c5b0b7a0e85be23b720818aef502ad187d627316d5645", size = 221100, upload-time = "2025-05-19T14:15:28.303Z" },
{ url = "https://files.pythonhosted.org/packages/71/7b/f2f3887bea71739a046d601ef10e689528d4f911d84da873b6be9194ffea/multidict-6.4.4-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:cbebaa076aaecad3d4bb4c008ecc73b09274c952cf6a1b78ccfd689e51f5a5b0", size = 232731, upload-time = "2025-05-19T14:15:30.263Z" },
{ url = "https://files.pythonhosted.org/packages/e5/b3/d9de808349df97fa75ec1372758701b5800ebad3c46ae377ad63058fbcc6/multidict-6.4.4-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:c93a6fb06cc8e5d3628b2b5fda215a5db01e8f08fc15fadd65662d9b857acbe4", size = 229637, upload-time = "2025-05-19T14:15:33.337Z" },
{ url = "https://files.pythonhosted.org/packages/5e/57/13207c16b615eb4f1745b44806a96026ef8e1b694008a58226c2d8f5f0a5/multidict-6.4.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8cd8f81f1310182362fb0c7898145ea9c9b08a71081c5963b40ee3e3cac589b1", size = 225594, upload-time = "2025-05-19T14:15:34.832Z" },
{ url = "https://files.pythonhosted.org/packages/3a/e4/d23bec2f70221604f5565000632c305fc8f25ba953e8ce2d8a18842b9841/multidict-6.4.4-cp313-cp313-win32.whl", hash = "sha256:3e9f1cd61a0ab857154205fb0b1f3d3ace88d27ebd1409ab7af5096e409614cd", size = 35359, upload-time = "2025-05-19T14:15:36.246Z" },
{ url = "https://files.pythonhosted.org/packages/a7/7a/cfe1a47632be861b627f46f642c1d031704cc1c0f5c0efbde2ad44aa34bd/multidict-6.4.4-cp313-cp313-win_amd64.whl", hash = "sha256:8ffb40b74400e4455785c2fa37eba434269149ec525fc8329858c862e4b35373", size = 38903, upload-time = "2025-05-19T14:15:37.507Z" },
{ url = "https://files.pythonhosted.org/packages/68/7b/15c259b0ab49938a0a1c8f3188572802704a779ddb294edc1b2a72252e7c/multidict-6.4.4-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:6a602151dbf177be2450ef38966f4be3467d41a86c6a845070d12e17c858a156", size = 68895, upload-time = "2025-05-19T14:15:38.856Z" },
{ url = "https://files.pythonhosted.org/packages/f1/7d/168b5b822bccd88142e0a3ce985858fea612404edd228698f5af691020c9/multidict-6.4.4-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0d2b9712211b860d123815a80b859075d86a4d54787e247d7fbee9db6832cf1c", size = 40183, upload-time = "2025-05-19T14:15:40.197Z" },
{ url = "https://files.pythonhosted.org/packages/e0/b7/d4b8d98eb850ef28a4922ba508c31d90715fd9b9da3801a30cea2967130b/multidict-6.4.4-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:d2fa86af59f8fc1972e121ade052145f6da22758f6996a197d69bb52f8204e7e", size = 39592, upload-time = "2025-05-19T14:15:41.508Z" },
{ url = "https://files.pythonhosted.org/packages/18/28/a554678898a19583548e742080cf55d169733baf57efc48c2f0273a08583/multidict-6.4.4-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50855d03e9e4d66eab6947ba688ffb714616f985838077bc4b490e769e48da51", size = 226071, upload-time = "2025-05-19T14:15:42.877Z" },
{ url = "https://files.pythonhosted.org/packages/ee/dc/7ba6c789d05c310e294f85329efac1bf5b450338d2542498db1491a264df/multidict-6.4.4-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:5bce06b83be23225be1905dcdb6b789064fae92499fbc458f59a8c0e68718601", size = 222597, upload-time = "2025-05-19T14:15:44.412Z" },
{ url = "https://files.pythonhosted.org/packages/24/4f/34eadbbf401b03768dba439be0fb94b0d187facae9142821a3d5599ccb3b/multidict-6.4.4-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:66ed0731f8e5dfd8369a883b6e564aca085fb9289aacabd9decd70568b9a30de", size = 228253, upload-time = "2025-05-19T14:15:46.474Z" },
{ url = "https://files.pythonhosted.org/packages/c0/e6/493225a3cdb0d8d80d43a94503fc313536a07dae54a3f030d279e629a2bc/multidict-6.4.4-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:329ae97fc2f56f44d91bc47fe0972b1f52d21c4b7a2ac97040da02577e2daca2", size = 226146, upload-time = "2025-05-19T14:15:48.003Z" },
{ url = "https://files.pythonhosted.org/packages/2f/70/e411a7254dc3bff6f7e6e004303b1b0591358e9f0b7c08639941e0de8bd6/multidict-6.4.4-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c27e5dcf520923d6474d98b96749e6805f7677e93aaaf62656005b8643f907ab", size = 220585, upload-time = "2025-05-19T14:15:49.546Z" },
{ url = "https://files.pythonhosted.org/packages/08/8f/beb3ae7406a619100d2b1fb0022c3bb55a8225ab53c5663648ba50dfcd56/multidict-6.4.4-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:058cc59b9e9b143cc56715e59e22941a5d868c322242278d28123a5d09cdf6b0", size = 212080, upload-time = "2025-05-19T14:15:51.151Z" },
{ url = "https://files.pythonhosted.org/packages/9c/ec/355124e9d3d01cf8edb072fd14947220f357e1c5bc79c88dff89297e9342/multidict-6.4.4-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:69133376bc9a03f8c47343d33f91f74a99c339e8b58cea90433d8e24bb298031", size = 226558, upload-time = "2025-05-19T14:15:52.665Z" },
{ url = "https://files.pythonhosted.org/packages/fd/22/d2b95cbebbc2ada3be3812ea9287dcc9712d7f1a012fad041770afddb2ad/multidict-6.4.4-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:d6b15c55721b1b115c5ba178c77104123745b1417527ad9641a4c5e2047450f0", size = 212168, upload-time = "2025-05-19T14:15:55.279Z" },
{ url = "https://files.pythonhosted.org/packages/4d/c5/62bfc0b2f9ce88326dbe7179f9824a939c6c7775b23b95de777267b9725c/multidict-6.4.4-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:a887b77f51d3d41e6e1a63cf3bc7ddf24de5939d9ff69441387dfefa58ac2e26", size = 217970, upload-time = "2025-05-19T14:15:56.806Z" },
{ url = "https://files.pythonhosted.org/packages/79/74/977cea1aadc43ff1c75d23bd5bc4768a8fac98c14e5878d6ee8d6bab743c/multidict-6.4.4-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:632a3bf8f1787f7ef7d3c2f68a7bde5be2f702906f8b5842ad6da9d974d0aab3", size = 226980, upload-time = "2025-05-19T14:15:58.313Z" },
{ url = "https://files.pythonhosted.org/packages/48/fc/cc4a1a2049df2eb84006607dc428ff237af38e0fcecfdb8a29ca47b1566c/multidict-6.4.4-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:a145c550900deb7540973c5cdb183b0d24bed6b80bf7bddf33ed8f569082535e", size = 220641, upload-time = "2025-05-19T14:15:59.866Z" },
{ url = "https://files.pythonhosted.org/packages/3b/6a/a7444d113ab918701988d4abdde373dbdfd2def7bd647207e2bf645c7eac/multidict-6.4.4-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:cc5d83c6619ca5c9672cb78b39ed8542f1975a803dee2cda114ff73cbb076edd", size = 221728, upload-time = "2025-05-19T14:16:01.535Z" },
{ url = "https://files.pythonhosted.org/packages/2b/b0/fdf4c73ad1c55e0f4dbbf2aa59dd37037334091f9a4961646d2b7ac91a86/multidict-6.4.4-cp313-cp313t-win32.whl", hash = "sha256:3312f63261b9df49be9d57aaa6abf53a6ad96d93b24f9cc16cf979956355ce6e", size = 41913, upload-time = "2025-05-19T14:16:03.199Z" },
{ url = "https://files.pythonhosted.org/packages/8e/92/27989ecca97e542c0d01d05a98a5ae12198a243a9ee12563a0313291511f/multidict-6.4.4-cp313-cp313t-win_amd64.whl", hash = "sha256:ba852168d814b2c73333073e1c7116d9395bea69575a01b0b3c89d2d5a87c8fb", size = 46112, upload-time = "2025-05-19T14:16:04.909Z" },
{ url = "https://files.pythonhosted.org/packages/84/5d/e17845bb0fa76334477d5de38654d27946d5b5d3695443987a094a71b440/multidict-6.4.4-py3-none-any.whl", hash = "sha256:bd4557071b561a8b3b6075c3ce93cf9bfb6182cb241805c3d66ced3b75eff4ac", size = 10481, upload-time = "2025-05-19T14:16:36.024Z" },
]
[[package]]
name = "mypy"
version = "1.16.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "mypy-extensions" },
{ name = "pathspec" },
{ name = "typing-extensions" },
]
sdist = { url = "https://files.pythonhosted.org/packages/d4/38/13c2f1abae94d5ea0354e146b95a1be9b2137a0d506728e0da037c4276f6/mypy-1.16.0.tar.gz", hash = "sha256:84b94283f817e2aa6350a14b4a8fb2a35a53c286f97c9d30f53b63620e7af8ab", size = 3323139, upload-time = "2025-05-29T13:46:12.532Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/24/c4/ff2f79db7075c274fe85b5fff8797d29c6b61b8854c39e3b7feb556aa377/mypy-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9f826aaa7ff8443bac6a494cf743f591488ea940dd360e7dd330e30dd772a5ab", size = 10884498, upload-time = "2025-05-29T13:18:54.066Z" },
{ url = "https://files.pythonhosted.org/packages/02/07/12198e83006235f10f6a7808917376b5d6240a2fd5dce740fe5d2ebf3247/mypy-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:82d056e6faa508501af333a6af192c700b33e15865bda49611e3d7d8358ebea2", size = 10011755, upload-time = "2025-05-29T13:34:00.851Z" },
{ url = "https://files.pythonhosted.org/packages/f1/9b/5fd5801a72b5d6fb6ec0105ea1d0e01ab2d4971893076e558d4b6d6b5f80/mypy-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:089bedc02307c2548eb51f426e085546db1fa7dd87fbb7c9fa561575cf6eb1ff", size = 11800138, upload-time = "2025-05-29T13:32:55.082Z" },
{ url = "https://files.pythonhosted.org/packages/2e/81/a117441ea5dfc3746431e51d78a4aca569c677aa225bca2cc05a7c239b61/mypy-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6a2322896003ba66bbd1318c10d3afdfe24e78ef12ea10e2acd985e9d684a666", size = 12533156, upload-time = "2025-05-29T13:19:12.963Z" },
{ url = "https://files.pythonhosted.org/packages/3f/38/88ec57c6c86014d3f06251e00f397b5a7daa6888884d0abf187e4f5f587f/mypy-1.16.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:021a68568082c5b36e977d54e8f1de978baf401a33884ffcea09bd8e88a98f4c", size = 12742426, upload-time = "2025-05-29T13:20:22.72Z" },
{ url = "https://files.pythonhosted.org/packages/bd/53/7e9d528433d56e6f6f77ccf24af6ce570986c2d98a5839e4c2009ef47283/mypy-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:54066fed302d83bf5128632d05b4ec68412e1f03ef2c300434057d66866cea4b", size = 9478319, upload-time = "2025-05-29T13:21:17.582Z" },
{ url = "https://files.pythonhosted.org/packages/70/cf/158e5055e60ca2be23aec54a3010f89dcffd788732634b344fc9cb1e85a0/mypy-1.16.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c5436d11e89a3ad16ce8afe752f0f373ae9620841c50883dc96f8b8805620b13", size = 11062927, upload-time = "2025-05-29T13:35:52.328Z" },
{ url = "https://files.pythonhosted.org/packages/94/34/cfff7a56be1609f5d10ef386342ce3494158e4d506516890142007e6472c/mypy-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f2622af30bf01d8fc36466231bdd203d120d7a599a6d88fb22bdcb9dbff84090", size = 10083082, upload-time = "2025-05-29T13:35:33.378Z" },
{ url = "https://files.pythonhosted.org/packages/b3/7f/7242062ec6288c33d8ad89574df87c3903d394870e5e6ba1699317a65075/mypy-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d045d33c284e10a038f5e29faca055b90eee87da3fc63b8889085744ebabb5a1", size = 11828306, upload-time = "2025-05-29T13:21:02.164Z" },
{ url = "https://files.pythonhosted.org/packages/6f/5f/b392f7b4f659f5b619ce5994c5c43caab3d80df2296ae54fa888b3d17f5a/mypy-1.16.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b4968f14f44c62e2ec4a038c8797a87315be8df7740dc3ee8d3bfe1c6bf5dba8", size = 12702764, upload-time = "2025-05-29T13:20:42.826Z" },
{ url = "https://files.pythonhosted.org/packages/9b/c0/7646ef3a00fa39ac9bc0938626d9ff29d19d733011be929cfea59d82d136/mypy-1.16.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:eb14a4a871bb8efb1e4a50360d4e3c8d6c601e7a31028a2c79f9bb659b63d730", size = 12896233, upload-time = "2025-05-29T13:18:37.446Z" },
{ url = "https://files.pythonhosted.org/packages/6d/38/52f4b808b3fef7f0ef840ee8ff6ce5b5d77381e65425758d515cdd4f5bb5/mypy-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:bd4e1ebe126152a7bbaa4daedd781c90c8f9643c79b9748caa270ad542f12bec", size = 9565547, upload-time = "2025-05-29T13:20:02.836Z" },
{ url = "https://files.pythonhosted.org/packages/97/9c/ca03bdbefbaa03b264b9318a98950a9c683e06472226b55472f96ebbc53d/mypy-1.16.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a9e056237c89f1587a3be1a3a70a06a698d25e2479b9a2f57325ddaaffc3567b", size = 11059753, upload-time = "2025-05-29T13:18:18.167Z" },
{ url = "https://files.pythonhosted.org/packages/36/92/79a969b8302cfe316027c88f7dc6fee70129490a370b3f6eb11d777749d0/mypy-1.16.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0b07e107affb9ee6ce1f342c07f51552d126c32cd62955f59a7db94a51ad12c0", size = 10073338, upload-time = "2025-05-29T13:19:48.079Z" },
{ url = "https://files.pythonhosted.org/packages/14/9b/a943f09319167da0552d5cd722104096a9c99270719b1afeea60d11610aa/mypy-1.16.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c6fb60cbd85dc65d4d63d37cb5c86f4e3a301ec605f606ae3a9173e5cf34997b", size = 11827764, upload-time = "2025-05-29T13:46:04.47Z" },
{ url = "https://files.pythonhosted.org/packages/ec/64/ff75e71c65a0cb6ee737287c7913ea155845a556c64144c65b811afdb9c7/mypy-1.16.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a7e32297a437cc915599e0578fa6bc68ae6a8dc059c9e009c628e1c47f91495d", size = 12701356, upload-time = "2025-05-29T13:35:13.553Z" },
{ url = "https://files.pythonhosted.org/packages/0a/ad/0e93c18987a1182c350f7a5fab70550852f9fabe30ecb63bfbe51b602074/mypy-1.16.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:afe420c9380ccec31e744e8baff0d406c846683681025db3531b32db56962d52", size = 12900745, upload-time = "2025-05-29T13:17:24.409Z" },
{ url = "https://files.pythonhosted.org/packages/28/5d/036c278d7a013e97e33f08c047fe5583ab4f1fc47c9a49f985f1cdd2a2d7/mypy-1.16.0-cp313-cp313-win_amd64.whl", hash = "sha256:55f9076c6ce55dd3f8cd0c6fff26a008ca8e5131b89d5ba6d86bd3f47e736eeb", size = 9572200, upload-time = "2025-05-29T13:33:44.92Z" },
{ url = "https://files.pythonhosted.org/packages/99/a3/6ed10530dec8e0fdc890d81361260c9ef1f5e5c217ad8c9b21ecb2b8366b/mypy-1.16.0-py3-none-any.whl", hash = "sha256:29e1499864a3888bca5c1542f2d7232c6e586295183320caa95758fc84034031", size = 2265773, upload-time = "2025-05-29T13:35:18.762Z" },
]
[[package]]
name = "mypy-extensions"
version = "1.1.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/a2/6e/371856a3fb9d31ca8dac321cda606860fa4548858c0cc45d9d1d4ca2628b/mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558", size = 6343, upload-time = "2025-04-22T14:54:24.164Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505", size = 4963, upload-time = "2025-04-22T14:54:22.983Z" },
]
[[package]]
name = "nh3"
version = "0.2.21"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/37/30/2f81466f250eb7f591d4d193930df661c8c23e9056bdc78e365b646054d8/nh3-0.2.21.tar.gz", hash = "sha256:4990e7ee6a55490dbf00d61a6f476c9a3258e31e711e13713b2ea7d6616f670e", size = 16581, upload-time = "2025-02-25T13:38:44.619Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/7f/81/b83775687fcf00e08ade6d4605f0be9c4584cb44c4973d9f27b7456a31c9/nh3-0.2.21-cp313-cp313t-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:fcff321bd60c6c5c9cb4ddf2554e22772bb41ebd93ad88171bbbb6f271255286", size = 1297678, upload-time = "2025-02-25T13:37:56.063Z" },
{ url = "https://files.pythonhosted.org/packages/22/ee/d0ad8fb4b5769f073b2df6807f69a5e57ca9cea504b78809921aef460d20/nh3-0.2.21-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:31eedcd7d08b0eae28ba47f43fd33a653b4cdb271d64f1aeda47001618348fde", size = 733774, upload-time = "2025-02-25T13:37:58.419Z" },
{ url = "https://files.pythonhosted.org/packages/ea/76/b450141e2d384ede43fe53953552f1c6741a499a8c20955ad049555cabc8/nh3-0.2.21-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d426d7be1a2f3d896950fe263332ed1662f6c78525b4520c8e9861f8d7f0d243", size = 760012, upload-time = "2025-02-25T13:38:01.017Z" },
{ url = "https://files.pythonhosted.org/packages/97/90/1182275db76cd8fbb1f6bf84c770107fafee0cb7da3e66e416bcb9633da2/nh3-0.2.21-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9d67709bc0d7d1f5797b21db26e7a8b3d15d21c9c5f58ccfe48b5328483b685b", size = 923619, upload-time = "2025-02-25T13:38:02.617Z" },
{ url = "https://files.pythonhosted.org/packages/29/c7/269a7cfbec9693fad8d767c34a755c25ccb8d048fc1dfc7a7d86bc99375c/nh3-0.2.21-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:55823c5ea1f6b267a4fad5de39bc0524d49a47783e1fe094bcf9c537a37df251", size = 1000384, upload-time = "2025-02-25T13:38:04.402Z" },
{ url = "https://files.pythonhosted.org/packages/68/a9/48479dbf5f49ad93f0badd73fbb48b3d769189f04c6c69b0df261978b009/nh3-0.2.21-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:818f2b6df3763e058efa9e69677b5a92f9bc0acff3295af5ed013da544250d5b", size = 918908, upload-time = "2025-02-25T13:38:06.693Z" },
{ url = "https://files.pythonhosted.org/packages/d7/da/0279c118f8be2dc306e56819880b19a1cf2379472e3b79fc8eab44e267e3/nh3-0.2.21-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:b3b5c58161e08549904ac4abd450dacd94ff648916f7c376ae4b2c0652b98ff9", size = 909180, upload-time = "2025-02-25T13:38:10.941Z" },
{ url = "https://files.pythonhosted.org/packages/26/16/93309693f8abcb1088ae143a9c8dbcece9c8f7fb297d492d3918340c41f1/nh3-0.2.21-cp313-cp313t-win32.whl", hash = "sha256:637d4a10c834e1b7d9548592c7aad760611415fcd5bd346f77fd8a064309ae6d", size = 532747, upload-time = "2025-02-25T13:38:12.548Z" },
{ url = "https://files.pythonhosted.org/packages/a2/3a/96eb26c56cbb733c0b4a6a907fab8408ddf3ead5d1b065830a8f6a9c3557/nh3-0.2.21-cp313-cp313t-win_amd64.whl", hash = "sha256:713d16686596e556b65e7f8c58328c2df63f1a7abe1277d87625dcbbc012ef82", size = 528908, upload-time = "2025-02-25T13:38:14.059Z" },
{ url = "https://files.pythonhosted.org/packages/ba/1d/b1ef74121fe325a69601270f276021908392081f4953d50b03cbb38b395f/nh3-0.2.21-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:a772dec5b7b7325780922dd904709f0f5f3a79fbf756de5291c01370f6df0967", size = 1316133, upload-time = "2025-02-25T13:38:16.601Z" },
{ url = "https://files.pythonhosted.org/packages/b8/f2/2c7f79ce6de55b41e7715f7f59b159fd59f6cdb66223c05b42adaee2b645/nh3-0.2.21-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d002b648592bf3033adfd875a48f09b8ecc000abd7f6a8769ed86b6ccc70c759", size = 758328, upload-time = "2025-02-25T13:38:18.972Z" },
{ url = "https://files.pythonhosted.org/packages/6d/ad/07bd706fcf2b7979c51b83d8b8def28f413b090cf0cb0035ee6b425e9de5/nh3-0.2.21-cp38-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2a5174551f95f2836f2ad6a8074560f261cf9740a48437d6151fd2d4d7d617ab", size = 747020, upload-time = "2025-02-25T13:38:20.571Z" },
{ url = "https://files.pythonhosted.org/packages/75/99/06a6ba0b8a0d79c3d35496f19accc58199a1fb2dce5e711a31be7e2c1426/nh3-0.2.21-cp38-abi3-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:b8d55ea1fc7ae3633d758a92aafa3505cd3cc5a6e40470c9164d54dff6f96d42", size = 944878, upload-time = "2025-02-25T13:38:22.204Z" },
{ url = "https://files.pythonhosted.org/packages/79/d4/dc76f5dc50018cdaf161d436449181557373869aacf38a826885192fc587/nh3-0.2.21-cp38-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6ae319f17cd8960d0612f0f0ddff5a90700fa71926ca800e9028e7851ce44a6f", size = 903460, upload-time = "2025-02-25T13:38:25.951Z" },
{ url = "https://files.pythonhosted.org/packages/cd/c3/d4f8037b2ab02ebf5a2e8637bd54736ed3d0e6a2869e10341f8d9085f00e/nh3-0.2.21-cp38-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:63ca02ac6f27fc80f9894409eb61de2cb20ef0a23740c7e29f9ec827139fa578", size = 839369, upload-time = "2025-02-25T13:38:28.174Z" },
{ url = "https://files.pythonhosted.org/packages/11/a9/1cd3c6964ec51daed7b01ca4686a5c793581bf4492cbd7274b3f544c9abe/nh3-0.2.21-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a5f77e62aed5c4acad635239ac1290404c7e940c81abe561fd2af011ff59f585", size = 739036, upload-time = "2025-02-25T13:38:30.539Z" },
{ url = "https://files.pythonhosted.org/packages/fd/04/bfb3ff08d17a8a96325010ae6c53ba41de6248e63cdb1b88ef6369a6cdfc/nh3-0.2.21-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:087ffadfdcd497658c3adc797258ce0f06be8a537786a7217649fc1c0c60c293", size = 768712, upload-time = "2025-02-25T13:38:32.992Z" },
{ url = "https://files.pythonhosted.org/packages/9e/aa/cfc0bf545d668b97d9adea4f8b4598667d2b21b725d83396c343ad12bba7/nh3-0.2.21-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:ac7006c3abd097790e611fe4646ecb19a8d7f2184b882f6093293b8d9b887431", size = 930559, upload-time = "2025-02-25T13:38:35.204Z" },
{ url = "https://files.pythonhosted.org/packages/78/9d/6f5369a801d3a1b02e6a9a097d56bcc2f6ef98cffebf03c4bb3850d8e0f0/nh3-0.2.21-cp38-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:6141caabe00bbddc869665b35fc56a478eb774a8c1dfd6fba9fe1dfdf29e6efa", size = 1008591, upload-time = "2025-02-25T13:38:37.099Z" },
{ url = "https://files.pythonhosted.org/packages/a6/df/01b05299f68c69e480edff608248313cbb5dbd7595c5e048abe8972a57f9/nh3-0.2.21-cp38-abi3-musllinux_1_2_i686.whl", hash = "sha256:20979783526641c81d2f5bfa6ca5ccca3d1e4472474b162c6256745fbfe31cd1", size = 925670, upload-time = "2025-02-25T13:38:38.696Z" },
{ url = "https://files.pythonhosted.org/packages/3d/79/bdba276f58d15386a3387fe8d54e980fb47557c915f5448d8c6ac6f7ea9b/nh3-0.2.21-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:a7ea28cd49293749d67e4fcf326c554c83ec912cd09cd94aa7ec3ab1921c8283", size = 917093, upload-time = "2025-02-25T13:38:40.249Z" },
{ url = "https://files.pythonhosted.org/packages/e7/d8/c6f977a5cd4011c914fb58f5ae573b071d736187ccab31bfb1d539f4af9f/nh3-0.2.21-cp38-abi3-win32.whl", hash = "sha256:6c9c30b8b0d291a7c5ab0967ab200598ba33208f754f2f4920e9343bdd88f79a", size = 537623, upload-time = "2025-02-25T13:38:41.893Z" },
{ url = "https://files.pythonhosted.org/packages/23/fc/8ce756c032c70ae3dd1d48a3552577a325475af2a2f629604b44f571165c/nh3-0.2.21-cp38-abi3-win_amd64.whl", hash = "sha256:bb0014948f04d7976aabae43fcd4cb7f551f9f8ce785a4c9ef66e6c2590f8629", size = 535283, upload-time = "2025-02-25T13:38:43.355Z" },
]
[[package]]
name = "nodeenv"
version = "1.9.1"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/43/16/fc88b08840de0e0a72a2f9d8c6bae36be573e475a6326ae854bcc549fc45/nodeenv-1.9.1.tar.gz", hash = "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f", size = 47437, upload-time = "2024-06-04T18:44:11.171Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/d2/1d/1b658dbd2b9fa9c4c9f32accbfc0205d532c8c6194dc0f2a4c0428e7128a/nodeenv-1.9.1-py2.py3-none-any.whl", hash = "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9", size = 22314, upload-time = "2024-06-04T18:44:08.352Z" },
]
[[package]]
name = "oauthlib"
version = "3.2.2"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/6d/fa/fbf4001037904031639e6bfbfc02badfc7e12f137a8afa254df6c4c8a670/oauthlib-3.2.2.tar.gz", hash = "sha256:9859c40929662bec5d64f34d01c99e093149682a3f38915dc0655d5a633dd918", size = 177352, upload-time = "2022-10-17T20:04:27.471Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/7e/80/cab10959dc1faead58dc8384a781dfbf93cb4d33d50988f7a69f1b7c9bbe/oauthlib-3.2.2-py3-none-any.whl", hash = "sha256:8139f29aac13e25d502680e9e19963e83f16838d48a0d71c287fe40e7067fbca", size = 151688, upload-time = "2022-10-17T20:04:24.037Z" },
]
[[package]]
name = "packaging"
version = "25.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/a1/d4/1fc4078c65507b51b96ca8f8c3ba19e6a61c8253c72794544580a7b6c24d/packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f", size = 165727, upload-time = "2025-04-19T11:48:59.673Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469, upload-time = "2025-04-19T11:48:57.875Z" },
]
[[package]]
name = "pathspec"
version = "0.12.1"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/ca/bc/f35b8446f4531a7cb215605d100cd88b7ac6f44ab3fc94870c120ab3adbf/pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712", size = 51043, upload-time = "2023-12-10T22:30:45Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", size = 31191, upload-time = "2023-12-10T22:30:43.14Z" },
]
[[package]]
name = "platformdirs"
version = "4.3.8"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/fe/8b/3c73abc9c759ecd3f1f7ceff6685840859e8070c4d947c93fae71f6a0bf2/platformdirs-4.3.8.tar.gz", hash = "sha256:3d512d96e16bcb959a814c9f348431070822a6496326a4be0911c40b5a74c2bc", size = 21362, upload-time = "2025-05-07T22:47:42.121Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/fe/39/979e8e21520d4e47a0bbe349e2713c0aac6f3d853d0e5b34d76206c439aa/platformdirs-4.3.8-py3-none-any.whl", hash = "sha256:ff7059bb7eb1179e2685604f4aaf157cfd9535242bd23742eadc3c13542139b4", size = 18567, upload-time = "2025-05-07T22:47:40.376Z" },
]
[[package]]
name = "pluggy"
version = "1.6.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" },
]
[[package]]
name = "pre-commit"
version = "4.2.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "cfgv" },
{ name = "identify" },
{ name = "nodeenv" },
{ name = "pyyaml" },
{ name = "virtualenv" },
]
sdist = { url = "https://files.pythonhosted.org/packages/08/39/679ca9b26c7bb2999ff122d50faa301e49af82ca9c066ec061cfbc0c6784/pre_commit-4.2.0.tar.gz", hash = "sha256:601283b9757afd87d40c4c4a9b2b5de9637a8ea02eaff7adc2d0fb4e04841146", size = 193424, upload-time = "2025-03-18T21:35:20.987Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/88/74/a88bf1b1efeae488a0c0b7bdf71429c313722d1fc0f377537fbe554e6180/pre_commit-4.2.0-py2.py3-none-any.whl", hash = "sha256:a009ca7205f1eb497d10b845e52c838a98b6cdd2102a6c8e4540e94ee75c58bd", size = 220707, upload-time = "2025-03-18T21:35:19.343Z" },
]
[[package]]
name = "propcache"
version = "0.3.1"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/07/c8/fdc6686a986feae3541ea23dcaa661bd93972d3940460646c6bb96e21c40/propcache-0.3.1.tar.gz", hash = "sha256:40d980c33765359098837527e18eddefc9a24cea5b45e078a7f3bb5b032c6ecf", size = 43651, upload-time = "2025-03-26T03:06:12.05Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/90/0f/5a5319ee83bd651f75311fcb0c492c21322a7fc8f788e4eef23f44243427/propcache-0.3.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7f30241577d2fef2602113b70ef7231bf4c69a97e04693bde08ddab913ba0ce5", size = 80243, upload-time = "2025-03-26T03:04:01.912Z" },
{ url = "https://files.pythonhosted.org/packages/ce/84/3db5537e0879942783e2256616ff15d870a11d7ac26541336fe1b673c818/propcache-0.3.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:43593c6772aa12abc3af7784bff4a41ffa921608dd38b77cf1dfd7f5c4e71371", size = 46503, upload-time = "2025-03-26T03:04:03.704Z" },
{ url = "https://files.pythonhosted.org/packages/e2/c8/b649ed972433c3f0d827d7f0cf9ea47162f4ef8f4fe98c5f3641a0bc63ff/propcache-0.3.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a75801768bbe65499495660b777e018cbe90c7980f07f8aa57d6be79ea6f71da", size = 45934, upload-time = "2025-03-26T03:04:05.257Z" },
{ url = "https://files.pythonhosted.org/packages/59/f9/4c0a5cf6974c2c43b1a6810c40d889769cc8f84cea676cbe1e62766a45f8/propcache-0.3.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f6f1324db48f001c2ca26a25fa25af60711e09b9aaf4b28488602776f4f9a744", size = 233633, upload-time = "2025-03-26T03:04:07.044Z" },
{ url = "https://files.pythonhosted.org/packages/e7/64/66f2f4d1b4f0007c6e9078bd95b609b633d3957fe6dd23eac33ebde4b584/propcache-0.3.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5cdb0f3e1eb6dfc9965d19734d8f9c481b294b5274337a8cb5cb01b462dcb7e0", size = 241124, upload-time = "2025-03-26T03:04:08.676Z" },
{ url = "https://files.pythonhosted.org/packages/aa/bf/7b8c9fd097d511638fa9b6af3d986adbdf567598a567b46338c925144c1b/propcache-0.3.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1eb34d90aac9bfbced9a58b266f8946cb5935869ff01b164573a7634d39fbcb5", size = 240283, upload-time = "2025-03-26T03:04:10.172Z" },
{ url = "https://files.pythonhosted.org/packages/fa/c9/e85aeeeaae83358e2a1ef32d6ff50a483a5d5248bc38510d030a6f4e2816/propcache-0.3.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f35c7070eeec2cdaac6fd3fe245226ed2a6292d3ee8c938e5bb645b434c5f256", size = 232498, upload-time = "2025-03-26T03:04:11.616Z" },
{ url = "https://files.pythonhosted.org/packages/8e/66/acb88e1f30ef5536d785c283af2e62931cb934a56a3ecf39105887aa8905/propcache-0.3.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b23c11c2c9e6d4e7300c92e022046ad09b91fd00e36e83c44483df4afa990073", size = 221486, upload-time = "2025-03-26T03:04:13.102Z" },
{ url = "https://files.pythonhosted.org/packages/f5/f9/233ddb05ffdcaee4448508ee1d70aa7deff21bb41469ccdfcc339f871427/propcache-0.3.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:3e19ea4ea0bf46179f8a3652ac1426e6dcbaf577ce4b4f65be581e237340420d", size = 222675, upload-time = "2025-03-26T03:04:14.658Z" },
{ url = "https://files.pythonhosted.org/packages/98/b8/eb977e28138f9e22a5a789daf608d36e05ed93093ef12a12441030da800a/propcache-0.3.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:bd39c92e4c8f6cbf5f08257d6360123af72af9f4da75a690bef50da77362d25f", size = 215727, upload-time = "2025-03-26T03:04:16.207Z" },
{ url = "https://files.pythonhosted.org/packages/89/2d/5f52d9c579f67b8ee1edd9ec073c91b23cc5b7ff7951a1e449e04ed8fdf3/propcache-0.3.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:b0313e8b923b3814d1c4a524c93dfecea5f39fa95601f6a9b1ac96cd66f89ea0", size = 217878, upload-time = "2025-03-26T03:04:18.11Z" },
{ url = "https://files.pythonhosted.org/packages/7a/fd/5283e5ed8a82b00c7a989b99bb6ea173db1ad750bf0bf8dff08d3f4a4e28/propcache-0.3.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:e861ad82892408487be144906a368ddbe2dc6297074ade2d892341b35c59844a", size = 230558, upload-time = "2025-03-26T03:04:19.562Z" },
{ url = "https://files.pythonhosted.org/packages/90/38/ab17d75938ef7ac87332c588857422ae126b1c76253f0f5b1242032923ca/propcache-0.3.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:61014615c1274df8da5991a1e5da85a3ccb00c2d4701ac6f3383afd3ca47ab0a", size = 233754, upload-time = "2025-03-26T03:04:21.065Z" },
{ url = "https://files.pythonhosted.org/packages/06/5d/3b921b9c60659ae464137508d3b4c2b3f52f592ceb1964aa2533b32fcf0b/propcache-0.3.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:71ebe3fe42656a2328ab08933d420df5f3ab121772eef78f2dc63624157f0ed9", size = 226088, upload-time = "2025-03-26T03:04:22.718Z" },
{ url = "https://files.pythonhosted.org/packages/54/6e/30a11f4417d9266b5a464ac5a8c5164ddc9dd153dfa77bf57918165eb4ae/propcache-0.3.1-cp311-cp311-win32.whl", hash = "sha256:58aa11f4ca8b60113d4b8e32d37e7e78bd8af4d1a5b5cb4979ed856a45e62005", size = 40859, upload-time = "2025-03-26T03:04:24.039Z" },
{ url = "https://files.pythonhosted.org/packages/1d/3a/8a68dd867da9ca2ee9dfd361093e9cb08cb0f37e5ddb2276f1b5177d7731/propcache-0.3.1-cp311-cp311-win_amd64.whl", hash = "sha256:9532ea0b26a401264b1365146c440a6d78269ed41f83f23818d4b79497aeabe7", size = 45153, upload-time = "2025-03-26T03:04:25.211Z" },
{ url = "https://files.pythonhosted.org/packages/41/aa/ca78d9be314d1e15ff517b992bebbed3bdfef5b8919e85bf4940e57b6137/propcache-0.3.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:f78eb8422acc93d7b69964012ad7048764bb45a54ba7a39bb9e146c72ea29723", size = 80430, upload-time = "2025-03-26T03:04:26.436Z" },
{ url = "https://files.pythonhosted.org/packages/1a/d8/f0c17c44d1cda0ad1979af2e593ea290defdde9eaeb89b08abbe02a5e8e1/propcache-0.3.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:89498dd49c2f9a026ee057965cdf8192e5ae070ce7d7a7bd4b66a8e257d0c976", size = 46637, upload-time = "2025-03-26T03:04:27.932Z" },
{ url = "https://files.pythonhosted.org/packages/ae/bd/c1e37265910752e6e5e8a4c1605d0129e5b7933c3dc3cf1b9b48ed83b364/propcache-0.3.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:09400e98545c998d57d10035ff623266927cb784d13dd2b31fd33b8a5316b85b", size = 46123, upload-time = "2025-03-26T03:04:30.659Z" },
{ url = "https://files.pythonhosted.org/packages/d4/b0/911eda0865f90c0c7e9f0415d40a5bf681204da5fd7ca089361a64c16b28/propcache-0.3.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aa8efd8c5adc5a2c9d3b952815ff8f7710cefdcaf5f2c36d26aff51aeca2f12f", size = 243031, upload-time = "2025-03-26T03:04:31.977Z" },
{ url = "https://files.pythonhosted.org/packages/0a/06/0da53397c76a74271621807265b6eb61fb011451b1ddebf43213df763669/propcache-0.3.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c2fe5c910f6007e716a06d269608d307b4f36e7babee5f36533722660e8c4a70", size = 249100, upload-time = "2025-03-26T03:04:33.45Z" },
{ url = "https://files.pythonhosted.org/packages/f1/eb/13090e05bf6b963fc1653cdc922133ced467cb4b8dab53158db5a37aa21e/propcache-0.3.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a0ab8cf8cdd2194f8ff979a43ab43049b1df0b37aa64ab7eca04ac14429baeb7", size = 250170, upload-time = "2025-03-26T03:04:35.542Z" },
{ url = "https://files.pythonhosted.org/packages/3b/4c/f72c9e1022b3b043ec7dc475a0f405d4c3e10b9b1d378a7330fecf0652da/propcache-0.3.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:563f9d8c03ad645597b8d010ef4e9eab359faeb11a0a2ac9f7b4bc8c28ebef25", size = 245000, upload-time = "2025-03-26T03:04:37.501Z" },
{ url = "https://files.pythonhosted.org/packages/e8/fd/970ca0e22acc829f1adf5de3724085e778c1ad8a75bec010049502cb3a86/propcache-0.3.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fb6e0faf8cb6b4beea5d6ed7b5a578254c6d7df54c36ccd3d8b3eb00d6770277", size = 230262, upload-time = "2025-03-26T03:04:39.532Z" },
{ url = "https://files.pythonhosted.org/packages/c4/42/817289120c6b9194a44f6c3e6b2c3277c5b70bbad39e7df648f177cc3634/propcache-0.3.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1c5c7ab7f2bb3f573d1cb921993006ba2d39e8621019dffb1c5bc94cdbae81e8", size = 236772, upload-time = "2025-03-26T03:04:41.109Z" },
{ url = "https://files.pythonhosted.org/packages/7c/9c/3b3942b302badd589ad6b672da3ca7b660a6c2f505cafd058133ddc73918/propcache-0.3.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:050b571b2e96ec942898f8eb46ea4bfbb19bd5502424747e83badc2d4a99a44e", size = 231133, upload-time = "2025-03-26T03:04:42.544Z" },
{ url = "https://files.pythonhosted.org/packages/98/a1/75f6355f9ad039108ff000dfc2e19962c8dea0430da9a1428e7975cf24b2/propcache-0.3.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:e1c4d24b804b3a87e9350f79e2371a705a188d292fd310e663483af6ee6718ee", size = 230741, upload-time = "2025-03-26T03:04:44.06Z" },
{ url = "https://files.pythonhosted.org/packages/67/0c/3e82563af77d1f8731132166da69fdfd95e71210e31f18edce08a1eb11ea/propcache-0.3.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:e4fe2a6d5ce975c117a6bb1e8ccda772d1e7029c1cca1acd209f91d30fa72815", size = 244047, upload-time = "2025-03-26T03:04:45.983Z" },
{ url = "https://files.pythonhosted.org/packages/f7/50/9fb7cca01532a08c4d5186d7bb2da6c4c587825c0ae134b89b47c7d62628/propcache-0.3.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:feccd282de1f6322f56f6845bf1207a537227812f0a9bf5571df52bb418d79d5", size = 246467, upload-time = "2025-03-26T03:04:47.699Z" },
{ url = "https://files.pythonhosted.org/packages/a9/02/ccbcf3e1c604c16cc525309161d57412c23cf2351523aedbb280eb7c9094/propcache-0.3.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ec314cde7314d2dd0510c6787326bbffcbdc317ecee6b7401ce218b3099075a7", size = 241022, upload-time = "2025-03-26T03:04:49.195Z" },
{ url = "https://files.pythonhosted.org/packages/db/19/e777227545e09ca1e77a6e21274ae9ec45de0f589f0ce3eca2a41f366220/propcache-0.3.1-cp312-cp312-win32.whl", hash = "sha256:7d2d5a0028d920738372630870e7d9644ce437142197f8c827194fca404bf03b", size = 40647, upload-time = "2025-03-26T03:04:50.595Z" },
{ url = "https://files.pythonhosted.org/packages/24/bb/3b1b01da5dd04c77a204c84e538ff11f624e31431cfde7201d9110b092b1/propcache-0.3.1-cp312-cp312-win_amd64.whl", hash = "sha256:88c423efef9d7a59dae0614eaed718449c09a5ac79a5f224a8b9664d603f04a3", size = 44784, upload-time = "2025-03-26T03:04:51.791Z" },
{ url = "https://files.pythonhosted.org/packages/58/60/f645cc8b570f99be3cf46714170c2de4b4c9d6b827b912811eff1eb8a412/propcache-0.3.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:f1528ec4374617a7a753f90f20e2f551121bb558fcb35926f99e3c42367164b8", size = 77865, upload-time = "2025-03-26T03:04:53.406Z" },
{ url = "https://files.pythonhosted.org/packages/6f/d4/c1adbf3901537582e65cf90fd9c26fde1298fde5a2c593f987112c0d0798/propcache-0.3.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:dc1915ec523b3b494933b5424980831b636fe483d7d543f7afb7b3bf00f0c10f", size = 45452, upload-time = "2025-03-26T03:04:54.624Z" },
{ url = "https://files.pythonhosted.org/packages/d1/b5/fe752b2e63f49f727c6c1c224175d21b7d1727ce1d4873ef1c24c9216830/propcache-0.3.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a110205022d077da24e60b3df8bcee73971be9575dec5573dd17ae5d81751111", size = 44800, upload-time = "2025-03-26T03:04:55.844Z" },
{ url = "https://files.pythonhosted.org/packages/62/37/fc357e345bc1971e21f76597028b059c3d795c5ca7690d7a8d9a03c9708a/propcache-0.3.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d249609e547c04d190e820d0d4c8ca03ed4582bcf8e4e160a6969ddfb57b62e5", size = 225804, upload-time = "2025-03-26T03:04:57.158Z" },
{ url = "https://files.pythonhosted.org/packages/0d/f1/16e12c33e3dbe7f8b737809bad05719cff1dccb8df4dafbcff5575002c0e/propcache-0.3.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5ced33d827625d0a589e831126ccb4f5c29dfdf6766cac441d23995a65825dcb", size = 230650, upload-time = "2025-03-26T03:04:58.61Z" },
{ url = "https://files.pythonhosted.org/packages/3e/a2/018b9f2ed876bf5091e60153f727e8f9073d97573f790ff7cdf6bc1d1fb8/propcache-0.3.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4114c4ada8f3181af20808bedb250da6bae56660e4b8dfd9cd95d4549c0962f7", size = 234235, upload-time = "2025-03-26T03:05:00.599Z" },
{ url = "https://files.pythonhosted.org/packages/45/5f/3faee66fc930dfb5da509e34c6ac7128870631c0e3582987fad161fcb4b1/propcache-0.3.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:975af16f406ce48f1333ec5e912fe11064605d5c5b3f6746969077cc3adeb120", size = 228249, upload-time = "2025-03-26T03:05:02.11Z" },
{ url = "https://files.pythonhosted.org/packages/62/1e/a0d5ebda5da7ff34d2f5259a3e171a94be83c41eb1e7cd21a2105a84a02e/propcache-0.3.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a34aa3a1abc50740be6ac0ab9d594e274f59960d3ad253cd318af76b996dd654", size = 214964, upload-time = "2025-03-26T03:05:03.599Z" },
{ url = "https://files.pythonhosted.org/packages/db/a0/d72da3f61ceab126e9be1f3bc7844b4e98c6e61c985097474668e7e52152/propcache-0.3.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9cec3239c85ed15bfaded997773fdad9fb5662b0a7cbc854a43f291eb183179e", size = 222501, upload-time = "2025-03-26T03:05:05.107Z" },
{ url = "https://files.pythonhosted.org/packages/18/6d/a008e07ad7b905011253adbbd97e5b5375c33f0b961355ca0a30377504ac/propcache-0.3.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:05543250deac8e61084234d5fc54f8ebd254e8f2b39a16b1dce48904f45b744b", size = 217917, upload-time = "2025-03-26T03:05:06.59Z" },
{ url = "https://files.pythonhosted.org/packages/98/37/02c9343ffe59e590e0e56dc5c97d0da2b8b19fa747ebacf158310f97a79a/propcache-0.3.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:5cb5918253912e088edbf023788de539219718d3b10aef334476b62d2b53de53", size = 217089, upload-time = "2025-03-26T03:05:08.1Z" },
{ url = "https://files.pythonhosted.org/packages/53/1b/d3406629a2c8a5666d4674c50f757a77be119b113eedd47b0375afdf1b42/propcache-0.3.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:f3bbecd2f34d0e6d3c543fdb3b15d6b60dd69970c2b4c822379e5ec8f6f621d5", size = 228102, upload-time = "2025-03-26T03:05:09.982Z" },
{ url = "https://files.pythonhosted.org/packages/cd/a7/3664756cf50ce739e5f3abd48febc0be1a713b1f389a502ca819791a6b69/propcache-0.3.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:aca63103895c7d960a5b9b044a83f544b233c95e0dcff114389d64d762017af7", size = 230122, upload-time = "2025-03-26T03:05:11.408Z" },
{ url = "https://files.pythonhosted.org/packages/35/36/0bbabaacdcc26dac4f8139625e930f4311864251276033a52fd52ff2a274/propcache-0.3.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5a0a9898fdb99bf11786265468571e628ba60af80dc3f6eb89a3545540c6b0ef", size = 226818, upload-time = "2025-03-26T03:05:12.909Z" },
{ url = "https://files.pythonhosted.org/packages/cc/27/4e0ef21084b53bd35d4dae1634b6d0bad35e9c58ed4f032511acca9d4d26/propcache-0.3.1-cp313-cp313-win32.whl", hash = "sha256:3a02a28095b5e63128bcae98eb59025924f121f048a62393db682f049bf4ac24", size = 40112, upload-time = "2025-03-26T03:05:14.289Z" },
{ url = "https://files.pythonhosted.org/packages/a6/2c/a54614d61895ba6dd7ac8f107e2b2a0347259ab29cbf2ecc7b94fa38c4dc/propcache-0.3.1-cp313-cp313-win_amd64.whl", hash = "sha256:813fbb8b6aea2fc9659815e585e548fe706d6f663fa73dff59a1677d4595a037", size = 44034, upload-time = "2025-03-26T03:05:15.616Z" },
{ url = "https://files.pythonhosted.org/packages/5a/a8/0a4fd2f664fc6acc66438370905124ce62e84e2e860f2557015ee4a61c7e/propcache-0.3.1-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:a444192f20f5ce8a5e52761a031b90f5ea6288b1eef42ad4c7e64fef33540b8f", size = 82613, upload-time = "2025-03-26T03:05:16.913Z" },
{ url = "https://files.pythonhosted.org/packages/4d/e5/5ef30eb2cd81576256d7b6caaa0ce33cd1d2c2c92c8903cccb1af1a4ff2f/propcache-0.3.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0fbe94666e62ebe36cd652f5fc012abfbc2342de99b523f8267a678e4dfdee3c", size = 47763, upload-time = "2025-03-26T03:05:18.607Z" },
{ url = "https://files.pythonhosted.org/packages/87/9a/87091ceb048efeba4d28e903c0b15bcc84b7c0bf27dc0261e62335d9b7b8/propcache-0.3.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:f011f104db880f4e2166bcdcf7f58250f7a465bc6b068dc84c824a3d4a5c94dc", size = 47175, upload-time = "2025-03-26T03:05:19.85Z" },
{ url = "https://files.pythonhosted.org/packages/3e/2f/854e653c96ad1161f96194c6678a41bbb38c7947d17768e8811a77635a08/propcache-0.3.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e584b6d388aeb0001d6d5c2bd86b26304adde6d9bb9bfa9c4889805021b96de", size = 292265, upload-time = "2025-03-26T03:05:21.654Z" },
{ url = "https://files.pythonhosted.org/packages/40/8d/090955e13ed06bc3496ba4a9fb26c62e209ac41973cb0d6222de20c6868f/propcache-0.3.1-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8a17583515a04358b034e241f952f1715243482fc2c2945fd99a1b03a0bd77d6", size = 294412, upload-time = "2025-03-26T03:05:23.147Z" },
{ url = "https://files.pythonhosted.org/packages/39/e6/d51601342e53cc7582449e6a3c14a0479fab2f0750c1f4d22302e34219c6/propcache-0.3.1-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5aed8d8308215089c0734a2af4f2e95eeb360660184ad3912686c181e500b2e7", size = 294290, upload-time = "2025-03-26T03:05:24.577Z" },
{ url = "https://files.pythonhosted.org/packages/3b/4d/be5f1a90abc1881884aa5878989a1acdafd379a91d9c7e5e12cef37ec0d7/propcache-0.3.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d8e309ff9a0503ef70dc9a0ebd3e69cf7b3894c9ae2ae81fc10943c37762458", size = 282926, upload-time = "2025-03-26T03:05:26.459Z" },
{ url = "https://files.pythonhosted.org/packages/57/2b/8f61b998c7ea93a2b7eca79e53f3e903db1787fca9373af9e2cf8dc22f9d/propcache-0.3.1-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b655032b202028a582d27aeedc2e813299f82cb232f969f87a4fde491a233f11", size = 267808, upload-time = "2025-03-26T03:05:28.188Z" },
{ url = "https://files.pythonhosted.org/packages/11/1c/311326c3dfce59c58a6098388ba984b0e5fb0381ef2279ec458ef99bd547/propcache-0.3.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9f64d91b751df77931336b5ff7bafbe8845c5770b06630e27acd5dbb71e1931c", size = 290916, upload-time = "2025-03-26T03:05:29.757Z" },
{ url = "https://files.pythonhosted.org/packages/4b/74/91939924b0385e54dc48eb2e4edd1e4903ffd053cf1916ebc5347ac227f7/propcache-0.3.1-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:19a06db789a4bd896ee91ebc50d059e23b3639c25d58eb35be3ca1cbe967c3bf", size = 262661, upload-time = "2025-03-26T03:05:31.472Z" },
{ url = "https://files.pythonhosted.org/packages/c2/d7/e6079af45136ad325c5337f5dd9ef97ab5dc349e0ff362fe5c5db95e2454/propcache-0.3.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:bef100c88d8692864651b5f98e871fb090bd65c8a41a1cb0ff2322db39c96c27", size = 264384, upload-time = "2025-03-26T03:05:32.984Z" },
{ url = "https://files.pythonhosted.org/packages/b7/d5/ba91702207ac61ae6f1c2da81c5d0d6bf6ce89e08a2b4d44e411c0bbe867/propcache-0.3.1-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:87380fb1f3089d2a0b8b00f006ed12bd41bd858fabfa7330c954c70f50ed8757", size = 291420, upload-time = "2025-03-26T03:05:34.496Z" },
{ url = "https://files.pythonhosted.org/packages/58/70/2117780ed7edcd7ba6b8134cb7802aada90b894a9810ec56b7bb6018bee7/propcache-0.3.1-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:e474fc718e73ba5ec5180358aa07f6aded0ff5f2abe700e3115c37d75c947e18", size = 290880, upload-time = "2025-03-26T03:05:36.256Z" },
{ url = "https://files.pythonhosted.org/packages/4a/1f/ecd9ce27710021ae623631c0146719280a929d895a095f6d85efb6a0be2e/propcache-0.3.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:17d1c688a443355234f3c031349da69444be052613483f3e4158eef751abcd8a", size = 287407, upload-time = "2025-03-26T03:05:37.799Z" },
{ url = "https://files.pythonhosted.org/packages/3e/66/2e90547d6b60180fb29e23dc87bd8c116517d4255240ec6d3f7dc23d1926/propcache-0.3.1-cp313-cp313t-win32.whl", hash = "sha256:359e81a949a7619802eb601d66d37072b79b79c2505e6d3fd8b945538411400d", size = 42573, upload-time = "2025-03-26T03:05:39.193Z" },
{ url = "https://files.pythonhosted.org/packages/cb/8f/50ad8599399d1861b4d2b6b45271f0ef6af1b09b0a2386a46dbaf19c9535/propcache-0.3.1-cp313-cp313t-win_amd64.whl", hash = "sha256:e7fb9a84c9abbf2b2683fa3e7b0d7da4d8ecf139a1c635732a8bda29c5214b0e", size = 46757, upload-time = "2025-03-26T03:05:40.811Z" },
{ url = "https://files.pythonhosted.org/packages/b8/d3/c3cb8f1d6ae3b37f83e1de806713a9b3642c5895f0215a62e1a4bd6e5e34/propcache-0.3.1-py3-none-any.whl", hash = "sha256:9a8ecf38de50a7f518c21568c80f985e776397b902f1ce0b01f799aba1608b40", size = 12376, upload-time = "2025-03-26T03:06:10.5Z" },
]
[[package]]
name = "pyatmo"
source = { editable = "." }
dependencies = [
{ name = "aiohttp" },
{ name = "oauthlib" },
{ name = "requests" },
{ name = "requests-oauthlib" },
]
[package.dev-dependencies]
dev = [
{ name = "anyio" },
{ name = "black" },
{ name = "codespell" },
{ name = "docutils" },
{ name = "mypy" },
{ name = "pre-commit" },
{ name = "pytest" },
{ name = "pytest-asyncio" },
{ name = "pytest-cov" },
{ name = "pytest-mock" },
{ name = "requests-mock" },
{ name = "ruff" },
{ name = "time-machine" },
{ name = "tox-uv" },
{ name = "twine" },
]
[package.metadata]
requires-dist = [
{ name = "aiohttp", specifier = ">=3.7.4,<4.0.0" },
{ name = "oauthlib", specifier = "~=3.1" },
{ name = "requests", specifier = "~=2.24" },
{ name = "requests-oauthlib", specifier = ">=1.3,<3.0" },
]
[package.metadata.requires-dev]
dev = [
{ name = "anyio", specifier = ">=4.3.0" },
{ name = "black", specifier = ">=24.8.0" },
{ name = "codespell", specifier = ">=2.3.0" },
{ name = "docutils", specifier = ">=0.21.2" },
{ name = "mypy", specifier = ">=1.11.2" },
{ name = "pre-commit", specifier = ">=3.8.0" },
{ name = "pytest", specifier = ">=8.3.3" },
{ name = "pytest-asyncio", specifier = ">=0.24.0" },
{ name = "pytest-cov", specifier = ">=5.0.0" },
{ name = "pytest-mock", specifier = ">=3.14.0" },
{ name = "requests-mock", specifier = ">=1.12.1" },
{ name = "ruff", specifier = ">=0.6.4" },
{ name = "time-machine", specifier = ">=2.15.0" },
{ name = "tox-uv", specifier = ">=1.25.0" },
{ name = "twine", specifier = ">=6.1.0" },
]
[[package]]
name = "pycparser"
version = "2.22"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/1d/b2/31537cf4b1ca988837256c910a668b553fceb8f069bedc4b1c826024b52c/pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6", size = 172736, upload-time = "2024-03-30T13:22:22.564Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc", size = 117552, upload-time = "2024-03-30T13:22:20.476Z" },
]
[[package]]
name = "pygments"
version = "2.19.1"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/7c/2d/c3338d48ea6cc0feb8446d8e6937e1408088a72a39937982cc6111d17f84/pygments-2.19.1.tar.gz", hash = "sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f", size = 4968581, upload-time = "2025-01-06T17:26:30.443Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/8a/0b/9fcc47d19c48b59121088dd6da2488a49d5f72dacf8262e2790a1d2c7d15/pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c", size = 1225293, upload-time = "2025-01-06T17:26:25.553Z" },
]
[[package]]
name = "pyproject-api"
version = "1.9.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "packaging" },
]
sdist = { url = "https://files.pythonhosted.org/packages/19/fd/437901c891f58a7b9096511750247535e891d2d5a5a6eefbc9386a2b41d5/pyproject_api-1.9.1.tar.gz", hash = "sha256:43c9918f49daab37e302038fc1aed54a8c7a91a9fa935d00b9a485f37e0f5335", size = 22710, upload-time = "2025-05-12T14:41:58.025Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/ef/e6/c293c06695d4a3ab0260ef124a74ebadba5f4c511ce3a4259e976902c00b/pyproject_api-1.9.1-py3-none-any.whl", hash = "sha256:7d6238d92f8962773dd75b5f0c4a6a27cce092a14b623b811dba656f3b628948", size = 13158, upload-time = "2025-05-12T14:41:56.217Z" },
]
[[package]]
name = "pytest"
version = "8.4.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "colorama", marker = "sys_platform == 'win32'" },
{ name = "iniconfig" },
{ name = "packaging" },
{ name = "pluggy" },
{ name = "pygments" },
]
sdist = { url = "https://files.pythonhosted.org/packages/fb/aa/405082ce2749be5398045152251ac69c0f3578c7077efc53431303af97ce/pytest-8.4.0.tar.gz", hash = "sha256:14d920b48472ea0dbf68e45b96cd1ffda4705f33307dcc86c676c1b5104838a6", size = 1515232, upload-time = "2025-06-02T17:36:30.03Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/2f/de/afa024cbe022b1b318a3d224125aa24939e99b4ff6f22e0ba639a2eaee47/pytest-8.4.0-py3-none-any.whl", hash = "sha256:f40f825768ad76c0977cbacdf1fd37c6f7a468e460ea6a0636078f8972d4517e", size = 363797, upload-time = "2025-06-02T17:36:27.859Z" },
]
[[package]]
name = "pytest-asyncio"
version = "1.0.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "pytest" },
]
sdist = { url = "https://files.pythonhosted.org/packages/d0/d4/14f53324cb1a6381bef29d698987625d80052bb33932d8e7cbf9b337b17c/pytest_asyncio-1.0.0.tar.gz", hash = "sha256:d15463d13f4456e1ead2594520216b225a16f781e144f8fdf6c5bb4667c48b3f", size = 46960, upload-time = "2025-05-26T04:54:40.484Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/30/05/ce271016e351fddc8399e546f6e23761967ee09c8c568bbfbecb0c150171/pytest_asyncio-1.0.0-py3-none-any.whl", hash = "sha256:4f024da9f1ef945e680dc68610b52550e36590a67fd31bb3b4943979a1f90ef3", size = 15976, upload-time = "2025-05-26T04:54:39.035Z" },
]
[[package]]
name = "pytest-cov"
version = "6.1.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "coverage", extra = ["toml"] },
{ name = "pytest" },
]
sdist = { url = "https://files.pythonhosted.org/packages/25/69/5f1e57f6c5a39f81411b550027bf72842c4567ff5fd572bed1edc9e4b5d9/pytest_cov-6.1.1.tar.gz", hash = "sha256:46935f7aaefba760e716c2ebfbe1c216240b9592966e7da99ea8292d4d3e2a0a", size = 66857, upload-time = "2025-04-05T14:07:51.592Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/28/d0/def53b4a790cfb21483016430ed828f64830dd981ebe1089971cd10cab25/pytest_cov-6.1.1-py3-none-any.whl", hash = "sha256:bddf29ed2d0ab6f4df17b4c55b0a657287db8684af9c42ea546b21b1041b3dde", size = 23841, upload-time = "2025-04-05T14:07:49.641Z" },
]
[[package]]
name = "pytest-mock"
version = "3.14.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "pytest" },
]
sdist = { url = "https://files.pythonhosted.org/packages/71/28/67172c96ba684058a4d24ffe144d64783d2a270d0af0d9e792737bddc75c/pytest_mock-3.14.1.tar.gz", hash = "sha256:159e9edac4c451ce77a5cdb9fc5d1100708d2dd4ba3c3df572f14097351af80e", size = 33241, upload-time = "2025-05-26T13:58:45.167Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/b2/05/77b60e520511c53d1c1ca75f1930c7dd8e971d0c4379b7f4b3f9644685ba/pytest_mock-3.14.1-py3-none-any.whl", hash = "sha256:178aefcd11307d874b4cd3100344e7e2d888d9791a6a1d9bfe90fbc1b74fd1d0", size = 9923, upload-time = "2025-05-26T13:58:43.487Z" },
]
[[package]]
name = "python-dateutil"
version = "2.9.0.post0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "six" },
]
sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432, upload-time = "2024-03-01T18:36:20.211Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" },
]
[[package]]
name = "pywin32-ctypes"
version = "0.2.3"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/85/9f/01a1a99704853cb63f253eea009390c88e7131c67e66a0a02099a8c917cb/pywin32-ctypes-0.2.3.tar.gz", hash = "sha256:d162dc04946d704503b2edc4d55f3dba5c1d539ead017afa00142c38b9885755", size = 29471, upload-time = "2024-08-14T10:15:34.626Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/de/3d/8161f7711c017e01ac9f008dfddd9410dff3674334c233bde66e7ba65bbf/pywin32_ctypes-0.2.3-py3-none-any.whl", hash = "sha256:8a1513379d709975552d202d942d9837758905c8d01eb82b8bcc30918929e7b8", size = 30756, upload-time = "2024-08-14T10:15:33.187Z" },
]
[[package]]
name = "pyyaml"
version = "6.0.2"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/54/ed/79a089b6be93607fa5cdaedf301d7dfb23af5f25c398d5ead2525b063e17/pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e", size = 130631, upload-time = "2024-08-06T20:33:50.674Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/f8/aa/7af4e81f7acba21a4c6be026da38fd2b872ca46226673c89a758ebdc4fd2/PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774", size = 184612, upload-time = "2024-08-06T20:32:03.408Z" },
{ url = "https://files.pythonhosted.org/packages/8b/62/b9faa998fd185f65c1371643678e4d58254add437edb764a08c5a98fb986/PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee", size = 172040, upload-time = "2024-08-06T20:32:04.926Z" },
{ url = "https://files.pythonhosted.org/packages/ad/0c/c804f5f922a9a6563bab712d8dcc70251e8af811fce4524d57c2c0fd49a4/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c", size = 736829, upload-time = "2024-08-06T20:32:06.459Z" },
{ url = "https://files.pythonhosted.org/packages/51/16/6af8d6a6b210c8e54f1406a6b9481febf9c64a3109c541567e35a49aa2e7/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317", size = 764167, upload-time = "2024-08-06T20:32:08.338Z" },
{ url = "https://files.pythonhosted.org/packages/75/e4/2c27590dfc9992f73aabbeb9241ae20220bd9452df27483b6e56d3975cc5/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85", size = 762952, upload-time = "2024-08-06T20:32:14.124Z" },
{ url = "https://files.pythonhosted.org/packages/9b/97/ecc1abf4a823f5ac61941a9c00fe501b02ac3ab0e373c3857f7d4b83e2b6/PyYAML-6.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4", size = 735301, upload-time = "2024-08-06T20:32:16.17Z" },
{ url = "https://files.pythonhosted.org/packages/45/73/0f49dacd6e82c9430e46f4a027baa4ca205e8b0a9dce1397f44edc23559d/PyYAML-6.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e", size = 756638, upload-time = "2024-08-06T20:32:18.555Z" },
{ url = "https://files.pythonhosted.org/packages/22/5f/956f0f9fc65223a58fbc14459bf34b4cc48dec52e00535c79b8db361aabd/PyYAML-6.0.2-cp311-cp311-win32.whl", hash = "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5", size = 143850, upload-time = "2024-08-06T20:32:19.889Z" },
{ url = "https://files.pythonhosted.org/packages/ed/23/8da0bbe2ab9dcdd11f4f4557ccaf95c10b9811b13ecced089d43ce59c3c8/PyYAML-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44", size = 161980, upload-time = "2024-08-06T20:32:21.273Z" },
{ url = "https://files.pythonhosted.org/packages/86/0c/c581167fc46d6d6d7ddcfb8c843a4de25bdd27e4466938109ca68492292c/PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab", size = 183873, upload-time = "2024-08-06T20:32:25.131Z" },
{ url = "https://files.pythonhosted.org/packages/a8/0c/38374f5bb272c051e2a69281d71cba6fdb983413e6758b84482905e29a5d/PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725", size = 173302, upload-time = "2024-08-06T20:32:26.511Z" },
{ url = "https://files.pythonhosted.org/packages/c3/93/9916574aa8c00aa06bbac729972eb1071d002b8e158bd0e83a3b9a20a1f7/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5", size = 739154, upload-time = "2024-08-06T20:32:28.363Z" },
{ url = "https://files.pythonhosted.org/packages/95/0f/b8938f1cbd09739c6da569d172531567dbcc9789e0029aa070856f123984/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425", size = 766223, upload-time = "2024-08-06T20:32:30.058Z" },
{ url = "https://files.pythonhosted.org/packages/b9/2b/614b4752f2e127db5cc206abc23a8c19678e92b23c3db30fc86ab731d3bd/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476", size = 767542, upload-time = "2024-08-06T20:32:31.881Z" },
{ url = "https://files.pythonhosted.org/packages/d4/00/dd137d5bcc7efea1836d6264f049359861cf548469d18da90cd8216cf05f/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48", size = 731164, upload-time = "2024-08-06T20:32:37.083Z" },
{ url = "https://files.pythonhosted.org/packages/c9/1f/4f998c900485e5c0ef43838363ba4a9723ac0ad73a9dc42068b12aaba4e4/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b", size = 756611, upload-time = "2024-08-06T20:32:38.898Z" },
{ url = "https://files.pythonhosted.org/packages/df/d1/f5a275fdb252768b7a11ec63585bc38d0e87c9e05668a139fea92b80634c/PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4", size = 140591, upload-time = "2024-08-06T20:32:40.241Z" },
{ url = "https://files.pythonhosted.org/packages/0c/e8/4f648c598b17c3d06e8753d7d13d57542b30d56e6c2dedf9c331ae56312e/PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8", size = 156338, upload-time = "2024-08-06T20:32:41.93Z" },
{ url = "https://files.pythonhosted.org/packages/ef/e3/3af305b830494fa85d95f6d95ef7fa73f2ee1cc8ef5b495c7c3269fb835f/PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba", size = 181309, upload-time = "2024-08-06T20:32:43.4Z" },
{ url = "https://files.pythonhosted.org/packages/45/9f/3b1c20a0b7a3200524eb0076cc027a970d320bd3a6592873c85c92a08731/PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1", size = 171679, upload-time = "2024-08-06T20:32:44.801Z" },
{ url = "https://files.pythonhosted.org/packages/7c/9a/337322f27005c33bcb656c655fa78325b730324c78620e8328ae28b64d0c/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133", size = 733428, upload-time = "2024-08-06T20:32:46.432Z" },
{ url = "https://files.pythonhosted.org/packages/a3/69/864fbe19e6c18ea3cc196cbe5d392175b4cf3d5d0ac1403ec3f2d237ebb5/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484", size = 763361, upload-time = "2024-08-06T20:32:51.188Z" },
{ url = "https://files.pythonhosted.org/packages/04/24/b7721e4845c2f162d26f50521b825fb061bc0a5afcf9a386840f23ea19fa/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5", size = 759523, upload-time = "2024-08-06T20:32:53.019Z" },
{ url = "https://files.pythonhosted.org/packages/2b/b2/e3234f59ba06559c6ff63c4e10baea10e5e7df868092bf9ab40e5b9c56b6/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc", size = 726660, upload-time = "2024-08-06T20:32:54.708Z" },
{ url = "https://files.pythonhosted.org/packages/fe/0f/25911a9f080464c59fab9027482f822b86bf0608957a5fcc6eaac85aa515/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652", size = 751597, upload-time = "2024-08-06T20:32:56.985Z" },
{ url = "https://files.pythonhosted.org/packages/14/0d/e2c3b43bbce3cf6bd97c840b46088a3031085179e596d4929729d8d68270/PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183", size = 140527, upload-time = "2024-08-06T20:33:03.001Z" },
{ url = "https://files.pythonhosted.org/packages/fa/de/02b54f42487e3d3c6efb3f89428677074ca7bf43aae402517bc7cca949f3/PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563", size = 156446, upload-time = "2024-08-06T20:33:04.33Z" },
]
[[package]]
name = "readme-renderer"
version = "44.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "docutils" },
{ name = "nh3" },
{ name = "pygments" },
]
sdist = { url = "https://files.pythonhosted.org/packages/5a/a9/104ec9234c8448c4379768221ea6df01260cd6c2ce13182d4eac531c8342/readme_renderer-44.0.tar.gz", hash = "sha256:8712034eabbfa6805cacf1402b4eeb2a73028f72d1166d6f5cb7f9c047c5d1e1", size = 32056, upload-time = "2024-07-08T15:00:57.805Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/e1/67/921ec3024056483db83953ae8e48079ad62b92db7880013ca77632921dd0/readme_renderer-44.0-py3-none-any.whl", hash = "sha256:2fbca89b81a08526aadf1357a8c2ae889ec05fb03f5da67f9769c9a592166151", size = 13310, upload-time = "2024-07-08T15:00:56.577Z" },
]
[[package]]
name = "requests"
version = "2.32.3"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "certifi" },
{ name = "charset-normalizer" },
{ name = "idna" },
{ name = "urllib3" },
]
sdist = { url = "https://files.pythonhosted.org/packages/63/70/2bf7780ad2d390a8d301ad0b550f1581eadbd9a20f896afe06353c2a2913/requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760", size = 131218, upload-time = "2024-05-29T15:37:49.536Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/f9/9b/335f9764261e915ed497fcdeb11df5dfd6f7bf257d4a6a2a686d80da4d54/requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6", size = 64928, upload-time = "2024-05-29T15:37:47.027Z" },
]
[[package]]
name = "requests-mock"
version = "1.12.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "requests" },
]
sdist = { url = "https://files.pythonhosted.org/packages/92/32/587625f91f9a0a3d84688bf9cfc4b2480a7e8ec327cefd0ff2ac891fd2cf/requests-mock-1.12.1.tar.gz", hash = "sha256:e9e12e333b525156e82a3c852f22016b9158220d2f47454de9cae8a77d371401", size = 60901, upload-time = "2024-03-29T03:54:29.446Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/97/ec/889fbc557727da0c34a33850950310240f2040f3b1955175fdb2b36a8910/requests_mock-1.12.1-py2.py3-none-any.whl", hash = "sha256:b1e37054004cdd5e56c84454cc7df12b25f90f382159087f4b6915aaeef39563", size = 27695, upload-time = "2024-03-29T03:54:27.64Z" },
]
[[package]]
name = "requests-oauthlib"
version = "2.0.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "oauthlib" },
{ name = "requests" },
]
sdist = { url = "https://files.pythonhosted.org/packages/42/f2/05f29bc3913aea15eb670be136045bf5c5bbf4b99ecb839da9b422bb2c85/requests-oauthlib-2.0.0.tar.gz", hash = "sha256:b3dffaebd884d8cd778494369603a9e7b58d29111bf6b41bdc2dcd87203af4e9", size = 55650, upload-time = "2024-03-22T20:32:29.939Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/3b/5d/63d4ae3b9daea098d5d6f5da83984853c1bbacd5dc826764b249fe119d24/requests_oauthlib-2.0.0-py2.py3-none-any.whl", hash = "sha256:7dd8a5c40426b779b0868c404bdef9768deccf22749cde15852df527e6269b36", size = 24179, upload-time = "2024-03-22T20:32:28.055Z" },
]
[[package]]
name = "requests-toolbelt"
version = "1.0.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "requests" },
]
sdist = { url = "https://files.pythonhosted.org/packages/f3/61/d7545dafb7ac2230c70d38d31cbfe4cc64f7144dc41f6e4e4b78ecd9f5bb/requests-toolbelt-1.0.0.tar.gz", hash = "sha256:7681a0a3d047012b5bdc0ee37d7f8f07ebe76ab08caeccfc3921ce23c88d5bc6", size = 206888, upload-time = "2023-05-01T04:11:33.229Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/3f/51/d4db610ef29373b879047326cbf6fa98b6c1969d6f6dc423279de2b1be2c/requests_toolbelt-1.0.0-py2.py3-none-any.whl", hash = "sha256:cccfdd665f0a24fcf4726e690f65639d272bb0637b9b92dfd91a5568ccf6bd06", size = 54481, upload-time = "2023-05-01T04:11:28.427Z" },
]
[[package]]
name = "rfc3986"
version = "2.0.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/85/40/1520d68bfa07ab5a6f065a186815fb6610c86fe957bc065754e47f7b0840/rfc3986-2.0.0.tar.gz", hash = "sha256:97aacf9dbd4bfd829baad6e6309fa6573aaf1be3f6fa735c8ab05e46cecb261c", size = 49026, upload-time = "2022-01-10T00:52:30.832Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/ff/9a/9afaade874b2fa6c752c36f1548f718b5b83af81ed9b76628329dab81c1b/rfc3986-2.0.0-py2.py3-none-any.whl", hash = "sha256:50b1502b60e289cb37883f3dfd34532b8873c7de9f49bb546641ce9cbd256ebd", size = 31326, upload-time = "2022-01-10T00:52:29.594Z" },
]
[[package]]
name = "rich"
version = "14.0.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "markdown-it-py" },
{ name = "pygments" },
]
sdist = { url = "https://files.pythonhosted.org/packages/a1/53/830aa4c3066a8ab0ae9a9955976fb770fe9c6102117c8ec4ab3ea62d89e8/rich-14.0.0.tar.gz", hash = "sha256:82f1bc23a6a21ebca4ae0c45af9bdbc492ed20231dcb63f297d6d1021a9d5725", size = 224078, upload-time = "2025-03-30T14:15:14.23Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/0d/9b/63f4c7ebc259242c89b3acafdb37b41d1185c07ff0011164674e9076b491/rich-14.0.0-py3-none-any.whl", hash = "sha256:1c9491e1951aac09caffd42f448ee3d04e58923ffe14993f6e83068dc395d7e0", size = 243229, upload-time = "2025-03-30T14:15:12.283Z" },
]
[[package]]
name = "ruff"
version = "0.11.12"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/15/0a/92416b159ec00cdf11e5882a9d80d29bf84bba3dbebc51c4898bfbca1da6/ruff-0.11.12.tar.gz", hash = "sha256:43cf7f69c7d7c7d7513b9d59c5d8cafd704e05944f978614aa9faff6ac202603", size = 4202289, upload-time = "2025-05-29T13:31:40.037Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/60/cc/53eb79f012d15e136d40a8e8fc519ba8f55a057f60b29c2df34efd47c6e3/ruff-0.11.12-py3-none-linux_armv6l.whl", hash = "sha256:c7680aa2f0d4c4f43353d1e72123955c7a2159b8646cd43402de6d4a3a25d7cc", size = 10285597, upload-time = "2025-05-29T13:30:57.539Z" },
{ url = "https://files.pythonhosted.org/packages/e7/d7/73386e9fb0232b015a23f62fea7503f96e29c29e6c45461d4a73bac74df9/ruff-0.11.12-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:2cad64843da9f134565c20bcc430642de897b8ea02e2e79e6e02a76b8dcad7c3", size = 11053154, upload-time = "2025-05-29T13:31:00.865Z" },
{ url = "https://files.pythonhosted.org/packages/4e/eb/3eae144c5114e92deb65a0cb2c72326c8469e14991e9bc3ec0349da1331c/ruff-0.11.12-py3-none-macosx_11_0_arm64.whl", hash = "sha256:9b6886b524a1c659cee1758140138455d3c029783d1b9e643f3624a5ee0cb0aa", size = 10403048, upload-time = "2025-05-29T13:31:03.413Z" },
{ url = "https://files.pythonhosted.org/packages/29/64/20c54b20e58b1058db6689e94731f2a22e9f7abab74e1a758dfba058b6ca/ruff-0.11.12-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3cc3a3690aad6e86c1958d3ec3c38c4594b6ecec75c1f531e84160bd827b2012", size = 10597062, upload-time = "2025-05-29T13:31:05.539Z" },
{ url = "https://files.pythonhosted.org/packages/29/3a/79fa6a9a39422a400564ca7233a689a151f1039110f0bbbabcb38106883a/ruff-0.11.12-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f97fdbc2549f456c65b3b0048560d44ddd540db1f27c778a938371424b49fe4a", size = 10155152, upload-time = "2025-05-29T13:31:07.986Z" },
{ url = "https://files.pythonhosted.org/packages/e5/a4/22c2c97b2340aa968af3a39bc38045e78d36abd4ed3fa2bde91c31e712e3/ruff-0.11.12-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:74adf84960236961090e2d1348c1a67d940fd12e811a33fb3d107df61eef8fc7", size = 11723067, upload-time = "2025-05-29T13:31:10.57Z" },
{ url = "https://files.pythonhosted.org/packages/bc/cf/3e452fbd9597bcd8058856ecd42b22751749d07935793a1856d988154151/ruff-0.11.12-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:b56697e5b8bcf1d61293ccfe63873aba08fdbcbbba839fc046ec5926bdb25a3a", size = 12460807, upload-time = "2025-05-29T13:31:12.88Z" },
{ url = "https://files.pythonhosted.org/packages/2f/ec/8f170381a15e1eb7d93cb4feef8d17334d5a1eb33fee273aee5d1f8241a3/ruff-0.11.12-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4d47afa45e7b0eaf5e5969c6b39cbd108be83910b5c74626247e366fd7a36a13", size = 12063261, upload-time = "2025-05-29T13:31:15.236Z" },
{ url = "https://files.pythonhosted.org/packages/0d/bf/57208f8c0a8153a14652a85f4116c0002148e83770d7a41f2e90b52d2b4e/ruff-0.11.12-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:692bf9603fe1bf949de8b09a2da896f05c01ed7a187f4a386cdba6760e7f61be", size = 11329601, upload-time = "2025-05-29T13:31:18.68Z" },
{ url = "https://files.pythonhosted.org/packages/c3/56/edf942f7fdac5888094d9ffa303f12096f1a93eb46570bcf5f14c0c70880/ruff-0.11.12-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:08033320e979df3b20dba567c62f69c45e01df708b0f9c83912d7abd3e0801cd", size = 11522186, upload-time = "2025-05-29T13:31:21.216Z" },
{ url = "https://files.pythonhosted.org/packages/ed/63/79ffef65246911ed7e2290aeece48739d9603b3a35f9529fec0fc6c26400/ruff-0.11.12-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:929b7706584f5bfd61d67d5070f399057d07c70585fa8c4491d78ada452d3bef", size = 10449032, upload-time = "2025-05-29T13:31:23.417Z" },
{ url = "https://files.pythonhosted.org/packages/88/19/8c9d4d8a1c2a3f5a1ea45a64b42593d50e28b8e038f1aafd65d6b43647f3/ruff-0.11.12-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:7de4a73205dc5756b8e09ee3ed67c38312dce1aa28972b93150f5751199981b5", size = 10129370, upload-time = "2025-05-29T13:31:25.777Z" },
{ url = "https://files.pythonhosted.org/packages/bc/0f/2d15533eaa18f460530a857e1778900cd867ded67f16c85723569d54e410/ruff-0.11.12-py3-none-musllinux_1_2_i686.whl", hash = "sha256:2635c2a90ac1b8ca9e93b70af59dfd1dd2026a40e2d6eebaa3efb0465dd9cf02", size = 11123529, upload-time = "2025-05-29T13:31:28.396Z" },
{ url = "https://files.pythonhosted.org/packages/4f/e2/4c2ac669534bdded835356813f48ea33cfb3a947dc47f270038364587088/ruff-0.11.12-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:d05d6a78a89166f03f03a198ecc9d18779076ad0eec476819467acb401028c0c", size = 11577642, upload-time = "2025-05-29T13:31:30.647Z" },
{ url = "https://files.pythonhosted.org/packages/a7/9b/c9ddf7f924d5617a1c94a93ba595f4b24cb5bc50e98b94433ab3f7ad27e5/ruff-0.11.12-py3-none-win32.whl", hash = "sha256:f5a07f49767c4be4772d161bfc049c1f242db0cfe1bd976e0f0886732a4765d6", size = 10475511, upload-time = "2025-05-29T13:31:32.917Z" },
{ url = "https://files.pythonhosted.org/packages/fd/d6/74fb6d3470c1aada019ffff33c0f9210af746cca0a4de19a1f10ce54968a/ruff-0.11.12-py3-none-win_amd64.whl", hash = "sha256:5a4d9f8030d8c3a45df201d7fb3ed38d0219bccd7955268e863ee4a115fa0832", size = 11523573, upload-time = "2025-05-29T13:31:35.782Z" },
{ url = "https://files.pythonhosted.org/packages/44/42/d58086ec20f52d2b0140752ae54b355ea2be2ed46f914231136dd1effcc7/ruff-0.11.12-py3-none-win_arm64.whl", hash = "sha256:65194e37853158d368e333ba282217941029a28ea90913c67e558c611d04daa5", size = 10697770, upload-time = "2025-05-29T13:31:38.009Z" },
]
[[package]]
name = "secretstorage"
version = "3.3.3"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "cryptography" },
{ name = "jeepney" },
]
sdist = { url = "https://files.pythonhosted.org/packages/53/a4/f48c9d79cb507ed1373477dbceaba7401fd8a23af63b837fa61f1dcd3691/SecretStorage-3.3.3.tar.gz", hash = "sha256:2403533ef369eca6d2ba81718576c5e0f564d5cca1b58f73a8b23e7d4eeebd77", size = 19739, upload-time = "2022-08-13T16:22:46.976Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/54/24/b4293291fa1dd830f353d2cb163295742fa87f179fcc8a20a306a81978b7/SecretStorage-3.3.3-py3-none-any.whl", hash = "sha256:f356e6628222568e3af06f2eba8df495efa13b3b63081dafd4f7d9a7b7bc9f99", size = 15221, upload-time = "2022-08-13T16:22:44.457Z" },
]
[[package]]
name = "six"
version = "1.17.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031, upload-time = "2024-12-04T17:35:28.174Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" },
]
[[package]]
name = "sniffio"
version = "1.3.1"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/a2/87/a6771e1546d97e7e041b6ae58d80074f81b7d5121207425c964ddf5cfdbd/sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc", size = 20372, upload-time = "2024-02-25T23:20:04.057Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235, upload-time = "2024-02-25T23:20:01.196Z" },
]
[[package]]
name = "time-machine"
version = "2.16.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "python-dateutil" },
]
sdist = { url = "https://files.pythonhosted.org/packages/fb/dd/5022939b9cadefe3af04f4012186c29b8afbe858b1ec2cfa38baeec94dab/time_machine-2.16.0.tar.gz", hash = "sha256:4a99acc273d2f98add23a89b94d4dd9e14969c01214c8514bfa78e4e9364c7e2", size = 24626, upload-time = "2024-10-08T14:21:59.734Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/38/7b/34aad93f75f86503dd1fa53bc120d8129fe4de83aef58ffa78c62b044ef9/time_machine-2.16.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:8f936566ef9f09136a3d5db305961ef6d897b76b240c9ff4199144aed6dd4fe5", size = 20169, upload-time = "2024-10-08T14:21:06.288Z" },
{ url = "https://files.pythonhosted.org/packages/68/cb/7d020d5c05d0460a4a96232b0777882ef989c1e6144d11ba984c4b0b4d1a/time_machine-2.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5886e23ede3478ca2a3e0a641f5d09dd784dfa9e48c96e8e5e31fc4fe77b6dc0", size = 16614, upload-time = "2024-10-08T14:21:07.253Z" },
{ url = "https://files.pythonhosted.org/packages/0d/24/ce1ff76c9a4f3be88c2b947f2411a5a8019390734597d3106a151f8a9416/time_machine-2.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c76caf539fa4941e1817b7c482c87c65c52a1903fea761e84525955c6106fafb", size = 32507, upload-time = "2024-10-08T14:21:08.289Z" },
{ url = "https://files.pythonhosted.org/packages/08/d7/ba1135587bd2ed105e59ed7e05969c913277d110fecc0ed871006ea3f763/time_machine-2.16.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:298aa423e07c8b21b991782f01d7749c871c792319c2af3e9755f9ab49033212", size = 30627, upload-time = "2024-10-08T14:21:09.246Z" },
{ url = "https://files.pythonhosted.org/packages/da/c6/f490aaddc80c54238f4b8fe97870bbfe0d2c70fe4a57269badc94f5f38a6/time_machine-2.16.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e3391ae9c484736850bb44ef125cbad52fe2d1b69e42c95dc88c43af8ead2cc7", size = 32362, upload-time = "2024-10-08T14:21:10.178Z" },
{ url = "https://files.pythonhosted.org/packages/b1/f7/2522ae1c1995a39d6d8b7ee7efed47ec8bd7ff3240fdb2662a8b7e11b84a/time_machine-2.16.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:503e7ff507c2089699d91885fc5b9c8ff16774a7b6aff48b4dcee0c0a0685b61", size = 32188, upload-time = "2024-10-08T14:21:11.743Z" },
{ url = "https://files.pythonhosted.org/packages/e9/53/b1ccb55f39e7e62660f852d7aedef438d2872ea9c73f64be46d0d3b3f3d7/time_machine-2.16.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:eee7b0fc4fbab2c6585ea17606c6548be83919c70deea0865409fe9fc2d8cdce", size = 30600, upload-time = "2024-10-08T14:21:12.728Z" },
{ url = "https://files.pythonhosted.org/packages/19/1f/37a5a9333a2da35b0fc43e8ac693b82dd5492892131bc3cc0c8f5835af94/time_machine-2.16.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9db5e5b3ccdadaafa5730c2f9db44c38b013234c9ad01f87738907e19bdba268", size = 31896, upload-time = "2024-10-08T14:21:14.451Z" },
{ url = "https://files.pythonhosted.org/packages/fc/97/e1a8bd64e5432adf47859cb63847b4472efc644b508602141c60ccf52112/time_machine-2.16.0-cp311-cp311-win32.whl", hash = "sha256:2552f0767bc10c9d668f108fef9b487809cdeb772439ce932e74136365c69baf", size = 19030, upload-time = "2024-10-08T14:21:15.662Z" },
{ url = "https://files.pythonhosted.org/packages/34/c9/f4764e447aa9da4031c89da60fa69f4f73fd45571415788c298cbd4620e9/time_machine-2.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:12474fcdbc475aa6fe5275fe7224e685c5b9777f5939647f35980e9614ae7558", size = 19924, upload-time = "2024-10-08T14:21:17.324Z" },
{ url = "https://files.pythonhosted.org/packages/8a/c0/788500d33656a044e3289b814106c2277209ac73316c00b9668012ce6027/time_machine-2.16.0-cp311-cp311-win_arm64.whl", hash = "sha256:ac2df0fa564356384515ed62cb6679f33f1f529435b16b0ec0f88414635dbe39", size = 17993, upload-time = "2024-10-08T14:21:18.346Z" },
{ url = "https://files.pythonhosted.org/packages/4a/f4/603a84e7ae6427a53953db9f61b689dc6adf233e03c5f5ca907a901452fd/time_machine-2.16.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:84788f4d62a8b1bf5e499bb9b0e23ceceea21c415ad6030be6267ce3d639842f", size = 20155, upload-time = "2024-10-08T14:21:20.055Z" },
{ url = "https://files.pythonhosted.org/packages/d8/94/dbe69aecb4b84be52d34814e63176c5ca61f38ee9e6ecda11104653405b5/time_machine-2.16.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:15ec236b6571730236a193d9d6c11d472432fc6ab54e85eac1c16d98ddcd71bf", size = 16640, upload-time = "2024-10-08T14:21:22.005Z" },
{ url = "https://files.pythonhosted.org/packages/da/13/27f11be25d7bd298e033b9da93217e5b68309bf724b6e494cdadb471d00d/time_machine-2.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cedc989717c8b44a3881ac3d68ab5a95820448796c550de6a2149ed1525157f0", size = 33721, upload-time = "2024-10-08T14:21:23.059Z" },
{ url = "https://files.pythonhosted.org/packages/e6/9d/70e4640fed1fd8122204ae825c688d0ef8c04f515ec6bf3c5f3086d6510e/time_machine-2.16.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9d26d79de1c63a8c6586c75967e09b0ff306aa7e944a1eaddb74595c9b1839ca", size = 31646, upload-time = "2024-10-08T14:21:24.037Z" },
{ url = "https://files.pythonhosted.org/packages/a1/cb/93bc0e51bea4e171a85151dbba3c3b3f612b50b953cd3076f5b4f0db9e14/time_machine-2.16.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:317b68b56a9c3731e0cf8886e0f94230727159e375988b36c60edce0ddbcb44a", size = 33403, upload-time = "2024-10-08T14:21:24.975Z" },
{ url = "https://files.pythonhosted.org/packages/89/71/2c6a63ad4fbce3d62d46bbd9ac4433f30bade7f25978ce00815b905bcfcf/time_machine-2.16.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:43e1e18279759897be3293a255d53e6b1cb0364b69d9591d0b80c51e461c94b0", size = 33327, upload-time = "2024-10-08T14:21:25.958Z" },
{ url = "https://files.pythonhosted.org/packages/68/4e/205c2b26763b8817cd6b8868242843800a1fbf275f2af35f5ba35ff2b01a/time_machine-2.16.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:e43adb22def972a29d2b147999b56897116085777a0fea182fd93ee45730611e", size = 31454, upload-time = "2024-10-08T14:21:27.367Z" },
{ url = "https://files.pythonhosted.org/packages/d7/95/44c1aa3994919f93534244c40cfd2fb9416d7686dc0c8b9b262c751b5118/time_machine-2.16.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:0c766bea27a0600e36806d628ebc4b47178b12fcdfb6c24dc0a566a9c06bfe7f", size = 32972, upload-time = "2024-10-08T14:21:28.351Z" },
{ url = "https://files.pythonhosted.org/packages/d4/ee/75243df9c7cf30f108758e887141a58e6544baaa46e2e647b9ccc56db819/time_machine-2.16.0-cp312-cp312-win32.whl", hash = "sha256:6dae82ab647d107817e013db82223e20a9853fa88543fec853ae326382d03c2e", size = 19078, upload-time = "2024-10-08T14:21:29.425Z" },
{ url = "https://files.pythonhosted.org/packages/d4/7c/d4e67cc031f9653c92167ccf87d241e3208653d191c96ac79281c273ab92/time_machine-2.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:265462c77dc9576267c3c7f20707780a171a9fdbac93ac22e608c309efd68c33", size = 19923, upload-time = "2024-10-08T14:21:30.759Z" },
{ url = "https://files.pythonhosted.org/packages/aa/b6/7047226fcb9afefe47fc80f605530535bf71ad99b6797f057abbfa4cd9a5/time_machine-2.16.0-cp312-cp312-win_arm64.whl", hash = "sha256:ef768e14768eebe3bb1196c0dece8e14c1c6991605721214a0c3c68cf77eb216", size = 18003, upload-time = "2024-10-08T14:21:32.662Z" },
{ url = "https://files.pythonhosted.org/packages/a6/18/3087d0eb185cedbc82385f46bf16032ec7102a0e070205a2c88c4ecf9952/time_machine-2.16.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:7751bf745d54e9e8b358c0afa332815da9b8a6194b26d0fd62876ab6c4d5c9c0", size = 20209, upload-time = "2024-10-08T14:21:34.222Z" },
{ url = "https://files.pythonhosted.org/packages/03/a3/fcc3eaf69390402ecf491d718e533b6d0e06d944d77fc8d87be3a2839102/time_machine-2.16.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:1784edf173ca840ba154de6eed000b5727f65ab92972c2f88cec5c4d6349c5f2", size = 16681, upload-time = "2024-10-08T14:21:35.14Z" },
{ url = "https://files.pythonhosted.org/packages/a2/96/8b76d264014bf9dc21873218de50d67223c71736f87fe6c65e582f7c29ac/time_machine-2.16.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2f5876a5682ce1f517e55d7ace2383432627889f6f7e338b961f99d684fd9e8d", size = 33768, upload-time = "2024-10-08T14:21:36.942Z" },
{ url = "https://files.pythonhosted.org/packages/5c/13/59ae8259be02b6c657ef6e3b6952bf274b43849f6f35cc61a576c68ce301/time_machine-2.16.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:806672529a2e255cd901f244c9033767dc1fa53466d0d3e3e49565a1572a64fe", size = 31685, upload-time = "2024-10-08T14:21:37.881Z" },
{ url = "https://files.pythonhosted.org/packages/3e/c1/9f142beb4d373a2a01ebb58d5117289315baa5131d880ec804db49e94bf7/time_machine-2.16.0-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:667b150fedb54acdca2a4bea5bf6da837b43e6dd12857301b48191f8803ba93f", size = 33447, upload-time = "2024-10-08T14:21:38.809Z" },
{ url = "https://files.pythonhosted.org/packages/95/f7/ed9ecd93c2d38dca77d0a28e070020f3ce0fb23e0d4a6edb14bcfffa5526/time_machine-2.16.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:da3ae1028af240c0c46c79adf9c1acffecc6ed1701f2863b8132f5ceae6ae4b5", size = 33408, upload-time = "2024-10-08T14:21:39.785Z" },
{ url = "https://files.pythonhosted.org/packages/91/40/d0d274d70fa2c4cad531745deb8c81346365beb0a2736be05a3acde8b94a/time_machine-2.16.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:520a814ea1b2706c89ab260a54023033d3015abef25c77873b83e3d7c1fafbb2", size = 31526, upload-time = "2024-10-08T14:21:40.769Z" },
{ url = "https://files.pythonhosted.org/packages/1d/ba/a27cdbb324d9a6d779cde0d514d47b696b5a6a653705d4b511fd65ef1514/time_machine-2.16.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8243664438bb468408b29c6865958662d75e51f79c91842d2794fa22629eb697", size = 33042, upload-time = "2024-10-08T14:21:41.722Z" },
{ url = "https://files.pythonhosted.org/packages/72/63/64e9156c9e38c18720d0cc41378168635241de44013ffe3dd5b099447eb0/time_machine-2.16.0-cp313-cp313-win32.whl", hash = "sha256:32d445ce20d25c60ab92153c073942b0bac9815bfbfd152ce3dcc225d15ce988", size = 19108, upload-time = "2024-10-08T14:21:43.596Z" },
{ url = "https://files.pythonhosted.org/packages/3d/40/27f5738fbd50b78dcc0682c14417eac5a49ccf430525dd0c5a058be125a2/time_machine-2.16.0-cp313-cp313-win_amd64.whl", hash = "sha256:f6927dda86425f97ffda36131f297b1a601c64a6ee6838bfa0e6d3149c2f0d9f", size = 19935, upload-time = "2024-10-08T14:21:45.277Z" },
{ url = "https://files.pythonhosted.org/packages/35/75/c4d8b2f0fe7dac22854d88a9c509d428e78ac4bf284bc54cfe83f75cc13b/time_machine-2.16.0-cp313-cp313-win_arm64.whl", hash = "sha256:4d3843143c46dddca6491a954bbd0abfd435681512ac343169560e9bab504129", size = 18047, upload-time = "2024-10-08T14:21:46.261Z" },
]
[[package]]
name = "tomli"
version = "2.2.1"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/18/87/302344fed471e44a87289cf4967697d07e532f2421fdaf868a303cbae4ff/tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff", size = 17175, upload-time = "2024-11-27T22:38:36.873Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/43/ca/75707e6efa2b37c77dadb324ae7d9571cb424e61ea73fad7c56c2d14527f/tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249", size = 131077, upload-time = "2024-11-27T22:37:54.956Z" },
{ url = "https://files.pythonhosted.org/packages/c7/16/51ae563a8615d472fdbffc43a3f3d46588c264ac4f024f63f01283becfbb/tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6", size = 123429, upload-time = "2024-11-27T22:37:56.698Z" },
{ url = "https://files.pythonhosted.org/packages/f1/dd/4f6cd1e7b160041db83c694abc78e100473c15d54620083dbd5aae7b990e/tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a", size = 226067, upload-time = "2024-11-27T22:37:57.63Z" },
{ url = "https://files.pythonhosted.org/packages/a9/6b/c54ede5dc70d648cc6361eaf429304b02f2871a345bbdd51e993d6cdf550/tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee", size = 236030, upload-time = "2024-11-27T22:37:59.344Z" },
{ url = "https://files.pythonhosted.org/packages/1f/47/999514fa49cfaf7a92c805a86c3c43f4215621855d151b61c602abb38091/tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e", size = 240898, upload-time = "2024-11-27T22:38:00.429Z" },
{ url = "https://files.pythonhosted.org/packages/73/41/0a01279a7ae09ee1573b423318e7934674ce06eb33f50936655071d81a24/tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4", size = 229894, upload-time = "2024-11-27T22:38:02.094Z" },
{ url = "https://files.pythonhosted.org/packages/55/18/5d8bc5b0a0362311ce4d18830a5d28943667599a60d20118074ea1b01bb7/tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106", size = 245319, upload-time = "2024-11-27T22:38:03.206Z" },
{ url = "https://files.pythonhosted.org/packages/92/a3/7ade0576d17f3cdf5ff44d61390d4b3febb8a9fc2b480c75c47ea048c646/tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8", size = 238273, upload-time = "2024-11-27T22:38:04.217Z" },
{ url = "https://files.pythonhosted.org/packages/72/6f/fa64ef058ac1446a1e51110c375339b3ec6be245af9d14c87c4a6412dd32/tomli-2.2.1-cp311-cp311-win32.whl", hash = "sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff", size = 98310, upload-time = "2024-11-27T22:38:05.908Z" },
{ url = "https://files.pythonhosted.org/packages/6a/1c/4a2dcde4a51b81be3530565e92eda625d94dafb46dbeb15069df4caffc34/tomli-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b", size = 108309, upload-time = "2024-11-27T22:38:06.812Z" },
{ url = "https://files.pythonhosted.org/packages/52/e1/f8af4c2fcde17500422858155aeb0d7e93477a0d59a98e56cbfe75070fd0/tomli-2.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea", size = 132762, upload-time = "2024-11-27T22:38:07.731Z" },
{ url = "https://files.pythonhosted.org/packages/03/b8/152c68bb84fc00396b83e7bbddd5ec0bd3dd409db4195e2a9b3e398ad2e3/tomli-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8", size = 123453, upload-time = "2024-11-27T22:38:09.384Z" },
{ url = "https://files.pythonhosted.org/packages/c8/d6/fc9267af9166f79ac528ff7e8c55c8181ded34eb4b0e93daa767b8841573/tomli-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192", size = 233486, upload-time = "2024-11-27T22:38:10.329Z" },
{ url = "https://files.pythonhosted.org/packages/5c/51/51c3f2884d7bab89af25f678447ea7d297b53b5a3b5730a7cb2ef6069f07/tomli-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222", size = 242349, upload-time = "2024-11-27T22:38:11.443Z" },
{ url = "https://files.pythonhosted.org/packages/ab/df/bfa89627d13a5cc22402e441e8a931ef2108403db390ff3345c05253935e/tomli-2.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77", size = 252159, upload-time = "2024-11-27T22:38:13.099Z" },
{ url = "https://files.pythonhosted.org/packages/9e/6e/fa2b916dced65763a5168c6ccb91066f7639bdc88b48adda990db10c8c0b/tomli-2.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6", size = 237243, upload-time = "2024-11-27T22:38:14.766Z" },
{ url = "https://files.pythonhosted.org/packages/b4/04/885d3b1f650e1153cbb93a6a9782c58a972b94ea4483ae4ac5cedd5e4a09/tomli-2.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd", size = 259645, upload-time = "2024-11-27T22:38:15.843Z" },
{ url = "https://files.pythonhosted.org/packages/9c/de/6b432d66e986e501586da298e28ebeefd3edc2c780f3ad73d22566034239/tomli-2.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e", size = 244584, upload-time = "2024-11-27T22:38:17.645Z" },
{ url = "https://files.pythonhosted.org/packages/1c/9a/47c0449b98e6e7d1be6cbac02f93dd79003234ddc4aaab6ba07a9a7482e2/tomli-2.2.1-cp312-cp312-win32.whl", hash = "sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98", size = 98875, upload-time = "2024-11-27T22:38:19.159Z" },
{ url = "https://files.pythonhosted.org/packages/ef/60/9b9638f081c6f1261e2688bd487625cd1e660d0a85bd469e91d8db969734/tomli-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4", size = 109418, upload-time = "2024-11-27T22:38:20.064Z" },
{ url = "https://files.pythonhosted.org/packages/04/90/2ee5f2e0362cb8a0b6499dc44f4d7d48f8fff06d28ba46e6f1eaa61a1388/tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7", size = 132708, upload-time = "2024-11-27T22:38:21.659Z" },
{ url = "https://files.pythonhosted.org/packages/c0/ec/46b4108816de6b385141f082ba99e315501ccd0a2ea23db4a100dd3990ea/tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c", size = 123582, upload-time = "2024-11-27T22:38:22.693Z" },
{ url = "https://files.pythonhosted.org/packages/a0/bd/b470466d0137b37b68d24556c38a0cc819e8febe392d5b199dcd7f578365/tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13", size = 232543, upload-time = "2024-11-27T22:38:24.367Z" },
{ url = "https://files.pythonhosted.org/packages/d9/e5/82e80ff3b751373f7cead2815bcbe2d51c895b3c990686741a8e56ec42ab/tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281", size = 241691, upload-time = "2024-11-27T22:38:26.081Z" },
{ url = "https://files.pythonhosted.org/packages/05/7e/2a110bc2713557d6a1bfb06af23dd01e7dde52b6ee7dadc589868f9abfac/tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272", size = 251170, upload-time = "2024-11-27T22:38:27.921Z" },
{ url = "https://files.pythonhosted.org/packages/64/7b/22d713946efe00e0adbcdfd6d1aa119ae03fd0b60ebed51ebb3fa9f5a2e5/tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140", size = 236530, upload-time = "2024-11-27T22:38:29.591Z" },
{ url = "https://files.pythonhosted.org/packages/38/31/3a76f67da4b0cf37b742ca76beaf819dca0ebef26d78fc794a576e08accf/tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2", size = 258666, upload-time = "2024-11-27T22:38:30.639Z" },
{ url = "https://files.pythonhosted.org/packages/07/10/5af1293da642aded87e8a988753945d0cf7e00a9452d3911dd3bb354c9e2/tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744", size = 243954, upload-time = "2024-11-27T22:38:31.702Z" },
{ url = "https://files.pythonhosted.org/packages/5b/b9/1ed31d167be802da0fc95020d04cd27b7d7065cc6fbefdd2f9186f60d7bd/tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec", size = 98724, upload-time = "2024-11-27T22:38:32.837Z" },
{ url = "https://files.pythonhosted.org/packages/c7/32/b0963458706accd9afcfeb867c0f9175a741bf7b19cd424230714d722198/tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69", size = 109383, upload-time = "2024-11-27T22:38:34.455Z" },
{ url = "https://files.pythonhosted.org/packages/6e/c2/61d3e0f47e2b74ef40a68b9e6ad5984f6241a942f7cd3bbfbdbd03861ea9/tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc", size = 14257, upload-time = "2024-11-27T22:38:35.385Z" },
]
[[package]]
name = "tox"
version = "4.26.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "cachetools" },
{ name = "chardet" },
{ name = "colorama" },
{ name = "filelock" },
{ name = "packaging" },
{ name = "platformdirs" },
{ name = "pluggy" },
{ name = "pyproject-api" },
{ name = "virtualenv" },
]
sdist = { url = "https://files.pythonhosted.org/packages/fd/3c/dcec0c00321a107f7f697fd00754c5112572ea6dcacb40b16d8c3eea7c37/tox-4.26.0.tar.gz", hash = "sha256:a83b3b67b0159fa58e44e646505079e35a43317a62d2ae94725e0586266faeca", size = 197260, upload-time = "2025-05-13T15:04:28.481Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/de/14/f58b4087cf248b18c795b5c838c7a8d1428dfb07cb468dad3ec7f54041ab/tox-4.26.0-py3-none-any.whl", hash = "sha256:75f17aaf09face9b97bd41645028d9f722301e912be8b4c65a3f938024560224", size = 172761, upload-time = "2025-05-13T15:04:26.207Z" },
]
[[package]]
name = "tox-uv"
version = "1.26.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "packaging" },
{ name = "tox" },
{ name = "uv" },
]
sdist = { url = "https://files.pythonhosted.org/packages/7e/da/37790b4a176f05b0ec7a699f54979078fc726f743640aa5c10c551c27edb/tox_uv-1.26.0.tar.gz", hash = "sha256:5045880c467eed58a98f7eaa7fe286b7ef688e2c56f2123d53e275011495c381", size = 21523, upload-time = "2025-05-27T14:51:42.702Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/46/b8/04c5cb83da072a3f96d357d68a551f5e97e162573c2011a09437df995811/tox_uv-1.26.0-py3-none-any.whl", hash = "sha256:894b2e7274fd6131c3bd1012813edc858753cad67727050c21cd973a08e691c8", size = 16562, upload-time = "2025-05-27T14:51:40.803Z" },
]
[[package]]
name = "twine"
version = "6.1.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "id" },
{ name = "keyring", marker = "platform_machine != 'ppc64le' and platform_machine != 's390x'" },
{ name = "packaging" },
{ name = "readme-renderer" },
{ name = "requests" },
{ name = "requests-toolbelt" },
{ name = "rfc3986" },
{ name = "rich" },
{ name = "urllib3" },
]
sdist = { url = "https://files.pythonhosted.org/packages/c8/a2/6df94fc5c8e2170d21d7134a565c3a8fb84f9797c1dd65a5976aaf714418/twine-6.1.0.tar.gz", hash = "sha256:be324f6272eff91d07ee93f251edf232fc647935dd585ac003539b42404a8dbd", size = 168404, upload-time = "2025-01-21T18:45:26.758Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/7c/b6/74e927715a285743351233f33ea3c684528a0d374d2e43ff9ce9585b73fe/twine-6.1.0-py3-none-any.whl", hash = "sha256:a47f973caf122930bf0fbbf17f80b83bc1602c9ce393c7845f289a3001dc5384", size = 40791, upload-time = "2025-01-21T18:45:24.584Z" },
]
[[package]]
name = "typing-extensions"
version = "4.14.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/d1/bc/51647cd02527e87d05cb083ccc402f93e441606ff1f01739a62c8ad09ba5/typing_extensions-4.14.0.tar.gz", hash = "sha256:8676b788e32f02ab42d9e7c61324048ae4c6d844a399eebace3d4979d75ceef4", size = 107423, upload-time = "2025-06-02T14:52:11.399Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/69/e0/552843e0d356fbb5256d21449fa957fa4eff3bbc135a74a691ee70c7c5da/typing_extensions-4.14.0-py3-none-any.whl", hash = "sha256:a1514509136dd0b477638fc68d6a91497af5076466ad0fa6c338e44e359944af", size = 43839, upload-time = "2025-06-02T14:52:10.026Z" },
]
[[package]]
name = "urllib3"
version = "2.4.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/8a/78/16493d9c386d8e60e442a35feac5e00f0913c0f4b7c217c11e8ec2ff53e0/urllib3-2.4.0.tar.gz", hash = "sha256:414bc6535b787febd7567804cc015fee39daab8ad86268f1310a9250697de466", size = 390672, upload-time = "2025-04-10T15:23:39.232Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/6b/11/cc635220681e93a0183390e26485430ca2c7b5f9d33b15c74c2861cb8091/urllib3-2.4.0-py3-none-any.whl", hash = "sha256:4e16665048960a0900c702d4a66415956a584919c03361cac9f1df5c5dd7e813", size = 128680, upload-time = "2025-04-10T15:23:37.377Z" },
]
[[package]]
name = "uv"
version = "0.7.9"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/9a/7c/8621d5928111f985196dc75c50a64147b3bad39f36164686f24d45581367/uv-0.7.9.tar.gz", hash = "sha256:baac54e49f3b0d05ee83f534fdcb27b91d2923c585bf349a1532ca25d62c216f", size = 3272882, upload-time = "2025-05-30T19:54:33.003Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/c5/7a/e4d12029e16f30279ef48f387545f8f3974dc3c4c9d8ef59c381ae7e6a7d/uv-0.7.9-py3-none-linux_armv6l.whl", hash = "sha256:0f8c53d411f95cec2fa19471c23b41ec456fc0d5f2efca96480d94e0c34026c2", size = 16746809, upload-time = "2025-05-30T19:53:35.447Z" },
{ url = "https://files.pythonhosted.org/packages/fc/85/8df3ca683e1a260117efa31373e91e1c03a4862b7add865662f60a967fdf/uv-0.7.9-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:85c1a63669e49b825923fc876b7467cc3c20d4aa010f522c0ac8b0f30ce2b18e", size = 16821006, upload-time = "2025-05-30T19:53:40.102Z" },
{ url = "https://files.pythonhosted.org/packages/77/d4/c40502ec8f5575798b7ec13ac38c0d5ded84cc32129c1d74a47f8cb7bc0a/uv-0.7.9-py3-none-macosx_11_0_arm64.whl", hash = "sha256:aa10c61668f94515acf93f31dbb8de41b1f2e7a9c41db828f2448cef786498ff", size = 15600148, upload-time = "2025-05-30T19:53:43.513Z" },
{ url = "https://files.pythonhosted.org/packages/4f/dd/4deec6d5b556f4033d6bcc35d6aad70c08acea3f5da749cb34112dced5da/uv-0.7.9-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:9de67ca9ea97db71e5697c1320508e25679fb68d4ee2cea27bbeac499a6bad56", size = 16038119, upload-time = "2025-05-30T19:53:46.504Z" },
{ url = "https://files.pythonhosted.org/packages/cb/c5/2c23763e18566a9a7767738714791203cc97a7530979f61e0fd32d8473a2/uv-0.7.9-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:13ce63524f88228152edf8a9c1c07cecc07d69a2853b32ecc02ac73538aaa5c1", size = 16467257, upload-time = "2025-05-30T19:53:49.592Z" },
{ url = "https://files.pythonhosted.org/packages/da/94/f452d0093f466f9f81a2ede3ea2d48632237b79eb1dc595c7c91be309de5/uv-0.7.9-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3453b7bb65eaea87c9129e27bff701007a8bd1a563249982a1ede7ec4357ced6", size = 17170719, upload-time = "2025-05-30T19:53:52.828Z" },
{ url = "https://files.pythonhosted.org/packages/69/bf/e15ef77520e9bbf00d29a3b639dfaf4fe63996863d6db00c53eba19535c7/uv-0.7.9-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:d7b1e36a8b39600d0f0333bf50c966e83beeaaee1a38380ccb0f16ab45f351c3", size = 18052903, upload-time = "2025-05-30T19:53:56.237Z" },
{ url = "https://files.pythonhosted.org/packages/32/9f/ebf3f9910121ef037c0fe9e7e7fb5f1c25b77d41a65a029d5cbcd85cc886/uv-0.7.9-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ab412ed3d415f07192805788669c8a89755086cdd6fe9f021e1ba21781728031", size = 17771828, upload-time = "2025-05-30T19:53:59.561Z" },
{ url = "https://files.pythonhosted.org/packages/fe/6c/82b4cd471432e721c239ddde2ebee2e674238f3bd88e279e6c71f3cbc775/uv-0.7.9-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cbeb229ee86f69913f5f9236ff1b8ccbae212f559d7f029f8432fa8d9abcc7e0", size = 17886161, upload-time = "2025-05-30T19:54:02.865Z" },
{ url = "https://files.pythonhosted.org/packages/63/e2/922d2eed25647b50a7257a7bfea10c36d9ff910d1451f9a1ba5e31766f41/uv-0.7.9-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f1d654a14d632ecb078969ae7252d89dd98c89205df567a1eff18b5f078a6d00", size = 17442630, upload-time = "2025-05-30T19:54:06.519Z" },
{ url = "https://files.pythonhosted.org/packages/96/b8/45a5598cc8d466bb1669ccf0fc4f556719babfdb7a1983edc24967cb3845/uv-0.7.9-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:f5f47e93a5f948f431ca55d765af6e818c925500807539b976bfda7f94369aa9", size = 16299207, upload-time = "2025-05-30T19:54:09.713Z" },
{ url = "https://files.pythonhosted.org/packages/14/35/7e70639cd175f340138c88290c819214a496dfc52461f30f71e51e776293/uv-0.7.9-py3-none-musllinux_1_1_armv7l.whl", hash = "sha256:267fe25ad3adf024e13617be9fc99bedebf96bf726c6140e48d856e844f21af4", size = 16427594, upload-time = "2025-05-30T19:54:13.318Z" },
{ url = "https://files.pythonhosted.org/packages/5e/f6/90fe538370bc60509cca942b703bca06c06c160ec09816ea6946882278d1/uv-0.7.9-py3-none-musllinux_1_1_i686.whl", hash = "sha256:473d3c6ee07588cff8319079d9225fb393ed177d8d57186fce0d7c1aebff79c0", size = 16751451, upload-time = "2025-05-30T19:54:16.833Z" },
{ url = "https://files.pythonhosted.org/packages/09/cb/c099aba21fb22e50713b42e874075a5b60c6b4d141cc3868ae22f505baa7/uv-0.7.9-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:19792c88058894c10f0370a5e5492bb4a7e6302c439fed9882e73ba2e4b231ef", size = 17594496, upload-time = "2025-05-30T19:54:20.383Z" },
{ url = "https://files.pythonhosted.org/packages/c0/2e/e35b2c5669533075987e1d74da45af891890ae5faee031f90997ed81cada/uv-0.7.9-py3-none-win32.whl", hash = "sha256:298e9b3c65742edcb3097c2cf3f62ec847df174a7c62c85fe139dddaa1b9ab65", size = 17121149, upload-time = "2025-05-30T19:54:23.608Z" },
{ url = "https://files.pythonhosted.org/packages/33/8e/d10425711156d0d5d9a28299950acb3ab4a3987b3150a3c871ac95ce2fdd/uv-0.7.9-py3-none-win_amd64.whl", hash = "sha256:82d76ea988ff1347158c6de46a571b1db7d344219e452bd7b3339c21ec37cfd8", size = 18622895, upload-time = "2025-05-30T19:54:27.427Z" },
{ url = "https://files.pythonhosted.org/packages/72/77/cac29a8fb608b5613b7a0863ec6bd7c2517f3a80b94c419e9d890c12257e/uv-0.7.9-py3-none-win_arm64.whl", hash = "sha256:4d419bcc3138fd787ce77305f1a09e2a984766e0804c6e5a2b54adfa55d2439a", size = 17316542, upload-time = "2025-05-30T19:54:30.697Z" },
]
[[package]]
name = "virtualenv"
version = "20.31.2"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "distlib" },
{ name = "filelock" },
{ name = "platformdirs" },
]
sdist = { url = "https://files.pythonhosted.org/packages/56/2c/444f465fb2c65f40c3a104fd0c495184c4f2336d65baf398e3c75d72ea94/virtualenv-20.31.2.tar.gz", hash = "sha256:e10c0a9d02835e592521be48b332b6caee6887f332c111aa79a09b9e79efc2af", size = 6076316, upload-time = "2025-05-08T17:58:23.811Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/f3/40/b1c265d4b2b62b58576588510fc4d1fe60a86319c8de99fd8e9fec617d2c/virtualenv-20.31.2-py3-none-any.whl", hash = "sha256:36efd0d9650ee985f0cad72065001e66d49a6f24eb44d98980f630686243cf11", size = 6057982, upload-time = "2025-05-08T17:58:21.15Z" },
]
[[package]]
name = "yarl"
version = "1.20.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "idna" },
{ name = "multidict" },
{ name = "propcache" },
]
sdist = { url = "https://files.pythonhosted.org/packages/62/51/c0edba5219027f6eab262e139f73e2417b0f4efffa23bf562f6e18f76ca5/yarl-1.20.0.tar.gz", hash = "sha256:686d51e51ee5dfe62dec86e4866ee0e9ed66df700d55c828a615640adc885307", size = 185258, upload-time = "2025-04-17T00:45:14.661Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/60/82/a59d8e21b20ffc836775fa7daedac51d16bb8f3010c4fcb495c4496aa922/yarl-1.20.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:fdb5204d17cb32b2de2d1e21c7461cabfacf17f3645e4b9039f210c5d3378bf3", size = 145178, upload-time = "2025-04-17T00:42:04.511Z" },
{ url = "https://files.pythonhosted.org/packages/ba/81/315a3f6f95947cfbf37c92d6fbce42a1a6207b6c38e8c2b452499ec7d449/yarl-1.20.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:eaddd7804d8e77d67c28d154ae5fab203163bd0998769569861258e525039d2a", size = 96859, upload-time = "2025-04-17T00:42:06.43Z" },
{ url = "https://files.pythonhosted.org/packages/ad/17/9b64e575583158551b72272a1023cdbd65af54fe13421d856b2850a6ddb7/yarl-1.20.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:634b7ba6b4a85cf67e9df7c13a7fb2e44fa37b5d34501038d174a63eaac25ee2", size = 94647, upload-time = "2025-04-17T00:42:07.976Z" },
{ url = "https://files.pythonhosted.org/packages/2c/29/8f291e7922a58a21349683f6120a85701aeefaa02e9f7c8a2dc24fe3f431/yarl-1.20.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6d409e321e4addf7d97ee84162538c7258e53792eb7c6defd0c33647d754172e", size = 355788, upload-time = "2025-04-17T00:42:09.902Z" },
{ url = "https://files.pythonhosted.org/packages/26/6d/b4892c80b805c42c228c6d11e03cafabf81662d371b0853e7f0f513837d5/yarl-1.20.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:ea52f7328a36960ba3231c6677380fa67811b414798a6e071c7085c57b6d20a9", size = 344613, upload-time = "2025-04-17T00:42:11.768Z" },
{ url = "https://files.pythonhosted.org/packages/d7/0e/517aa28d3f848589bae9593717b063a544b86ba0a807d943c70f48fcf3bb/yarl-1.20.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c8703517b924463994c344dcdf99a2d5ce9eca2b6882bb640aa555fb5efc706a", size = 370953, upload-time = "2025-04-17T00:42:13.983Z" },
{ url = "https://files.pythonhosted.org/packages/5f/9b/5bd09d2f1ad6e6f7c2beae9e50db78edd2cca4d194d227b958955573e240/yarl-1.20.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:077989b09ffd2f48fb2d8f6a86c5fef02f63ffe6b1dd4824c76de7bb01e4f2e2", size = 369204, upload-time = "2025-04-17T00:42:16.386Z" },
{ url = "https://files.pythonhosted.org/packages/9c/85/d793a703cf4bd0d4cd04e4b13cc3d44149470f790230430331a0c1f52df5/yarl-1.20.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0acfaf1da020253f3533526e8b7dd212838fdc4109959a2c53cafc6db611bff2", size = 358108, upload-time = "2025-04-17T00:42:18.622Z" },
{ url = "https://files.pythonhosted.org/packages/6f/54/b6c71e13549c1f6048fbc14ce8d930ac5fb8bafe4f1a252e621a24f3f1f9/yarl-1.20.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b4230ac0b97ec5eeb91d96b324d66060a43fd0d2a9b603e3327ed65f084e41f8", size = 346610, upload-time = "2025-04-17T00:42:20.9Z" },
{ url = "https://files.pythonhosted.org/packages/a0/1a/d6087d58bdd0d8a2a37bbcdffac9d9721af6ebe50d85304d9f9b57dfd862/yarl-1.20.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0a6a1e6ae21cdd84011c24c78d7a126425148b24d437b5702328e4ba640a8902", size = 365378, upload-time = "2025-04-17T00:42:22.926Z" },
{ url = "https://files.pythonhosted.org/packages/02/84/e25ddff4cbc001dbc4af76f8d41a3e23818212dd1f0a52044cbc60568872/yarl-1.20.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:86de313371ec04dd2531f30bc41a5a1a96f25a02823558ee0f2af0beaa7ca791", size = 356919, upload-time = "2025-04-17T00:42:25.145Z" },
{ url = "https://files.pythonhosted.org/packages/04/76/898ae362353bf8f64636495d222c8014c8e5267df39b1a9fe1e1572fb7d0/yarl-1.20.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:dd59c9dd58ae16eaa0f48c3d0cbe6be8ab4dc7247c3ff7db678edecbaf59327f", size = 364248, upload-time = "2025-04-17T00:42:27.475Z" },
{ url = "https://files.pythonhosted.org/packages/1b/b0/9d9198d83a622f1c40fdbf7bd13b224a6979f2e1fc2cf50bfb1d8773c495/yarl-1.20.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:a0bc5e05f457b7c1994cc29e83b58f540b76234ba6b9648a4971ddc7f6aa52da", size = 378418, upload-time = "2025-04-17T00:42:29.333Z" },
{ url = "https://files.pythonhosted.org/packages/c7/ce/1f50c1cc594cf5d3f5bf4a9b616fca68680deaec8ad349d928445ac52eb8/yarl-1.20.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:c9471ca18e6aeb0e03276b5e9b27b14a54c052d370a9c0c04a68cefbd1455eb4", size = 383850, upload-time = "2025-04-17T00:42:31.668Z" },
{ url = "https://files.pythonhosted.org/packages/89/1e/a59253a87b35bfec1a25bb5801fb69943330b67cfd266278eb07e0609012/yarl-1.20.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:40ed574b4df723583a26c04b298b283ff171bcc387bc34c2683235e2487a65a5", size = 381218, upload-time = "2025-04-17T00:42:33.523Z" },
{ url = "https://files.pythonhosted.org/packages/85/b0/26f87df2b3044b0ef1a7cf66d321102bdca091db64c5ae853fcb2171c031/yarl-1.20.0-cp311-cp311-win32.whl", hash = "sha256:db243357c6c2bf3cd7e17080034ade668d54ce304d820c2a58514a4e51d0cfd6", size = 86606, upload-time = "2025-04-17T00:42:35.873Z" },
{ url = "https://files.pythonhosted.org/packages/33/46/ca335c2e1f90446a77640a45eeb1cd8f6934f2c6e4df7db0f0f36ef9f025/yarl-1.20.0-cp311-cp311-win_amd64.whl", hash = "sha256:8c12cd754d9dbd14204c328915e23b0c361b88f3cffd124129955e60a4fbfcfb", size = 93374, upload-time = "2025-04-17T00:42:37.586Z" },
{ url = "https://files.pythonhosted.org/packages/c3/e8/3efdcb83073df978bb5b1a9cc0360ce596680e6c3fac01f2a994ccbb8939/yarl-1.20.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e06b9f6cdd772f9b665e5ba8161968e11e403774114420737f7884b5bd7bdf6f", size = 147089, upload-time = "2025-04-17T00:42:39.602Z" },
{ url = "https://files.pythonhosted.org/packages/60/c3/9e776e98ea350f76f94dd80b408eaa54e5092643dbf65fd9babcffb60509/yarl-1.20.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b9ae2fbe54d859b3ade40290f60fe40e7f969d83d482e84d2c31b9bff03e359e", size = 97706, upload-time = "2025-04-17T00:42:41.469Z" },
{ url = "https://files.pythonhosted.org/packages/0c/5b/45cdfb64a3b855ce074ae607b9fc40bc82e7613b94e7612b030255c93a09/yarl-1.20.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6d12b8945250d80c67688602c891237994d203d42427cb14e36d1a732eda480e", size = 95719, upload-time = "2025-04-17T00:42:43.666Z" },
{ url = "https://files.pythonhosted.org/packages/2d/4e/929633b249611eeed04e2f861a14ed001acca3ef9ec2a984a757b1515889/yarl-1.20.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:087e9731884621b162a3e06dc0d2d626e1542a617f65ba7cc7aeab279d55ad33", size = 343972, upload-time = "2025-04-17T00:42:45.391Z" },
{ url = "https://files.pythonhosted.org/packages/49/fd/047535d326c913f1a90407a3baf7ff535b10098611eaef2c527e32e81ca1/yarl-1.20.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:69df35468b66c1a6e6556248e6443ef0ec5f11a7a4428cf1f6281f1879220f58", size = 339639, upload-time = "2025-04-17T00:42:47.552Z" },
{ url = "https://files.pythonhosted.org/packages/48/2f/11566f1176a78f4bafb0937c0072410b1b0d3640b297944a6a7a556e1d0b/yarl-1.20.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3b2992fe29002fd0d4cbaea9428b09af9b8686a9024c840b8a2b8f4ea4abc16f", size = 353745, upload-time = "2025-04-17T00:42:49.406Z" },
{ url = "https://files.pythonhosted.org/packages/26/17/07dfcf034d6ae8837b33988be66045dd52f878dfb1c4e8f80a7343f677be/yarl-1.20.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4c903e0b42aab48abfbac668b5a9d7b6938e721a6341751331bcd7553de2dcae", size = 354178, upload-time = "2025-04-17T00:42:51.588Z" },
{ url = "https://files.pythonhosted.org/packages/15/45/212604d3142d84b4065d5f8cab6582ed3d78e4cc250568ef2a36fe1cf0a5/yarl-1.20.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf099e2432131093cc611623e0b0bcc399b8cddd9a91eded8bfb50402ec35018", size = 349219, upload-time = "2025-04-17T00:42:53.674Z" },
{ url = "https://files.pythonhosted.org/packages/e6/e0/a10b30f294111c5f1c682461e9459935c17d467a760c21e1f7db400ff499/yarl-1.20.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8a7f62f5dc70a6c763bec9ebf922be52aa22863d9496a9a30124d65b489ea672", size = 337266, upload-time = "2025-04-17T00:42:55.49Z" },
{ url = "https://files.pythonhosted.org/packages/33/a6/6efa1d85a675d25a46a167f9f3e80104cde317dfdf7f53f112ae6b16a60a/yarl-1.20.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:54ac15a8b60382b2bcefd9a289ee26dc0920cf59b05368c9b2b72450751c6eb8", size = 360873, upload-time = "2025-04-17T00:42:57.895Z" },
{ url = "https://files.pythonhosted.org/packages/77/67/c8ab718cb98dfa2ae9ba0f97bf3cbb7d45d37f13fe1fbad25ac92940954e/yarl-1.20.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:25b3bc0763a7aca16a0f1b5e8ef0f23829df11fb539a1b70476dcab28bd83da7", size = 360524, upload-time = "2025-04-17T00:43:00.094Z" },
{ url = "https://files.pythonhosted.org/packages/bd/e8/c3f18660cea1bc73d9f8a2b3ef423def8dadbbae6c4afabdb920b73e0ead/yarl-1.20.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b2586e36dc070fc8fad6270f93242124df68b379c3a251af534030a4a33ef594", size = 365370, upload-time = "2025-04-17T00:43:02.242Z" },
{ url = "https://files.pythonhosted.org/packages/c9/99/33f3b97b065e62ff2d52817155a89cfa030a1a9b43fee7843ef560ad9603/yarl-1.20.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:866349da9d8c5290cfefb7fcc47721e94de3f315433613e01b435473be63daa6", size = 373297, upload-time = "2025-04-17T00:43:04.189Z" },
{ url = "https://files.pythonhosted.org/packages/3d/89/7519e79e264a5f08653d2446b26d4724b01198a93a74d2e259291d538ab1/yarl-1.20.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:33bb660b390a0554d41f8ebec5cd4475502d84104b27e9b42f5321c5192bfcd1", size = 378771, upload-time = "2025-04-17T00:43:06.609Z" },
{ url = "https://files.pythonhosted.org/packages/3a/58/6c460bbb884abd2917c3eef6f663a4a873f8dc6f498561fc0ad92231c113/yarl-1.20.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:737e9f171e5a07031cbee5e9180f6ce21a6c599b9d4b2c24d35df20a52fabf4b", size = 375000, upload-time = "2025-04-17T00:43:09.01Z" },
{ url = "https://files.pythonhosted.org/packages/3b/2a/dd7ed1aa23fea996834278d7ff178f215b24324ee527df53d45e34d21d28/yarl-1.20.0-cp312-cp312-win32.whl", hash = "sha256:839de4c574169b6598d47ad61534e6981979ca2c820ccb77bf70f4311dd2cc64", size = 86355, upload-time = "2025-04-17T00:43:11.311Z" },
{ url = "https://files.pythonhosted.org/packages/ca/c6/333fe0338305c0ac1c16d5aa7cc4841208d3252bbe62172e0051006b5445/yarl-1.20.0-cp312-cp312-win_amd64.whl", hash = "sha256:3d7dbbe44b443b0c4aa0971cb07dcb2c2060e4a9bf8d1301140a33a93c98e18c", size = 92904, upload-time = "2025-04-17T00:43:13.087Z" },
{ url = "https://files.pythonhosted.org/packages/0f/6f/514c9bff2900c22a4f10e06297714dbaf98707143b37ff0bcba65a956221/yarl-1.20.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:2137810a20b933b1b1b7e5cf06a64c3ed3b4747b0e5d79c9447c00db0e2f752f", size = 145030, upload-time = "2025-04-17T00:43:15.083Z" },
{ url = "https://files.pythonhosted.org/packages/4e/9d/f88da3fa319b8c9c813389bfb3463e8d777c62654c7168e580a13fadff05/yarl-1.20.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:447c5eadd750db8389804030d15f43d30435ed47af1313303ed82a62388176d3", size = 96894, upload-time = "2025-04-17T00:43:17.372Z" },
{ url = "https://files.pythonhosted.org/packages/cd/57/92e83538580a6968b2451d6c89c5579938a7309d4785748e8ad42ddafdce/yarl-1.20.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:42fbe577272c203528d402eec8bf4b2d14fd49ecfec92272334270b850e9cd7d", size = 94457, upload-time = "2025-04-17T00:43:19.431Z" },
{ url = "https://files.pythonhosted.org/packages/e9/ee/7ee43bd4cf82dddd5da97fcaddb6fa541ab81f3ed564c42f146c83ae17ce/yarl-1.20.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18e321617de4ab170226cd15006a565d0fa0d908f11f724a2c9142d6b2812ab0", size = 343070, upload-time = "2025-04-17T00:43:21.426Z" },
{ url = "https://files.pythonhosted.org/packages/4a/12/b5eccd1109e2097bcc494ba7dc5de156e41cf8309fab437ebb7c2b296ce3/yarl-1.20.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:4345f58719825bba29895011e8e3b545e6e00257abb984f9f27fe923afca2501", size = 337739, upload-time = "2025-04-17T00:43:23.634Z" },
{ url = "https://files.pythonhosted.org/packages/7d/6b/0eade8e49af9fc2585552f63c76fa59ef469c724cc05b29519b19aa3a6d5/yarl-1.20.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5d9b980d7234614bc4674468ab173ed77d678349c860c3af83b1fffb6a837ddc", size = 351338, upload-time = "2025-04-17T00:43:25.695Z" },
{ url = "https://files.pythonhosted.org/packages/45/cb/aaaa75d30087b5183c7b8a07b4fb16ae0682dd149a1719b3a28f54061754/yarl-1.20.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:af4baa8a445977831cbaa91a9a84cc09debb10bc8391f128da2f7bd070fc351d", size = 353636, upload-time = "2025-04-17T00:43:27.876Z" },
{ url = "https://files.pythonhosted.org/packages/98/9d/d9cb39ec68a91ba6e66fa86d97003f58570327d6713833edf7ad6ce9dde5/yarl-1.20.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:123393db7420e71d6ce40d24885a9e65eb1edefc7a5228db2d62bcab3386a5c0", size = 348061, upload-time = "2025-04-17T00:43:29.788Z" },
{ url = "https://files.pythonhosted.org/packages/72/6b/103940aae893d0cc770b4c36ce80e2ed86fcb863d48ea80a752b8bda9303/yarl-1.20.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ab47acc9332f3de1b39e9b702d9c916af7f02656b2a86a474d9db4e53ef8fd7a", size = 334150, upload-time = "2025-04-17T00:43:31.742Z" },
{ url = "https://files.pythonhosted.org/packages/ef/b2/986bd82aa222c3e6b211a69c9081ba46484cffa9fab2a5235e8d18ca7a27/yarl-1.20.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4a34c52ed158f89876cba9c600b2c964dfc1ca52ba7b3ab6deb722d1d8be6df2", size = 362207, upload-time = "2025-04-17T00:43:34.099Z" },
{ url = "https://files.pythonhosted.org/packages/14/7c/63f5922437b873795d9422cbe7eb2509d4b540c37ae5548a4bb68fd2c546/yarl-1.20.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:04d8cfb12714158abf2618f792c77bc5c3d8c5f37353e79509608be4f18705c9", size = 361277, upload-time = "2025-04-17T00:43:36.202Z" },
{ url = "https://files.pythonhosted.org/packages/81/83/450938cccf732466953406570bdb42c62b5ffb0ac7ac75a1f267773ab5c8/yarl-1.20.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:7dc63ad0d541c38b6ae2255aaa794434293964677d5c1ec5d0116b0e308031f5", size = 364990, upload-time = "2025-04-17T00:43:38.551Z" },
{ url = "https://files.pythonhosted.org/packages/b4/de/af47d3a47e4a833693b9ec8e87debb20f09d9fdc9139b207b09a3e6cbd5a/yarl-1.20.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:f9d02b591a64e4e6ca18c5e3d925f11b559c763b950184a64cf47d74d7e41877", size = 374684, upload-time = "2025-04-17T00:43:40.481Z" },
{ url = "https://files.pythonhosted.org/packages/62/0b/078bcc2d539f1faffdc7d32cb29a2d7caa65f1a6f7e40795d8485db21851/yarl-1.20.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:95fc9876f917cac7f757df80a5dda9de59d423568460fe75d128c813b9af558e", size = 382599, upload-time = "2025-04-17T00:43:42.463Z" },
{ url = "https://files.pythonhosted.org/packages/74/a9/4fdb1a7899f1fb47fd1371e7ba9e94bff73439ce87099d5dd26d285fffe0/yarl-1.20.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:bb769ae5760cd1c6a712135ee7915f9d43f11d9ef769cb3f75a23e398a92d384", size = 378573, upload-time = "2025-04-17T00:43:44.797Z" },
{ url = "https://files.pythonhosted.org/packages/fd/be/29f5156b7a319e4d2e5b51ce622b4dfb3aa8d8204cd2a8a339340fbfad40/yarl-1.20.0-cp313-cp313-win32.whl", hash = "sha256:70e0c580a0292c7414a1cead1e076c9786f685c1fc4757573d2967689b370e62", size = 86051, upload-time = "2025-04-17T00:43:47.076Z" },
{ url = "https://files.pythonhosted.org/packages/52/56/05fa52c32c301da77ec0b5f63d2d9605946fe29defacb2a7ebd473c23b81/yarl-1.20.0-cp313-cp313-win_amd64.whl", hash = "sha256:4c43030e4b0af775a85be1fa0433119b1565673266a70bf87ef68a9d5ba3174c", size = 92742, upload-time = "2025-04-17T00:43:49.193Z" },
{ url = "https://files.pythonhosted.org/packages/d4/2f/422546794196519152fc2e2f475f0e1d4d094a11995c81a465faf5673ffd/yarl-1.20.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:b6c4c3d0d6a0ae9b281e492b1465c72de433b782e6b5001c8e7249e085b69051", size = 163575, upload-time = "2025-04-17T00:43:51.533Z" },
{ url = "https://files.pythonhosted.org/packages/90/fc/67c64ddab6c0b4a169d03c637fb2d2a212b536e1989dec8e7e2c92211b7f/yarl-1.20.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:8681700f4e4df891eafa4f69a439a6e7d480d64e52bf460918f58e443bd3da7d", size = 106121, upload-time = "2025-04-17T00:43:53.506Z" },
{ url = "https://files.pythonhosted.org/packages/6d/00/29366b9eba7b6f6baed7d749f12add209b987c4cfbfa418404dbadc0f97c/yarl-1.20.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:84aeb556cb06c00652dbf87c17838eb6d92cfd317799a8092cee0e570ee11229", size = 103815, upload-time = "2025-04-17T00:43:55.41Z" },
{ url = "https://files.pythonhosted.org/packages/28/f4/a2a4c967c8323c03689383dff73396281ced3b35d0ed140580825c826af7/yarl-1.20.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f166eafa78810ddb383e930d62e623d288fb04ec566d1b4790099ae0f31485f1", size = 408231, upload-time = "2025-04-17T00:43:57.825Z" },
{ url = "https://files.pythonhosted.org/packages/0f/a1/66f7ffc0915877d726b70cc7a896ac30b6ac5d1d2760613603b022173635/yarl-1.20.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:5d3d6d14754aefc7a458261027a562f024d4f6b8a798adb472277f675857b1eb", size = 390221, upload-time = "2025-04-17T00:44:00.526Z" },
{ url = "https://files.pythonhosted.org/packages/41/15/cc248f0504610283271615e85bf38bc014224122498c2016d13a3a1b8426/yarl-1.20.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2a8f64df8ed5d04c51260dbae3cc82e5649834eebea9eadfd829837b8093eb00", size = 411400, upload-time = "2025-04-17T00:44:02.853Z" },
{ url = "https://files.pythonhosted.org/packages/5c/af/f0823d7e092bfb97d24fce6c7269d67fcd1aefade97d0a8189c4452e4d5e/yarl-1.20.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4d9949eaf05b4d30e93e4034a7790634bbb41b8be2d07edd26754f2e38e491de", size = 411714, upload-time = "2025-04-17T00:44:04.904Z" },
{ url = "https://files.pythonhosted.org/packages/83/70/be418329eae64b9f1b20ecdaac75d53aef098797d4c2299d82ae6f8e4663/yarl-1.20.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c366b254082d21cc4f08f522ac201d0d83a8b8447ab562732931d31d80eb2a5", size = 404279, upload-time = "2025-04-17T00:44:07.721Z" },
{ url = "https://files.pythonhosted.org/packages/19/f5/52e02f0075f65b4914eb890eea1ba97e6fd91dd821cc33a623aa707b2f67/yarl-1.20.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:91bc450c80a2e9685b10e34e41aef3d44ddf99b3a498717938926d05ca493f6a", size = 384044, upload-time = "2025-04-17T00:44:09.708Z" },
{ url = "https://files.pythonhosted.org/packages/6a/36/b0fa25226b03d3f769c68d46170b3e92b00ab3853d73127273ba22474697/yarl-1.20.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9c2aa4387de4bc3a5fe158080757748d16567119bef215bec643716b4fbf53f9", size = 416236, upload-time = "2025-04-17T00:44:11.734Z" },
{ url = "https://files.pythonhosted.org/packages/cb/3a/54c828dd35f6831dfdd5a79e6c6b4302ae2c5feca24232a83cb75132b205/yarl-1.20.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:d2cbca6760a541189cf87ee54ff891e1d9ea6406079c66341008f7ef6ab61145", size = 402034, upload-time = "2025-04-17T00:44:13.975Z" },
{ url = "https://files.pythonhosted.org/packages/10/97/c7bf5fba488f7e049f9ad69c1b8fdfe3daa2e8916b3d321aa049e361a55a/yarl-1.20.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:798a5074e656f06b9fad1a162be5a32da45237ce19d07884d0b67a0aa9d5fdda", size = 407943, upload-time = "2025-04-17T00:44:16.052Z" },
{ url = "https://files.pythonhosted.org/packages/fd/a4/022d2555c1e8fcff08ad7f0f43e4df3aba34f135bff04dd35d5526ce54ab/yarl-1.20.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:f106e75c454288472dbe615accef8248c686958c2e7dd3b8d8ee2669770d020f", size = 423058, upload-time = "2025-04-17T00:44:18.547Z" },
{ url = "https://files.pythonhosted.org/packages/4c/f6/0873a05563e5df29ccf35345a6ae0ac9e66588b41fdb7043a65848f03139/yarl-1.20.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:3b60a86551669c23dc5445010534d2c5d8a4e012163218fc9114e857c0586fdd", size = 423792, upload-time = "2025-04-17T00:44:20.639Z" },
{ url = "https://files.pythonhosted.org/packages/9e/35/43fbbd082708fa42e923f314c24f8277a28483d219e049552e5007a9aaca/yarl-1.20.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:3e429857e341d5e8e15806118e0294f8073ba9c4580637e59ab7b238afca836f", size = 422242, upload-time = "2025-04-17T00:44:22.851Z" },
{ url = "https://files.pythonhosted.org/packages/ed/f7/f0f2500cf0c469beb2050b522c7815c575811627e6d3eb9ec7550ddd0bfe/yarl-1.20.0-cp313-cp313t-win32.whl", hash = "sha256:65a4053580fe88a63e8e4056b427224cd01edfb5f951498bfefca4052f0ce0ac", size = 93816, upload-time = "2025-04-17T00:44:25.491Z" },
{ url = "https://files.pythonhosted.org/packages/3f/93/f73b61353b2a699d489e782c3f5998b59f974ec3156a2050a52dfd7e8946/yarl-1.20.0-cp313-cp313t-win_amd64.whl", hash = "sha256:53b2da3a6ca0a541c1ae799c349788d480e5144cac47dba0266c7cb6c76151fe", size = 101093, upload-time = "2025-04-17T00:44:27.418Z" },
{ url = "https://files.pythonhosted.org/packages/ea/1f/70c57b3d7278e94ed22d85e09685d3f0a38ebdd8c5c73b65ba4c0d0fe002/yarl-1.20.0-py3-none-any.whl", hash = "sha256:5d0fe6af927a47a230f31e6004621fd0959eaa915fc62acfafa67ff7229a3124", size = 46124, upload-time = "2025-04-17T00:45:12.199Z" },
]
[[package]]
name = "zipp"
version = "3.22.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/12/b6/7b3d16792fdf94f146bed92be90b4eb4563569eca91513c8609aebf0c167/zipp-3.22.0.tar.gz", hash = "sha256:dd2f28c3ce4bc67507bfd3781d21b7bb2be31103b51a4553ad7d90b84e57ace5", size = 25257, upload-time = "2025-05-26T14:46:32.217Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/ad/da/f64669af4cae46f17b90798a827519ce3737d31dbafad65d391e49643dc4/zipp-3.22.0-py3-none-any.whl", hash = "sha256:fe208f65f2aca48b81f9e6fd8cf7b8b32c26375266b009b413d45306b6148343", size = 9796, upload-time = "2025-05-26T14:46:30.775Z" },
]