pax_global_header 0000666 0000000 0000000 00000000064 14661167274 0014530 g ustar 00root root 0000000 0000000 52 comment=0ad4e667e2edcf30cd42f1cbfc6941e3a9ebfb8c
jabesq-org-pyatmo-6216472/ 0000775 0000000 0000000 00000000000 14661167274 0015266 5 ustar 00root root 0000000 0000000 jabesq-org-pyatmo-6216472/.devcontainer/ 0000775 0000000 0000000 00000000000 14661167274 0020025 5 ustar 00root root 0000000 0000000 jabesq-org-pyatmo-6216472/.devcontainer/Dockerfile.dev 0000664 0000000 0000000 00000001606 14661167274 0022577 0 ustar 00root root 0000000 0000000 ARG VARIANT="3.10"
FROM mcr.microsoft.com/vscode/devcontainers/python:0-${VARIANT} as builder
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
WORKDIR /workspaces
COPY Pipfile ./
# Create Python requirements files from pipenv (lockfile)
RUN pip3 install -U pip \
&& pip3 install pipenv \
&& pipenv lock \
&& pipenv requirements > /tmp/requirements.txt \
&& pipenv requirements --dev > /tmp/requirements_dev.txt
FROM mcr.microsoft.com/vscode/devcontainers/python:0-${VARIANT}
COPY --from=builder /tmp/requirements.txt /tmp/
COPY --from=builder /tmp/requirements_dev.txt /tmp/
# Install Python dependencies from requirements
RUN pip3 install -r /tmp/requirements.txt \
&& pip3 install pdbpp \
&& pip3 install -r /tmp/requirements_dev.txt \
&& rm -rf /tmp/requirements.txt /tmp/requirements_dev.txt pyatmo/
# Set the default shell to bash instead of sh
ENV SHELL /bin/bash
jabesq-org-pyatmo-6216472/.devcontainer/devcontainer.json 0000664 0000000 0000000 00000002256 14661167274 0023406 0 ustar 00root root 0000000 0000000 {
"name": "pyatmo Dev",
"context": "..",
"dockerFile": "./Dockerfile.dev",
"containerEnv": {
"DEVCONTAINER": "1"
},
"postCreateCommand": "pip3 install -e . && pre-commit run flake8",
"runArgs": [
"-e",
"GIT_EDITOR=code --wait"
],
"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",
}
}
jabesq-org-pyatmo-6216472/.github/ 0000775 0000000 0000000 00000000000 14661167274 0016626 5 ustar 00root root 0000000 0000000 jabesq-org-pyatmo-6216472/.github/dependabot.yml 0000664 0000000 0000000 00000001317 14661167274 0021460 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: "pip" # See documentation for possible values
directory: "/" # Location of package manifests
schedule:
interval: "weekly"
# Check for pip updates on Sundays
day: "sunday"
jabesq-org-pyatmo-6216472/.github/workflows/ 0000775 0000000 0000000 00000000000 14661167274 0020663 5 ustar 00root root 0000000 0000000 jabesq-org-pyatmo-6216472/.github/workflows/publish-to-pypi.yml 0000664 0000000 0000000 00000001752 14661167274 0024460 0 ustar 00root root 0000000 0000000 name: Publish 📦 to PyPI
on:
push:
tags:
- "v*"
jobs:
build-n-publish:
name: Build and publish 📦 to PyPI
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Python 3.10
uses: actions/setup-python@v5.1.1
with:
python-version: 3.10.8
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install setuptools wheel 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@master
# with:
# password: ${{ secrets.PYPI_TEST_TOKEN }}
# repository-url: https://test.pypi.org/legacy/
- name: Publish 📦 to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
password: ${{ secrets.pypi_prod_token }}
jabesq-org-pyatmo-6216472/.github/workflows/publish-to-test-pypi.yml 0000664 0000000 0000000 00000001540 14661167274 0025430 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
steps:
- uses: actions/checkout@v4
with:
ref: development
fetch-depth: 0
- name: Set up Python 3.10
uses: actions/setup-python@v5.1.1
with:
python-version: 3.10.8
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install setuptools wheel 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/
jabesq-org-pyatmo-6216472/.github/workflows/pythonpackage.yml 0000664 0000000 0000000 00000003276 14661167274 0024253 0 ustar 00root root 0000000 0000000 name: Python package
on:
push:
branches:
- master
- development
pull_request:
branches:
- master
- development
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.1.1
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.1.1
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
build:
runs-on: ubuntu-latest
strategy:
max-parallel: 4
matrix:
python-version: [3.10.8, 3.11.4]
steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5.1.1
with:
python-version: ${{ matrix.python-version }}
- name: Run tests with tox
run: |
pip install tox tox-gh-actions
tox
jabesq-org-pyatmo-6216472/.github/workflows/release_gh.yml 0000664 0000000 0000000 00000002544 14661167274 0023511 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 }}
jabesq-org-pyatmo-6216472/.gitignore 0000664 0000000 0000000 00000013144 14661167274 0017261 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
jabesq-org-pyatmo-6216472/.pre-commit-config.yaml 0000664 0000000 0000000 00000003266 14661167274 0021556 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: [commit, push]
exclude: ^(fixtures/)
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.4.9
hooks:
- id: ruff
args:
- --fix
- repo: https://github.com/asottile/pyupgrade
rev: v3.16.0
hooks:
- id: pyupgrade
args: [--py310-plus]
exclude: "external_src/int-tools"
- repo: https://github.com/asottile/add-trailing-comma
rev: v3.1.0
hooks:
- id: add-trailing-comma
args: [--py36-plus]
exclude: "external_src/int-tools"
- repo: https://github.com/asottile/yesqa
rev: v1.5.0
hooks:
- id: yesqa
- repo: https://github.com/psf/black
rev: 24.4.2
hooks:
- id: black
language_version: python3
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.10.0
hooks:
- id: mypy
name: mypy
exclude: tests/
additional_dependencies:
- types-requests
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.6.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
- repo: https://github.com/asottile/setup-cfg-fmt
rev: v2.5.0
hooks:
- id: setup-cfg-fmt
args: [--include-version-classifiers]
jabesq-org-pyatmo-6216472/.tool-versions 0000664 0000000 0000000 00000000016 14661167274 0020107 0 ustar 00root root 0000000 0000000 python 3.11.4
jabesq-org-pyatmo-6216472/.vscode/ 0000775 0000000 0000000 00000000000 14661167274 0016627 5 ustar 00root root 0000000 0000000 jabesq-org-pyatmo-6216472/.vscode/tasks.json 0000664 0000000 0000000 00000004633 14661167274 0020655 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": "Flake8",
"detail": "Run flake8 style checker",
"type": "shell",
"command": "pre-commit run flake8 --all-files",
"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"
}
}
]
}
jabesq-org-pyatmo-6216472/CHANGELOG.md 0000664 0000000 0000000 00000020176 14661167274 0017105 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
-
### Deprecated
-
### Removed
-
### Fixed
-
### Security
## [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/pyatmo/compare/v8.0.3...HEAD
[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.1]: 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
jabesq-org-pyatmo-6216472/CODEOWNERS 0000664 0000000 0000000 00000000337 14661167274 0016664 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
jabesq-org-pyatmo-6216472/CODE_OF_CONDUCT.md 0000664 0000000 0000000 00000012122 14661167274 0020063 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.
jabesq-org-pyatmo-6216472/LICENSE.txt 0000664 0000000 0000000 00000002054 14661167274 0017112 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.
jabesq-org-pyatmo-6216472/MANIFEST.in 0000664 0000000 0000000 00000000046 14661167274 0017024 0 ustar 00root root 0000000 0000000 include README.md
include LICENSE.txt
jabesq-org-pyatmo-6216472/Pipfile 0000664 0000000 0000000 00000000626 14661167274 0016605 0 ustar 00root root 0000000 0000000 [[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true
[dev-packages]
black = "*"
bleach = "~=6.1"
docutils = "*"
time-machine = "*"
mypy = "*"
pre-commit = "*"
pytest = "*"
pytest-asyncio = "*"
pytest-cov = "*"
pytest-mock = "*"
requests-mock = "*"
ruff = "*"
tox = ">=3.25"
twine = "*"
no-implicit-optional = "*"
[packages]
requests = "*"
requests-oauthlib = "*"
aiohttp = ">3.8.1"
jabesq-org-pyatmo-6216472/README.md 0000664 0000000 0000000 00000004622 14661167274 0016551 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.
---
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
Clone the repo and install dependencies:
git clone
cd pyatmo
pipenv install --dev
To add the pre-commit hook to your environment run:
pip install pre-commit
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
jabesq-org-pyatmo-6216472/fixtures/ 0000775 0000000 0000000 00000000000 14661167274 0017137 5 ustar 00root root 0000000 0000000 jabesq-org-pyatmo-6216472/fixtures/archive/ 0000775 0000000 0000000 00000000000 14661167274 0020560 5 ustar 00root root 0000000 0000000 jabesq-org-pyatmo-6216472/fixtures/archive/camera_data_empty.json 0000664 0000000 0000000 00000000130 14661167274 0025104 0 ustar 00root root 0000000 0000000 {
"status": "ok",
"time_exec": 0.03621506690979,
"time_server": 1560626960
} jabesq-org-pyatmo-6216472/fixtures/archive/camera_data_events_until.json 0000664 0000000 0000000 00000010566 14661167274 0026503 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
} jabesq-org-pyatmo-6216472/fixtures/archive/camera_home_data.json 0000664 0000000 0000000 00000040022 14661167274 0024702 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
} jabesq-org-pyatmo-6216472/fixtures/archive/camera_home_data_disconnected.json 0000664 0000000 0000000 00000022163 14661167274 0027432 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
} jabesq-org-pyatmo-6216472/fixtures/archive/camera_home_data_no_homes.json 0000664 0000000 0000000 00000000540 14661167274 0026572 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
} jabesq-org-pyatmo-6216472/fixtures/archive/camera_image_sample.jpg 0000664 0000000 0000000 00000001237 14661167274 0025220 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ÞÜž§½ ÿÙ jabesq-org-pyatmo-6216472/fixtures/archive/camera_ping.json 0000664 0000000 0000000 00000000163 14661167274 0023720 0 ustar 00root root 0000000 0000000 {
"local_url": "http://192.168.0.123/678460a0d47e5618699fb31169e2b47d",
"product_name": "Welcome Netatmo"
} jabesq-org-pyatmo-6216472/fixtures/archive/camera_set_state_error.json 0000664 0000000 0000000 00000000146 14661167274 0026170 0 ustar 00root root 0000000 0000000 {
"error": {
"code": 21,
"message": "Invalid device_id, 12:34:56:00:f1:ff"
}
} jabesq-org-pyatmo-6216472/fixtures/archive/camera_set_state_error_already_on.json 0000664 0000000 0000000 00000000560 14661167274 0030365 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"
}
]
}
} jabesq-org-pyatmo-6216472/fixtures/archive/camera_set_state_error_wrong_parameter.json 0000664 0000000 0000000 00000000175 14661167274 0031446 0 ustar 00root root 0000000 0000000 {
"error": {
"code": 21,
"message": "cannot set property floodlight for module 12:34:56:00:f1:62"
}
} jabesq-org-pyatmo-6216472/fixtures/archive/camera_set_state_ok.json 0000664 0000000 0000000 00000000065 14661167274 0025450 0 ustar 00root root 0000000 0000000 {
"status": "ok",
"time_server": 1582932411
} jabesq-org-pyatmo-6216472/fixtures/archive/error_scope.json 0000664 0000000 0000000 00000000122 14661167274 0023770 0 ustar 00root root 0000000 0000000 {"error":{"code":13,"message":"Application does not have the good scope rights"}}
jabesq-org-pyatmo-6216472/fixtures/archive/home_coach_no_devices.json 0000664 0000000 0000000 00000000737 14661167274 0025745 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
} jabesq-org-pyatmo-6216472/fixtures/archive/home_coach_simple.json 0000664 0000000 0000000 00000015364 14661167274 0025122 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
} jabesq-org-pyatmo-6216472/fixtures/archive/home_data_empty.json 0000664 0000000 0000000 00000000151 14661167274 0024607 0 ustar 00root root 0000000 0000000 {
"body": {},
"status": "ok",
"time_exec": 0.056135892868042,
"time_server": 1559171003
} jabesq-org-pyatmo-6216472/fixtures/archive/home_data_no_devices.json 0000664 0000000 0000000 00000001511 14661167274 0025570 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
} jabesq-org-pyatmo-6216472/fixtures/archive/home_data_no_homes.json 0000664 0000000 0000000 00000000661 14661167274 0025266 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
} jabesq-org-pyatmo-6216472/fixtures/archive/home_data_nohomename.json 0000664 0000000 0000000 00000037167 14661167274 0025620 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
} jabesq-org-pyatmo-6216472/fixtures/archive/home_data_simple.json 0000664 0000000 0000000 00000055627 14661167274 0024764 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
} jabesq-org-pyatmo-6216472/fixtures/archive/home_status_empty.json 0000664 0000000 0000000 00000000105 14661167274 0025220 0 ustar 00root root 0000000 0000000 {
"status": "ok",
"time_server": 1559292039,
"body": {}
} jabesq-org-pyatmo-6216472/fixtures/archive/home_status_error_and_data.json 0000664 0000000 0000000 00000007470 14661167274 0027042 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"
}
]
}
} jabesq-org-pyatmo-6216472/fixtures/archive/home_status_error_invalid_id.json 0000664 0000000 0000000 00000000114 14661167274 0027375 0 ustar 00root root 0000000 0000000 {
"error": {
"code": 21,
"message": "Invalid id"
}
} jabesq-org-pyatmo-6216472/fixtures/archive/home_status_error_missing_home_id.json 0000664 0000000 0000000 00000000121 14661167274 0030426 0 ustar 00root root 0000000 0000000 {
"error": {
"code": 10,
"message": "Missing home_id"
}
} jabesq-org-pyatmo-6216472/fixtures/archive/home_status_error_missing_parameters.json 0000664 0000000 0000000 00000000124 14661167274 0031170 0 ustar 00root root 0000000 0000000 {
"error": {
"code": 10,
"message": "Missing parameters"
}
} jabesq-org-pyatmo-6216472/fixtures/archive/home_status_error_mode_not_authorized.json 0000664 0000000 0000000 00000000125 14661167274 0031337 0 ustar 00root root 0000000 0000000 {
"error": {
"code": 21,
"message": "mode not authorized"
}
} jabesq-org-pyatmo-6216472/fixtures/archive/invalid_grant.json 0000664 0000000 0000000 00000000040 14661167274 0024266 0 ustar 00root root 0000000 0000000 {
"error": "invalid_grant"
} jabesq-org-pyatmo-6216472/fixtures/archive/oauth2_token.json 0000664 0000000 0000000 00000000636 14661167274 0024062 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
} jabesq-org-pyatmo-6216472/fixtures/archive/public_data_error_mongo.json 0000664 0000000 0000000 00000000263 14661167274 0026333 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
}
}
jabesq-org-pyatmo-6216472/fixtures/archive/public_data_simple.json 0000664 0000000 0000000 00000026314 14661167274 0025301 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"
}
}
]
} jabesq-org-pyatmo-6216472/fixtures/archive/thermostat_data_simple.json 0000664 0000000 0000000 00000025524 14661167274 0026217 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
} jabesq-org-pyatmo-6216472/fixtures/archive/too_many_connections.json 0000664 0000000 0000000 00000000047 14661167274 0025703 0 ustar 00root root 0000000 0000000 {
"error": "too_many_connections"
} jabesq-org-pyatmo-6216472/fixtures/archive/weatherstation_data_simple.json 0000664 0000000 0000000 00000055176 14661167274 0027074 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
} jabesq-org-pyatmo-6216472/fixtures/archive/weatherstation_data_unreachable_station.json 0000664 0000000 0000000 00000024533 14661167274 0031606 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
} jabesq-org-pyatmo-6216472/fixtures/archive/weatherstation_measure.json 0000664 0000000 0000000 00000001412 14661167274 0026233 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
} jabesq-org-pyatmo-6216472/fixtures/getevents.json 0000664 0000000 0000000 00000015174 14661167274 0022046 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
} jabesq-org-pyatmo-6216472/fixtures/gethomecoachsdata.json 0000664 0000000 0000000 00000015364 14661167274 0023506 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 00000000276 14661167274 0020311 x ustar 00root root 0000000 0000000 190 path=jabesq-org-pyatmo-6216472/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 14661167274 0017150 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 00000000276 14661167274 0020533 x ustar 00root root 0000000 0000000 190 path=jabesq-org-pyatmo-6216472/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 14661167274 0017375 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
} jabesq-org-pyatmo-6216472/fixtures/getpublicdata.json 0000664 0000000 0000000 00000015767 14661167274 0022662 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"
}
}
]
}
jabesq-org-pyatmo-6216472/fixtures/getstationsdata.json 0000664 0000000 0000000 00000051274 14661167274 0023241 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
}
jabesq-org-pyatmo-6216472/fixtures/home_multi_status_error_disconnected.json 0000664 0000000 0000000 00000000356 14661167274 0027536 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
} jabesq-org-pyatmo-6216472/fixtures/home_status_error_disconnected.json 0000664 0000000 0000000 00000000356 14661167274 0026324 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
} jabesq-org-pyatmo-6216472/fixtures/home_status_error_invalid_schedule_id.json 0000664 0000000 0000000 00000000157 14661167274 0027637 0 ustar 00root root 0000000 0000000 {
"error": {
"code": 21,
"message": "schedule is not therm schedule"
}
} jabesq-org-pyatmo-6216472/fixtures/home_status_error_mode_is_missing.json 0000664 0000000 0000000 00000000121 14661167274 0027020 0 ustar 00root root 0000000 0000000 {
"error": {
"code": 10,
"message": "mode is missing"
}
} jabesq-org-pyatmo-6216472/fixtures/home_status_simple.json 0000664 0000000 0000000 00000010231 14661167274 0023733 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
}
]
}
}
} jabesq-org-pyatmo-6216472/fixtures/homesdata.json 0000664 0000000 0000000 00000056371 14661167274 0022013 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:10:f1:66",
"12:34:56:00:e3:9b",
"0009999992",
"0009999993"
]
},
{
"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"
]
},
{
"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"
]
},
{
"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"
]
}
],
"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: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: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"
]
},
{
"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: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"
}
],
"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,
"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
}
jabesq-org-pyatmo-6216472/fixtures/homesdata_emtpy_home.json 0000664 0000000 0000000 00000021773 14661167274 0024237 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
} jabesq-org-pyatmo-6216472/fixtures/homesdata_multi.json 0000664 0000000 0000000 00000607333 14661167274 0023225 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
} jabesq-org-pyatmo-6216472/fixtures/homestatus_91763b24c43d3e344f424e8b.json 0000664 0000000 0000000 00000026373 14661167274 0025462 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: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: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
}
],
"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
}
]
}
}
}
jabesq-org-pyatmo-6216472/fixtures/homestatus_91763b24c43d3e344f424e8c.json 0000664 0000000 0000000 00000001006 14661167274 0025445 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
}
]
}
}
} jabesq-org-pyatmo-6216472/fixtures/ping.json 0000664 0000000 0000000 00000000163 14661167274 0020767 0 ustar 00root root 0000000 0000000 {
"local_url": "http://192.168.0.123/678460a0d47e5618699fb31169e2b47d",
"product_name": "Welcome Netatmo"
} jabesq-org-pyatmo-6216472/fixtures/status_ok.json 0000664 0000000 0000000 00000000131 14661167274 0022041 0 ustar 00root root 0000000 0000000 {
"status": "ok",
"time_exec": 0.020781993865967,
"time_server": 1559162635
} jabesq-org-pyatmo-6216472/pyproject.toml 0000664 0000000 0000000 00000012616 14661167274 0020210 0 ustar 00root root 0000000 0000000 [build-system]
requires = ["wheel", "setuptools", "attrs>=17.1"]
build-backend = "setuptools.build_meta"
[tool.pytest.ini_options]
minversion = "7.0"
asyncio_mode = "auto"
[tool.ruff]
select = [
"B002", # Python does not support the unary prefix increment
"B007", # Loop control variable {name} not used within loop body
"B014", # Exception handler with duplicate exception
"B023", # Function definition does not bind loop variable {name}
"B026", # Star-arg unpacking after a keyword argument is strongly discouraged
"C", # complexity
"COM818", # Trailing comma on bare tuple prohibited
"D", # docstrings
"DTZ003", # Use datetime.now(tz=) instead of datetime.utcnow()
"DTZ004", # Use datetime.fromtimestamp(ts, tz=) instead of datetime.utcfromtimestamp(ts)
"E", # pycodestyle
"F", # pyflakes/autoflake
"G", # flake8-logging-format
"I", # isort
"ICN001", # import concentions; {name} should be imported as {asname}
"ISC001", # Implicitly concatenated string literals on one line
"N804", # First argument of a class method should be named cls
"N805", # First argument of a method should be named self
"N815", # Variable {name} in class scope should not be mixedCase
"PGH001", # No builtin eval() allowed
"PGH004", # Use specific rule codes when using noqa
"PLC0414", # Useless import alias. Import alias does not rename original package.
"PLC", # pylint
"PLE", # pylint
"PLR", # pylint
"PLW", # pylint
"Q000", # Double quotes found but single quotes preferred
"RUF006", # Store a reference to the return value of asyncio.create_task
"S102", # Use of exec detected
"S103", # bad-file-permissions
"S108", # hardcoded-temp-file
"S306", # suspicious-mktemp-usage
"S307", # suspicious-eval-usage
"S313", # suspicious-xmlc-element-tree-usage
"S314", # suspicious-xml-element-tree-usage
"S315", # suspicious-xml-expat-reader-usage
"S316", # suspicious-xml-expat-builder-usage
"S317", # suspicious-xml-sax-usage
"S318", # suspicious-xml-mini-dom-usage
"S319", # suspicious-xml-pull-dom-usage
"S320", # suspicious-xmle-tree-usage
"S601", # paramiko-call
"S602", # subprocess-popen-with-shell-equals-true
"S604", # call-with-shell-equals-true
"S608", # hardcoded-sql-expression
"S609", # unix-command-wildcard-injection
"SIM105", # Use contextlib.suppress({exception}) instead of try-except-pass
"SIM117", # Merge with-statements that use the same scope
"SIM118", # Use {key} in {dict} instead of {key} in {dict}.keys()
"SIM201", # Use {left} != {right} instead of not {left} == {right}
"SIM208", # Use {expr} instead of not (not {expr})
"SIM212", # Use {a} if {a} else {b} instead of {b} if not {a} else {a}
"SIM300", # Yoda conditions. Use 'age == 42' instead of '42 == age'.
"SIM401", # Use get from dict with default instead of an if block
"T100", # Trace found: {name} used
"T20", # flake8-print
"TID251", # Banned imports
"TRY004", # Prefer TypeError exception for invalid type
"TRY200", # Use raise from to specify exception cause
"TRY302", # Remove exception handler; error is immediately re-raised
"UP", # pyupgrade
"W", # pycodestyle
]
ignore = [
"D202", # No blank lines allowed after function docstring
"D203", # 1 blank line required before class docstring
"D213", # Multi-line docstring summary should start at the second line
"D406", # Section name should end with a newline
"D407", # Section name underlining
"E501", # line too long
"E731", # do not assign a lambda expression, use a def
# False positives https://github.com/astral-sh/ruff/issues/5386
"PLC0208", # Use a sequence type instead of a `set` when iterating over values
"PLR0911", # Too many return statements ({returns} > {max_returns})
"PLR0912", # Too many branches ({branches} > {max_branches})
"PLR0913", # Too many arguments to function call ({c_args} > {max_args})
"PLR0915", # Too many statements ({statements} > {max_statements})
"PLR2004", # Magic value used in comparison, consider replacing {value} with a constant variable
"PLW2901", # Outer {outer_kind} variable {name} overwritten by inner {inner_kind} target
"UP006", # keep type annotation style as is
"UP007", # keep type annotation style as is
# Ignored due to performance: https://github.com/charliermarsh/ruff/issues/2923
"UP038", # Use `X | Y` in `isinstance` call instead of `(X, Y)`
]
[tool.ruff.flake8-pytest-style]
fixture-parentheses = false
[tool.ruff.flake8-tidy-imports.banned-api]
"pytz".msg = "use zoneinfo instead"
[tool.ruff.isort]
force-sort-within-sections = true
combine-as-imports = true
split-on-trailing-comma = false
[tool.ruff.per-file-ignores]
# Allow for main entry & scripts to write to stdout
"src/pyatmo/__main__.py" = ["T201"]
# Exceptions for tests
"tests/*" = ["D10"]
[tool.ruff.mccabe]
max-complexity = 25
[tool.setuptools_scm]
local_scheme = "no-local-version"
tag_regex = "^(?Pv)?(?P[^\\+]+)(?P.*)?$"
write_to = "src/pyatmo/__version__.py"
write_to_template = '''"""
Pyatmo: Simple API to access Netatmo devices and data
DO NO EDIT THIS FILE - VERSION IS MANAGED BY SETUPTOOLS_SCM
"""
__version__ = "{version}"
'''
jabesq-org-pyatmo-6216472/setup.cfg 0000664 0000000 0000000 00000002352 14661167274 0017111 0 ustar 00root root 0000000 0000000 [metadata]
name = pyatmo
description = Simple API to access Netatmo weather station data from any Python 3 script. Designed for Home Assistant (but not only)
long_description = file: README.md
long_description_content_type = text/markdown
url = https://github.com/jabesq/pyatmo
author = Hugo Dupras
author_email = jabesq@gmail.com
license = MIT
license_files = LICENSE.txt
classifiers =
License :: OSI Approved :: MIT License
Programming Language :: Python :: 3
Programming Language :: Python :: 3 :: Only
Programming Language :: Python :: 3.10
Programming Language :: Python :: 3.11
Programming Language :: Python :: 3.12
Programming Language :: Python :: Implementation :: CPython
Programming Language :: Python :: Implementation :: PyPy
Topic :: Home Automation
[options]
packages = find:
install_requires =
aiohttp>=3.7.4,<4.0.0
oauthlib~=3.1
requests~=2.24
requests-oauthlib>=1.3,<3.0
python_requires = >=3.10
include_package_data = True
package_dir = =src
setup_requires =
setuptools-scm
[options.packages.find]
where = src
exclude = tests
[options.package_data]
pyatmo = py.typed
[pep8]
max-line-length = 88
ignore = W503, E501
[mypy]
ignore_missing_imports = True
[isort]
profile = black
jabesq-org-pyatmo-6216472/src/ 0000775 0000000 0000000 00000000000 14661167274 0016055 5 ustar 00root root 0000000 0000000 jabesq-org-pyatmo-6216472/src/pyatmo/ 0000775 0000000 0000000 00000000000 14661167274 0017366 5 ustar 00root root 0000000 0000000 jabesq-org-pyatmo-6216472/src/pyatmo/__init__.py 0000664 0000000 0000000 00000001345 14661167274 0021502 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,
ApiErrorThrottling,
ApiHomeReachabilityError,
InvalidHome,
InvalidRoom,
NoDevice,
NoSchedule,
)
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",
"ApiErrorThrottling",
"ApiHomeReachabilityError",
"AsyncAccount",
"InvalidHome",
"InvalidRoom",
"Home",
"Module",
"Room",
"DeviceType",
"NoDevice",
"NoSchedule",
"const",
"modules",
]
jabesq-org-pyatmo-6216472/src/pyatmo/account.py 0000664 0000000 0000000 00000025015 14661167274 0021377 0 ustar 00root root 0000000 0000000 """Support for a Netatmo account."""
from __future__ import annotations
import logging
from typing import TYPE_CHECKING, Any
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 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."""
await getattr(self.homes[home_id].modules[module_id], "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
jabesq-org-pyatmo-6216472/src/pyatmo/auth.py 0000664 0000000 0000000 00000014437 14661167274 0020712 0 ustar 00root root 0000000 0000000 """Support for Netatmo authentication."""
from __future__ import annotations
from abc import ABC, abstractmethod
import asyncio
from json import JSONDecodeError
import logging
from typing import Any
from aiohttp import ClientError, ClientResponse, ClientSession, ContentTypeError
from pyatmo.const import (
AUTHORIZATION_HEADER,
DEFAULT_BASE_URL,
ERRORS,
WEBHOOK_URL_ADD_ENDPOINT,
WEBHOOK_URL_DROP_ENDPOINT,
)
from pyatmo.exceptions import ApiError, ApiErrorThrottling
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,
timeout: int = 5,
) -> bytes:
"""Wrap async get requests."""
try:
access_token = await self.async_get_access_token()
except ClientError as err:
raise ApiError(f"Access token failure: {err}") from err
headers = {AUTHORIZATION_HEADER: f"Bearer {access_token}"}
req_args = {"data": params if params is not None else {}}
url = (base_url or self.base_url) + endpoint
async with self.websession.get(
url,
**req_args, # type: ignore
headers=headers,
timeout=timeout,
) as resp:
resp_content = await resp.read()
if resp.headers.get("content-type") == "image/jpeg":
return resp_content
raise ApiError(
f"{resp.status} - "
f"invalid content-type in response"
f"when accessing '{url}'",
)
async def async_post_api_request(
self,
endpoint: str,
base_url: str | None = None,
params: dict[str, Any] | None = None,
timeout: int = 5,
) -> ClientResponse:
"""Wrap async post requests."""
return await self.async_post_request(
url=(base_url or self.base_url) + endpoint,
params=params,
timeout=timeout,
)
async def async_post_request(
self,
url: str,
params: dict[str, Any] | None = None,
timeout: int = 5,
) -> 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=timeout,
) as resp:
return await self.process_response(resp, url)
async def get_access_token(self):
"""Get access token."""
try:
return await self.async_get_access_token()
except ClientError as err:
raise ApiError(f"Access token failure: {err}") from err
def prepare_request_arguments(self, params):
"""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, url):
"""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, resp_status, url):
"""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 == 403 and resp_json["error"]["code"] == 26:
raise ApiErrorThrottling(
message,
)
else:
raise ApiError(
message,
)
except (JSONDecodeError, ContentTypeError) as exc:
raise ApiError(
f"{resp_status} - "
f"{ERRORS.get(resp_status, '')} - "
f"when accessing '{url}'",
) from exc
async def handle_success_response(self, resp, resp_content):
"""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 asyncio.exceptions.TimeoutError as exc:
raise ApiError("Webhook registration timed out") 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 asyncio.exceptions.TimeoutError as exc:
raise ApiError("Webhook registration timed out") from exc
else:
LOG.debug("dropwebhook: %s", resp)
jabesq-org-pyatmo-6216472/src/pyatmo/const.py 0000664 0000000 0000000 00000006740 14661167274 0021075 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
]
MANUAL = "manual"
MAX = "max"
HOME = "home"
FROSTGUARD = "hg"
SCHEDULES = "schedules"
EVENTS = "events"
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"
jabesq-org-pyatmo-6216472/src/pyatmo/event.py 0000664 0000000 0000000 00000005554 14661167274 0021072 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 pyatmo.const import RawData
EVENT_ATTRIBUTES_MAP = {"id": "entity_id", "type": "event_type", "time": "event_time"}
class EventTypes(Enum):
"""Event types."""
# temporarily disable locally-disabled and locally-enabled
# pylint: disable=C0103
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"
# pylint: enable=C0103
class VideoStatus(Enum):
"""Video states."""
# temporarily disable locally-disabled and locally-enabled
# pylint: disable=C0103
available = "available"
deleted = "deleted"
# pylint: enable=C0103
@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
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)
jabesq-org-pyatmo-6216472/src/pyatmo/exceptions.py 0000664 0000000 0000000 00000001563 14661167274 0022126 0 ustar 00root root 0000000 0000000 """Exceptions for pyatmo."""
class NoSchedule(Exception):
"""Raised when no schedule is found."""
pass
class InvalidSchedule(Exception):
"""Raised when an invalid schedule is encountered."""
pass
class InvalidHome(Exception):
"""Raised when an invalid home is encountered."""
pass
class InvalidRoom(Exception):
"""Raised when an invalid room is encountered."""
pass
class NoDevice(Exception):
"""Raised when no device is found."""
pass
class ApiError(Exception):
"""Raised when an API error is encountered."""
pass
class ApiErrorThrottling(ApiError):
"""Raised when an API error is encountered."""
pass
class ApiHomeReachabilityError(ApiError):
"""Raised when an API error is encountered."""
pass
class InvalidState(Exception):
"""Raised when an invalid state is encountered."""
pass
jabesq-org-pyatmo-6216472/src/pyatmo/helpers.py 0000664 0000000 0000000 00000003024 14661167274 0021401 0 ustar 00root root 0000000 0000000 """Collection of helper functions."""
from __future__ import annotations
import logging
from typing import Any, cast
from pyatmo.const import RawData
from pyatmo.exceptions import NoDevice
LOG: logging.Logger = logging.getLogger(__name__)
def fix_id(raw_data: RawData) -> dict[str, Any]:
"""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: Any, tag: str) -> dict[str, Any]:
"""Extract raw data from server response."""
raw_data = {}
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)
raise NoDevice("No device found, errors in response")
if tag == "homes":
return {
tag: fix_id(resp["body"].get(tag)),
"errors": resp["body"].get("errors", []),
}
if not (raw_data := fix_id(resp["body"].get(tag))):
LOG.debug("Server response (tag: %s): %s", tag, resp)
raise NoDevice("No device data available")
return {tag: raw_data, "errors": resp["body"].get("errors", [])}
jabesq-org-pyatmo-6216472/src/pyatmo/home.py 0000664 0000000 0000000 00000032106 14661167274 0020672 0 ustar 00root root 0000000 0000000 """Module to represent a Netatmo home."""
from __future__ import annotations
import logging
from typing import TYPE_CHECKING, Any
from aiohttp import ClientResponse
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.event import Event
from pyatmo.exceptions import (
ApiHomeReachabilityError,
InvalidSchedule,
InvalidState,
NoSchedule,
)
from pyatmo.modules import Module
from pyatmo.person import Person
from pyatmo.room import Room
from pyatmo.schedule import Schedule
if TYPE_CHECKING:
from pyatmo.auth import AbstractAsyncAuth
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: str | 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 = 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 getattr(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 = 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)
self.schedules = {
s["id"]: Schedule(home=self, raw_data=s)
for s in raw_data.get(SCHEDULES, [])
}
async def update(
self,
raw_data: RawData,
do_raise_for_reachability_error=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 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"):
setattr(
module,
"events",
[
event
for event in self.events.values()
if getattr(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
):
raise ApiHomeReachabilityError(
"No Home update could be performed, all modules unreachable and not updated",
)
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),
None,
)
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,
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):
raise NoSchedule(f"{schedule_id} is not a valid schedule id.")
if mode is None:
raise NoSchedule(f"{mode} is not a valid mode.")
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):
raise NoSchedule(f"{schedule_id} is not a valid schedule id")
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):
raise InvalidState("Data for '/set_state' contains errors.")
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: int,
temps: dict[str, int],
) -> None:
"""Set the scheduled room temperature for the given schedule ID."""
selected_schedule = self.get_selected_schedule()
if selected_schedule is None:
raise NoSchedule("Could not determine selected schedule.")
zones = []
timetable_entries = [
{
"m_offset": timetable_entry.m_offset,
"zone_id": timetable_entry.zone_id,
}
for timetable_entry in selected_schedule.timetable
]
for zone in selected_schedule.zones:
new_zone = {
"id": zone.entity_id,
"name": zone.name,
"type": zone.type,
"rooms": [],
}
for room in zone.rooms:
temp = room.therm_setpoint_temperature
if zone.entity_id == zone_id and room.entity_id in temps:
temp = temps[room.entity_id]
new_zone["rooms"].append(
{"id": room.entity_id, "therm_setpoint_temperature": temp},
)
zones.append(new_zone)
schedule = {
"away_temp": selected_schedule.away_temp,
"hg_temp": selected_schedule.hg_temp,
"timetable": timetable_entries,
"zones": zones,
}
await self.async_sync_schedule(selected_schedule.entity_id, schedule)
async def async_sync_schedule(
self,
schedule_id: str,
schedule: dict[str, Any],
) -> None:
"""Modify an existing schedule."""
if not is_valid_schedule(schedule):
raise InvalidSchedule("Data for '/synchomeschedule' contains errors.")
LOG.debug(
"Setting schedule (%s) for home (%s) to %s",
schedule_id,
self.entity_id,
schedule,
)
resp = await self.auth.async_post_api_request(
endpoint=SYNCHOMESCHEDULE_ENDPOINT,
params={
"params": {
"home_id": self.entity_id,
"schedule_id": schedule_id,
"name": "Default",
},
"json": schedule,
},
)
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: dict[str, Any]) -> bool:
"""Check schedule."""
return schedule is not None
jabesq-org-pyatmo-6216472/src/pyatmo/modules/ 0000775 0000000 0000000 00000000000 14661167274 0021036 5 ustar 00root root 0000000 0000000 jabesq-org-pyatmo-6216472/src/pyatmo/modules/__init__.py 0000664 0000000 0000000 00000004050 14661167274 0023146 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,
NLunknown,
)
from .module import Camera, Dimmer, Fan, Module, Shutter, Switch
from .netatmo import (
NCO,
NDB,
NHC,
NIS,
NOC,
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",
"Camera",
"Dimmer",
"EBU",
"Fan",
"Location",
"Module",
"NACamDoorTag",
"NACamera",
"NAMain",
"NAModule1",
"NAModule2",
"NAModule3",
"NAModule4",
"NAPlug",
"NATherm1",
"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",
"NLunknown",
"NLUO",
"NLUP",
"NLV",
"NOC",
"NRV",
"NSD",
"OTH",
"OTM",
"Place",
"PublicWeatherArea",
"Shutter",
"Switch",
"TPSRS",
"Z3L",
]
jabesq-org-pyatmo-6216472/src/pyatmo/modules/base_class.py 0000664 0000000 0000000 00000012323 14661167274 0023510 0 ustar 00root root 0000000 0000000 """Base class for Netatmo entities."""
from __future__ import annotations
from abc import ABC
import bisect
from collections.abc import Iterable
from dataclasses import dataclass
import logging
from operator import itemgetter
from typing import TYPE_CHECKING, Any
from pyatmo.const import MAX_HISTORY_TIME_FRAME, RawData
from pyatmo.modules.device_types import DeviceType
if TYPE_CHECKING:
from pyatmo.event import EventTypes
from pyatmo.home import Home
from time import time
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, y: 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"),
}
def default(key: str, val: Any) -> Any:
"""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[str, [int, int]] | {}
name: str | None
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)
if (
self.bridge
and self.bridge in self.home.modules
and getattr(self, "device_category") == "weather"
):
self.name = update_name(self.name, self.home.modules[self.bridge].name)
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, 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):
if hist_f[i][0] == time:
hist_f[i] = (time, value, self.entity_id)
i = None
if i is not None:
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: int, to_ts: int | None = None):
"""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) -> Iterable[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:
"""Initialize self."""
if data is None:
return
self.altitude = data.get("altitude")
self.city = data.get("city")
self.country = data.get("country")
self.timezone = data.get("timezone")
self.location = Location(*list(data.get("location", [])))
jabesq-org-pyatmo-6216472/src/pyatmo/modules/bticino.py 0000664 0000000 0000000 00000002263 14661167274 0023042 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): # pylint: disable=too-many-ancestors
"""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."""
jabesq-org-pyatmo-6216472/src/pyatmo/modules/device_types.py 0000664 0000000 0000000 00000026105 14661167274 0024077 0 ustar 00root root 0000000 0000000 """Definitions of Netatmo devices types."""
from __future__ import annotations
from enum import Enum
import logging
LOG = logging.getLogger(__name__)
# pylint: disable=W0613
class DeviceType(str, Enum):
"""Class to represent Netatmo device types."""
# temporarily disable locally-disabled and locally-enabled
# pylint: disable=C0103
# Climate/Energy
NAPlug = "NAPlug" # Smart thermostat gateway
NATherm1 = "NATherm1" # Smart thermostat
NRV = "NRV" # Smart valve
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)
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" # 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" # Global 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
# Magellan
NLDP = "NLDP" # Pocket Remote
# pylint: enable=C0103
@classmethod
def _missing_(cls, key):
"""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
# pylint: disable=C0103
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"
# pylint: enable=C0103
DEVICE_CATEGORY_MAP: dict[DeviceType, DeviceCategory] = {
DeviceType.NRV: DeviceCategory.climate,
DeviceType.NATherm1: DeviceCategory.climate,
DeviceType.OTM: DeviceCategory.climate,
DeviceType.NOC: 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.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.NLD: DeviceCategory.switch,
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.OTH: ("Netatmo", "OpenTherm Gateway"),
DeviceType.OTM: ("Netatmo", "OpenTherm Modulating Thermostat"),
# Netatmo Cameras/Security
DeviceType.NOC: ("Netatmo", "Smart Outdoor Camera"),
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", "Dimmer"),
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.EBU: ("3rd Party", "EBU gas meter"),
DeviceType.NLPD: ("Drivia", "Dry contact"),
}
jabesq-org-pyatmo-6216472/src/pyatmo/modules/idiamant.py 0000664 0000000 0000000 00000001257 14661167274 0023203 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."""
...
jabesq-org-pyatmo-6216472/src/pyatmo/modules/legrand.py 0000664 0000000 0000000 00000006474 14661167274 0023037 0 ustar 00root root 0000000 0000000 """Module to represent Legrand modules."""
from __future__ import annotations
import logging
from pyatmo.modules.module import (
BatteryMixin,
ContactorMixin,
DimmableMixin,
Dimmer,
EnergyHistoryLegacyMixin,
EnergyHistoryMixin,
Fan,
FirmwareMixin,
Module,
OffloadMixin,
PowerMixin,
RfMixin,
ShutterMixin,
Switch,
SwitchMixin,
WifiMixin,
)
LOG = logging.getLogger(__name__)
# pylint: disable=R0901
class NLG(FirmwareMixin, OffloadMixin, WifiMixin, Module):
"""Legrand gateway."""
class NLT(DimmableMixin, FirmwareMixin, BatteryMixin, SwitchMixin, Module):
"""Legrand global remote control...but also wireless switch, like NLD."""
class NLP(Switch, OffloadMixin):
"""Legrand plug."""
class NLPM(Switch, OffloadMixin):
"""Legrand mobile plug."""
class NLPO(ContactorMixin, OffloadMixin, Switch):
"""Legrand contactor."""
class NLPT(Switch, OffloadMixin):
"""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."""
class NLD(DimmableMixin, FirmwareMixin, BatteryMixin, SwitchMixin, Module):
"""Legrand Double On/Off dimmer remote. Wireless 2 button switch light."""
class NLL(Switch, WifiMixin):
"""Legrand / BTicino italian light switch with neutral."""
class NLV(FirmwareMixin, RfMixin, ShutterMixin, Module):
"""Legrand / BTicino shutters."""
class NLLV(FirmwareMixin, RfMixin, ShutterMixin, Module):
"""Legrand / BTicino shutters."""
class NLLM(FirmwareMixin, RfMixin, 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(Switch, OffloadMixin):
"""Legrand / BTicino cable outlet."""
class NLDD(FirmwareMixin, Module):
"""Legrand NLDD dimmer remote control."""
class NLUP(Switch):
"""Legrand NLUP Power outlet."""
class NLAO(FirmwareMixin, SwitchMixin, Module):
"""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(Module):
"""NLAS wireless batteryless scene switch."""
class Z3L(Dimmer):
"""Zigbee 3 Light."""
class EBU(Module):
"""EBU gas meter."""
class NLTS(Module):
"""NLTS motion sensor."""
class NLPD(Switch, OffloadMixin):
"""NLPD dry contact."""
class NLJ(FirmwareMixin, RfMixin, ShutterMixin, Module):
"""Legrand garage door opener."""
jabesq-org-pyatmo-6216472/src/pyatmo/modules/module.py 0000664 0000000 0000000 00000105121 14661167274 0022675 0 ustar 00root root 0000000 0000000 """Module to represent a Netatmo module."""
from __future__ import annotations
from datetime import datetime, timedelta, timezone
from enum import Enum
import logging
from typing import TYPE_CHECKING, Any
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
from pyatmo.modules.device_types import DEVICE_CATEGORY_MAP, DeviceCategory, DeviceType
if TYPE_CHECKING:
from pyatmo.event import Event
from pyatmo.home import Home
from operator import itemgetter
from time import time
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",
}
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):
"""Initialize firmware mixin."""
super().__init__(home, module) # type: ignore # mypy issue 4335
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):
"""Initialize wifi mixin."""
super().__init__(home, module) # type: ignore # mypy issue 4335
self.wifi_strength: int | None = None
class RfMixin(EntityBase):
"""Mixin for rf data."""
def __init__(self, home: Home, module: ModuleT):
"""Initialize rf mixin."""
super().__init__(home, module) # type: ignore # mypy issue 4335
self.rf_strength: int | None = None
class RainMixin(EntityBase):
"""Mixin for rain data."""
def __init__(self, home: Home, module: ModuleT):
"""Initialize rain mixin."""
super().__init__(home, module) # type: ignore # mypy issue 4335
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):
"""Initialize wind mixin."""
super().__init__(home, module) # type: ignore # mypy issue 4335
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."""
if angle >= 330:
return "N"
if angle >= 300:
return "NW"
if angle >= 240:
return "W"
if angle >= 210:
return "SW"
if angle >= 150:
return "S"
if angle >= 120:
return "SE"
if angle >= 60:
return "E"
return "NE" if angle >= 30 else "N"
class TemperatureMixin(EntityBase):
"""Mixin for temperature data."""
def __init__(self, home: Home, module: ModuleT):
"""Initialize temperature mixin."""
super().__init__(home, module) # type: ignore # mypy issue 4335
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):
"""Initialize humidity mixin."""
super().__init__(home, module) # type: ignore # mypy issue 4335
self.humidity: int | None = None
class CO2Mixin(EntityBase):
"""Mixin for CO2 data."""
def __init__(self, home: Home, module: ModuleT):
"""Initialize CO2 mixin."""
super().__init__(home, module) # type: ignore # mypy issue 4335
self.co2: int | None = None
class HealthIndexMixin(EntityBase):
"""Mixin for health index data."""
def __init__(self, home: Home, module: ModuleT):
"""Initialize health index mixin."""
super().__init__(home, module) # type: ignore # mypy issue 4335
self.health_idx: int | None = None
class NoiseMixin(EntityBase):
"""Mixin for noise data."""
def __init__(self, home: Home, module: ModuleT):
"""Initialize noise mixin."""
super().__init__(home, module) # type: ignore # mypy issue 4335
self.noise: int | None = None
class PressureMixin(EntityBase):
"""Mixin for pressure data."""
def __init__(self, home: Home, module: ModuleT):
"""Initialize pressure mixin."""
super().__init__(home, module) # type: ignore # mypy issue 4335
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):
"""Initialize boiler mixin."""
super().__init__(home, module) # type: ignore # mypy issue 4335
self.boiler_status: bool | None = None
class CoolerMixin(EntityBase):
"""Mixin for cooler data."""
def __init__(self, home: Home, module: ModuleT):
"""Initialize cooler mixin."""
super().__init__(home, module) # type: ignore # mypy issue 4335
self.cooler_status: bool | None = None
class BatteryMixin(EntityBase):
"""Mixin for battery data."""
def __init__(self, home: Home, module: ModuleT):
"""Initialize battery mixin."""
super().__init__(home, module) # type: ignore # mypy issue 4335
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):
"""Initialize place mixin."""
super().__init__(home, module) # type: ignore # mypy issue 4335
self.place: Place | None = None
class DimmableMixin(EntityBase):
"""Mixin for dimmable data."""
def __init__(self, home: Home, module: ModuleT):
"""Initialize dimmable mixin."""
super().__init__(home, module) # type: ignore # mypy issue 4335
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."""
def __init__(self, home: Home, module: ModuleT):
"""Initialize appliance type mixin."""
super().__init__(home, module) # type: ignore # mypy issue 4335
self.appliance_type: str | None = None
class PowerMixin(EntityBase):
"""Mixin for power data."""
def __init__(self, home: Home, module: ModuleT):
"""Initialize power mixin."""
super().__init__(home, module) # type: ignore # mypy issue 4335
self.power: int | None = None
self.history_features.add("power")
class EventMixin(EntityBase):
"""Mixin for event data."""
def __init__(self, home: Home, module: ModuleT):
"""Initialize event mixin."""
super().__init__(home, module) # type: ignore # mypy issue 4335
self.events: list[Event] = []
class ContactorMixin(EntityBase):
"""Mixin for contactor data."""
def __init__(self, home: Home, module: ModuleT):
"""Initialize contactor mixin."""
super().__init__(home, module) # type: ignore # mypy issue 4335
self.contactor_mode: str | None = None
class OffloadMixin(EntityBase):
"""Mixin for offload data."""
def __init__(self, home: Home, module: ModuleT):
"""Initialize offload mixin."""
super().__init__(home, module) # type: ignore # mypy issue 4335
self.offload: bool | None = None
class SwitchMixin(EntityBase):
"""Mixin for switch data."""
def __init__(self, home: Home, module: ModuleT):
"""Initialize switch mixin."""
super().__init__(home, module) # type: ignore # mypy issue 4335
self.on: bool | None = None
async def async_set_switch(self, target_position: int) -> 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):
"""Initialize fan speed mixin."""
super().__init__(home, module) # type: ignore # mypy issue 4335
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):
"""Initialize shutter mixin."""
super().__init__(home, module) # type: ignore # mypy issue 4335
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):
"""Initialize camera mixin."""
super().__init__(home, module) # type: ignore # mypy issue 4335
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",
timeout=10,
)
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 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
assert not isinstance(resp, bytes)
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):
"""Initialize floodlight mixin."""
super().__init__(home, module) # type: ignore # mypy issue 4335
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):
"""Initialize status mixin."""
super().__init__(home, module) # type: ignore # mypy issue 4335
self.status: str | None = None
class MonitoringMixin(EntityBase):
"""Mixin for monitoring data."""
def __init__(self, home: Home, module: ModuleT):
"""Initialize monitoring mixin."""
super().__init__(home, module) # type: ignore # mypy issue 4335
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
):
"""Compute energy from power with a rieman sum."""
delta_energy = 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
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):
"""Initialize history mixin."""
super().__init__(home, module) # type: ignore # mypy issue 4335
self.historical_data: list[dict[str, Any]] | None = None
self.start_time: int | None = None
self.end_time: int | None = None
self.interval: MeasureInterval | None = None
self.sum_energy_elec: int | None = None
self.sum_energy_elec_peak: int | None = None
self.sum_energy_elec_off_peak: int | None = None
self._anchor_for_power_adjustment: int | None = None
self.in_reset: bool | False = False
def reset_measures(self, start_power_time, in_reset=True):
"""Reset energy measures."""
self.in_reset = in_reset
self.historical_data = []
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())
self.sum_energy_elec = 0
self.sum_energy_elec_peak = 0
self.sum_energy_elec_off_peak = 0
def get_sum_energy_elec_power_adapted(
self, to_ts: int | float | None = None, conservative: bool = False
):
"""Compute proper energy value with adaptation from power."""
v = self.sum_energy_elec
if v is None:
return None, 0
delta_energy = 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, end_time, msg=None, body=None):
if body is None:
body = "NO BODY"
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,
)
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 = end - timedelta(days=days)
start_time = int(start_time.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
)
self.historical_data = []
prev_sum_energy_elec = self.sum_energy_elec
self.sum_energy_elec = 0
self.sum_energy_elec_peak = 0
self.sum_energy_elec_off_peak = 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,
prev_start_time,
prev_sum_energy_elec,
)
async def _prepare_exported_historical_data(
self,
start_time,
end_time,
delta_range,
hist_good_vals,
prev_end_time,
prev_start_time,
prev_sum_energy_elec,
):
computed_start = 0
computed_end = 0
computed_end_for_calculus = 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
# - delta_range not sure, revert ... it seems the energy value effectively stops at those mid values
computed_end_for_calculus = c_end # - delta_range
start_time_string = f"{datetime.fromtimestamp(c_start + 1, tz=timezone.utc).isoformat().split('+')[0]}Z"
end_time_string = f"{datetime.fromtimestamp(c_end, tz=timezone.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, end_time, delta_range, raw_data
):
hist_good_vals = []
values_lots = raw_data
for values_lot in values_lots:
try:
start_lot_time = int(values_lot["beg_time"])
except Exception:
self._log_energy_error(
start_time,
end_time,
msg="beg_time missing",
body=values_lots,
)
raise ApiError(
f"Energy badly formed resp beg_time missing: {values_lots} - "
f"module: {self.name}"
) 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
hist_good_vals = sorted(hist_good_vals, key=itemgetter(0))
return hist_good_vals
def _get_energy_filers(self):
return ENERGY_FILTERS
async def _energy_API_calls(self, start_time, end_time, interval):
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
)
raise ApiError(
f"Energy badly formed resp: {rw_dt_f} - "
f"module: {self.name} - "
f"when accessing '{filters}'"
)
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):
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)
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")
# pylint: disable=too-many-ancestors
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, 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."""
...
# pylint: enable=too-many-ancestors
jabesq-org-pyatmo-6216472/src/pyatmo/modules/netatmo.py 0000664 0000000 0000000 00000016411 14661167274 0023062 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__)
# pylint: disable=R0901
class NRV(FirmwareMixin, RfMixin, BatteryMixin, Module):
"""Class to represent a Netatmo NRV."""
...
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 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
jabesq-org-pyatmo-6216472/src/pyatmo/modules/smarther.py 0000664 0000000 0000000 00000000542 14661167274 0023236 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."""
jabesq-org-pyatmo-6216472/src/pyatmo/modules/somfy.py 0000664 0000000 0000000 00000000412 14661167274 0022542 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."""
...
jabesq-org-pyatmo-6216472/src/pyatmo/person.py 0000664 0000000 0000000 00000001726 14661167274 0021254 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.const import RawData
from pyatmo.modules.base_class import NetatmoBase
if TYPE_CHECKING:
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")
jabesq-org-pyatmo-6216472/src/pyatmo/py.typed 0000664 0000000 0000000 00000000000 14661167274 0021053 0 ustar 00root root 0000000 0000000 jabesq-org-pyatmo-6216472/src/pyatmo/room.py 0000664 0000000 0000000 00000016154 14661167274 0020723 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
from pyatmo.const import (
FROSTGUARD,
HOME,
MANUAL,
SETROOMTHERMPOINT_ENDPOINT,
UNKNOWN,
RawData,
)
from pyatmo.modules.base_class import NetatmoBase
from pyatmo.modules.device_types import DeviceType
if TYPE_CHECKING:
from pyatmo.home import Home
from pyatmo.modules.module import Module
LOG = logging.getLogger(__name__)
MODE_MAP = {"schedule": "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_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
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.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."""
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 "OTM" in self.device_types:
self.climate_type = DeviceType.OTM
elif "NRV" in self.device_types:
self.climate_type = DeviceType.NRV
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 "BNTH" in self.device_types:
self.climate_type = DeviceType.BNTH
def update(self, raw_data: RawData) -> None:
"""Update room data."""
self.humidity = raw_data.get("humidity")
if self.climate_type == DeviceType.BNTH:
# BNTH is wired, so the room is always reachable
self.reachable = True
else:
self.reachable = raw_data.get("reachable")
self.therm_measured_temperature = raw_data.get("therm_measured_temperature")
self.reachable = raw_data.get("reachable")
self.heating_power_request = raw_data.get("heating_power_request")
self.therm_setpoint_mode = raw_data.get("therm_setpoint_mode")
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,
temp: float | None = None,
end_time: int | None = None,
) -> None:
"""Set room temperature set point."""
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)
async def _async_therm_set(
self,
mode: str,
temp: float | None = None,
end_time: int | None = None,
) -> bool:
"""Set room temperature set point (OTM)."""
json_therm_set: dict[str, Any] = {
"rooms": [
{
"id": self.entity_id,
"therm_setpoint_mode": mode,
},
],
}
if temp:
json_therm_set["rooms"][0]["therm_setpoint_temperature"] = temp
if end_time:
json_therm_set["rooms"][0]["therm_setpoint_end_time"] = end_time
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,
)
jabesq-org-pyatmo-6216472/src/pyatmo/schedule.py 0000664 0000000 0000000 00000004073 14661167274 0021540 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.const import RawData
from pyatmo.modules.base_class import NetatmoBase
from pyatmo.room import Room
if TYPE_CHECKING:
from .home import Home
LOG = logging.getLogger(__name__)
@dataclass
class Schedule(NetatmoBase):
"""Class to represent a Netatmo schedule."""
selected: bool
away_temp: float | None
hg_temp: float | None
timetable: list[TimetableEntry]
def __init__(self, home: Home, raw_data: RawData) -> None:
"""Initialize a Netatmo schedule instance."""
super().__init__(raw_data)
self.home = home
self.selected = raw_data.get("selected", False)
self.hg_temp = raw_data.get("hg_temp")
self.away_temp = raw_data.get("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", [])]
@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(home, room_raw_data, {})
room.update(room_raw_data)
return room
self.rooms = [room_factory(home, r) for r in raw_data.get("rooms", [])]
jabesq-org-pyatmo-6216472/tests/ 0000775 0000000 0000000 00000000000 14661167274 0016430 5 ustar 00root root 0000000 0000000 jabesq-org-pyatmo-6216472/tests/__init__.py 0000664 0000000 0000000 00000000000 14661167274 0020527 0 ustar 00root root 0000000 0000000 jabesq-org-pyatmo-6216472/tests/common.py 0000664 0000000 0000000 00000004163 14661167274 0020276 0 ustar 00root root 0000000 0000000 """Define shared test helpers."""
# pylint: disable=redefined-outer-name, protected-access, unused-argument
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(*args, **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")
type = kwargs.get("params", {}).get("type")
payload = json.loads(
load_fixture(f"{endpoint}_{type}_{module_id.replace(':', '_')}.json"),
)
else:
postfix = kwargs.get("POSTFIX", None)
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"
r = await fake_post_request(*args, **kwargs)
return r
jabesq-org-pyatmo-6216472/tests/conftest.py 0000664 0000000 0000000 00000003745 14661167274 0020640 0 ustar 00root root 0000000 0000000 """Define shared fixtures."""
# pylint: disable=redefined-outer-name, protected-access
from contextlib import contextmanager
from unittest.mock import AsyncMock, patch
import pyatmo
import pytest
from .common import fake_post_request, fake_post_request_multi
@contextmanager
def does_not_raise():
yield
@pytest.fixture(scope="function")
async def async_auth():
"""AsyncAuth fixture."""
with patch("pyatmo.auth.AbstractAsyncAuth", AsyncMock()) as auth:
yield auth
@pytest.fixture(scope="function")
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(scope="function")
async def async_home(async_account):
"""AsyncClimate fixture for home_id 91763b24c43d3e344f424e8b."""
home_id = "91763b24c43d3e344f424e8b"
await async_account.async_update_status(home_id)
yield async_account.homes[home_id]
@pytest.fixture(scope="function")
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(scope="function")
async def async_home_multi(async_account_multi):
"""AsyncClimate fixture for home_id 91763b24c43d3e344f424e8b."""
home_id = "aaaaaaaaaaabbbbbbbbbbccc"
await async_account_multi.async_update_status(home_id)
yield async_account_multi.homes[home_id]
jabesq-org-pyatmo-6216472/tests/test_camera.py 0000664 0000000 0000000 00000007740 14661167274 0021301 0 ustar 00root root 0000000 0000000 """Define tests for camera module."""
import json
from unittest.mock import AsyncMock, patch
from pyatmo import DeviceType
import pytest
from tests.common import MockResponse
# pylint: disable=F6401
@pytest.mark.asyncio
async def test_async_camera_NACamera(async_home): # pylint: disable=invalid-name
"""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
@pytest.mark.asyncio
async def test_async_NOC(async_home): # pylint: disable=invalid-name
"""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"
with open("fixtures/status_ok.json", encoding="utf-8") as json_file:
response = json.load(json_file)
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",
)
@pytest.mark.asyncio
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
with open("fixtures/status_ok.json", encoding="utf-8") as json_file:
response = json.load(json_file)
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",
)
jabesq-org-pyatmo-6216472/tests/test_climate.py 0000664 0000000 0000000 00000024613 14661167274 0021465 0 ustar 00root root 0000000 0000000 """Define tests for climate module."""
import json
from unittest.mock import AsyncMock, patch
from pyatmo import DeviceType, NoSchedule
from pyatmo.modules import NATherm1
from pyatmo.modules.device_types import DeviceCategory
import pytest
from tests.common import MockResponse, fake_post_request
from tests.conftest import does_not_raise
# pylint: disable=F6401
@pytest.mark.asyncio
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
@pytest.mark.asyncio
async def test_async_climate_NATherm1(async_home): # pylint: disable=invalid-name
"""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
@pytest.mark.asyncio
async def test_async_climate_NRV(async_home): # pylint: disable=invalid-name
"""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
@pytest.mark.asyncio
async def test_async_climate_NAPlug(async_home): # pylint: disable=invalid-name
"""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
@pytest.mark.asyncio
async def test_async_climate_NIS(async_home): # pylint: disable=invalid-name
"""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
@pytest.mark.asyncio
async def test_async_climate_OTM(async_home): # pylint: disable=invalid-name
"""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
@pytest.mark.asyncio
async def test_async_climate_OTH(async_home): # pylint: disable=invalid-name
"""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
@pytest.mark.asyncio
async def test_async_climate_BNS(async_home): # pylint: disable=invalid-name
"""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}
@pytest.mark.asyncio
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)
with open(
"fixtures/home_status_error_disconnected.json",
encoding="utf-8",
) as json_file:
home_status_fixture = json.load(json_file)
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
with open("fixtures/home_status_simple.json", encoding="utf-8") as json_file:
home_status_fixture = json.load(json_file)
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(NoSchedule),
),
],
)
@pytest.mark.asyncio
async def test_async_climate_switch_schedule(
async_home,
t_sched_id,
expected,
):
with open("fixtures/status_ok.json", encoding="utf-8") as json_file:
response = json.load(json_file)
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,
),
],
)
@pytest.mark.asyncio
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)
with open("fixtures/status_ok.json", encoding="utf-8") as json_file:
response = json.load(json_file)
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(NoSchedule),
),
(
None,
None,
None,
"home_status_error_mode_is_missing.json",
False,
pytest.raises(NoSchedule),
),
(
"away",
1559162650,
0000000,
"status_ok.json",
True,
pytest.raises(NoSchedule),
),
(
"schedule",
None,
"blahblahblah",
"home_status_error_invalid_schedule_id.json",
False,
pytest.raises(NoSchedule),
),
],
)
@pytest.mark.asyncio
async def test_async_climate_set_thermmode(
async_home,
mode,
end_time,
schedule_id,
json_fixture,
expected,
exception,
):
with open(f"fixtures/{json_fixture}", encoding="utf-8") as json_file:
response = json.load(json_file)
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
@pytest.mark.asyncio
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
jabesq-org-pyatmo-6216472/tests/test_energy.py 0000664 0000000 0000000 00000011522 14661167274 0021333 0 ustar 00root root 0000000 0000000 """Define tests for energy module."""
import datetime as dt
import json
from unittest.mock import AsyncMock, patch
from pyatmo import ApiHomeReachabilityError, DeviceType
from pyatmo.modules.module import EnergyHistoryMixin, MeasureInterval
import pytest
import time_machine
from tests.common import MockResponse
# pylint: disable=F6401
@pytest.mark.asyncio
async def test_async_energy_NLPC(async_home): # pylint: disable=invalid-name
"""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))
@pytest.mark.asyncio
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))
@pytest.mark.asyncio
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
async def test_disconnected_main_bridge(async_account_multi):
"""Test retrieval of historical measurements."""
home_id = "aaaaaaaaaaabbbbbbbbbbccc"
with open(
"fixtures/home_multi_status_error_disconnected.json",
encoding="utf-8",
) as json_file:
home_status_fixture = json.load(json_file)
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:
try:
await async_account_multi.async_update_status(home_id)
except ApiHomeReachabilityError:
pass # expected error
else:
assert False
jabesq-org-pyatmo-6216472/tests/test_fan.py 0000664 0000000 0000000 00000001045 14661167274 0020605 0 ustar 00root root 0000000 0000000 """Define tests for fan module."""
from pyatmo import DeviceType
import pytest
# pylint: disable=F6401
@pytest.mark.asyncio
async def test_async_fan_NLLF(async_home): # pylint: disable=invalid-name
"""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
jabesq-org-pyatmo-6216472/tests/test_home.py 0000664 0000000 0000000 00000011062 14661167274 0020771 0 ustar 00root root 0000000 0000000 """Define tests for home module."""
# import datetime as dt
import json
from unittest.mock import AsyncMock, patch
import pyatmo
from pyatmo import DeviceType, NoDevice
import pytest
from tests.common import MockResponse
# pylint: disable=F6401
@pytest.mark.asyncio
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,
}
assert len(async_home.rooms) == 8
assert len(async_home.modules) == 38
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"
@pytest.mark.asyncio
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
@pytest.mark.asyncio
async def test_async_home_data_no_body(async_auth):
with open("fixtures/homesdata_emtpy_home.json", encoding="utf-8") as fixture_file:
json_fixture = json.load(fixture_file)
with patch(
"pyatmo.auth.AbstractAsyncAuth.async_post_api_request",
AsyncMock(return_value=json_fixture),
) as mock_request:
climate = pyatmo.AsyncAccount(async_auth)
with pytest.raises(NoDevice):
await climate.async_update_topology()
mock_request.assert_called()
@pytest.mark.asyncio
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",
]
with open("fixtures/status_ok.json", encoding="utf-8") as json_file:
response = json.load(json_file)
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",
)
@pytest.mark.asyncio
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]
with open("fixtures/status_ok.json", encoding="utf-8") as json_file:
response = json.load(json_file)
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",
)
@pytest.mark.asyncio
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
jabesq-org-pyatmo-6216472/tests/test_shutter.py 0000664 0000000 0000000 00000006322 14661167274 0021542 0 ustar 00root root 0000000 0000000 """Define tests for shutter module."""
import json
from unittest.mock import AsyncMock, patch
from pyatmo import DeviceType
import pytest
from tests.common import MockResponse
# pylint: disable=F6401
@pytest.mark.asyncio
async def test_async_shutter_NBR(async_home): # pylint: disable=invalid-name
"""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
@pytest.mark.asyncio
async def test_async_shutter_NBO(async_home): # pylint: disable=invalid-name
"""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
@pytest.mark.asyncio
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
with open("fixtures/status_ok.json", encoding="utf-8") as json_file:
response = json.load(json_file)
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",
)
jabesq-org-pyatmo-6216472/tests/test_switch.py 0000664 0000000 0000000 00000001674 14661167274 0021352 0 ustar 00root root 0000000 0000000 """Define tests for switch module."""
from pyatmo import DeviceType
import pytest
# pylint: disable=F6401
@pytest.mark.asyncio
async def test_async_switch_NLP(async_home): # pylint: disable=invalid-name
"""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
@pytest.mark.asyncio
async def test_async_switch_NLF(async_home): # pylint: disable=invalid-name
"""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
jabesq-org-pyatmo-6216472/tests/test_weather.py 0000664 0000000 0000000 00000023374 14661167274 0021511 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
import pytest
# pylint: disable=F6401
@pytest.mark.asyncio
async def test_async_weather_NAMain(async_home): # pylint: disable=invalid-name
"""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
@pytest.mark.asyncio
async def test_async_weather_update(async_account):
"""Test basic weather station update."""
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",
},
)
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
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
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
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
@pytest.mark.asyncio
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
@pytest.mark.asyncio
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
@pytest.mark.asyncio
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.netatmo.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}
jabesq-org-pyatmo-6216472/tests/testing_main_template.py 0000664 0000000 0000000 00000002006 14661167274 0023354 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 # 1709421000+15*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,
)
# print(account)
if __name__ == "__main__":
topology = asyncio.run(main())
# print(topology)
jabesq-org-pyatmo-6216472/tox.ini 0000664 0000000 0000000 00000001111 14661167274 0016573 0 ustar 00root root 0000000 0000000 [tox]
envlist = py310,py311
isolated_build = True
skip_missing_interpreters = True
[gh-actions]
python =
3.10: py310
3.11: py311
[testenv]
deps =
pytest
pytest-cov
pytest-mock
pytest-asyncio
requests-mock
time-machine
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