mirror of
https://github.com/home-assistant/core.git
synced 2026-06-27 17:15:23 +02:00
Compare commits
52 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 03fb4b099c | |||
| 46a6048f60 | |||
| c598d2c10e | |||
| 67bcd7550c | |||
| e44e822cec | |||
| daff150276 | |||
| 1f33859297 | |||
| 512fe8c022 | |||
| 6f038bb5b2 | |||
| d0b5162507 | |||
| 9e9978b6cb | |||
| 76feb821f4 | |||
| cd41529a89 | |||
| 8a1434332d | |||
| 36b714b513 | |||
| 46f1e4c957 | |||
| 431dcda092 | |||
| c575ef51b9 | |||
| 87690d2000 | |||
| 7afb26b1c0 | |||
| b6d5af0480 | |||
| f56098df5f | |||
| 427dd028f5 | |||
| cef9461610 | |||
| ace5398012 | |||
| 3791c83b95 | |||
| 4bdfa5c25b | |||
| 5a60771a14 | |||
| 70aba68326 | |||
| f20f86a067 | |||
| ee0c98e450 | |||
| 907a5c3c6c | |||
| a1e1b400f3 | |||
| 1544ae83dd | |||
| 145c490816 | |||
| bb7a756f84 | |||
| 183e6af8c2 | |||
| 2b66d045ff | |||
| 4841329814 | |||
| e710fc8782 | |||
| 99e18dcdd8 | |||
| eeedf28b6f | |||
| 5cca9328d6 | |||
| ebf3de3073 | |||
| 41e79927d0 | |||
| 4022eb93de | |||
| 28171dfe90 | |||
| e9af932fbe | |||
| 3212e0f051 | |||
| 87f0720450 | |||
| 534ff3f3dc | |||
| 1096c8af13 |
@@ -95,7 +95,6 @@ components: &components
|
||||
- homeassistant/components/input_select/**
|
||||
- homeassistant/components/input_text/**
|
||||
- homeassistant/components/labs/**
|
||||
- homeassistant/components/llm/**
|
||||
- homeassistant/components/logbook/**
|
||||
- homeassistant/components/logger/**
|
||||
- homeassistant/components/lovelace/**
|
||||
|
||||
@@ -12,7 +12,6 @@ on:
|
||||
types: [opened, synchronize, reopened]
|
||||
paths:
|
||||
- "requirements*.txt"
|
||||
- "**/requirements*.txt"
|
||||
- "homeassistant/package_constraints.txt"
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
@@ -59,7 +58,6 @@ jobs:
|
||||
echo "head_sha=${HEAD_SHA}" >> "${GITHUB_OUTPUT}"
|
||||
- name: Run deterministic checks
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
PR_NUMBER: ${{ inputs.pull_request_number || github.event.pull_request.number }}
|
||||
HEAD_SHA: ${{ steps.pr.outputs.head_sha }}
|
||||
run: |
|
||||
|
||||
+129
-58
@@ -1,5 +1,5 @@
|
||||
# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"36a7fc263a2ce868d74a266f23eb7772d82fd397806464384fe087479ddd4a70","body_hash":"bba8c011f2b82bb4d9847a359f43f0e7d91245b280678c20e5112b3c9e77d5cd","compiler_version":"v0.79.6","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.60"}}
|
||||
# gh-aw-manifest: {"version":1,"secrets":["COPILOT_GITHUB_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/checkout","sha":"df4cb1c069e1874edd31b4311f1884172cec0e10","version":"v6.0.3"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"5c2fe865bb4dc46e1450f6ee0d0541d759aea73a","version":"v0.79.6"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.27.2","digest":"sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.27.2@sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2","digest":"sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2@sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.27.2","digest":"sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.27.2@sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.25","digest":"sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.25@sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa"},{"image":"ghcr.io/github/github-mcp-server:v1.1.2","digest":"sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c","pinned_image":"ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c"}]}
|
||||
# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"7b142e96e0f8b454cdcc9c0c25070cf9a52c44d83a6b1fbc3ad6725b6567337c","body_hash":"3894ded07d5934ac5f29d160ffb1f9115cf72b6da8a7e453a4d4f69e8641a48e","compiler_version":"v0.79.6","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.60"}}
|
||||
# gh-aw-manifest: {"version":1,"secrets":["COPILOT_GITHUB_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/checkout","sha":"df4cb1c069e1874edd31b4311f1884172cec0e10","version":"v6.0.3"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"v0.79.6","version":"v0.79.6"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.27.2","digest":"sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.27.2@sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2","digest":"sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2@sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.27.2","digest":"sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.27.2@sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.25","digest":"sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.25@sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa"},{"image":"ghcr.io/github/github-mcp-server:v1.1.2","digest":"sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c","pinned_image":"ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c"}]}
|
||||
# ___ _ _
|
||||
# / _ \ | | (_)
|
||||
# | |_| | __ _ ___ _ __ | |_ _ ___
|
||||
@@ -31,12 +31,12 @@
|
||||
# - GITHUB_TOKEN
|
||||
#
|
||||
# Custom actions used:
|
||||
# - actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
# - actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
# - actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
# - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||||
# - actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
||||
# - actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
# - github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6
|
||||
# - github/gh-aw-actions/setup@v0.79.6
|
||||
#
|
||||
# Container images used:
|
||||
# - ghcr.io/github/gh-aw-firewall/agent:0.27.2@sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6
|
||||
@@ -92,7 +92,7 @@ jobs:
|
||||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
@@ -155,7 +155,7 @@ jobs:
|
||||
env:
|
||||
COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
|
||||
- name: Checkout .github and .agents folders
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
sparse-checkout: |
|
||||
@@ -344,8 +344,9 @@ jobs:
|
||||
agent:
|
||||
needs:
|
||||
- activation
|
||||
- prepare
|
||||
if: (needs.prepare.outputs.skip != 'true') && (needs.activation.outputs.daily_effective_workflow_exceeded != 'true')
|
||||
- extract_pr_number
|
||||
- gate
|
||||
if: needs.activation.outputs.daily_effective_workflow_exceeded != 'true'
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
actions: read
|
||||
@@ -382,7 +383,7 @@ jobs:
|
||||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
@@ -403,7 +404,7 @@ jobs:
|
||||
echo "GH_AW_SAFE_OUTPUTS_TOOLS_PATH=${RUNNER_TEMP}/gh-aw/safeoutputs/tools.json"
|
||||
} >> "$GITHUB_OUTPUT"
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Create gh-aw temp directory
|
||||
@@ -488,15 +489,15 @@ jobs:
|
||||
mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs"
|
||||
mkdir -p /tmp/gh-aw/safeoutputs
|
||||
mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs
|
||||
cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_823c5547a5e52957_EOF'
|
||||
{"add_comment":{"max":1,"target":"${{ needs.prepare.outputs.pr_number }}"},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{}}
|
||||
GH_AW_SAFE_OUTPUTS_CONFIG_823c5547a5e52957_EOF
|
||||
cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_f496a449c5dccca1_EOF'
|
||||
{"add_comment":{"max":1,"target":"${{ needs.extract_pr_number.outputs.pr_number }}"},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{}}
|
||||
GH_AW_SAFE_OUTPUTS_CONFIG_f496a449c5dccca1_EOF
|
||||
- name: Generate Safe Outputs Tools
|
||||
env:
|
||||
GH_AW_TOOLS_META_JSON: |
|
||||
{
|
||||
"description_suffixes": {
|
||||
"add_comment": " CONSTRAINTS: Maximum 1 comment(s) can be added. Target: ${{ needs.prepare.outputs.pr_number }}. Supports reply_to_id for discussion threading."
|
||||
"add_comment": " CONSTRAINTS: Maximum 1 comment(s) can be added. Target: ${{ needs.extract_pr_number.outputs.pr_number }}. Supports reply_to_id for discussion threading."
|
||||
},
|
||||
"repo_params": {},
|
||||
"dynamic_tools": []
|
||||
@@ -993,7 +994,8 @@ jobs:
|
||||
- activation
|
||||
- agent
|
||||
- detection
|
||||
- prepare
|
||||
- extract_pr_number
|
||||
- gate
|
||||
- safe_outputs
|
||||
if: >
|
||||
always() && (needs.agent.result != 'skipped' || needs.activation.outputs.lockdown_check_failed == 'true' ||
|
||||
@@ -1016,7 +1018,7 @@ jobs:
|
||||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
@@ -1206,7 +1208,7 @@ jobs:
|
||||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
@@ -1234,7 +1236,7 @@ jobs:
|
||||
echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT"
|
||||
- name: Checkout repository for patch context
|
||||
if: needs.agent.outputs.has_patch == 'true'
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
# --- Threat Detection ---
|
||||
@@ -1427,6 +1429,111 @@ jobs:
|
||||
}
|
||||
}
|
||||
|
||||
extract_pr_number:
|
||||
needs: gate
|
||||
if: needs.gate.outputs.skip != 'true' && github.event.workflow_run.conclusion == 'success'
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
actions: read
|
||||
|
||||
outputs:
|
||||
pr_number: ${{ steps.extract.outputs.pr_number }}
|
||||
steps:
|
||||
- name: Configure GH_HOST for enterprise compatibility
|
||||
id: ghes-host-config
|
||||
shell: bash
|
||||
# zizmor: ignore[github-env] - GITHUB_SERVER_URL is set by GitHub Actions, not user input.
|
||||
run: |
|
||||
# Derive GH_HOST from GITHUB_SERVER_URL so the gh CLI targets the correct
|
||||
# GitHub instance (GHES/GHEC). On github.com this is a harmless no-op.
|
||||
GH_HOST="${GITHUB_SERVER_URL#https://}"
|
||||
GH_HOST="${GH_HOST#http://}"
|
||||
echo "GH_HOST=${GH_HOST}" >> "$GITHUB_ENV"
|
||||
- name: Download deterministic-results artifact
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
name: check-requirements-deterministic
|
||||
path: /tmp/deterministic
|
||||
run-id: ${{ github.event.workflow_run.id }}
|
||||
- name: Extract PR number from artifact
|
||||
id: extract
|
||||
run: |
|
||||
PR=$(jq -r '.pr_number' /tmp/deterministic/results.json)
|
||||
echo "pr_number=${PR}" >> "${GITHUB_OUTPUT}"
|
||||
|
||||
gate:
|
||||
needs: activation
|
||||
if: github.event.workflow_run.conclusion == 'success'
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
pull-requests: read
|
||||
|
||||
outputs:
|
||||
skip: ${{ steps.gate.outputs.skip }}
|
||||
steps:
|
||||
- name: Configure GH_HOST for enterprise compatibility
|
||||
id: ghes-host-config
|
||||
shell: bash
|
||||
# zizmor: ignore[github-env] - GITHUB_SERVER_URL is set by GitHub Actions, not user input.
|
||||
run: |
|
||||
# Derive GH_HOST from GITHUB_SERVER_URL so the gh CLI targets the correct
|
||||
# GitHub instance (GHES/GHEC). On github.com this is a harmless no-op.
|
||||
GH_HOST="${GITHUB_SERVER_URL#https://}"
|
||||
GH_HOST="${GH_HOST#http://}"
|
||||
echo "GH_HOST=${GH_HOST}" >> "$GITHUB_ENV"
|
||||
- name: Download deterministic-results artifact
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
name: check-requirements-deterministic
|
||||
path: /tmp/gate
|
||||
run-id: ${{ github.event.workflow_run.id }}
|
||||
- name: Decide whether requirements changed since the last comment
|
||||
id: gate
|
||||
run: |
|
||||
PR=$(jq -r '.pr_number' /tmp/gate/results.json)
|
||||
HEAD=$(jq -r '.head_sha // empty' /tmp/gate/results.json)
|
||||
if [ -z "${HEAD}" ]; then
|
||||
echo "Artifact has no head_sha; running the agent."
|
||||
exit 0
|
||||
fi
|
||||
# Recover the commit recorded in the most recent requirements-check
|
||||
# comment from the "Checked at commit" link
|
||||
PRIOR=$(gh api --paginate "repos/${GITHUB_REPOSITORY}/issues/${PR}/comments" \
|
||||
--jq '.[] | select(.body | contains("<!-- requirements-check -->")) | .body' \
|
||||
| grep -oiE '/commit/[0-9a-f]{40}' \
|
||||
| grep -oiE '[0-9a-f]{40}' | tail -1 || true)
|
||||
if [ -z "${PRIOR}" ]; then
|
||||
echo "No previous comment with a recorded commit; running the agent."
|
||||
exit 0
|
||||
fi
|
||||
if [ "${PRIOR}" = "${HEAD}" ]; then
|
||||
echo "Head ${HEAD} unchanged since the last comment; skipping the agent."
|
||||
echo "skip=true" >> "${GITHUB_OUTPUT}"
|
||||
exit 0
|
||||
fi
|
||||
# List files changed between the recorded commit and the current head.
|
||||
# Tracked patterns mirror script/check_requirements/diff.py TRACKED_PATTERNS.
|
||||
CHANGED=$(gh api "repos/${GITHUB_REPOSITORY}/compare/${PRIOR}...${HEAD}" \
|
||||
--jq '.files[].filename' 2>/dev/null) || {
|
||||
echo "Could not compare ${PRIOR}...${HEAD}; running the agent."
|
||||
exit 0
|
||||
}
|
||||
TRACKED=$(printf '%s\n' "${CHANGED}" \
|
||||
| grep -Ex 'requirements.*\.txt|homeassistant/package_constraints\.txt' || true)
|
||||
if [ -z "${TRACKED}" ]; then
|
||||
echo "No tracked requirement files changed since ${PRIOR}; skipping the agent."
|
||||
echo "skip=true" >> "${GITHUB_OUTPUT}"
|
||||
else
|
||||
echo "Tracked requirement files changed since ${PRIOR}; running the agent:"
|
||||
printf '%s\n' "${TRACKED}"
|
||||
fi
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
pre_activation:
|
||||
runs-on: ubuntu-slim
|
||||
outputs:
|
||||
@@ -1438,7 +1545,7 @@ jobs:
|
||||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
@@ -1461,48 +1568,12 @@ jobs:
|
||||
const { main } = require('${{ runner.temp }}/gh-aw/actions/check_membership.cjs');
|
||||
await main();
|
||||
|
||||
prepare:
|
||||
needs: activation
|
||||
if: github.event.workflow_run.conclusion == 'success'
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
|
||||
outputs:
|
||||
pr_number: ${{ steps.prepare.outputs.pr_number }}
|
||||
skip: ${{ steps.prepare.outputs.skip }}
|
||||
steps:
|
||||
- name: Configure GH_HOST for enterprise compatibility
|
||||
id: ghes-host-config
|
||||
shell: bash
|
||||
# zizmor: ignore[github-env] - GITHUB_SERVER_URL is set by GitHub Actions, not user input.
|
||||
run: |
|
||||
# Derive GH_HOST from GITHUB_SERVER_URL so the gh CLI targets the correct
|
||||
# GitHub instance (GHES/GHEC). On github.com this is a harmless no-op.
|
||||
GH_HOST="${GITHUB_SERVER_URL#https://}"
|
||||
GH_HOST="${GH_HOST#http://}"
|
||||
echo "GH_HOST=${GH_HOST}" >> "$GITHUB_ENV"
|
||||
- name: Download deterministic-results artifact
|
||||
id: download
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
name: check-requirements-deterministic
|
||||
path: /tmp/deterministic
|
||||
run-id: ${{ github.event.workflow_run.id }}
|
||||
- name: Resolve skip and PR number from the artifact
|
||||
id: prepare
|
||||
run: |
|
||||
echo "skip=$(jq -r '.skip_aw' /tmp/deterministic/results.json)" >> "${GITHUB_OUTPUT}"
|
||||
echo "pr_number=$(jq -r '.pr_number' /tmp/deterministic/results.json)" >> "${GITHUB_OUTPUT}"
|
||||
|
||||
safe_outputs:
|
||||
needs:
|
||||
- activation
|
||||
- agent
|
||||
- detection
|
||||
- prepare
|
||||
- extract_pr_number
|
||||
if: (!cancelled()) && needs.agent.result != 'skipped' && needs.detection.result == 'success'
|
||||
runs-on: ubuntu-slim
|
||||
permissions:
|
||||
@@ -1538,7 +1609,7 @@ jobs:
|
||||
steps:
|
||||
- name: Setup Scripts
|
||||
id: setup
|
||||
uses: github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6
|
||||
uses: github/gh-aw-actions/setup@v0.79.6
|
||||
with:
|
||||
destination: ${{ runner.temp }}/gh-aw/actions
|
||||
job-name: ${{ github.job }}
|
||||
@@ -1583,7 +1654,7 @@ jobs:
|
||||
GH_AW_ALLOWED_DOMAINS: "*.pythonhosted.org,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,binstar.org,bootstrap.pypa.io,conda.anaconda.org,conda.binstar.org,files.pythonhosted.org,github.com,host.docker.internal,pip.pypa.io,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.npmjs.org,repo.anaconda.com,repo.continuum.io,telemetry.enterprise.githubcopilot.com"
|
||||
GITHUB_SERVER_URL: ${{ github.server_url }}
|
||||
GITHUB_API_URL: ${{ github.api_url }}
|
||||
GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"add_comment\":{\"max\":1,\"target\":\"${{ needs.prepare.outputs.pr_number }}\"},\"create_report_incomplete_issue\":{},\"missing_data\":{},\"missing_tool\":{},\"noop\":{\"max\":1,\"report-as-issue\":\"true\"},\"report_incomplete\":{}}"
|
||||
GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"add_comment\":{\"max\":1,\"target\":\"${{ needs.extract_pr_number.outputs.pr_number }}\"},\"create_report_incomplete_issue\":{},\"missing_data\":{},\"missing_tool\":{},\"noop\":{\"max\":1,\"report-as-issue\":\"true\"},\"report_incomplete\":{}}"
|
||||
with:
|
||||
github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
|
||||
@@ -15,41 +15,94 @@ tools:
|
||||
github:
|
||||
toolsets: [repos, pull_requests]
|
||||
min-integrity: unapproved
|
||||
if: needs.prepare.outputs.skip != 'true'
|
||||
safe-outputs:
|
||||
add-comment:
|
||||
max: 1
|
||||
target: "${{ needs.prepare.outputs.pr_number }}"
|
||||
target: "${{ needs.extract_pr_number.outputs.pr_number }}"
|
||||
needs:
|
||||
- prepare
|
||||
- extract_pr_number
|
||||
jobs:
|
||||
prepare:
|
||||
# The deterministic stage always uploads an artifact; its `skip_aw` flag is
|
||||
# true when no tracked requirement file changed since the last comment,
|
||||
# which is our cue to skip the (token-spending) agent. Recover the PR number
|
||||
# to comment on either way.
|
||||
gate:
|
||||
# Skip the (token-spending) agent when no tracked requirement file changed
|
||||
if: github.event.workflow_run.conclusion == 'success'
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
pull-requests: read
|
||||
outputs:
|
||||
skip: ${{ steps.prepare.outputs.skip }}
|
||||
pr_number: ${{ steps.prepare.outputs.pr_number }}
|
||||
skip: ${{ steps.gate.outputs.skip }}
|
||||
steps:
|
||||
- name: Download deterministic-results artifact
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
with:
|
||||
name: check-requirements-deterministic
|
||||
path: /tmp/gate
|
||||
run-id: ${{ github.event.workflow_run.id }}
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Decide whether requirements changed since the last comment
|
||||
id: gate
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
PR=$(jq -r '.pr_number' /tmp/gate/results.json)
|
||||
HEAD=$(jq -r '.head_sha // empty' /tmp/gate/results.json)
|
||||
if [ -z "${HEAD}" ]; then
|
||||
echo "Artifact has no head_sha; running the agent."
|
||||
exit 0
|
||||
fi
|
||||
# Recover the commit recorded in the most recent requirements-check
|
||||
# comment from the "Checked at commit" link
|
||||
PRIOR=$(gh api --paginate "repos/${GITHUB_REPOSITORY}/issues/${PR}/comments" \
|
||||
--jq '.[] | select(.body | contains("<!-- requirements-check -->")) | .body' \
|
||||
| grep -oiE '/commit/[0-9a-f]{40}' \
|
||||
| grep -oiE '[0-9a-f]{40}' | tail -1 || true)
|
||||
if [ -z "${PRIOR}" ]; then
|
||||
echo "No previous comment with a recorded commit; running the agent."
|
||||
exit 0
|
||||
fi
|
||||
if [ "${PRIOR}" = "${HEAD}" ]; then
|
||||
echo "Head ${HEAD} unchanged since the last comment; skipping the agent."
|
||||
echo "skip=true" >> "${GITHUB_OUTPUT}"
|
||||
exit 0
|
||||
fi
|
||||
# List files changed between the recorded commit and the current head.
|
||||
# Tracked patterns mirror script/check_requirements/diff.py TRACKED_PATTERNS.
|
||||
CHANGED=$(gh api "repos/${GITHUB_REPOSITORY}/compare/${PRIOR}...${HEAD}" \
|
||||
--jq '.files[].filename' 2>/dev/null) || {
|
||||
echo "Could not compare ${PRIOR}...${HEAD}; running the agent."
|
||||
exit 0
|
||||
}
|
||||
TRACKED=$(printf '%s\n' "${CHANGED}" \
|
||||
| grep -Ex 'requirements.*\.txt|homeassistant/package_constraints\.txt' || true)
|
||||
if [ -z "${TRACKED}" ]; then
|
||||
echo "No tracked requirement files changed since ${PRIOR}; skipping the agent."
|
||||
echo "skip=true" >> "${GITHUB_OUTPUT}"
|
||||
else
|
||||
echo "Tracked requirement files changed since ${PRIOR}; running the agent:"
|
||||
printf '%s\n' "${TRACKED}"
|
||||
fi
|
||||
extract_pr_number:
|
||||
needs: gate
|
||||
if: needs.gate.outputs.skip != 'true' && github.event.workflow_run.conclusion == 'success'
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
actions: read
|
||||
outputs:
|
||||
pr_number: ${{ steps.extract.outputs.pr_number }}
|
||||
steps:
|
||||
- name: Download deterministic-results artifact
|
||||
id: download
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
with:
|
||||
name: check-requirements-deterministic
|
||||
path: /tmp/deterministic
|
||||
run-id: ${{ github.event.workflow_run.id }}
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Resolve skip and PR number from the artifact
|
||||
id: prepare
|
||||
- name: Extract PR number from artifact
|
||||
id: extract
|
||||
run: |
|
||||
echo "skip=$(jq -r '.skip_aw' /tmp/deterministic/results.json)" >> "${GITHUB_OUTPUT}"
|
||||
echo "pr_number=$(jq -r '.pr_number' /tmp/deterministic/results.json)" >> "${GITHUB_OUTPUT}"
|
||||
PR=$(jq -r '.pr_number' /tmp/deterministic/results.json)
|
||||
echo "pr_number=${PR}" >> "${GITHUB_OUTPUT}"
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.workflow_run.id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
@@ -39,7 +39,7 @@ on:
|
||||
env:
|
||||
CACHE_VERSION: 3
|
||||
MYPY_CACHE_VERSION: 1
|
||||
HA_SHORT_VERSION: "2026.8"
|
||||
HA_SHORT_VERSION: "2026.7"
|
||||
ADDITIONAL_PYTHON_VERSIONS: "[]"
|
||||
# 10.3 is the oldest supported version
|
||||
# - 10.3.32 is the version currently shipped with Synology (as of 17 Feb 2022)
|
||||
|
||||
Generated
+2
-5
@@ -181,7 +181,6 @@ CLAUDE.md @home-assistant/core
|
||||
/tests/components/asuswrt/ @kennedyshead @ollo69 @Vaskivskyi
|
||||
/homeassistant/components/atag/ @MatsNL
|
||||
/tests/components/atag/ @MatsNL
|
||||
/homeassistant/components/aten_pe/ @mtdcr
|
||||
/homeassistant/components/atome/ @baqs
|
||||
/homeassistant/components/august/ @bdraco
|
||||
/tests/components/august/ @bdraco
|
||||
@@ -790,8 +789,8 @@ CLAUDE.md @home-assistant/core
|
||||
/tests/components/html5/ @alexyao2015 @tr4nt0r
|
||||
/homeassistant/components/http/ @home-assistant/core
|
||||
/tests/components/http/ @home-assistant/core
|
||||
/homeassistant/components/huawei_lte/ @fphammerle
|
||||
/tests/components/huawei_lte/ @fphammerle
|
||||
/homeassistant/components/huawei_lte/ @scop @fphammerle
|
||||
/tests/components/huawei_lte/ @scop @fphammerle
|
||||
/homeassistant/components/hue/ @marcelveldt
|
||||
/tests/components/hue/ @marcelveldt
|
||||
/homeassistant/components/hue_ble/ @flip-dots
|
||||
@@ -1027,8 +1026,6 @@ CLAUDE.md @home-assistant/core
|
||||
/tests/components/litterrobot/ @natekspencer @tkdrob
|
||||
/homeassistant/components/livisi/ @StefanIacobLivisi @planbnet
|
||||
/tests/components/livisi/ @StefanIacobLivisi @planbnet
|
||||
/homeassistant/components/llm/ @home-assistant/core
|
||||
/tests/components/llm/ @home-assistant/core
|
||||
/homeassistant/components/local_calendar/ @allenporter
|
||||
/tests/components/local_calendar/ @allenporter
|
||||
/homeassistant/components/local_ip/ @issacg
|
||||
|
||||
@@ -27,7 +27,7 @@ from .const import CONDITIONS_MAP, DOMAIN, FORECAST_MAP
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
API_TIMEOUT: Final[int] = 120
|
||||
WEATHER_UPDATE_INTERVAL = timedelta(minutes=10)
|
||||
WEATHER_UPDATE_INTERVAL = timedelta(minutes=20)
|
||||
|
||||
type AemetConfigEntry = ConfigEntry[AemetData]
|
||||
|
||||
|
||||
@@ -11,10 +11,10 @@ from homeassistant.components.sensor import (
|
||||
SensorStateClass,
|
||||
)
|
||||
from homeassistant.const import (
|
||||
CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
CONF_NAME,
|
||||
UnitOfDensity,
|
||||
PERCENTAGE,
|
||||
UnitOfPressure,
|
||||
UnitOfRatio,
|
||||
UnitOfTemperature,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
@@ -76,14 +76,14 @@ SENSOR_TYPES: tuple[AirlySensorEntityDescription, ...] = (
|
||||
AirlySensorEntityDescription(
|
||||
key=ATTR_API_PM1,
|
||||
device_class=SensorDeviceClass.PM1,
|
||||
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
|
||||
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
suggested_display_precision=0,
|
||||
),
|
||||
AirlySensorEntityDescription(
|
||||
key=ATTR_API_PM25,
|
||||
device_class=SensorDeviceClass.PM25,
|
||||
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
|
||||
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
suggested_display_precision=0,
|
||||
attrs=lambda data: {
|
||||
@@ -94,7 +94,7 @@ SENSOR_TYPES: tuple[AirlySensorEntityDescription, ...] = (
|
||||
AirlySensorEntityDescription(
|
||||
key=ATTR_API_PM10,
|
||||
device_class=SensorDeviceClass.PM10,
|
||||
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
|
||||
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
suggested_display_precision=0,
|
||||
attrs=lambda data: {
|
||||
@@ -105,7 +105,7 @@ SENSOR_TYPES: tuple[AirlySensorEntityDescription, ...] = (
|
||||
AirlySensorEntityDescription(
|
||||
key=ATTR_API_HUMIDITY,
|
||||
device_class=SensorDeviceClass.HUMIDITY,
|
||||
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
suggested_display_precision=1,
|
||||
),
|
||||
@@ -126,7 +126,7 @@ SENSOR_TYPES: tuple[AirlySensorEntityDescription, ...] = (
|
||||
AirlySensorEntityDescription(
|
||||
key=ATTR_API_CO,
|
||||
device_class=SensorDeviceClass.CO,
|
||||
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
|
||||
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
suggested_display_precision=0,
|
||||
attrs=lambda data: {
|
||||
@@ -137,7 +137,7 @@ SENSOR_TYPES: tuple[AirlySensorEntityDescription, ...] = (
|
||||
AirlySensorEntityDescription(
|
||||
key=ATTR_API_NO2,
|
||||
device_class=SensorDeviceClass.NITROGEN_DIOXIDE,
|
||||
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
|
||||
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
suggested_display_precision=0,
|
||||
attrs=lambda data: {
|
||||
@@ -148,7 +148,7 @@ SENSOR_TYPES: tuple[AirlySensorEntityDescription, ...] = (
|
||||
AirlySensorEntityDescription(
|
||||
key=ATTR_API_SO2,
|
||||
device_class=SensorDeviceClass.SULPHUR_DIOXIDE,
|
||||
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
|
||||
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
suggested_display_precision=0,
|
||||
attrs=lambda data: {
|
||||
@@ -159,7 +159,7 @@ SENSOR_TYPES: tuple[AirlySensorEntityDescription, ...] = (
|
||||
AirlySensorEntityDescription(
|
||||
key=ATTR_API_O3,
|
||||
device_class=SensorDeviceClass.OZONE,
|
||||
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
|
||||
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
suggested_display_precision=0,
|
||||
attrs=lambda data: {
|
||||
|
||||
@@ -8,5 +8,5 @@
|
||||
"iot_class": "cloud_polling",
|
||||
"loggers": ["aioamazondevices"],
|
||||
"quality_scale": "platinum",
|
||||
"requirements": ["aioamazondevices==14.1.6"]
|
||||
"requirements": ["aioamazondevices==14.1.8"]
|
||||
}
|
||||
|
||||
@@ -9,5 +9,5 @@
|
||||
"iot_class": "cloud_polling",
|
||||
"loggers": ["pyanglianwater"],
|
||||
"quality_scale": "bronze",
|
||||
"requirements": ["pyanglianwater==3.2.2"]
|
||||
"requirements": ["pyanglianwater==3.2.3"]
|
||||
}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
"""The ATEN PE component."""
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"domain": "aten_pe",
|
||||
"name": "ATEN Rack PDU",
|
||||
"codeowners": ["@mtdcr"],
|
||||
"documentation": "https://www.home-assistant.io/integrations/aten_pe",
|
||||
"iot_class": "local_polling",
|
||||
"quality_scale": "legacy",
|
||||
"requirements": ["atenpdu==0.3.6"]
|
||||
}
|
||||
@@ -1,119 +0,0 @@
|
||||
"""The ATEN PE switch component."""
|
||||
|
||||
import logging
|
||||
from typing import Any, override
|
||||
|
||||
from atenpdu import AtenPE, AtenPEError
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components.switch import (
|
||||
PLATFORM_SCHEMA as SWITCH_PLATFORM_SCHEMA,
|
||||
SwitchDeviceClass,
|
||||
SwitchEntity,
|
||||
)
|
||||
from homeassistant.const import CONF_HOST, CONF_PORT, CONF_USERNAME
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import PlatformNotReady
|
||||
from homeassistant.helpers import config_validation as cv
|
||||
from homeassistant.helpers.device_registry import CONNECTION_NETWORK_MAC, DeviceInfo
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
CONF_AUTH_KEY = "auth_key"
|
||||
CONF_COMMUNITY = "community"
|
||||
CONF_PRIV_KEY = "priv_key"
|
||||
DEFAULT_COMMUNITY = "private"
|
||||
DEFAULT_PORT = "161"
|
||||
DEFAULT_USERNAME = "administrator"
|
||||
|
||||
PLATFORM_SCHEMA = SWITCH_PLATFORM_SCHEMA.extend(
|
||||
{
|
||||
vol.Required(CONF_HOST): cv.string,
|
||||
vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port,
|
||||
vol.Optional(CONF_COMMUNITY, default=DEFAULT_COMMUNITY): cv.string,
|
||||
vol.Optional(CONF_USERNAME, default=DEFAULT_USERNAME): cv.string,
|
||||
vol.Optional(CONF_AUTH_KEY): cv.string,
|
||||
vol.Optional(CONF_PRIV_KEY): cv.string,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
async def async_setup_platform(
|
||||
hass: HomeAssistant,
|
||||
config: ConfigType,
|
||||
async_add_entities: AddEntitiesCallback,
|
||||
discovery_info: DiscoveryInfoType | None = None,
|
||||
) -> None:
|
||||
"""Set up the ATEN PE switch."""
|
||||
node = config[CONF_HOST]
|
||||
serv = config[CONF_PORT]
|
||||
|
||||
dev = AtenPE(
|
||||
node=node,
|
||||
serv=serv,
|
||||
community=config[CONF_COMMUNITY],
|
||||
username=config[CONF_USERNAME],
|
||||
authkey=config.get(CONF_AUTH_KEY),
|
||||
privkey=config.get(CONF_PRIV_KEY),
|
||||
)
|
||||
|
||||
try:
|
||||
await hass.async_add_executor_job(dev.initialize)
|
||||
mac = await dev.deviceMAC()
|
||||
outlets = dev.outlets()
|
||||
name = await dev.deviceName()
|
||||
model = await dev.modelName()
|
||||
sw_version = await dev.deviceFWversion()
|
||||
except AtenPEError as exc:
|
||||
_LOGGER.error("Failed to initialize %s:%s: %s", node, serv, str(exc))
|
||||
raise PlatformNotReady from exc
|
||||
|
||||
info = DeviceInfo(
|
||||
connections={(CONNECTION_NETWORK_MAC, mac)},
|
||||
manufacturer="ATEN",
|
||||
model=model,
|
||||
name=name,
|
||||
sw_version=sw_version,
|
||||
)
|
||||
|
||||
async_add_entities(
|
||||
(AtenSwitch(dev, info, mac, outlet.id, outlet.name) for outlet in outlets), True
|
||||
)
|
||||
|
||||
|
||||
class AtenSwitch(SwitchEntity):
|
||||
"""Represents an ATEN PE switch."""
|
||||
|
||||
_attr_device_class = SwitchDeviceClass.OUTLET
|
||||
|
||||
def __init__(
|
||||
self, device: AtenPE, info: DeviceInfo, mac: str, outlet: str, name: str
|
||||
) -> None:
|
||||
"""Initialize an ATEN PE switch."""
|
||||
self._device = device
|
||||
self._outlet = outlet
|
||||
self._attr_device_info = info
|
||||
self._attr_unique_id = f"{mac}-{outlet}"
|
||||
self._attr_name = name or f"Outlet {outlet}"
|
||||
|
||||
@override
|
||||
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||
"""Turn the switch on."""
|
||||
await self._device.setOutletStatus(self._outlet, "on")
|
||||
self._attr_is_on = True
|
||||
|
||||
@override
|
||||
async def async_turn_off(self, **kwargs: Any) -> None:
|
||||
"""Turn the switch off."""
|
||||
await self._device.setOutletStatus(self._outlet, "off")
|
||||
self._attr_is_on = False
|
||||
|
||||
async def async_update(self) -> None:
|
||||
"""Process update from entity."""
|
||||
status = await self._device.displayOutletStatus(self._outlet)
|
||||
if status == "on":
|
||||
self._attr_is_on = True
|
||||
elif status == "off":
|
||||
self._attr_is_on = False
|
||||
@@ -15,15 +15,16 @@ from homeassistant.components.sensor import (
|
||||
SensorStateClass,
|
||||
)
|
||||
from homeassistant.const import (
|
||||
CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
CONCENTRATION_PARTS_PER_MILLION,
|
||||
LIGHT_LUX,
|
||||
PERCENTAGE,
|
||||
UnitOfApparentPower,
|
||||
UnitOfDensity,
|
||||
UnitOfElectricCurrent,
|
||||
UnitOfElectricPotential,
|
||||
UnitOfEnergy,
|
||||
UnitOfFrequency,
|
||||
UnitOfPower,
|
||||
UnitOfRatio,
|
||||
UnitOfReactiveEnergy,
|
||||
UnitOfReactivePower,
|
||||
UnitOfSpeed,
|
||||
@@ -52,19 +53,19 @@ SENSOR_TYPES: tuple[BleBoxSensorEntityDescription, ...] = (
|
||||
BleBoxSensorEntityDescription(
|
||||
key="pm1",
|
||||
device_class=SensorDeviceClass.PM1,
|
||||
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
|
||||
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
BleBoxSensorEntityDescription(
|
||||
key="pm2_5",
|
||||
device_class=SensorDeviceClass.PM25,
|
||||
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
|
||||
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
BleBoxSensorEntityDescription(
|
||||
key="pm10",
|
||||
device_class=SensorDeviceClass.PM10,
|
||||
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
|
||||
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
BleBoxSensorEntityDescription(
|
||||
@@ -83,7 +84,7 @@ SENSOR_TYPES: tuple[BleBoxSensorEntityDescription, ...] = (
|
||||
BleBoxSensorEntityDescription(
|
||||
key="humidity",
|
||||
device_class=SensorDeviceClass.HUMIDITY,
|
||||
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
BleBoxSensorEntityDescription(
|
||||
@@ -178,7 +179,7 @@ SENSOR_TYPES: tuple[BleBoxSensorEntityDescription, ...] = (
|
||||
BleBoxSensorEntityDescription(
|
||||
key="co2",
|
||||
device_class=SensorDeviceClass.CO2,
|
||||
native_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
|
||||
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
BleBoxSensorEntityDescription(
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
"""Support for Dovado router."""
|
||||
|
||||
# mypy: ignore-errors
|
||||
from datetime import timedelta
|
||||
import logging
|
||||
|
||||
# import dovado
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.const import (
|
||||
CONF_HOST,
|
||||
CONF_PASSWORD,
|
||||
CONF_PORT,
|
||||
CONF_USERNAME,
|
||||
DEVICE_DEFAULT_NAME,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import config_validation as cv
|
||||
from homeassistant.helpers.typing import ConfigType
|
||||
from homeassistant.util import Throttle
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
DOMAIN = "dovado"
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema(
|
||||
{
|
||||
DOMAIN: vol.Schema(
|
||||
{
|
||||
vol.Required(CONF_USERNAME): cv.string,
|
||||
vol.Required(CONF_PASSWORD): cv.string,
|
||||
vol.Optional(CONF_HOST): cv.string,
|
||||
vol.Optional(CONF_PORT): cv.port,
|
||||
}
|
||||
)
|
||||
},
|
||||
extra=vol.ALLOW_EXTRA,
|
||||
)
|
||||
|
||||
MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=30)
|
||||
|
||||
|
||||
def setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
||||
"""Set up the Dovado component."""
|
||||
|
||||
hass.data[DOMAIN] = DovadoData(
|
||||
dovado.Dovado(
|
||||
config[DOMAIN][CONF_USERNAME],
|
||||
config[DOMAIN][CONF_PASSWORD],
|
||||
config[DOMAIN].get(CONF_HOST),
|
||||
config[DOMAIN].get(CONF_PORT),
|
||||
)
|
||||
)
|
||||
return True
|
||||
|
||||
|
||||
class DovadoData:
|
||||
"""Maintain a connection to the router."""
|
||||
|
||||
def __init__(self, client):
|
||||
"""Set up a new Dovado connection."""
|
||||
self._client = client
|
||||
self.state = {}
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Name of the router."""
|
||||
return self.state.get("product name", DEVICE_DEFAULT_NAME)
|
||||
|
||||
@Throttle(MIN_TIME_BETWEEN_UPDATES)
|
||||
def update(self):
|
||||
"""Update device state."""
|
||||
try:
|
||||
self.state = self._client.state or {}
|
||||
if not self.state:
|
||||
return False
|
||||
self.state.update(connected=self.state.get("modem status") == "CONNECTED")
|
||||
except OSError as error:
|
||||
_LOGGER.warning("Could not contact the router: %s", error)
|
||||
return None
|
||||
_LOGGER.debug("Received: %s", self.state)
|
||||
return True
|
||||
|
||||
@property
|
||||
def client(self):
|
||||
"""Dovado client instance."""
|
||||
return self._client
|
||||
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"domain": "dovado",
|
||||
"name": "Dovado",
|
||||
"codeowners": [],
|
||||
"disabled": "This integration is disabled because it uses non-open source code to operate.",
|
||||
"documentation": "https://www.home-assistant.io/integrations/dovado",
|
||||
"iot_class": "local_polling",
|
||||
"quality_scale": "legacy",
|
||||
"requirements": ["dovado==0.4.1"]
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
"""Support for SMS notifications from the Dovado router."""
|
||||
|
||||
import logging
|
||||
from typing import Any, override
|
||||
|
||||
from homeassistant.components.notify import ATTR_TARGET, BaseNotificationService
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
||||
|
||||
from . import DOMAIN
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def get_service(
|
||||
hass: HomeAssistant,
|
||||
config: ConfigType,
|
||||
discovery_info: DiscoveryInfoType | None = None,
|
||||
) -> DovadoSMSNotificationService:
|
||||
"""Get the Dovado Router SMS notification service."""
|
||||
return DovadoSMSNotificationService(hass.data[DOMAIN].client)
|
||||
|
||||
|
||||
class DovadoSMSNotificationService(BaseNotificationService):
|
||||
"""Implement the notification service for the Dovado SMS component."""
|
||||
|
||||
def __init__(self, client):
|
||||
"""Initialize the service."""
|
||||
self._client = client
|
||||
|
||||
@override
|
||||
def send_message(self, message: str, **kwargs: Any) -> None:
|
||||
"""Send SMS to the specified target phone number."""
|
||||
if not (target := kwargs.get(ATTR_TARGET)):
|
||||
_LOGGER.error("One target is required")
|
||||
return
|
||||
|
||||
self._client.send_sms(target, message)
|
||||
@@ -1,5 +0,0 @@
|
||||
extend = "../../../pyproject.toml"
|
||||
|
||||
lint.extend-ignore = [
|
||||
"F821"
|
||||
]
|
||||
@@ -1,143 +0,0 @@
|
||||
"""Support for sensors from the Dovado router."""
|
||||
|
||||
from dataclasses import dataclass
|
||||
from datetime import timedelta
|
||||
import re
|
||||
from typing import Any, override
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components.sensor import (
|
||||
PLATFORM_SCHEMA as SENSOR_PLATFORM_SCHEMA,
|
||||
SensorDeviceClass,
|
||||
SensorEntity,
|
||||
SensorEntityDescription,
|
||||
)
|
||||
from homeassistant.const import CONF_SENSORS, PERCENTAGE, UnitOfInformation
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import config_validation as cv
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
||||
|
||||
from . import DOMAIN
|
||||
|
||||
MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=30)
|
||||
|
||||
SENSOR_UPLOAD = "upload"
|
||||
SENSOR_DOWNLOAD = "download"
|
||||
SENSOR_SIGNAL = "signal"
|
||||
SENSOR_NETWORK = "network"
|
||||
SENSOR_SMS_UNREAD = "sms"
|
||||
|
||||
|
||||
@dataclass(frozen=True, kw_only=True)
|
||||
class DovadoSensorEntityDescription(SensorEntityDescription):
|
||||
"""Describes Dovado sensor entity."""
|
||||
|
||||
identifier: str
|
||||
|
||||
|
||||
SENSOR_TYPES: tuple[DovadoSensorEntityDescription, ...] = (
|
||||
DovadoSensorEntityDescription(
|
||||
identifier=SENSOR_NETWORK,
|
||||
key="signal strength",
|
||||
name="Network",
|
||||
icon="mdi:access-point-network",
|
||||
),
|
||||
DovadoSensorEntityDescription(
|
||||
identifier=SENSOR_SIGNAL,
|
||||
key="signal strength",
|
||||
name="Signal Strength",
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
icon="mdi:signal",
|
||||
),
|
||||
DovadoSensorEntityDescription(
|
||||
identifier=SENSOR_SMS_UNREAD,
|
||||
key="sms unread",
|
||||
name="SMS unread",
|
||||
icon="mdi:message-text-outline",
|
||||
),
|
||||
DovadoSensorEntityDescription(
|
||||
identifier=SENSOR_UPLOAD,
|
||||
key="traffic modem tx",
|
||||
name="Sent",
|
||||
native_unit_of_measurement=UnitOfInformation.GIGABYTES,
|
||||
device_class=SensorDeviceClass.DATA_SIZE,
|
||||
icon="mdi:cloud-upload",
|
||||
),
|
||||
DovadoSensorEntityDescription(
|
||||
identifier=SENSOR_DOWNLOAD,
|
||||
key="traffic modem rx",
|
||||
name="Received",
|
||||
native_unit_of_measurement=UnitOfInformation.GIGABYTES,
|
||||
device_class=SensorDeviceClass.DATA_SIZE,
|
||||
icon="mdi:cloud-download",
|
||||
),
|
||||
)
|
||||
|
||||
SENSOR_KEYS: list[str] = [desc.key for desc in SENSOR_TYPES]
|
||||
|
||||
PLATFORM_SCHEMA = SENSOR_PLATFORM_SCHEMA.extend(
|
||||
{vol.Required(CONF_SENSORS): vol.All(cv.ensure_list, [vol.In(SENSOR_KEYS)])}
|
||||
)
|
||||
|
||||
|
||||
def setup_platform(
|
||||
hass: HomeAssistant,
|
||||
config: ConfigType,
|
||||
add_entities: AddEntitiesCallback,
|
||||
discovery_info: DiscoveryInfoType | None = None,
|
||||
) -> None:
|
||||
"""Set up the Dovado sensor platform."""
|
||||
dovado = hass.data[DOMAIN]
|
||||
|
||||
sensors = config[CONF_SENSORS]
|
||||
entities = [
|
||||
DovadoSensor(dovado, description)
|
||||
for description in SENSOR_TYPES
|
||||
if description.key in sensors
|
||||
]
|
||||
add_entities(entities)
|
||||
|
||||
|
||||
class DovadoSensor(SensorEntity):
|
||||
"""Representation of a Dovado sensor."""
|
||||
|
||||
entity_description: DovadoSensorEntityDescription
|
||||
|
||||
def __init__(self, data, description: DovadoSensorEntityDescription) -> None:
|
||||
"""Initialize the sensor."""
|
||||
self.entity_description = description
|
||||
self._data = data
|
||||
|
||||
self._attr_name = f"{data.name} {description.name}"
|
||||
self._attr_native_value = self._compute_state()
|
||||
|
||||
def _compute_state(self):
|
||||
"""Compute the state of the sensor."""
|
||||
state = self._data.state.get(self.entity_description.key)
|
||||
sensor_identifier = self.entity_description.identifier
|
||||
if sensor_identifier == SENSOR_NETWORK:
|
||||
match = re.search(r"\((.+)\)", state)
|
||||
return match.group(1) if match else None
|
||||
if sensor_identifier == SENSOR_SIGNAL:
|
||||
try:
|
||||
return int(state.split()[0])
|
||||
except ValueError:
|
||||
return None
|
||||
if sensor_identifier == SENSOR_SMS_UNREAD:
|
||||
return int(state)
|
||||
if sensor_identifier in [SENSOR_UPLOAD, SENSOR_DOWNLOAD]:
|
||||
return round(float(state) / 1e6, 1)
|
||||
return state
|
||||
|
||||
def update(self) -> None:
|
||||
"""Update sensor values."""
|
||||
self._data.update()
|
||||
self._attr_native_value = self._compute_state()
|
||||
|
||||
@property
|
||||
@override
|
||||
def extra_state_attributes(self) -> dict[str, Any]:
|
||||
"""Return the state attributes."""
|
||||
return {k: v for k, v in self._data.state.items() if k not in ["date", "time"]}
|
||||
@@ -8,6 +8,6 @@
|
||||
"documentation": "https://www.home-assistant.io/integrations/dropbox",
|
||||
"integration_type": "service",
|
||||
"iot_class": "cloud_polling",
|
||||
"quality_scale": "silver",
|
||||
"quality_scale": "bronze",
|
||||
"requirements": ["python-dropbox-api==0.1.4"]
|
||||
}
|
||||
|
||||
@@ -52,9 +52,7 @@ rules:
|
||||
status: exempt
|
||||
comment: Integration does not have any entities.
|
||||
integration-owner: done
|
||||
log-when-unavailable:
|
||||
status: exempt
|
||||
comment: Integration does not have any entities.
|
||||
log-when-unavailable: todo
|
||||
parallel-updates:
|
||||
status: exempt
|
||||
comment: Integration does not make any entity updates.
|
||||
|
||||
@@ -27,6 +27,19 @@ _LOGGER = logging.getLogger(__name__)
|
||||
|
||||
PARALLEL_UPDATES = 1
|
||||
|
||||
SUPPORTED_SELECT_NODE_TYPES = {
|
||||
NodeType.BOX,
|
||||
NodeType.VLV,
|
||||
NodeType.VLVRH,
|
||||
NodeType.VLVVOC,
|
||||
NodeType.VLVCO2,
|
||||
NodeType.VLVCO2RH,
|
||||
NodeType.EAV,
|
||||
NodeType.EAVRH,
|
||||
NodeType.EAVVOC,
|
||||
NodeType.EAVCO2,
|
||||
}
|
||||
|
||||
|
||||
def _get_ventilation_options(action: ActionItem) -> tuple[str, ...] | None:
|
||||
"""Return ventilation options advertised by a node action."""
|
||||
@@ -71,7 +84,9 @@ async def async_setup_entry(
|
||||
if node.node_id in known_nodes:
|
||||
continue
|
||||
|
||||
if node.general.node_type is not NodeType.BOX:
|
||||
# Duco advertises SetVentilationState broadly, so keep the select
|
||||
# limited to the box and known valve node families.
|
||||
if node.general.node_type not in SUPPORTED_SELECT_NODE_TYPES:
|
||||
continue
|
||||
|
||||
options = options_by_node.get(node.node_id)
|
||||
|
||||
@@ -15,9 +15,10 @@ from homeassistant.components.sensor import (
|
||||
SensorStateClass,
|
||||
)
|
||||
from homeassistant.const import (
|
||||
CONCENTRATION_PARTS_PER_MILLION,
|
||||
PERCENTAGE,
|
||||
SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
|
||||
EntityCategory,
|
||||
UnitOfRatio,
|
||||
UnitOfTime,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
@@ -71,7 +72,7 @@ SENSOR_DESCRIPTIONS: tuple[DucoSensorEntityDescription, ...] = (
|
||||
key="target_flow_level",
|
||||
translation_key="target_flow_level",
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
suggested_display_precision=0,
|
||||
value_fn=lambda node: (
|
||||
node.ventilation.flow_lvl_tgt if node.ventilation else None
|
||||
@@ -95,7 +96,7 @@ SENSOR_DESCRIPTIONS: tuple[DucoSensorEntityDescription, ...] = (
|
||||
key="co2",
|
||||
device_class=SensorDeviceClass.CO2,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
native_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
|
||||
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
|
||||
value_fn=lambda node: node.sensor.co2 if node.sensor else None,
|
||||
node_types=(
|
||||
NodeType.BSCO2,
|
||||
@@ -107,7 +108,7 @@ SENSOR_DESCRIPTIONS: tuple[DucoSensorEntityDescription, ...] = (
|
||||
DucoSensorEntityDescription(
|
||||
key="iaq_co2",
|
||||
translation_key="iaq_co2",
|
||||
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
entity_registry_enabled_default=False,
|
||||
value_fn=lambda node: node.sensor.iaq_co2 if node.sensor else None,
|
||||
@@ -122,14 +123,14 @@ SENSOR_DESCRIPTIONS: tuple[DucoSensorEntityDescription, ...] = (
|
||||
key="humidity",
|
||||
device_class=SensorDeviceClass.HUMIDITY,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
value_fn=lambda node: node.sensor.rh if node.sensor else None,
|
||||
node_types=(NodeType.BSRH, NodeType.UCRH, NodeType.VLVRH, NodeType.VLVCO2RH),
|
||||
),
|
||||
DucoSensorEntityDescription(
|
||||
key="iaq_rh",
|
||||
translation_key="iaq_rh",
|
||||
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
entity_registry_enabled_default=False,
|
||||
value_fn=lambda node: node.sensor.iaq_rh if node.sensor else None,
|
||||
|
||||
@@ -65,6 +65,14 @@ async def _get_fixture_collection(envoy: Envoy, serial: str) -> dict[str, Any]:
|
||||
"/ivp/meters/readings",
|
||||
"/ivp/pdm/device_data",
|
||||
"/home",
|
||||
"/inventory.json?deleted=1",
|
||||
"/admin/lib/acb_config",
|
||||
"/ivp/sc/sched",
|
||||
"/admin/lib/network_display",
|
||||
"/admin/lib/wireless_display",
|
||||
"/ivp/ensemble/relay",
|
||||
"/ivp/livedata/status",
|
||||
"/ivp/pdm/energy",
|
||||
]
|
||||
|
||||
for end_point in end_points:
|
||||
@@ -134,16 +142,15 @@ async def async_get_config_entry_diagnostics(
|
||||
"encharge_power": envoy_data.encharge_power,
|
||||
"encharge_aggregate": envoy_data.encharge_aggregate,
|
||||
"enpower": envoy_data.enpower,
|
||||
"acb_power": envoy_data.acb_power,
|
||||
"acb_inventory": envoy_data.acb_inventory,
|
||||
"battery_aggregate": envoy_data.battery_aggregate,
|
||||
"collar": envoy_data.collar,
|
||||
"c6cc": envoy_data.c6cc,
|
||||
"system_consumption": envoy_data.system_consumption,
|
||||
"system_production": envoy_data.system_production,
|
||||
"system_consumption_phases": envoy_data.system_consumption_phases,
|
||||
"system_production_phases": envoy_data.system_production_phases,
|
||||
"ctmeter_production": envoy_data.ctmeter_production,
|
||||
"ctmeter_consumption": envoy_data.ctmeter_consumption,
|
||||
"ctmeter_storage": envoy_data.ctmeter_storage,
|
||||
"ctmeter_production_phases": envoy_data.ctmeter_production_phases,
|
||||
"ctmeter_consumption_phases": envoy_data.ctmeter_consumption_phases,
|
||||
"ctmeter_storage_phases": envoy_data.ctmeter_storage_phases,
|
||||
"ctmeters": envoy_data.ctmeters,
|
||||
"ctmeters_phases": envoy_data.ctmeters_phases,
|
||||
"dry_contact_status": envoy_data.dry_contact_status,
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
"mqtt": ["esphome/discover/#"],
|
||||
"quality_scale": "platinum",
|
||||
"requirements": [
|
||||
"aioesphomeapi==45.5.2",
|
||||
"aioesphomeapi==45.3.1",
|
||||
"esphome-dashboard-api==1.3.0",
|
||||
"bleak-esphome==3.9.4"
|
||||
],
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
"""The greenwave component."""
|
||||
@@ -1,123 +0,0 @@
|
||||
"""Support for Greenwave Reality (TCP Connected) lights."""
|
||||
|
||||
from datetime import timedelta
|
||||
import logging
|
||||
import os
|
||||
from typing import Any, override
|
||||
|
||||
import greenwavereality as greenwave
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components.light import (
|
||||
ATTR_BRIGHTNESS,
|
||||
PLATFORM_SCHEMA as LIGHT_PLATFORM_SCHEMA,
|
||||
ColorMode,
|
||||
LightEntity,
|
||||
)
|
||||
from homeassistant.const import CONF_HOST
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import config_validation as cv
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
||||
from homeassistant.util import Throttle
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
CONF_VERSION = "version"
|
||||
|
||||
PLATFORM_SCHEMA = LIGHT_PLATFORM_SCHEMA.extend(
|
||||
{vol.Required(CONF_HOST): cv.string, vol.Required(CONF_VERSION): cv.positive_int}
|
||||
)
|
||||
|
||||
MIN_TIME_BETWEEN_UPDATES = timedelta(minutes=1)
|
||||
|
||||
|
||||
def setup_platform(
|
||||
hass: HomeAssistant,
|
||||
config: ConfigType,
|
||||
add_entities: AddEntitiesCallback,
|
||||
discovery_info: DiscoveryInfoType | None = None,
|
||||
) -> None:
|
||||
"""Set up the Greenwave Reality Platform."""
|
||||
host = config.get(CONF_HOST)
|
||||
tokenfilename = hass.config.path(".greenwave")
|
||||
if config.get(CONF_VERSION) == 3:
|
||||
if os.path.exists(tokenfilename):
|
||||
with open(tokenfilename, encoding="utf8") as tokenfile:
|
||||
token = tokenfile.read()
|
||||
else:
|
||||
try:
|
||||
token = greenwave.grab_token(host, "hass", "homeassistant")
|
||||
except PermissionError:
|
||||
_LOGGER.error("The Gateway Is Not In Sync Mode")
|
||||
raise
|
||||
with open(tokenfilename, "w+", encoding="utf8") as tokenfile:
|
||||
tokenfile.write(token)
|
||||
else:
|
||||
token = None
|
||||
bulbs = greenwave.grab_bulbs(host, token)
|
||||
add_entities(
|
||||
GreenwaveLight(device, host, token, GatewayData(host, token))
|
||||
for device in bulbs.values()
|
||||
)
|
||||
|
||||
|
||||
class GreenwaveLight(LightEntity):
|
||||
"""Representation of an Greenwave Reality Light."""
|
||||
|
||||
_attr_color_mode = ColorMode.BRIGHTNESS
|
||||
_attr_supported_color_modes = {ColorMode.BRIGHTNESS}
|
||||
|
||||
def __init__(self, light, host, token, gatewaydata):
|
||||
"""Initialize a Greenwave Reality Light."""
|
||||
self._did = int(light["did"])
|
||||
self._attr_name = light["name"]
|
||||
self._attr_is_on = bool(int(light["state"]))
|
||||
self._attr_brightness = greenwave.hass_brightness(light)
|
||||
self._host = host
|
||||
self._attr_available = greenwave.check_online(light)
|
||||
self._token = token
|
||||
self._gatewaydata = gatewaydata
|
||||
|
||||
@override
|
||||
def turn_on(self, **kwargs: Any) -> None:
|
||||
"""Instruct the light to turn on."""
|
||||
temp_brightness = int((kwargs.get(ATTR_BRIGHTNESS, 255) / 255) * 100)
|
||||
greenwave.set_brightness(self._host, self._did, temp_brightness, self._token)
|
||||
greenwave.turn_on(self._host, self._did, self._token)
|
||||
|
||||
@override
|
||||
def turn_off(self, **kwargs: Any) -> None:
|
||||
"""Instruct the light to turn off."""
|
||||
greenwave.turn_off(self._host, self._did, self._token)
|
||||
|
||||
def update(self) -> None:
|
||||
"""Fetch new state data for this light."""
|
||||
self._gatewaydata.update()
|
||||
bulbs = self._gatewaydata.greenwave
|
||||
|
||||
self._attr_is_on = bool(int(bulbs[self._did]["state"]))
|
||||
self._attr_brightness = greenwave.hass_brightness(bulbs[self._did])
|
||||
self._attr_available = greenwave.check_online(bulbs[self._did])
|
||||
self._attr_name = bulbs[self._did]["name"]
|
||||
|
||||
|
||||
class GatewayData:
|
||||
"""Handle Gateway data and limit updates."""
|
||||
|
||||
def __init__(self, host, token):
|
||||
"""Initialize the data object."""
|
||||
self._host = host
|
||||
self._token = token
|
||||
self._greenwave = greenwave.grab_bulbs(host, token)
|
||||
|
||||
@property
|
||||
def greenwave(self):
|
||||
"""Return Gateway API object."""
|
||||
return self._greenwave
|
||||
|
||||
@Throttle(MIN_TIME_BETWEEN_UPDATES)
|
||||
def update(self):
|
||||
"""Get the latest data from the gateway."""
|
||||
self._greenwave = greenwave.grab_bulbs(self._host, self._token)
|
||||
return self._greenwave
|
||||
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"domain": "greenwave",
|
||||
"name": "Greenwave Reality",
|
||||
"codeowners": [],
|
||||
"documentation": "https://www.home-assistant.io/integrations/greenwave",
|
||||
"iot_class": "local_polling",
|
||||
"loggers": ["greenwavereality"],
|
||||
"quality_scale": "legacy",
|
||||
"requirements": ["greenwavereality==0.5.1"]
|
||||
}
|
||||
@@ -92,7 +92,7 @@ class SupervisorJobs:
|
||||
# We catch all errors to prevent an error in one from stopping the others
|
||||
for match in [job for job in self._jobs.values() if subscription.matches(job)]:
|
||||
try:
|
||||
return subscription.event_callback(match)
|
||||
subscription.event_callback(match)
|
||||
except Exception as err: # noqa: BLE001
|
||||
_LOGGER.error(
|
||||
"Error encountered processing Supervisor Job (%s %s %s) - %s",
|
||||
|
||||
@@ -26,17 +26,18 @@ from homeassistant.components.sensor import (
|
||||
)
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import (
|
||||
CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
CONCENTRATION_PARTS_PER_MILLION,
|
||||
LIGHT_LUX,
|
||||
PERCENTAGE,
|
||||
SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
|
||||
EntityCategory,
|
||||
Platform,
|
||||
UnitOfDensity,
|
||||
UnitOfElectricCurrent,
|
||||
UnitOfElectricPotential,
|
||||
UnitOfEnergy,
|
||||
UnitOfPower,
|
||||
UnitOfPressure,
|
||||
UnitOfRatio,
|
||||
UnitOfSoundPressure,
|
||||
UnitOfTemperature,
|
||||
)
|
||||
@@ -253,7 +254,7 @@ SIMPLE_SENSOR: dict[str, HomeKitSensorEntityDescription] = {
|
||||
name="Current Humidity",
|
||||
device_class=SensorDeviceClass.HUMIDITY,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
# This sensor is only for humidity characteristics that are not part
|
||||
# of a humidity sensor service.
|
||||
probe=(lambda char: char.service.type != ServicesTypes.HUMIDITY_SENSOR),
|
||||
@@ -269,42 +270,42 @@ SIMPLE_SENSOR: dict[str, HomeKitSensorEntityDescription] = {
|
||||
name="PM2.5 Density",
|
||||
device_class=SensorDeviceClass.PM25,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
|
||||
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
),
|
||||
CharacteristicsTypes.DENSITY_PM10: HomeKitSensorEntityDescription(
|
||||
key=CharacteristicsTypes.DENSITY_PM10,
|
||||
name="PM10 Density",
|
||||
device_class=SensorDeviceClass.PM10,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
|
||||
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
),
|
||||
CharacteristicsTypes.DENSITY_OZONE: HomeKitSensorEntityDescription(
|
||||
key=CharacteristicsTypes.DENSITY_OZONE,
|
||||
name="Ozone Density",
|
||||
device_class=SensorDeviceClass.OZONE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
|
||||
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
),
|
||||
CharacteristicsTypes.DENSITY_NO2: HomeKitSensorEntityDescription(
|
||||
key=CharacteristicsTypes.DENSITY_NO2,
|
||||
name="Nitrogen Dioxide Density",
|
||||
device_class=SensorDeviceClass.NITROGEN_DIOXIDE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
|
||||
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
),
|
||||
CharacteristicsTypes.DENSITY_SO2: HomeKitSensorEntityDescription(
|
||||
key=CharacteristicsTypes.DENSITY_SO2,
|
||||
name="Sulphur Dioxide Density",
|
||||
device_class=SensorDeviceClass.SULPHUR_DIOXIDE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
|
||||
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
),
|
||||
CharacteristicsTypes.DENSITY_VOC: HomeKitSensorEntityDescription(
|
||||
key=CharacteristicsTypes.DENSITY_VOC,
|
||||
name="Volatile Organic Compound Density",
|
||||
device_class=SensorDeviceClass.VOLATILE_ORGANIC_COMPOUNDS,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
|
||||
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
),
|
||||
CharacteristicsTypes.THREAD_NODE_CAPABILITIES: HomeKitSensorEntityDescription(
|
||||
key=CharacteristicsTypes.THREAD_NODE_CAPABILITIES,
|
||||
@@ -362,13 +363,13 @@ SIMPLE_SENSOR: dict[str, HomeKitSensorEntityDescription] = {
|
||||
key=CharacteristicsTypes.FILTER_LIFE_LEVEL,
|
||||
name="Filter lifetime",
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
),
|
||||
CharacteristicsTypes.WATER_LEVEL: HomeKitSensorEntityDescription(
|
||||
key=CharacteristicsTypes.WATER_LEVEL,
|
||||
name="Water level",
|
||||
translation_key="water_level",
|
||||
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
CharacteristicsTypes.VENDOR_EVE_THERMO_VALVE_POSITION: (
|
||||
@@ -378,7 +379,7 @@ SIMPLE_SENSOR: dict[str, HomeKitSensorEntityDescription] = {
|
||||
translation_key="valve_position",
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
)
|
||||
),
|
||||
}
|
||||
@@ -408,7 +409,7 @@ class HomeKitHumiditySensor(HomeKitSensor):
|
||||
"""Representation of a Homekit humidity sensor."""
|
||||
|
||||
_attr_device_class = SensorDeviceClass.HUMIDITY
|
||||
_attr_native_unit_of_measurement = UnitOfRatio.PERCENTAGE
|
||||
_attr_native_unit_of_measurement = PERCENTAGE
|
||||
|
||||
@override
|
||||
def get_characteristic_types(self) -> list[str]:
|
||||
@@ -480,7 +481,7 @@ class HomeKitCarbonDioxideSensor(HomeKitSensor):
|
||||
"""Representation of a Homekit Carbon Dioxide sensor."""
|
||||
|
||||
_attr_device_class = SensorDeviceClass.CO2
|
||||
_attr_native_unit_of_measurement = UnitOfRatio.PARTS_PER_MILLION
|
||||
_attr_native_unit_of_measurement = CONCENTRATION_PARTS_PER_MILLION
|
||||
|
||||
@override
|
||||
def get_characteristic_types(self) -> list[str]:
|
||||
@@ -504,7 +505,7 @@ class HomeKitBatterySensor(HomeKitSensor):
|
||||
"""Representation of a Homekit battery sensor."""
|
||||
|
||||
_attr_device_class = SensorDeviceClass.BATTERY
|
||||
_attr_native_unit_of_measurement = UnitOfRatio.PERCENTAGE
|
||||
_attr_native_unit_of_measurement = PERCENTAGE
|
||||
_attr_entity_category = EntityCategory.DIAGNOSTIC
|
||||
|
||||
@override
|
||||
|
||||
@@ -50,13 +50,14 @@ from homeassistant.components.sensor import (
|
||||
SensorStateClass,
|
||||
)
|
||||
from homeassistant.const import (
|
||||
CONCENTRATION_GRAMS_PER_CUBIC_METER,
|
||||
CONCENTRATION_MILLIGRAMS_PER_CUBIC_METER,
|
||||
DEGREE,
|
||||
LIGHT_LUX,
|
||||
UnitOfDensity,
|
||||
PERCENTAGE,
|
||||
UnitOfEnergy,
|
||||
UnitOfPower,
|
||||
UnitOfPrecipitationDepth,
|
||||
UnitOfRatio,
|
||||
UnitOfSpeed,
|
||||
UnitOfTemperature,
|
||||
UnitOfVolume,
|
||||
@@ -83,7 +84,7 @@ SMOKE_DETECTOR_SENSORS: tuple[HmipSmokeDetectorSensorDescription, ...] = (
|
||||
HmipSmokeDetectorSensorDescription(
|
||||
key="dirt_level",
|
||||
translation_key="smoke_detector_dirt_level",
|
||||
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
entity_registry_enabled_default=False,
|
||||
channel_field="dirtLevel",
|
||||
@@ -531,7 +532,7 @@ class HomematicipFloorTerminalBlockMechanicChannelValve(
|
||||
):
|
||||
"""Representation of the HomematicIP floor terminal block."""
|
||||
|
||||
_attr_native_unit_of_measurement = UnitOfRatio.PERCENTAGE
|
||||
_attr_native_unit_of_measurement = PERCENTAGE
|
||||
_attr_state_class = SensorStateClass.MEASUREMENT
|
||||
|
||||
def __init__(
|
||||
@@ -580,7 +581,7 @@ class HomematicipAccesspointDutyCycle(HomematicipGenericEntity, SensorEntity):
|
||||
"""Representation of then HomeMaticIP access point."""
|
||||
|
||||
_attr_icon = "mdi:access-point-network"
|
||||
_attr_native_unit_of_measurement = UnitOfRatio.PERCENTAGE
|
||||
_attr_native_unit_of_measurement = PERCENTAGE
|
||||
_attr_state_class = SensorStateClass.MEASUREMENT
|
||||
|
||||
def __init__(self, hap: HomematicipHAP, device) -> None:
|
||||
@@ -599,7 +600,7 @@ class HomematicipAccesspointDutyCycle(HomematicipGenericEntity, SensorEntity):
|
||||
class HomematicipHeatingThermostat(HomematicipGenericEntity, SensorEntity):
|
||||
"""Representation of the HomematicIP heating thermostat."""
|
||||
|
||||
_attr_native_unit_of_measurement = UnitOfRatio.PERCENTAGE
|
||||
_attr_native_unit_of_measurement = PERCENTAGE
|
||||
|
||||
def __init__(self, hap: HomematicipHAP, device) -> None:
|
||||
"""Initialize heating thermostat device."""
|
||||
@@ -628,7 +629,7 @@ class HomematicipHumiditySensor(HomematicipGenericEntity, SensorEntity):
|
||||
"""Representation of the HomematicIP humidity sensor."""
|
||||
|
||||
_attr_device_class = SensorDeviceClass.HUMIDITY
|
||||
_attr_native_unit_of_measurement = UnitOfRatio.PERCENTAGE
|
||||
_attr_native_unit_of_measurement = PERCENTAGE
|
||||
_attr_state_class = SensorStateClass.MEASUREMENT
|
||||
|
||||
def __init__(self, hap: HomematicipHAP, device) -> None:
|
||||
@@ -679,9 +680,9 @@ class HomematicipAbsoluteHumiditySensor(HomematicipGenericEntity, SensorEntity):
|
||||
"""Representation of the HomematicIP absolute humidity sensor."""
|
||||
|
||||
_attr_device_class = SensorDeviceClass.ABSOLUTE_HUMIDITY
|
||||
_attr_native_unit_of_measurement = UnitOfDensity.GRAMS_PER_CUBIC_METER
|
||||
_attr_native_unit_of_measurement = CONCENTRATION_GRAMS_PER_CUBIC_METER
|
||||
_attr_suggested_display_precision = 1
|
||||
_attr_suggested_unit_of_measurement = UnitOfDensity.MILLIGRAMS_PER_CUBIC_METER
|
||||
_attr_suggested_unit_of_measurement = CONCENTRATION_MILLIGRAMS_PER_CUBIC_METER
|
||||
_attr_state_class = SensorStateClass.MEASUREMENT
|
||||
|
||||
def __init__(self, hap: HomematicipHAP, device) -> None:
|
||||
@@ -1142,7 +1143,7 @@ class HomematicipSoilMoistureSensor(HomematicipGenericEntity, SensorEntity):
|
||||
"""Representation of the HomematicIP soil moisture sensor."""
|
||||
|
||||
_attr_device_class = SensorDeviceClass.MOISTURE
|
||||
_attr_native_unit_of_measurement = UnitOfRatio.PERCENTAGE
|
||||
_attr_native_unit_of_measurement = PERCENTAGE
|
||||
_attr_state_class = SensorStateClass.MEASUREMENT
|
||||
|
||||
def __init__(self, hap: HomematicipHAP, device) -> None:
|
||||
|
||||
@@ -245,14 +245,11 @@ class HuaweiLteConfigFlow(ConfigFlow, domain=DOMAIN):
|
||||
)
|
||||
assert conn
|
||||
|
||||
def _get_info_and_disconnect() -> tuple[dict, dict]:
|
||||
result = get_device_info(conn)
|
||||
self._disconnect(conn)
|
||||
return result
|
||||
|
||||
info, wlan_settings = await self.hass.async_add_executor_job(
|
||||
_get_info_and_disconnect
|
||||
get_device_info, conn
|
||||
)
|
||||
# pylint: disable-next=home-assistant-sequential-executor-jobs
|
||||
await self.hass.async_add_executor_job(self._disconnect, conn)
|
||||
|
||||
user_input.update(
|
||||
{
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"domain": "huawei_lte",
|
||||
"name": "Huawei LTE",
|
||||
"codeowners": ["@fphammerle"],
|
||||
"codeowners": ["@scop", "@fphammerle"],
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/huawei_lte",
|
||||
"integration_type": "device",
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
"""The LLM integration.
|
||||
|
||||
Owns the LLM tools platform: integrations contribute tools to the LLM APIs
|
||||
through an ``<integration>/llm.py`` platform with an ``async_get_tools`` hook.
|
||||
The platforms are loaded lazily and queried per request. The framework
|
||||
(``Tool``, the APIs) lives in ``homeassistant.helpers.llm``.
|
||||
"""
|
||||
|
||||
from dataclasses import dataclass
|
||||
import logging
|
||||
from typing import Protocol
|
||||
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers import config_validation as cv
|
||||
from homeassistant.helpers.integration_platform import LazyIntegrationPlatforms
|
||||
from homeassistant.helpers.llm import LLMContext, Tool
|
||||
from homeassistant.helpers.typing import ConfigType
|
||||
from homeassistant.util.hass_dict import HassKey
|
||||
|
||||
from .const import DOMAIN
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
CONFIG_SCHEMA = cv.empty_config_schema(DOMAIN)
|
||||
|
||||
DATA_PLATFORMS: HassKey[LazyIntegrationPlatforms[LLMToolsPlatformProtocol]] = HassKey(
|
||||
"llm_platforms"
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True)
|
||||
class LLMTools:
|
||||
"""Tools and an optional prompt fragment contributed by a platform."""
|
||||
|
||||
tools: list[Tool]
|
||||
prompt: str | None = None
|
||||
|
||||
|
||||
class LLMToolsPlatformProtocol(Protocol):
|
||||
"""Define the format that LLM tools platforms can have."""
|
||||
|
||||
@callback
|
||||
def async_get_tools(self, hass: HomeAssistant, llm_context: LLMContext) -> LLMTools:
|
||||
"""Return the integration's LLM tools for the given context."""
|
||||
|
||||
|
||||
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
||||
"""Set up the LLM integration."""
|
||||
hass.data[DATA_PLATFORMS] = LazyIntegrationPlatforms(
|
||||
hass, DOMAIN, _process_llm_tools_platform
|
||||
)
|
||||
return True
|
||||
|
||||
|
||||
@callback
|
||||
def _process_llm_tools_platform(
|
||||
hass: HomeAssistant, domain: str, platform: LLMToolsPlatformProtocol
|
||||
) -> LLMToolsPlatformProtocol:
|
||||
"""Process an integration's LLM tools platform."""
|
||||
return platform
|
||||
|
||||
|
||||
async def async_get_tools(hass: HomeAssistant, llm_context: LLMContext) -> LLMTools:
|
||||
"""Return the tools and merged prompt from all integration platforms."""
|
||||
platforms = await hass.data[DATA_PLATFORMS].async_get_platforms()
|
||||
|
||||
tools: list[Tool] = []
|
||||
prompts: list[str] = []
|
||||
# Sort by domain so the tool and prompt order is independent of load order.
|
||||
for domain, platform in sorted(platforms.items()):
|
||||
try:
|
||||
result = platform.async_get_tools(hass, llm_context)
|
||||
except Exception:
|
||||
_LOGGER.exception("Error getting tools from LLM platform %s", domain)
|
||||
continue
|
||||
tools.extend(result.tools)
|
||||
if result.prompt:
|
||||
prompts.append(result.prompt)
|
||||
return LLMTools(tools=tools, prompt="\n".join(prompts) if prompts else None)
|
||||
@@ -1,3 +0,0 @@
|
||||
"""Constants for the LLM integration."""
|
||||
|
||||
DOMAIN = "llm"
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"domain": "llm",
|
||||
"name": "LLM",
|
||||
"codeowners": ["@home-assistant/core"],
|
||||
"documentation": "https://www.home-assistant.io/integrations/llm",
|
||||
"integration_type": "system",
|
||||
"iot_class": "calculated",
|
||||
"quality_scale": "internal"
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
"""Support for sending data to Logentries webhook endpoint."""
|
||||
|
||||
import json
|
||||
import logging
|
||||
|
||||
import requests
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.const import CONF_TOKEN, EVENT_STATE_CHANGED
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import config_validation as cv, state as state_helper
|
||||
from homeassistant.helpers.typing import ConfigType
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
DOMAIN = "logentries"
|
||||
|
||||
DEFAULT_HOST = "https://webhook.logentries.com/noformat/logs/"
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema(
|
||||
{DOMAIN: vol.Schema({vol.Required(CONF_TOKEN): cv.string})}, extra=vol.ALLOW_EXTRA
|
||||
)
|
||||
|
||||
|
||||
def setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
||||
"""Set up the Logentries component."""
|
||||
conf = config[DOMAIN]
|
||||
token = conf.get(CONF_TOKEN)
|
||||
le_wh = f"{DEFAULT_HOST}{token}"
|
||||
|
||||
def logentries_event_listener(event):
|
||||
"""Listen for new messages on the bus and sends them to Logentries."""
|
||||
if (state := event.data.get("new_state")) is None:
|
||||
return
|
||||
try:
|
||||
_state = state_helper.state_as_number(state)
|
||||
except ValueError:
|
||||
_state = state.state
|
||||
json_body = [
|
||||
{
|
||||
"domain": state.domain,
|
||||
"entity_id": state.object_id,
|
||||
"attributes": dict(state.attributes),
|
||||
"time": str(event.time_fired),
|
||||
"value": _state,
|
||||
}
|
||||
]
|
||||
try:
|
||||
payload = {"host": le_wh, "event": json_body}
|
||||
requests.post(le_wh, data=json.dumps(payload), timeout=10)
|
||||
except requests.exceptions.RequestException:
|
||||
_LOGGER.exception("Error sending to Logentries")
|
||||
|
||||
hass.bus.listen(EVENT_STATE_CHANGED, logentries_event_listener)
|
||||
|
||||
return True
|
||||
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"domain": "logentries",
|
||||
"name": "Logentries",
|
||||
"codeowners": [],
|
||||
"documentation": "https://www.home-assistant.io/integrations/logentries",
|
||||
"iot_class": "cloud_push",
|
||||
"quality_scale": "legacy"
|
||||
}
|
||||
@@ -12,9 +12,11 @@ from homeassistant.components.sensor import (
|
||||
SensorStateClass,
|
||||
)
|
||||
from homeassistant.const import (
|
||||
CONCENTRATION_PARTS_PER_BILLION,
|
||||
CONCENTRATION_PARTS_PER_MILLION,
|
||||
LIGHT_LUX,
|
||||
PERCENTAGE,
|
||||
UnitOfPressure,
|
||||
UnitOfRatio,
|
||||
UnitOfTemperature,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
@@ -30,7 +32,7 @@ SENSOR_TYPES: Final[dict[str, SensorEntityDescription]] = {
|
||||
SensorType.AIR_HUMIDITY: SensorEntityDescription(
|
||||
key="air_humidity",
|
||||
device_class=SensorDeviceClass.HUMIDITY,
|
||||
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
SensorType.AIR_PRESSURE: SensorEntityDescription(
|
||||
@@ -47,7 +49,7 @@ SENSOR_TYPES: Final[dict[str, SensorEntityDescription]] = {
|
||||
SensorType.ECO2: SensorEntityDescription(
|
||||
key="eco2",
|
||||
device_class=SensorDeviceClass.CO2,
|
||||
native_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
|
||||
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
SensorType.LIGHT: SensorEntityDescription(
|
||||
@@ -65,7 +67,7 @@ SENSOR_TYPES: Final[dict[str, SensorEntityDescription]] = {
|
||||
SensorType.VOC: SensorEntityDescription(
|
||||
key="voc",
|
||||
device_class=SensorDeviceClass.VOLATILE_ORGANIC_COMPOUNDS_PARTS,
|
||||
native_unit_of_measurement=UnitOfRatio.PARTS_PER_BILLION,
|
||||
native_unit_of_measurement=CONCENTRATION_PARTS_PER_BILLION,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
}
|
||||
|
||||
@@ -22,19 +22,20 @@ from homeassistant.components.sensor import (
|
||||
SensorStateClass,
|
||||
)
|
||||
from homeassistant.const import (
|
||||
CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
CONCENTRATION_PARTS_PER_MILLION,
|
||||
LIGHT_LUX,
|
||||
PERCENTAGE,
|
||||
REVOLUTIONS_PER_MINUTE,
|
||||
SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
|
||||
EntityCategory,
|
||||
Platform,
|
||||
UnitOfApparentPower,
|
||||
UnitOfDensity,
|
||||
UnitOfElectricCurrent,
|
||||
UnitOfElectricPotential,
|
||||
UnitOfEnergy,
|
||||
UnitOfPower,
|
||||
UnitOfPressure,
|
||||
UnitOfRatio,
|
||||
UnitOfReactivePower,
|
||||
UnitOfTemperature,
|
||||
UnitOfTime,
|
||||
@@ -443,7 +444,7 @@ DISCOVERY_SCHEMAS = [
|
||||
platform=Platform.SENSOR,
|
||||
entity_description=MatterSensorEntityDescription(
|
||||
key="HumiditySensor",
|
||||
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
device_class=SensorDeviceClass.HUMIDITY,
|
||||
device_to_ha=lambda x: x / HUMIDITY_SCALING_FACTOR,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
@@ -458,7 +459,7 @@ DISCOVERY_SCHEMAS = [
|
||||
platform=Platform.SENSOR,
|
||||
entity_description=MatterSensorEntityDescription(
|
||||
key="SoilMoistureSensor",
|
||||
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
device_class=SensorDeviceClass.MOISTURE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
@@ -483,7 +484,7 @@ DISCOVERY_SCHEMAS = [
|
||||
platform=Platform.SENSOR,
|
||||
entity_description=MatterSensorEntityDescription(
|
||||
key="PowerSource",
|
||||
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
device_class=SensorDeviceClass.BATTERY,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
# value has double precision
|
||||
@@ -624,7 +625,7 @@ DISCOVERY_SCHEMAS = [
|
||||
entity_description=MatterSensorEntityDescription(
|
||||
key="EveThermoValvePosition",
|
||||
translation_key="valve_position",
|
||||
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
),
|
||||
entity_class=MatterSensor,
|
||||
required_attributes=(EveCluster.Attributes.ValvePosition,),
|
||||
@@ -657,7 +658,7 @@ DISCOVERY_SCHEMAS = [
|
||||
platform=Platform.SENSOR,
|
||||
entity_description=MatterSensorEntityDescription(
|
||||
key="CarbonDioxideSensor",
|
||||
native_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
|
||||
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
|
||||
device_class=SensorDeviceClass.CO2,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
@@ -670,7 +671,7 @@ DISCOVERY_SCHEMAS = [
|
||||
platform=Platform.SENSOR,
|
||||
entity_description=MatterSensorEntityDescription(
|
||||
key="TotalVolatileOrganicCompoundsSensor",
|
||||
native_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
|
||||
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
|
||||
device_class=SensorDeviceClass.VOLATILE_ORGANIC_COMPOUNDS_PARTS,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
@@ -698,7 +699,7 @@ DISCOVERY_SCHEMAS = [
|
||||
platform=Platform.SENSOR,
|
||||
entity_description=MatterSensorEntityDescription(
|
||||
key="PM1Sensor",
|
||||
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
|
||||
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
device_class=SensorDeviceClass.PM1,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
@@ -711,7 +712,7 @@ DISCOVERY_SCHEMAS = [
|
||||
platform=Platform.SENSOR,
|
||||
entity_description=MatterSensorEntityDescription(
|
||||
key="PM25Sensor",
|
||||
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
|
||||
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
device_class=SensorDeviceClass.PM25,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
@@ -724,7 +725,7 @@ DISCOVERY_SCHEMAS = [
|
||||
platform=Platform.SENSOR,
|
||||
entity_description=MatterSensorEntityDescription(
|
||||
key="PM10Sensor",
|
||||
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
|
||||
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
device_class=SensorDeviceClass.PM10,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
@@ -749,7 +750,7 @@ DISCOVERY_SCHEMAS = [
|
||||
platform=Platform.SENSOR,
|
||||
entity_description=MatterSensorEntityDescription(
|
||||
key="CarbonMonoxideSensor",
|
||||
native_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
|
||||
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
|
||||
device_class=SensorDeviceClass.CO,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
@@ -762,7 +763,7 @@ DISCOVERY_SCHEMAS = [
|
||||
platform=Platform.SENSOR,
|
||||
entity_description=MatterSensorEntityDescription(
|
||||
key="NitrogenDioxideSensor",
|
||||
native_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
|
||||
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
|
||||
device_class=SensorDeviceClass.NITROGEN_DIOXIDE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
@@ -775,7 +776,7 @@ DISCOVERY_SCHEMAS = [
|
||||
platform=Platform.SENSOR,
|
||||
entity_description=MatterSensorEntityDescription(
|
||||
key="OzoneConcentrationSensor",
|
||||
native_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
|
||||
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
|
||||
device_class=SensorDeviceClass.OZONE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
@@ -801,7 +802,7 @@ DISCOVERY_SCHEMAS = [
|
||||
platform=Platform.SENSOR,
|
||||
entity_description=MatterSensorEntityDescription(
|
||||
key="HepaFilterCondition",
|
||||
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
translation_key="hepa_filter_condition",
|
||||
),
|
||||
@@ -812,7 +813,7 @@ DISCOVERY_SCHEMAS = [
|
||||
platform=Platform.SENSOR,
|
||||
entity_description=MatterSensorEntityDescription(
|
||||
key="ActivatedCarbonFilterCondition",
|
||||
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
translation_key="activated_carbon_filter_condition",
|
||||
),
|
||||
@@ -1296,7 +1297,7 @@ DISCOVERY_SCHEMAS = [
|
||||
entity_description=MatterSensorEntityDescription(
|
||||
key="ThermostatPIHeatingDemand",
|
||||
translation_key="pi_heating_demand",
|
||||
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
),
|
||||
entity_class=MatterSensor,
|
||||
@@ -1378,7 +1379,7 @@ DISCOVERY_SCHEMAS = [
|
||||
entity_registry_enabled_default=False,
|
||||
translation_key="window_covering_target_position",
|
||||
device_to_ha=lambda x: round((10000 - x) / 100),
|
||||
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
),
|
||||
entity_class=MatterSensor,
|
||||
required_attributes=(
|
||||
@@ -1463,7 +1464,7 @@ DISCOVERY_SCHEMAS = [
|
||||
entity_description=MatterSensorEntityDescription(
|
||||
key="EnergyEvseStateOfCharge",
|
||||
translation_key="evse_soc",
|
||||
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
device_class=SensorDeviceClass.BATTERY,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
@@ -1487,7 +1488,7 @@ DISCOVERY_SCHEMAS = [
|
||||
entity_description=MatterSensorEntityDescription(
|
||||
key="WaterHeaterManagementTankPercentage",
|
||||
translation_key="tank_percentage",
|
||||
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
entity_class=MatterSensor,
|
||||
|
||||
@@ -11,7 +11,6 @@ from homeassistant.components.sensor import (
|
||||
SensorEntityDescription,
|
||||
SensorStateClass,
|
||||
)
|
||||
from homeassistant.const import EntityCategory
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
|
||||
from homeassistant.helpers.typing import StateType
|
||||
@@ -74,7 +73,6 @@ async def async_setup_entry(
|
||||
class MealieStatisticSensors(MealieEntity, SensorEntity):
|
||||
"""Defines a Mealie sensor."""
|
||||
|
||||
_attr_entity_category = EntityCategory.DIAGNOSTIC
|
||||
entity_description: MealieStatisticsSensorEntityDescription
|
||||
coordinator: MealieStatisticsCoordinator
|
||||
|
||||
|
||||
@@ -15,29 +15,16 @@ from homeassistant.const import (
|
||||
CONF_PASSWORD,
|
||||
CONF_USERNAME,
|
||||
)
|
||||
from homeassistant.helpers import config_validation as cv
|
||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||
from homeassistant.helpers.selector import (
|
||||
TextSelector,
|
||||
TextSelectorConfig,
|
||||
TextSelectorType,
|
||||
)
|
||||
from homeassistant.helpers.service_info import zeroconf
|
||||
|
||||
from .const import CONF_SERIAL, DOMAIN
|
||||
|
||||
USER_SCHEMA = vol.Schema({vol.Required(CONF_HOST): TextSelector()})
|
||||
USER_SCHEMA = vol.Schema({vol.Required(CONF_HOST): cv.string})
|
||||
|
||||
AUTH_SCHEMA = vol.Schema(
|
||||
{
|
||||
vol.Required(CONF_USERNAME): TextSelector(
|
||||
TextSelectorConfig(autocomplete="username")
|
||||
),
|
||||
vol.Required(CONF_PASSWORD): TextSelector(
|
||||
TextSelectorConfig(
|
||||
type=TextSelectorType.PASSWORD, autocomplete="current-password"
|
||||
)
|
||||
),
|
||||
}
|
||||
{vol.Required(CONF_USERNAME): cv.string, vol.Required(CONF_PASSWORD): cv.string}
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -15,12 +15,13 @@ from homeassistant.components.sensor import (
|
||||
SensorStateClass,
|
||||
)
|
||||
from homeassistant.const import (
|
||||
CONCENTRATION_PARTS_PER_MILLION,
|
||||
LIGHT_LUX,
|
||||
PERCENTAGE,
|
||||
SIGNAL_STRENGTH_DECIBELS,
|
||||
EntityCategory,
|
||||
UnitOfEnergy,
|
||||
UnitOfPower,
|
||||
UnitOfRatio,
|
||||
UnitOfSpeed,
|
||||
UnitOfTemperature,
|
||||
UnitOfTime,
|
||||
@@ -54,7 +55,7 @@ SENSOR_DESCRIPTIONS: list[OverkizSensorDescription] = [
|
||||
OverkizSensorDescription(
|
||||
key=OverkizState.CORE_BATTERY_LEVEL,
|
||||
name="Battery level",
|
||||
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
device_class=SensorDeviceClass.BATTERY,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
@@ -328,7 +329,7 @@ SENSOR_DESCRIPTIONS: list[OverkizSensorDescription] = [
|
||||
native_value=lambda value: round(cast(float, value), 2),
|
||||
device_class=SensorDeviceClass.HUMIDITY,
|
||||
# core:MeasuredValueType = core:RelativeValueInPercentage
|
||||
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
# TemperatureSensor/TemperatureSensor
|
||||
@@ -368,7 +369,7 @@ SENSOR_DESCRIPTIONS: list[OverkizSensorDescription] = [
|
||||
key=OverkizState.CORE_CO_CONCENTRATION,
|
||||
name="CO concentration",
|
||||
device_class=SensorDeviceClass.CO,
|
||||
native_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
|
||||
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
# AirSensor/CO2Sensor
|
||||
@@ -376,7 +377,7 @@ SENSOR_DESCRIPTIONS: list[OverkizSensorDescription] = [
|
||||
key=OverkizState.CORE_CO2_CONCENTRATION,
|
||||
name="CO2 concentration",
|
||||
device_class=SensorDeviceClass.CO2,
|
||||
native_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
|
||||
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
# SunSensor/SunEnergySensor
|
||||
@@ -488,7 +489,7 @@ SENSOR_DESCRIPTIONS: list[OverkizSensorDescription] = [
|
||||
OverkizSensorDescription(
|
||||
key=OverkizState.CORE_TARGET_CLOSURE,
|
||||
name="Target closure",
|
||||
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
entity_registry_enabled_default=False,
|
||||
),
|
||||
# ThreeWayWindowHandle/WindowHandle
|
||||
|
||||
@@ -16,7 +16,7 @@ from homeassistant.components.sensor import (
|
||||
SensorStateClass,
|
||||
StateType,
|
||||
)
|
||||
from homeassistant.const import UnitOfInformation, UnitOfRatio
|
||||
from homeassistant.const import PERCENTAGE, UnitOfInformation
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
|
||||
|
||||
@@ -122,7 +122,7 @@ CONTAINER_SENSORS: tuple[PortainerContainerSensorEntityDescription, ...] = (
|
||||
and data.stats.memory_stats.usage > 0
|
||||
else 0.0
|
||||
),
|
||||
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
suggested_display_precision=2,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
@@ -151,7 +151,7 @@ CONTAINER_SENSORS: tuple[PortainerContainerSensorEntityDescription, ...] = (
|
||||
and data.stats.cpu_stats.online_cpus > 0
|
||||
else 0.0
|
||||
),
|
||||
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
suggested_display_precision=2,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
|
||||
@@ -22,14 +22,15 @@ from homeassistant.components.sensor import (
|
||||
SensorStateClass,
|
||||
)
|
||||
from homeassistant.const import (
|
||||
CONCENTRATION_PARTS_PER_MILLION,
|
||||
LIGHT_LUX,
|
||||
PERCENTAGE,
|
||||
UnitOfElectricCurrent,
|
||||
UnitOfElectricPotential,
|
||||
UnitOfEnergy,
|
||||
UnitOfLength,
|
||||
UnitOfPower,
|
||||
UnitOfPressure,
|
||||
UnitOfRatio,
|
||||
UnitOfSoundPressure,
|
||||
UnitOfSpeed,
|
||||
UnitOfTemperature,
|
||||
@@ -125,7 +126,7 @@ _GAUGE_VARIANT_DESCRIPTIONS = {
|
||||
"AIRQUALITY": SensorEntityDescription(
|
||||
key="airquality",
|
||||
device_class=SensorDeviceClass.CO2,
|
||||
native_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
|
||||
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
"CURRENT": SensorEntityDescription(
|
||||
@@ -155,7 +156,7 @@ _GAUGE_VARIANT_DESCRIPTIONS = {
|
||||
"HUMIDITY": SensorEntityDescription(
|
||||
key="humidity",
|
||||
device_class=SensorDeviceClass.HUMIDITY,
|
||||
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
"LIGHT": SensorEntityDescription(
|
||||
@@ -352,7 +353,7 @@ class QbusHumiditySensor(QbusEntity, SensorEntity):
|
||||
|
||||
_attr_device_class = SensorDeviceClass.HUMIDITY
|
||||
_attr_name = None
|
||||
_attr_native_unit_of_measurement = UnitOfRatio.PERCENTAGE
|
||||
_attr_native_unit_of_measurement = PERCENTAGE
|
||||
_attr_state_class = SensorStateClass.MEASUREMENT
|
||||
|
||||
@override
|
||||
@@ -381,7 +382,7 @@ class QbusVentilationSensor(QbusEntity, SensorEntity):
|
||||
|
||||
_attr_device_class = SensorDeviceClass.CO2
|
||||
_attr_name = None
|
||||
_attr_native_unit_of_measurement = UnitOfRatio.PARTS_PER_MILLION
|
||||
_attr_native_unit_of_measurement = CONCENTRATION_PARTS_PER_MILLION
|
||||
_attr_state_class = SensorStateClass.MEASUREMENT
|
||||
_attr_suggested_display_precision = 0
|
||||
|
||||
|
||||
@@ -286,7 +286,10 @@ async def register_callbacks(
|
||||
return async_camera_wake
|
||||
|
||||
host.api.baichuan.register_callback(
|
||||
"privacy_mode_change", async_privacy_mode_change, 623
|
||||
"privacy_mode_change_623", async_privacy_mode_change, 623
|
||||
)
|
||||
host.api.baichuan.register_callback(
|
||||
"privacy_mode_change_574", async_privacy_mode_change, 574
|
||||
)
|
||||
for channel in host.api.channels:
|
||||
if host.api.supported(channel, "battery"):
|
||||
@@ -306,7 +309,8 @@ async def async_unload_entry(
|
||||
|
||||
await host.stop()
|
||||
|
||||
host.api.baichuan.unregister_callback("privacy_mode_change")
|
||||
host.api.baichuan.unregister_callback("privacy_mode_change_623")
|
||||
host.api.baichuan.unregister_callback("privacy_mode_change_574")
|
||||
for channel in host.api.channels:
|
||||
if host.api.supported(channel, "battery"):
|
||||
host.api.baichuan.unregister_callback(f"camera_{channel}_wake")
|
||||
|
||||
@@ -75,6 +75,7 @@ LIGHT_ENTITIES = (
|
||||
ReolinkLightEntityDescription(
|
||||
key="status_led",
|
||||
cmd_key="GetPowerLed",
|
||||
cmd_id=208,
|
||||
translation_key="status_led",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
supported=lambda api, ch: api.supported(ch, "power_led"),
|
||||
|
||||
@@ -20,5 +20,5 @@
|
||||
"iot_class": "local_push",
|
||||
"loggers": ["reolink_aio"],
|
||||
"quality_scale": "platinum",
|
||||
"requirements": ["reolink-aio==0.21.2"]
|
||||
"requirements": ["reolink-aio==0.21.3"]
|
||||
}
|
||||
|
||||
@@ -195,6 +195,7 @@ NUMBER_ENTITIES = (
|
||||
key="volume",
|
||||
cmd_key="GetAudioCfg",
|
||||
translation_key="volume",
|
||||
cmd_id=264,
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
native_step=1,
|
||||
native_min_value=0,
|
||||
@@ -206,6 +207,7 @@ NUMBER_ENTITIES = (
|
||||
ReolinkNumberEntityDescription(
|
||||
key="volume_speak",
|
||||
cmd_key="GetAudioCfg",
|
||||
cmd_id=264,
|
||||
translation_key="volume_speak",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
native_step=1,
|
||||
@@ -218,6 +220,7 @@ NUMBER_ENTITIES = (
|
||||
ReolinkNumberEntityDescription(
|
||||
key="volume_doorbell",
|
||||
cmd_key="GetAudioCfg",
|
||||
cmd_id=264,
|
||||
translation_key="volume_doorbell",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
native_step=1,
|
||||
@@ -269,6 +272,7 @@ NUMBER_ENTITIES = (
|
||||
ReolinkNumberEntityDescription(
|
||||
key="pir_sensitivity",
|
||||
cmd_key="GetPirInfo",
|
||||
cmd_id=212,
|
||||
translation_key="pir_sensitivity",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
native_step=1,
|
||||
@@ -281,6 +285,7 @@ NUMBER_ENTITIES = (
|
||||
ReolinkNumberEntityDescription(
|
||||
key="pir_interval",
|
||||
cmd_key="GetPirInfo",
|
||||
cmd_id=212,
|
||||
translation_key="pir_interval",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
device_class=NumberDeviceClass.DURATION,
|
||||
@@ -296,6 +301,7 @@ NUMBER_ENTITIES = (
|
||||
ReolinkNumberEntityDescription(
|
||||
key="ai_face_sensititvity",
|
||||
cmd_key="GetAiAlarm",
|
||||
cmd_id=342,
|
||||
translation_key="ai_face_sensitivity",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
native_step=1,
|
||||
@@ -310,6 +316,7 @@ NUMBER_ENTITIES = (
|
||||
ReolinkNumberEntityDescription(
|
||||
key="ai_person_sensititvity",
|
||||
cmd_key="GetAiAlarm",
|
||||
cmd_id=342,
|
||||
translation_key="ai_person_sensitivity",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
native_step=1,
|
||||
@@ -324,6 +331,7 @@ NUMBER_ENTITIES = (
|
||||
ReolinkNumberEntityDescription(
|
||||
key="ai_vehicle_sensititvity",
|
||||
cmd_key="GetAiAlarm",
|
||||
cmd_id=342,
|
||||
translation_key="ai_vehicle_sensitivity",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
native_step=1,
|
||||
@@ -338,6 +346,7 @@ NUMBER_ENTITIES = (
|
||||
ReolinkNumberEntityDescription(
|
||||
key="ai_non_motor_vehicle_sensitivity",
|
||||
cmd_key="GetAiAlarm",
|
||||
cmd_id=342,
|
||||
translation_key="ai_non_motor_vehicle_sensitivity",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
native_step=1,
|
||||
@@ -355,6 +364,7 @@ NUMBER_ENTITIES = (
|
||||
ReolinkNumberEntityDescription(
|
||||
key="ai_package_sensititvity",
|
||||
cmd_key="GetAiAlarm",
|
||||
cmd_id=342,
|
||||
translation_key="ai_package_sensitivity",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
native_step=1,
|
||||
@@ -369,6 +379,7 @@ NUMBER_ENTITIES = (
|
||||
ReolinkNumberEntityDescription(
|
||||
key="ai_pet_sensititvity",
|
||||
cmd_key="GetAiAlarm",
|
||||
cmd_id=342,
|
||||
translation_key="ai_pet_sensitivity",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
native_step=1,
|
||||
@@ -385,6 +396,7 @@ NUMBER_ENTITIES = (
|
||||
ReolinkNumberEntityDescription(
|
||||
key="ai_pet_sensititvity",
|
||||
cmd_key="GetAiAlarm",
|
||||
cmd_id=342,
|
||||
translation_key="ai_animal_sensitivity",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
native_step=1,
|
||||
@@ -411,6 +423,7 @@ NUMBER_ENTITIES = (
|
||||
ReolinkNumberEntityDescription(
|
||||
key="ai_face_delay",
|
||||
cmd_key="GetAiAlarm",
|
||||
cmd_id=342,
|
||||
translation_key="ai_face_delay",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
device_class=NumberDeviceClass.DURATION,
|
||||
@@ -428,6 +441,7 @@ NUMBER_ENTITIES = (
|
||||
ReolinkNumberEntityDescription(
|
||||
key="ai_person_delay",
|
||||
cmd_key="GetAiAlarm",
|
||||
cmd_id=342,
|
||||
translation_key="ai_person_delay",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
device_class=NumberDeviceClass.DURATION,
|
||||
@@ -445,6 +459,7 @@ NUMBER_ENTITIES = (
|
||||
ReolinkNumberEntityDescription(
|
||||
key="ai_non_motor_vehicle_delay",
|
||||
cmd_key="GetAiAlarm",
|
||||
cmd_id=342,
|
||||
translation_key="ai_non_motor_vehicle_delay",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
device_class=NumberDeviceClass.DURATION,
|
||||
@@ -464,6 +479,7 @@ NUMBER_ENTITIES = (
|
||||
ReolinkNumberEntityDescription(
|
||||
key="ai_vehicle_delay",
|
||||
cmd_key="GetAiAlarm",
|
||||
cmd_id=342,
|
||||
translation_key="ai_vehicle_delay",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
device_class=NumberDeviceClass.DURATION,
|
||||
@@ -481,6 +497,7 @@ NUMBER_ENTITIES = (
|
||||
ReolinkNumberEntityDescription(
|
||||
key="ai_package_delay",
|
||||
cmd_key="GetAiAlarm",
|
||||
cmd_id=342,
|
||||
translation_key="ai_package_delay",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
device_class=NumberDeviceClass.DURATION,
|
||||
@@ -498,6 +515,7 @@ NUMBER_ENTITIES = (
|
||||
ReolinkNumberEntityDescription(
|
||||
key="ai_pet_delay",
|
||||
cmd_key="GetAiAlarm",
|
||||
cmd_id=342,
|
||||
translation_key="ai_pet_delay",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
device_class=NumberDeviceClass.DURATION,
|
||||
@@ -517,6 +535,7 @@ NUMBER_ENTITIES = (
|
||||
ReolinkNumberEntityDescription(
|
||||
key="ai_pet_delay",
|
||||
cmd_key="GetAiAlarm",
|
||||
cmd_id=342,
|
||||
translation_key="ai_animal_delay",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
device_class=NumberDeviceClass.DURATION,
|
||||
|
||||
@@ -185,6 +185,7 @@ SELECT_ENTITIES = (
|
||||
ReolinkSelectEntityDescription(
|
||||
key="status_led",
|
||||
cmd_key="GetPowerLed",
|
||||
cmd_id=208,
|
||||
translation_key="doorbell_led",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
get_options=lambda api, ch: api.doorbell_led_list(ch),
|
||||
@@ -232,6 +233,7 @@ SELECT_ENTITIES = (
|
||||
ReolinkSelectEntityDescription(
|
||||
key="main_frame_rate",
|
||||
cmd_key="GetEnc",
|
||||
cmd_id=56,
|
||||
translation_key="main_frame_rate",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
entity_registry_enabled_default=False,
|
||||
@@ -244,6 +246,7 @@ SELECT_ENTITIES = (
|
||||
ReolinkSelectEntityDescription(
|
||||
key="sub_frame_rate",
|
||||
cmd_key="GetEnc",
|
||||
cmd_id=56,
|
||||
translation_key="sub_frame_rate",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
entity_registry_enabled_default=False,
|
||||
@@ -256,6 +259,7 @@ SELECT_ENTITIES = (
|
||||
ReolinkSelectEntityDescription(
|
||||
key="main_bit_rate",
|
||||
cmd_key="GetEnc",
|
||||
cmd_id=56,
|
||||
translation_key="main_bit_rate",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
entity_registry_enabled_default=False,
|
||||
@@ -268,6 +272,7 @@ SELECT_ENTITIES = (
|
||||
ReolinkSelectEntityDescription(
|
||||
key="sub_bit_rate",
|
||||
cmd_key="GetEnc",
|
||||
cmd_id=56,
|
||||
translation_key="sub_bit_rate",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
entity_registry_enabled_default=False,
|
||||
@@ -280,6 +285,7 @@ SELECT_ENTITIES = (
|
||||
ReolinkSelectEntityDescription(
|
||||
key="main_encoding",
|
||||
cmd_key="GetEnc",
|
||||
cmd_id=56,
|
||||
translation_key="main_encoding",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
entity_registry_enabled_default=False,
|
||||
@@ -291,6 +297,7 @@ SELECT_ENTITIES = (
|
||||
ReolinkSelectEntityDescription(
|
||||
key="sub_encoding",
|
||||
cmd_key="GetEnc",
|
||||
cmd_id=56,
|
||||
translation_key="sub_encoding",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
entity_registry_enabled_default=False,
|
||||
@@ -316,6 +323,7 @@ SELECT_ENTITIES = (
|
||||
ReolinkSelectEntityDescription(
|
||||
key="post_rec_time",
|
||||
cmd_key="GetRec",
|
||||
cmd_id=54,
|
||||
translation_key="post_rec_time",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
entity_registry_enabled_default=False,
|
||||
@@ -340,6 +348,7 @@ HOST_SELECT_ENTITIES = (
|
||||
ReolinkHostSelectEntityDescription(
|
||||
key="packing_time",
|
||||
cmd_key="GetRec",
|
||||
cmd_id=54,
|
||||
translation_key="packing_time",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
entity_registry_enabled_default=False,
|
||||
|
||||
@@ -74,6 +74,7 @@ SWITCH_ENTITIES = (
|
||||
ReolinkSwitchEntityDescription(
|
||||
key="ir_lights",
|
||||
cmd_key="GetIrLights",
|
||||
cmd_id=208,
|
||||
translation_key="ir_lights",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
supported=lambda api, ch: api.supported(ch, "ir_lights"),
|
||||
@@ -83,6 +84,7 @@ SWITCH_ENTITIES = (
|
||||
ReolinkSwitchEntityDescription(
|
||||
key="record_audio",
|
||||
cmd_key="GetEnc",
|
||||
cmd_id=56,
|
||||
translation_key="record_audio",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
supported=lambda api, ch: api.supported(ch, "audio"),
|
||||
@@ -92,6 +94,7 @@ SWITCH_ENTITIES = (
|
||||
ReolinkSwitchEntityDescription(
|
||||
key="siren_on_event",
|
||||
cmd_key="GetAudioAlarm",
|
||||
cmd_id=232,
|
||||
translation_key="siren_on_event",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
supported=lambda api, ch: api.supported(ch, "siren"),
|
||||
@@ -136,6 +139,7 @@ SWITCH_ENTITIES = (
|
||||
ReolinkSwitchEntityDescription(
|
||||
key="email",
|
||||
cmd_key="GetEmail",
|
||||
cmd_id=217,
|
||||
translation_key="email",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
supported=lambda api, ch: api.supported(ch, "email") and api.is_nvr,
|
||||
@@ -145,6 +149,7 @@ SWITCH_ENTITIES = (
|
||||
ReolinkSwitchEntityDescription(
|
||||
key="ftp_upload",
|
||||
cmd_key="GetFtp",
|
||||
cmd_id=70,
|
||||
translation_key="ftp_upload",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
supported=lambda api, ch: api.supported(ch, "ftp") and api.is_nvr,
|
||||
@@ -163,6 +168,7 @@ SWITCH_ENTITIES = (
|
||||
ReolinkSwitchEntityDescription(
|
||||
key="record",
|
||||
cmd_key="GetRec",
|
||||
cmd_id=81,
|
||||
translation_key="record",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
supported=lambda api, ch: api.supported(ch, "rec_enable") and api.is_nvr,
|
||||
@@ -200,6 +206,7 @@ SWITCH_ENTITIES = (
|
||||
ReolinkSwitchEntityDescription(
|
||||
key="doorbell_button_sound",
|
||||
cmd_key="GetAudioCfg",
|
||||
cmd_id=264,
|
||||
translation_key="doorbell_button_sound",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
supported=lambda api, ch: api.supported(ch, "doorbell_button_sound"),
|
||||
@@ -209,6 +216,7 @@ SWITCH_ENTITIES = (
|
||||
ReolinkSwitchEntityDescription(
|
||||
key="pir_enabled",
|
||||
cmd_key="GetPirInfo",
|
||||
cmd_id=212,
|
||||
translation_key="pir_enabled",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
entity_registry_enabled_default=False,
|
||||
@@ -219,6 +227,7 @@ SWITCH_ENTITIES = (
|
||||
ReolinkSwitchEntityDescription(
|
||||
key="pir_reduce_alarm",
|
||||
cmd_key="GetPirInfo",
|
||||
cmd_id=212,
|
||||
translation_key="pir_reduce_alarm",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
entity_registry_enabled_default=False,
|
||||
@@ -260,6 +269,7 @@ HOST_SWITCH_ENTITIES = (
|
||||
ReolinkHostSwitchEntityDescription(
|
||||
key="email",
|
||||
cmd_key="GetEmail",
|
||||
cmd_id=217,
|
||||
translation_key="email",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
supported=lambda api: api.supported(None, "email") and not api.is_hub,
|
||||
@@ -269,6 +279,7 @@ HOST_SWITCH_ENTITIES = (
|
||||
ReolinkHostSwitchEntityDescription(
|
||||
key="ftp_upload",
|
||||
cmd_key="GetFtp",
|
||||
cmd_id=70,
|
||||
translation_key="ftp_upload",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
supported=lambda api: api.supported(None, "ftp") and not api.is_hub,
|
||||
@@ -287,6 +298,7 @@ HOST_SWITCH_ENTITIES = (
|
||||
ReolinkHostSwitchEntityDescription(
|
||||
key="record",
|
||||
cmd_key="GetRec",
|
||||
cmd_id=81,
|
||||
translation_key="record",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
supported=lambda api: api.supported(None, "rec_enable") and not api.is_hub,
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
"loggers": ["roborock"],
|
||||
"quality_scale": "silver",
|
||||
"requirements": [
|
||||
"python-roborock==5.14.2",
|
||||
"python-roborock==5.21.0",
|
||||
"vacuum-map-parser-roborock==0.1.5"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ class RoborockNumberDescription(NumberEntityDescription):
|
||||
trait: Callable[[PropertiesApi], Any | None]
|
||||
"""Function to determine if number entity is supported by the device."""
|
||||
|
||||
get_value: Callable[[Any], float]
|
||||
get_value: Callable[[Any], float | None]
|
||||
"""Function to get the value from the trait."""
|
||||
|
||||
set_value: Callable[[Any, float], Coroutine[Any, Any, None]]
|
||||
@@ -51,7 +51,9 @@ NUMBER_DESCRIPTIONS: list[RoborockNumberDescription] = [
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
trait=lambda api: api.sound_volume,
|
||||
get_value=lambda trait: float(trait.volume),
|
||||
get_value=lambda trait: (
|
||||
float(trait.volume) if trait.volume is not None else None
|
||||
),
|
||||
set_value=lambda trait, value: trait.set_volume(int(value)),
|
||||
)
|
||||
]
|
||||
|
||||
@@ -37,7 +37,7 @@ class RoborockTimeDescription(TimeEntityDescription):
|
||||
trait: Callable[[Any], Any | None]
|
||||
"""Function to determine if time entity is supported by the device."""
|
||||
|
||||
get_value: Callable[[Any], datetime.time]
|
||||
get_value: Callable[[Any], datetime.time | None]
|
||||
"""Function to get the value from the trait."""
|
||||
|
||||
update_value: Callable[[Any, datetime.time], Coroutine[Any, Any, None]]
|
||||
@@ -58,9 +58,7 @@ TIME_DESCRIPTIONS: list[RoborockTimeDescription] = [
|
||||
end_minute=trait.end_minute,
|
||||
)
|
||||
),
|
||||
get_value=lambda trait: datetime.time(
|
||||
hour=trait.start_hour, minute=trait.start_minute
|
||||
),
|
||||
get_value=lambda trait: trait.start_time,
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
),
|
||||
RoborockTimeDescription(
|
||||
@@ -76,9 +74,7 @@ TIME_DESCRIPTIONS: list[RoborockTimeDescription] = [
|
||||
end_minute=desired_time.minute,
|
||||
)
|
||||
),
|
||||
get_value=lambda trait: datetime.time(
|
||||
hour=trait.end_hour, minute=trait.end_minute
|
||||
),
|
||||
get_value=lambda trait: trait.end_time,
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
),
|
||||
RoborockTimeDescription(
|
||||
@@ -94,9 +90,7 @@ TIME_DESCRIPTIONS: list[RoborockTimeDescription] = [
|
||||
end_minute=trait.end_minute,
|
||||
)
|
||||
),
|
||||
get_value=lambda trait: datetime.time(
|
||||
hour=trait.start_hour, minute=trait.start_minute
|
||||
),
|
||||
get_value=lambda trait: trait.start_time,
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
entity_registry_enabled_default=False,
|
||||
),
|
||||
@@ -113,9 +107,7 @@ TIME_DESCRIPTIONS: list[RoborockTimeDescription] = [
|
||||
end_minute=desired_time.minute,
|
||||
)
|
||||
),
|
||||
get_value=lambda trait: datetime.time(
|
||||
hour=trait.end_hour, minute=trait.end_minute
|
||||
),
|
||||
get_value=lambda trait: trait.end_time,
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
entity_registry_enabled_default=False,
|
||||
),
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
"""The Steam integration."""
|
||||
|
||||
from homeassistant.const import Platform
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from .coordinator import SteamConfigEntry, SteamDataUpdateCoordinator
|
||||
|
||||
@@ -22,22 +21,3 @@ async def async_setup_entry(hass: HomeAssistant, entry: SteamConfigEntry) -> boo
|
||||
async def async_unload_entry(hass: HomeAssistant, entry: SteamConfigEntry) -> bool:
|
||||
"""Unload a config entry."""
|
||||
return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
|
||||
|
||||
|
||||
async def async_migrate_entry(hass: HomeAssistant, entry: SteamConfigEntry) -> bool:
|
||||
"""Migrate old entry."""
|
||||
|
||||
if entry.version < 2:
|
||||
# Migrate entity unique id
|
||||
|
||||
@callback
|
||||
def migrate_unique_id(entity_entry: er.RegistryEntry) -> dict[str, str] | None:
|
||||
if entity_entry.unique_id.startswith("sensor.steam_"):
|
||||
new = entity_entry.unique_id.removeprefix("sensor.steam_") + "_account"
|
||||
return {"new_unique_id": new}
|
||||
return None
|
||||
|
||||
await er.async_migrate_entries(hass, entry.entry_id, migrate_unique_id)
|
||||
hass.config_entries.async_update_entry(entry, version=2)
|
||||
|
||||
return True
|
||||
|
||||
@@ -41,8 +41,6 @@ def validate_input(user_input: dict[str, str]) -> dict[str, str | int]:
|
||||
class SteamFlowHandler(ConfigFlow, domain=DOMAIN):
|
||||
"""Handle a config flow for Steam."""
|
||||
|
||||
VERSION = 2
|
||||
|
||||
@staticmethod
|
||||
@callback
|
||||
@override
|
||||
@@ -152,7 +150,7 @@ class SteamOptionsFlowHandler(OptionsFlowWithReload):
|
||||
for _id in self.options[CONF_ACCOUNTS]:
|
||||
if _id not in user_input[CONF_ACCOUNTS] and (
|
||||
entity_id := er.async_get(self.hass).async_get_entity_id(
|
||||
Platform.SENSOR, DOMAIN, f"{_id}_account"
|
||||
Platform.SENSOR, DOMAIN, f"sensor.steam_{_id}"
|
||||
)
|
||||
):
|
||||
er.async_get(self.hass).async_remove(entity_id)
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
"""Entity classes for the Steam integration."""
|
||||
|
||||
from homeassistant.components.sensor import SensorEntityDescription
|
||||
from homeassistant.helpers.device_registry import DeviceEntryType, DeviceInfo
|
||||
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
||||
|
||||
@@ -13,17 +12,9 @@ class SteamEntity(CoordinatorEntity[SteamDataUpdateCoordinator]):
|
||||
|
||||
_attr_has_entity_name = True
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
coordinator: SteamDataUpdateCoordinator,
|
||||
steamid: str,
|
||||
description: SensorEntityDescription,
|
||||
) -> None:
|
||||
def __init__(self, coordinator: SteamDataUpdateCoordinator) -> None:
|
||||
"""Initialize a Steam entity."""
|
||||
super().__init__(coordinator)
|
||||
self._steamid = steamid
|
||||
self.entity_description = description
|
||||
self._attr_unique_id = f"{steamid}_{description.key}"
|
||||
self._attr_device_info = DeviceInfo(
|
||||
configuration_url="https://store.steampowered.com",
|
||||
entry_type=DeviceEntryType.SERVICE,
|
||||
|
||||
@@ -80,7 +80,10 @@ class SteamSensorEntity(SteamEntity, SensorEntity):
|
||||
description: SteamSensorEntityDescription,
|
||||
) -> None:
|
||||
"""Initialize the sensor."""
|
||||
super().__init__(coordinator, steamid, description)
|
||||
super().__init__(coordinator)
|
||||
self._steamid = steamid
|
||||
self.entity_description = description
|
||||
self._attr_unique_id = f"sensor.steam_{steamid}"
|
||||
self._attr_name = self.entity_description.name_fn(coordinator.data[steamid])
|
||||
|
||||
@property
|
||||
|
||||
@@ -42,5 +42,5 @@
|
||||
"iot_class": "local_push",
|
||||
"loggers": ["switchbot"],
|
||||
"quality_scale": "gold",
|
||||
"requirements": ["PySwitchbot==2.3.0"]
|
||||
"requirements": ["PySwitchbot==2.2.0"]
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
"state": {
|
||||
"cool": "mdi:fan-speed-2",
|
||||
"full_speed": "mdi:fan-speed-3",
|
||||
"low_power": "mdi:fan-chevron-down",
|
||||
"quiet": "mdi:fan-speed-1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
"integration_type": "device",
|
||||
"iot_class": "local_polling",
|
||||
"loggers": ["synology_dsm"],
|
||||
"requirements": ["py-synologydsm-api==2.10.0"],
|
||||
"requirements": ["py-synologydsm-api==2.10.1"],
|
||||
"ssdp": [
|
||||
{
|
||||
"deviceType": "urn:schemas-upnp-org:device:Basic:1",
|
||||
|
||||
@@ -15,6 +15,7 @@ from .coordinator import SynologyDSMCentralUpdateCoordinator, SynologyDSMConfigE
|
||||
from .entity import SynologyDSMBaseEntity, SynologyDSMEntityDescription
|
||||
|
||||
FAN_SPEED_MAP = {
|
||||
FanSpeed.QUIET_STOP: "low_power",
|
||||
FanSpeed.QUIET: "quiet",
|
||||
FanSpeed.COOL: "cool",
|
||||
FanSpeed.FULL: "full_speed",
|
||||
@@ -47,7 +48,6 @@ class SynologyDSMFanSpeedMode(
|
||||
):
|
||||
"""Represent a Synology DSM fan speed mode select entity."""
|
||||
|
||||
_attr_options = list(FAN_SPEED_MAP.values())
|
||||
entity_description: SynologyDSMSelectEntityDescription
|
||||
|
||||
def __init__(
|
||||
@@ -62,6 +62,11 @@ class SynologyDSMFanSpeedMode(
|
||||
translation_key="fan_speed_mode",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
)
|
||||
self._attr_options = [
|
||||
val
|
||||
for fs, val in FAN_SPEED_MAP.items()
|
||||
if fs in api.dsm.hardware.supported_fan_speeds
|
||||
]
|
||||
super().__init__(api, coordinator, description)
|
||||
|
||||
@property
|
||||
|
||||
@@ -87,6 +87,7 @@
|
||||
"state": {
|
||||
"cool": "Cool mode",
|
||||
"full_speed": "Full-speed mode",
|
||||
"low_power": "Low-Power mode",
|
||||
"quiet": "Quiet mode"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
"""The thermoworks_smoke component."""
|
||||
@@ -1,11 +0,0 @@
|
||||
{
|
||||
"domain": "thermoworks_smoke",
|
||||
"name": "ThermoWorks Smoke",
|
||||
"codeowners": [],
|
||||
"disabled": "This integration is disabled because it creates an unresolvable dependency conflict.",
|
||||
"documentation": "https://www.home-assistant.io/integrations/thermoworks_smoke",
|
||||
"iot_class": "cloud_polling",
|
||||
"loggers": ["thermoworks_smoke"],
|
||||
"quality_scale": "legacy",
|
||||
"requirements": ["stringcase==1.2.0", "thermoworks-smoke==0.1.8"]
|
||||
}
|
||||
@@ -1,166 +0,0 @@
|
||||
"""Support for getting the state of a Thermoworks Smoke Thermometer.
|
||||
|
||||
Requires Smoke Gateway Wifi with an internet connection.
|
||||
"""
|
||||
|
||||
import logging
|
||||
|
||||
from requests import RequestException
|
||||
from requests.exceptions import HTTPError
|
||||
from stringcase import camelcase
|
||||
import thermoworks_smoke
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components.sensor import (
|
||||
PLATFORM_SCHEMA as SENSOR_PLATFORM_SCHEMA,
|
||||
SensorDeviceClass,
|
||||
SensorEntity,
|
||||
)
|
||||
from homeassistant.const import (
|
||||
ATTR_BATTERY_LEVEL,
|
||||
CONF_EMAIL,
|
||||
CONF_EXCLUDE,
|
||||
CONF_MONITORED_CONDITIONS,
|
||||
CONF_PASSWORD,
|
||||
UnitOfTemperature,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import config_validation as cv
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
||||
from homeassistant.util import snakecase
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
PROBE_1 = "probe1"
|
||||
PROBE_2 = "probe2"
|
||||
PROBE_1_MIN = "probe1_min"
|
||||
PROBE_1_MAX = "probe1_max"
|
||||
PROBE_2_MIN = "probe2_min"
|
||||
PROBE_2_MAX = "probe2_max"
|
||||
BATTERY_LEVEL = "battery"
|
||||
FIRMWARE = "firmware"
|
||||
|
||||
SERIAL_REGEX = "^(?:[0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}$"
|
||||
|
||||
# map types to labels
|
||||
SENSOR_TYPES = {
|
||||
PROBE_1: "Probe 1",
|
||||
PROBE_2: "Probe 2",
|
||||
PROBE_1_MIN: "Probe 1 Min",
|
||||
PROBE_1_MAX: "Probe 1 Max",
|
||||
PROBE_2_MIN: "Probe 2 Min",
|
||||
PROBE_2_MAX: "Probe 2 Max",
|
||||
}
|
||||
|
||||
# exclude these keys from thermoworks data
|
||||
EXCLUDE_KEYS = [FIRMWARE]
|
||||
|
||||
PLATFORM_SCHEMA = SENSOR_PLATFORM_SCHEMA.extend(
|
||||
{
|
||||
vol.Required(CONF_EMAIL): cv.string,
|
||||
vol.Required(CONF_PASSWORD): cv.string,
|
||||
vol.Optional(CONF_MONITORED_CONDITIONS, default=[PROBE_1, PROBE_2]): vol.All(
|
||||
cv.ensure_list, [vol.In(SENSOR_TYPES)]
|
||||
),
|
||||
vol.Optional(CONF_EXCLUDE, default=[]): vol.All(
|
||||
cv.ensure_list, [cv.matches_regex(SERIAL_REGEX)]
|
||||
),
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
def setup_platform(
|
||||
hass: HomeAssistant,
|
||||
config: ConfigType,
|
||||
add_entities: AddEntitiesCallback,
|
||||
discovery_info: DiscoveryInfoType | None = None,
|
||||
) -> None:
|
||||
"""Set up the thermoworks sensor."""
|
||||
|
||||
email = config[CONF_EMAIL]
|
||||
password = config[CONF_PASSWORD]
|
||||
monitored_variables = config[CONF_MONITORED_CONDITIONS]
|
||||
excluded = config[CONF_EXCLUDE]
|
||||
|
||||
try:
|
||||
mgr = thermoworks_smoke.initialize_app(email, password, True, excluded)
|
||||
except HTTPError as error:
|
||||
msg = f"{error.strerror}"
|
||||
if "EMAIL_NOT_FOUND" in msg or "INVALID_PASSWORD" in msg:
|
||||
_LOGGER.error("Invalid email and password combination")
|
||||
else:
|
||||
_LOGGER.error(msg)
|
||||
else:
|
||||
add_entities(
|
||||
(
|
||||
ThermoworksSmokeSensor(variable, serial, mgr)
|
||||
for serial in mgr.serials()
|
||||
for variable in monitored_variables
|
||||
),
|
||||
True,
|
||||
)
|
||||
|
||||
|
||||
class ThermoworksSmokeSensor(SensorEntity):
|
||||
"""Implementation of a thermoworks smoke sensor."""
|
||||
|
||||
def __init__(self, sensor_type, serial, mgr):
|
||||
"""Initialize the sensor."""
|
||||
self.type = sensor_type
|
||||
self.serial = serial
|
||||
self.mgr = mgr
|
||||
self._attr_name = f"{mgr.name(serial)} {SENSOR_TYPES[sensor_type]}"
|
||||
self._attr_native_unit_of_measurement = UnitOfTemperature.FAHRENHEIT
|
||||
self._attr_unique_id = f"{serial}-{sensor_type}"
|
||||
self._attr_device_class = SensorDeviceClass.TEMPERATURE
|
||||
self.update_unit()
|
||||
|
||||
def update_unit(self):
|
||||
"""Set the units from the data."""
|
||||
if PROBE_2 in self.type:
|
||||
self._attr_native_unit_of_measurement = self.mgr.units(self.serial, PROBE_2)
|
||||
else:
|
||||
self._attr_native_unit_of_measurement = self.mgr.units(self.serial, PROBE_1)
|
||||
|
||||
def update(self) -> None:
|
||||
"""Get the monitored data from firebase."""
|
||||
|
||||
try:
|
||||
values = self.mgr.data(self.serial)
|
||||
|
||||
# set state from data based on type of sensor
|
||||
self._attr_native_value = values.get(camelcase(self.type))
|
||||
|
||||
# set units
|
||||
self.update_unit()
|
||||
|
||||
# set basic attributes for all sensors
|
||||
self._attr_extra_state_attributes = {
|
||||
"time": values["time"],
|
||||
"localtime": values["localtime"],
|
||||
}
|
||||
|
||||
# set extended attributes for main probe sensors
|
||||
if self.type in (PROBE_1, PROBE_2):
|
||||
for key, val in values.items():
|
||||
# add all attributes that don't contain any probe name
|
||||
# or contain a matching probe name
|
||||
if (self.type == PROBE_1 and key.find(PROBE_2) == -1) or (
|
||||
self.type == PROBE_2 and key.find(PROBE_1) == -1
|
||||
):
|
||||
if key == BATTERY_LEVEL:
|
||||
key = ATTR_BATTERY_LEVEL
|
||||
else:
|
||||
# strip probe label and convert to snake_case
|
||||
key = snakecase(key.replace(self.type, ""))
|
||||
# add to attrs
|
||||
if key and key not in EXCLUDE_KEYS:
|
||||
self._attr_extra_state_attributes[key] = val
|
||||
# store actual unit because attributes are not converted
|
||||
self._attr_extra_state_attributes["unit_of_min_max"] = (
|
||||
self._attr_native_unit_of_measurement
|
||||
)
|
||||
|
||||
except RequestException, ValueError, KeyError:
|
||||
_LOGGER.warning("Could not update status for %s", self.name)
|
||||
@@ -13,7 +13,12 @@ from homeassistant.components.sensor import (
|
||||
SensorEntityDescription,
|
||||
SensorStateClass,
|
||||
)
|
||||
from homeassistant.const import Platform, UnitOfDensity, UnitOfRatio, UnitOfTime
|
||||
from homeassistant.const import (
|
||||
CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
PERCENTAGE,
|
||||
Platform,
|
||||
UnitOfTime,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
|
||||
@@ -57,7 +62,7 @@ SENSOR_DESCRIPTIONS_BATTERY: tuple[TradfriSensorEntityDescription, ...] = (
|
||||
key="battery_level",
|
||||
device_class=SensorDeviceClass.BATTERY,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
value=lambda device: cast(int, device.device_info.battery_level),
|
||||
),
|
||||
)
|
||||
@@ -68,7 +73,7 @@ SENSOR_DESCRIPTIONS_FAN: tuple[TradfriSensorEntityDescription, ...] = (
|
||||
key="aqi",
|
||||
translation_key="aqi",
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
|
||||
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
value=_get_air_quality,
|
||||
),
|
||||
TradfriSensorEntityDescription(
|
||||
|
||||
@@ -6,18 +6,21 @@ import logging
|
||||
|
||||
from homeassistant.components.sensor import SensorDeviceClass
|
||||
from homeassistant.const import (
|
||||
CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
CONCENTRATION_MILLIGRAMS_PER_CUBIC_METER,
|
||||
CONCENTRATION_PARTS_PER_BILLION,
|
||||
CONCENTRATION_PARTS_PER_MILLION,
|
||||
LIGHT_LUX,
|
||||
PERCENTAGE,
|
||||
SIGNAL_STRENGTH_DECIBELS,
|
||||
SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
|
||||
Platform,
|
||||
UnitOfConductivity,
|
||||
UnitOfDensity,
|
||||
UnitOfElectricCurrent,
|
||||
UnitOfElectricPotential,
|
||||
UnitOfEnergy,
|
||||
UnitOfPower,
|
||||
UnitOfPressure,
|
||||
UnitOfRatio,
|
||||
UnitOfTemperature,
|
||||
UnitOfVolume,
|
||||
UnitOfVolumetricFlux,
|
||||
@@ -1020,7 +1023,7 @@ UNITS = (
|
||||
},
|
||||
),
|
||||
UnitOfMeasurement(
|
||||
unit=UnitOfRatio.PERCENTAGE,
|
||||
unit=PERCENTAGE,
|
||||
aliases={"pct", "percent", "% RH"},
|
||||
device_classes={
|
||||
SensorDeviceClass.BATTERY,
|
||||
@@ -1029,14 +1032,14 @@ UNITS = (
|
||||
},
|
||||
),
|
||||
UnitOfMeasurement(
|
||||
unit=UnitOfRatio.PARTS_PER_MILLION,
|
||||
unit=CONCENTRATION_PARTS_PER_MILLION,
|
||||
device_classes={
|
||||
SensorDeviceClass.CO,
|
||||
SensorDeviceClass.CO2,
|
||||
},
|
||||
),
|
||||
UnitOfMeasurement(
|
||||
unit=UnitOfRatio.PARTS_PER_BILLION,
|
||||
unit=CONCENTRATION_PARTS_PER_BILLION,
|
||||
device_classes={
|
||||
SensorDeviceClass.CO,
|
||||
SensorDeviceClass.CO2,
|
||||
@@ -1083,7 +1086,7 @@ UNITS = (
|
||||
device_classes={SensorDeviceClass.ILLUMINANCE},
|
||||
),
|
||||
UnitOfMeasurement(
|
||||
unit=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
|
||||
unit=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
# The μ-char has 2 unicode variants \u00b5 and \u03bc
|
||||
# The \u03bc variant (Greek Mu char) is recommended
|
||||
aliases={"ug/m3", "\u03bcg/m3", "\u00b5g/m3", "ug/m³"},
|
||||
@@ -1100,7 +1103,7 @@ UNITS = (
|
||||
},
|
||||
),
|
||||
UnitOfMeasurement(
|
||||
unit=UnitOfDensity.MILLIGRAMS_PER_CUBIC_METER,
|
||||
unit=CONCENTRATION_MILLIGRAMS_PER_CUBIC_METER,
|
||||
aliases={"mg/m3"},
|
||||
device_classes={
|
||||
SensorDeviceClass.NITROGEN_DIOXIDE,
|
||||
|
||||
@@ -31,13 +31,14 @@ from homeassistant.components.sensor import (
|
||||
SensorStateClass,
|
||||
)
|
||||
from homeassistant.const import (
|
||||
CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
CONCENTRATION_PARTS_PER_MILLION,
|
||||
PERCENTAGE,
|
||||
EntityCategory,
|
||||
UnitOfDensity,
|
||||
UnitOfElectricCurrent,
|
||||
UnitOfElectricPotential,
|
||||
UnitOfEnergy,
|
||||
UnitOfPower,
|
||||
UnitOfRatio,
|
||||
UnitOfTime,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
@@ -74,7 +75,7 @@ BATTERY_SENSORS: tuple[TuyaSensorEntityDescription, ...] = (
|
||||
TuyaSensorEntityDescription(
|
||||
key=DPCode.BATTERY_PERCENTAGE,
|
||||
translation_key="battery",
|
||||
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
device_class=SensorDeviceClass.BATTERY,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
@@ -82,7 +83,7 @@ BATTERY_SENSORS: tuple[TuyaSensorEntityDescription, ...] = (
|
||||
TuyaSensorEntityDescription(
|
||||
key=DPCode.BATTERY, # Used by non-standard contact sensor implementations
|
||||
translation_key="battery",
|
||||
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
device_class=SensorDeviceClass.BATTERY,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
@@ -180,7 +181,7 @@ SENSORS: dict[DeviceCategory, tuple[TuyaSensorEntityDescription, ...]] = {
|
||||
translation_key="carbon_dioxide",
|
||||
device_class=SensorDeviceClass.CO2,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
suggested_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
|
||||
suggested_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
|
||||
),
|
||||
TuyaSensorEntityDescription(
|
||||
key=DPCode.CH2O_VALUE,
|
||||
@@ -198,7 +199,7 @@ SENSORS: dict[DeviceCategory, tuple[TuyaSensorEntityDescription, ...]] = {
|
||||
translation_key="pm25",
|
||||
device_class=SensorDeviceClass.PM25,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
suggested_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
|
||||
suggested_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
),
|
||||
TuyaSensorEntityDescription(
|
||||
key=DPCode.PM10,
|
||||
@@ -214,7 +215,7 @@ SENSORS: dict[DeviceCategory, tuple[TuyaSensorEntityDescription, ...]] = {
|
||||
translation_key="carbon_monoxide",
|
||||
device_class=SensorDeviceClass.CO,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
suggested_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
|
||||
suggested_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
|
||||
),
|
||||
*BATTERY_SENSORS,
|
||||
),
|
||||
@@ -301,21 +302,21 @@ SENSORS: dict[DeviceCategory, tuple[TuyaSensorEntityDescription, ...]] = {
|
||||
translation_key="pm25",
|
||||
device_class=SensorDeviceClass.PM25,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
suggested_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
|
||||
suggested_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
),
|
||||
TuyaSensorEntityDescription(
|
||||
key=DPCode.CO_VALUE,
|
||||
translation_key="carbon_monoxide",
|
||||
device_class=SensorDeviceClass.CO,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
suggested_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
|
||||
suggested_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
|
||||
),
|
||||
TuyaSensorEntityDescription(
|
||||
key=DPCode.CO2_VALUE,
|
||||
translation_key="carbon_dioxide",
|
||||
device_class=SensorDeviceClass.CO2,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
suggested_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
|
||||
suggested_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
|
||||
),
|
||||
TuyaSensorEntityDescription(
|
||||
key=DPCode.EC_CURRENT,
|
||||
@@ -534,7 +535,7 @@ SENSORS: dict[DeviceCategory, tuple[TuyaSensorEntityDescription, ...]] = {
|
||||
translation_key="carbon_dioxide",
|
||||
device_class=SensorDeviceClass.CO2,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
suggested_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
|
||||
suggested_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
|
||||
),
|
||||
TuyaSensorEntityDescription(
|
||||
key=DPCode.CH2O_VALUE,
|
||||
@@ -552,14 +553,14 @@ SENSORS: dict[DeviceCategory, tuple[TuyaSensorEntityDescription, ...]] = {
|
||||
translation_key="pm25",
|
||||
device_class=SensorDeviceClass.PM25,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
suggested_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
|
||||
suggested_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
),
|
||||
TuyaSensorEntityDescription(
|
||||
key=DPCode.PM10,
|
||||
translation_key="pm10",
|
||||
device_class=SensorDeviceClass.PM10,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
suggested_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
|
||||
suggested_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
),
|
||||
*BATTERY_SENSORS,
|
||||
),
|
||||
@@ -569,7 +570,7 @@ SENSORS: dict[DeviceCategory, tuple[TuyaSensorEntityDescription, ...]] = {
|
||||
translation_key="carbon_dioxide",
|
||||
device_class=SensorDeviceClass.CO2,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
suggested_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
|
||||
suggested_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
|
||||
),
|
||||
TuyaSensorEntityDescription(
|
||||
key=DPCode.VOC_VALUE,
|
||||
@@ -582,7 +583,7 @@ SENSORS: dict[DeviceCategory, tuple[TuyaSensorEntityDescription, ...]] = {
|
||||
translation_key="pm25",
|
||||
device_class=SensorDeviceClass.PM25,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
suggested_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
|
||||
suggested_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
),
|
||||
TuyaSensorEntityDescription(
|
||||
key=DPCode.VA_HUMIDITY,
|
||||
@@ -683,7 +684,7 @@ SENSORS: dict[DeviceCategory, tuple[TuyaSensorEntityDescription, ...]] = {
|
||||
translation_key="pm25",
|
||||
device_class=SensorDeviceClass.PM25,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
suggested_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
|
||||
suggested_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
),
|
||||
TuyaSensorEntityDescription(
|
||||
key=DPCode.TEMP,
|
||||
@@ -708,7 +709,7 @@ SENSORS: dict[DeviceCategory, tuple[TuyaSensorEntityDescription, ...]] = {
|
||||
translation_key="concentration_carbon_dioxide",
|
||||
device_class=SensorDeviceClass.CO2,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
suggested_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
|
||||
suggested_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
|
||||
),
|
||||
TuyaSensorEntityDescription(
|
||||
key=DPCode.TOTAL_TIME,
|
||||
@@ -755,7 +756,7 @@ SENSORS: dict[DeviceCategory, tuple[TuyaSensorEntityDescription, ...]] = {
|
||||
translation_key="carbon_dioxide",
|
||||
device_class=SensorDeviceClass.CO2,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
suggested_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
|
||||
suggested_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
|
||||
),
|
||||
*BATTERY_SENSORS,
|
||||
),
|
||||
@@ -807,7 +808,7 @@ SENSORS: dict[DeviceCategory, tuple[TuyaSensorEntityDescription, ...]] = {
|
||||
translation_key="pm25",
|
||||
device_class=SensorDeviceClass.PM25,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
suggested_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
|
||||
suggested_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
),
|
||||
TuyaSensorEntityDescription(
|
||||
key=DPCode.CH2O_VALUE,
|
||||
@@ -831,7 +832,7 @@ SENSORS: dict[DeviceCategory, tuple[TuyaSensorEntityDescription, ...]] = {
|
||||
translation_key="carbon_dioxide",
|
||||
device_class=SensorDeviceClass.CO2,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
suggested_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
|
||||
suggested_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
|
||||
),
|
||||
TuyaSensorEntityDescription(
|
||||
key=DPCode.HUMIDITY_VALUE,
|
||||
@@ -844,14 +845,14 @@ SENSORS: dict[DeviceCategory, tuple[TuyaSensorEntityDescription, ...]] = {
|
||||
translation_key="pm1",
|
||||
device_class=SensorDeviceClass.PM1,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
suggested_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
|
||||
suggested_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
),
|
||||
TuyaSensorEntityDescription(
|
||||
key=DPCode.PM10,
|
||||
translation_key="pm10",
|
||||
device_class=SensorDeviceClass.PM10,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
suggested_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
|
||||
suggested_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
),
|
||||
*BATTERY_SENSORS,
|
||||
),
|
||||
@@ -1229,14 +1230,14 @@ SENSORS: dict[DeviceCategory, tuple[TuyaSensorEntityDescription, ...]] = {
|
||||
translation_key="carbon_dioxide",
|
||||
device_class=SensorDeviceClass.CO2,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
suggested_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
|
||||
suggested_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
|
||||
),
|
||||
TuyaSensorEntityDescription(
|
||||
key=DPCode.PM25_VALUE,
|
||||
translation_key="pm25",
|
||||
device_class=SensorDeviceClass.PM25,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
suggested_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
|
||||
suggested_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
),
|
||||
TuyaSensorEntityDescription(
|
||||
key=DPCode.CH2O_VALUE,
|
||||
|
||||
@@ -9,5 +9,5 @@
|
||||
"iot_class": "local_push",
|
||||
"loggers": ["uiprotect"],
|
||||
"quality_scale": "platinum",
|
||||
"requirements": ["uiprotect==15.1.0"]
|
||||
"requirements": ["uiprotect==15.3.0"]
|
||||
}
|
||||
|
||||
@@ -20,16 +20,16 @@ from homeassistant.components.sensor import (
|
||||
SensorStateClass,
|
||||
)
|
||||
from homeassistant.const import (
|
||||
CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
PERCENTAGE,
|
||||
REVOLUTIONS_PER_MINUTE,
|
||||
SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
|
||||
EntityCategory,
|
||||
UnitOfDensity,
|
||||
UnitOfElectricCurrent,
|
||||
UnitOfEnergy,
|
||||
UnitOfMass,
|
||||
UnitOfPower,
|
||||
UnitOfPressure,
|
||||
UnitOfRatio,
|
||||
UnitOfTemperature,
|
||||
UnitOfTime,
|
||||
UnitOfVolume,
|
||||
@@ -80,7 +80,7 @@ VICARE_UNIT_TO_HA_UNIT = {
|
||||
VICARE_CUBIC_METER: UnitOfVolume.CUBIC_METERS,
|
||||
VICARE_KW: UnitOfPower.KILO_WATT,
|
||||
VICARE_KWH: UnitOfEnergy.KILO_WATT_HOUR,
|
||||
VICARE_PERCENT: UnitOfRatio.PERCENTAGE,
|
||||
VICARE_PERCENT: PERCENTAGE,
|
||||
VICARE_W: UnitOfPower.WATT,
|
||||
VICARE_WH: UnitOfEnergy.WATT_HOUR,
|
||||
}
|
||||
@@ -117,7 +117,7 @@ GLOBAL_SENSORS: tuple[ViCareSensorEntityDescription, ...] = (
|
||||
ViCareSensorEntityDescription(
|
||||
key="outside_humidity",
|
||||
translation_key="outside_humidity",
|
||||
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
value_getter=lambda api: api.getOutsideHumidity(),
|
||||
device_class=SensorDeviceClass.HUMIDITY,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
@@ -165,7 +165,7 @@ GLOBAL_SENSORS: tuple[ViCareSensorEntityDescription, ...] = (
|
||||
ViCareSensorEntityDescription(
|
||||
key="primary_circuit_pump_rotation",
|
||||
translation_key="primary_circuit_pump_rotation",
|
||||
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
value_getter=lambda api: api.getPrimaryCircuitPumpRotation(),
|
||||
unit_getter=lambda api: api.getPrimaryCircuitPumpRotationUnit(),
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
@@ -799,7 +799,7 @@ GLOBAL_SENSORS: tuple[ViCareSensorEntityDescription, ...] = (
|
||||
ViCareSensorEntityDescription(
|
||||
key="ess_state_of_charge",
|
||||
translation_key="ess_state_of_charge",
|
||||
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
device_class=SensorDeviceClass.BATTERY,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
value_getter=lambda api: api.getElectricalEnergySystemSOC(),
|
||||
@@ -996,7 +996,7 @@ GLOBAL_SENSORS: tuple[ViCareSensorEntityDescription, ...] = (
|
||||
ViCareSensorEntityDescription(
|
||||
key="room_humidity",
|
||||
device_class=SensorDeviceClass.HUMIDITY,
|
||||
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
value_getter=lambda api: api.getHumidity(),
|
||||
),
|
||||
@@ -1122,7 +1122,7 @@ GLOBAL_SENSORS: tuple[ViCareSensorEntityDescription, ...] = (
|
||||
),
|
||||
ViCareSensorEntityDescription(
|
||||
key="battery_level",
|
||||
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
device_class=SensorDeviceClass.BATTERY,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
@@ -1142,7 +1142,7 @@ GLOBAL_SENSORS: tuple[ViCareSensorEntityDescription, ...] = (
|
||||
translation_key="zigbee_signal_strength",
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
value_getter=lambda api: api.getZigbeeSignalStrength(),
|
||||
entity_registry_enabled_default=False,
|
||||
),
|
||||
@@ -1150,7 +1150,7 @@ GLOBAL_SENSORS: tuple[ViCareSensorEntityDescription, ...] = (
|
||||
key="valve_position",
|
||||
translation_key="valve_position",
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
value_getter=lambda api: api.getValvePosition(),
|
||||
entity_registry_enabled_default=False,
|
||||
),
|
||||
@@ -1177,7 +1177,7 @@ GLOBAL_SENSORS: tuple[ViCareSensorEntityDescription, ...] = (
|
||||
key="supply_humidity",
|
||||
translation_key="supply_humidity",
|
||||
device_class=SensorDeviceClass.HUMIDITY,
|
||||
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
value_getter=lambda api: api.getSupplyHumidity(),
|
||||
),
|
||||
@@ -1229,28 +1229,28 @@ GLOBAL_SENSORS: tuple[ViCareSensorEntityDescription, ...] = (
|
||||
ViCareSensorEntityDescription(
|
||||
key="pm01",
|
||||
device_class=SensorDeviceClass.PM1,
|
||||
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
|
||||
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
value_getter=lambda api: api.getAirborneDustPM1(),
|
||||
),
|
||||
ViCareSensorEntityDescription(
|
||||
key="pm02",
|
||||
device_class=SensorDeviceClass.PM25,
|
||||
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
|
||||
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
value_getter=lambda api: api.getAirborneDustPM2d5(),
|
||||
),
|
||||
ViCareSensorEntityDescription(
|
||||
key="pm04",
|
||||
device_class=SensorDeviceClass.PM4,
|
||||
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
|
||||
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
value_getter=lambda api: api.getAirborneDustPM4(),
|
||||
),
|
||||
ViCareSensorEntityDescription(
|
||||
key="pm10",
|
||||
device_class=SensorDeviceClass.PM10,
|
||||
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
|
||||
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
value_getter=lambda api: api.getAirborneDustPM10(),
|
||||
),
|
||||
@@ -1293,7 +1293,7 @@ BURNER_SENSORS: tuple[ViCareSensorEntityDescription, ...] = (
|
||||
ViCareSensorEntityDescription(
|
||||
key="burner_modulation",
|
||||
translation_key="burner_modulation",
|
||||
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
value_getter=lambda api: api.getModulation(),
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
@@ -1312,7 +1312,7 @@ COMPRESSOR_SENSORS: tuple[ViCareSensorEntityDescription, ...] = (
|
||||
ViCareSensorEntityDescription(
|
||||
key="compressor_modulation",
|
||||
translation_key="compressor_modulation",
|
||||
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
value_getter=lambda api: api.getModulation(),
|
||||
unit_getter=lambda api: api.getModulationUnit(),
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
|
||||
@@ -145,9 +145,7 @@ class VodafoneStationRouter(DataUpdateCoordinator[UpdateCoordinatorDataType]):
|
||||
translation_placeholders={"error": repr(err)},
|
||||
) from err
|
||||
except (
|
||||
exceptions.CannotConnect,
|
||||
exceptions.AlreadyLogged,
|
||||
exceptions.GenericLoginError,
|
||||
exceptions.VodafoneError,
|
||||
JSONDecodeError,
|
||||
) as err:
|
||||
if isinstance(err, JSONDecodeError):
|
||||
|
||||
@@ -21,8 +21,8 @@ if TYPE_CHECKING:
|
||||
|
||||
APPLICATION_NAME: Final = "HomeAssistant"
|
||||
MAJOR_VERSION: Final = 2026
|
||||
MINOR_VERSION: Final = 8
|
||||
PATCH_VERSION: Final = "0.dev0"
|
||||
MINOR_VERSION: Final = 7
|
||||
PATCH_VERSION: Final = "0b2"
|
||||
__short_version__: Final = f"{MAJOR_VERSION}.{MINOR_VERSION}"
|
||||
__version__: Final = f"{__short_version__}.{PATCH_VERSION}"
|
||||
REQUIRED_PYTHON_VER: Final[tuple[int, int, int]] = (3, 14, 2)
|
||||
|
||||
@@ -590,12 +590,6 @@
|
||||
"config_flow": true,
|
||||
"iot_class": "local_polling"
|
||||
},
|
||||
"aten_pe": {
|
||||
"name": "ATEN Rack PDU",
|
||||
"integration_type": "hub",
|
||||
"config_flow": false,
|
||||
"iot_class": "local_polling"
|
||||
},
|
||||
"atlanticcityelectric": {
|
||||
"name": "Atlantic City Electric",
|
||||
"integration_type": "virtual",
|
||||
@@ -1489,12 +1483,6 @@
|
||||
"config_flow": true,
|
||||
"iot_class": "local_polling"
|
||||
},
|
||||
"dovado": {
|
||||
"name": "Dovado",
|
||||
"integration_type": "hub",
|
||||
"config_flow": false,
|
||||
"iot_class": "local_polling"
|
||||
},
|
||||
"downloader": {
|
||||
"name": "Downloader",
|
||||
"integration_type": "service",
|
||||
@@ -2730,12 +2718,6 @@
|
||||
"config_flow": false,
|
||||
"iot_class": "local_push"
|
||||
},
|
||||
"greenwave": {
|
||||
"name": "Greenwave Reality",
|
||||
"integration_type": "hub",
|
||||
"config_flow": false,
|
||||
"iot_class": "local_polling"
|
||||
},
|
||||
"growatt_server": {
|
||||
"integration_type": "hub",
|
||||
"config_flow": true,
|
||||
@@ -3947,12 +3929,6 @@
|
||||
"config_flow": true,
|
||||
"iot_class": "local_push"
|
||||
},
|
||||
"logentries": {
|
||||
"name": "Logentries",
|
||||
"integration_type": "hub",
|
||||
"config_flow": false,
|
||||
"iot_class": "cloud_push"
|
||||
},
|
||||
"logitech": {
|
||||
"name": "Logitech",
|
||||
"integrations": {
|
||||
@@ -7201,12 +7177,6 @@
|
||||
"config_flow": true,
|
||||
"iot_class": "local_push"
|
||||
},
|
||||
"thermoworks_smoke": {
|
||||
"name": "ThermoWorks Smoke",
|
||||
"integration_type": "hub",
|
||||
"config_flow": false,
|
||||
"iot_class": "cloud_polling"
|
||||
},
|
||||
"thethingsnetwork": {
|
||||
"name": "The Things Network",
|
||||
"integration_type": "hub",
|
||||
|
||||
@@ -71,7 +71,7 @@ typing-extensions>=4.15.0,<5.0
|
||||
ulid-transform==2.2.9
|
||||
urllib3>=2.0
|
||||
uv==0.11.21
|
||||
voluptuous-openapi==0.3.0
|
||||
voluptuous-openapi==0.4.1
|
||||
voluptuous-serialize==2.7.0
|
||||
voluptuous==0.15.2
|
||||
webrtc-models==0.3.0
|
||||
|
||||
+2
-2
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "homeassistant"
|
||||
version = "2026.8.0.dev0"
|
||||
version = "2026.7.0b2"
|
||||
license = "Apache-2.0"
|
||||
license-files = ["LICENSE*", "homeassistant/backports/LICENSE*"]
|
||||
description = "Open-source home automation platform running on Python 3."
|
||||
@@ -77,7 +77,7 @@ dependencies = [
|
||||
"uv==0.11.21",
|
||||
"voluptuous==0.15.2",
|
||||
"voluptuous-serialize==2.7.0",
|
||||
"voluptuous-openapi==0.3.0",
|
||||
"voluptuous-openapi==0.4.1",
|
||||
"yarl==1.24.2",
|
||||
"webrtc-models==0.3.0",
|
||||
"zeroconf==0.150.0",
|
||||
|
||||
Generated
+1
-1
@@ -56,7 +56,7 @@ typing-extensions>=4.15.0,<5.0
|
||||
ulid-transform==2.2.9
|
||||
urllib3>=2.0
|
||||
uv==0.11.21
|
||||
voluptuous-openapi==0.3.0
|
||||
voluptuous-openapi==0.4.1
|
||||
voluptuous-serialize==2.7.0
|
||||
voluptuous==0.15.2
|
||||
webrtc-models==0.3.0
|
||||
|
||||
Generated
+8
-14
@@ -83,7 +83,7 @@ PyRMVtransport==0.3.3
|
||||
PySrDaliGateway==0.21.0
|
||||
|
||||
# homeassistant.components.switchbot
|
||||
PySwitchbot==2.3.0
|
||||
PySwitchbot==2.2.0
|
||||
|
||||
# homeassistant.components.switchmate
|
||||
PySwitchmate==0.5.1
|
||||
@@ -193,7 +193,7 @@ aioairzone-cloud==0.7.2
|
||||
aioairzone==1.0.5
|
||||
|
||||
# homeassistant.components.alexa_devices
|
||||
aioamazondevices==14.1.6
|
||||
aioamazondevices==14.1.8
|
||||
|
||||
# homeassistant.components.ambient_network
|
||||
# homeassistant.components.ambient_station
|
||||
@@ -260,7 +260,7 @@ aioelectricitymaps==1.1.1
|
||||
aioemonitor==1.0.5
|
||||
|
||||
# homeassistant.components.esphome
|
||||
aioesphomeapi==45.5.2
|
||||
aioesphomeapi==45.3.1
|
||||
|
||||
# homeassistant.components.matrix
|
||||
# homeassistant.components.slack
|
||||
@@ -583,9 +583,6 @@ asyncsleepiq==1.7.1
|
||||
# homeassistant.components.sftp_storage
|
||||
asyncssh==2.21.0
|
||||
|
||||
# homeassistant.components.aten_pe
|
||||
# atenpdu==0.3.6
|
||||
|
||||
# homeassistant.components.aurora
|
||||
auroranoaa==0.0.5
|
||||
|
||||
@@ -1179,9 +1176,6 @@ greeneye_monitor==3.0.3
|
||||
# homeassistant.components.green_planet_energy
|
||||
greenplanet-energy-api==0.1.10
|
||||
|
||||
# homeassistant.components.greenwave
|
||||
greenwavereality==0.5.1
|
||||
|
||||
# homeassistant.components.pure_energie
|
||||
gridnet==5.0.1
|
||||
|
||||
@@ -1948,7 +1942,7 @@ py-schluter==0.1.7
|
||||
py-sucks==0.9.11
|
||||
|
||||
# homeassistant.components.synology_dsm
|
||||
py-synologydsm-api==2.10.0
|
||||
py-synologydsm-api==2.10.1
|
||||
|
||||
# homeassistant.components.unifi_access
|
||||
py-unifi-access==1.3.0
|
||||
@@ -2018,7 +2012,7 @@ pyairobotrest==0.3.0
|
||||
pyairvisual==2023.08.1
|
||||
|
||||
# homeassistant.components.anglian_water
|
||||
pyanglianwater==3.2.2
|
||||
pyanglianwater==3.2.3
|
||||
|
||||
# homeassistant.components.aprilaire
|
||||
pyaprilaire==0.9.1
|
||||
@@ -2730,7 +2724,7 @@ python-rabbitair==0.0.8
|
||||
python-ripple-api==0.0.3
|
||||
|
||||
# homeassistant.components.roborock
|
||||
python-roborock==5.14.2
|
||||
python-roborock==5.21.0
|
||||
|
||||
# homeassistant.components.smarttub
|
||||
python-smarttub==0.0.47
|
||||
@@ -2899,7 +2893,7 @@ renault-api==0.5.12
|
||||
renson-endura-delta==1.7.2
|
||||
|
||||
# homeassistant.components.reolink
|
||||
reolink-aio==0.21.2
|
||||
reolink-aio==0.21.3
|
||||
|
||||
# homeassistant.components.radio_frequency
|
||||
rf-protocols==4.3.0
|
||||
@@ -3245,7 +3239,7 @@ uasiren==0.0.1
|
||||
uhooapi==1.2.8
|
||||
|
||||
# homeassistant.components.unifiprotect
|
||||
uiprotect==15.1.0
|
||||
uiprotect==15.3.0
|
||||
|
||||
# homeassistant.components.landisgyr_heat_meter
|
||||
ultraheat-api==0.6.1
|
||||
|
||||
@@ -19,7 +19,6 @@ mock-open==1.4.0
|
||||
mypy==2.1.0
|
||||
prek==0.2.28
|
||||
pydantic==2.13.4
|
||||
PyGithub==2.9.1
|
||||
pylint==4.0.6
|
||||
pylint-per-file-ignores==3.2.1
|
||||
pipdeptree==2.26.1
|
||||
|
||||
@@ -2,28 +2,12 @@
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
import sys
|
||||
|
||||
from .gate import GateDecision, decide_skip
|
||||
from .models import CheckRunResult
|
||||
from .runner import run_checks
|
||||
|
||||
|
||||
def _resolve_skip(pr_number: int, head_sha: str | None) -> GateDecision:
|
||||
"""Decide whether this run can skip re-checking the PR.
|
||||
|
||||
Needs the repo and a token (from the Actions environment) to read prior
|
||||
comments; without them it falls open and runs the checks.
|
||||
"""
|
||||
repo = os.environ.get("GITHUB_REPOSITORY")
|
||||
token = os.environ.get("GITHUB_TOKEN")
|
||||
if not head_sha or not repo or not token:
|
||||
return GateDecision(False, "Gate inputs unavailable; running checks.")
|
||||
return decide_skip(pr_number, head_sha, repo, token)
|
||||
|
||||
|
||||
def main(argv: list[str] | None = None) -> int:
|
||||
"""Run the deterministic check_requirements stage and write its artifact."""
|
||||
parser = argparse.ArgumentParser(prog="python -m script.check_requirements")
|
||||
@@ -47,32 +31,24 @@ def main(argv: list[str] | None = None) -> int:
|
||||
)
|
||||
args = parser.parse_args(argv)
|
||||
|
||||
decision = _resolve_skip(args.pr_number, args.head_sha)
|
||||
print(decision.reason, file=sys.stderr)
|
||||
if decision.skip:
|
||||
result = CheckRunResult(
|
||||
pr_number=args.pr_number, head_sha=args.head_sha, skip_aw=True
|
||||
)
|
||||
else:
|
||||
try:
|
||||
diff_text = args.diff.read_text(encoding="utf-8")
|
||||
except FileNotFoundError:
|
||||
parser.error(f"input file {args.diff} not found")
|
||||
result = run_checks(
|
||||
pr_number=args.pr_number,
|
||||
diff_text=diff_text,
|
||||
head_sha=args.head_sha,
|
||||
)
|
||||
print(
|
||||
f"check_requirements: {len(result.packages)} package change(s); "
|
||||
f"needs_agent={result.needs_agent}",
|
||||
file=sys.stderr,
|
||||
)
|
||||
|
||||
try:
|
||||
diff_text = args.diff.read_text(encoding="utf-8")
|
||||
except FileNotFoundError:
|
||||
parser.error(f"input file {args.diff} not found")
|
||||
result = run_checks(
|
||||
pr_number=args.pr_number,
|
||||
diff_text=diff_text,
|
||||
head_sha=args.head_sha,
|
||||
)
|
||||
args.output.write_text(
|
||||
json.dumps(result.to_dict(), indent=2, ensure_ascii=False) + "\n",
|
||||
encoding="utf-8",
|
||||
)
|
||||
print(
|
||||
f"check_requirements: {len(result.packages)} package change(s); "
|
||||
f"needs_agent={result.needs_agent}",
|
||||
file=sys.stderr,
|
||||
)
|
||||
return 0
|
||||
|
||||
|
||||
|
||||
@@ -17,13 +17,11 @@ from .models import PackageChange
|
||||
# of truth for pinned package changes.
|
||||
TRACKED_PATTERNS = (
|
||||
"requirements*.txt",
|
||||
"**/requirements*.txt",
|
||||
"homeassistant/package_constraints.txt",
|
||||
)
|
||||
|
||||
|
||||
def is_tracked(path: str) -> bool:
|
||||
"""Return True if `path` is a requirement file the checks care about."""
|
||||
def _is_tracked(path: str) -> bool:
|
||||
return any(fnmatchcase(path, pattern) for pattern in TRACKED_PATTERNS)
|
||||
|
||||
|
||||
@@ -63,7 +61,7 @@ def parse_diff(diff_text: str) -> list[PackageChange]:
|
||||
added: dict[str, _Pin] = {}
|
||||
removed: dict[str, _Pin] = {}
|
||||
for patched_file in PatchSet(diff_text):
|
||||
if not is_tracked(patched_file.path):
|
||||
if not _is_tracked(patched_file.path):
|
||||
continue
|
||||
for hunk in patched_file:
|
||||
for line in hunk:
|
||||
|
||||
@@ -1,107 +0,0 @@
|
||||
"""Decide whether the deterministic stage can skip re-checking a PR.
|
||||
|
||||
The deterministic stage re-runs on every `synchronize` where the PR touches a
|
||||
tracked requirement file, even when the latest push changed only unrelated
|
||||
files. This module answers "did a tracked requirement file actually change
|
||||
since we last commented?" so the stage can skip the PyPI work and flag the
|
||||
uploaded artifact as skipped, telling the agentic stage to no-op.
|
||||
"""
|
||||
|
||||
from dataclasses import dataclass
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
|
||||
from github import Auth, Github, GithubException
|
||||
from github.IssueComment import IssueComment
|
||||
|
||||
from .diff import is_tracked
|
||||
from .render import COMMIT_PATH
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
# The "Checked at commit [`abc1234`](...COMMIT_PATH<40-hex>)." link rendered by
|
||||
# render._intro is the only place the head SHA is recorded in the comment.
|
||||
_COMMIT_SHA_RE = re.compile(re.escape(COMMIT_PATH) + r"([0-9a-f]{40})", re.IGNORECASE)
|
||||
_TRUSTED_AUTHOR = "github-actions[bot]"
|
||||
|
||||
|
||||
def _is_trusted_author(comment: IssueComment) -> bool:
|
||||
"""True only for the github-actions bot that posts the check comment."""
|
||||
return comment.user is not None and comment.user.login == _TRUSTED_AUTHOR
|
||||
|
||||
|
||||
@dataclass(slots=True, frozen=True)
|
||||
class GateDecision:
|
||||
"""Whether to skip the deterministic checks, with a human-readable reason."""
|
||||
|
||||
skip: bool
|
||||
reason: str
|
||||
|
||||
|
||||
def _client(token: str) -> Github:
|
||||
"""A lazy GitHub client on the configured (possibly GHES) API base."""
|
||||
base_url = os.environ.get("GITHUB_API_URL", "https://api.github.com").rstrip("/")
|
||||
return Github(auth=Auth.Token(token), base_url=base_url, lazy=True)
|
||||
|
||||
|
||||
def fetch_marker_comment_bodies(pr_number: int, repo: str, token: str) -> list[str]:
|
||||
"""Return the trusted requirements-check comment bodies, oldest-first."""
|
||||
try:
|
||||
comments = _client(token).get_repo(repo).get_issue(pr_number).get_comments()
|
||||
return [comment.body for comment in comments if _is_trusted_author(comment)]
|
||||
except GithubException as err:
|
||||
_LOGGER.warning("Could not read comments for PR #%s: %s", pr_number, err)
|
||||
return []
|
||||
|
||||
|
||||
def extract_prior_sha(bodies: list[str]) -> str | None:
|
||||
"""Return the head SHA recorded in the most recent marker comment."""
|
||||
shas = [
|
||||
match.group(1).lower()
|
||||
for body in bodies
|
||||
for match in _COMMIT_SHA_RE.finditer(body)
|
||||
]
|
||||
return shas[-1] if shas else None
|
||||
|
||||
|
||||
def compare_changed_files(
|
||||
base: str, head: str, repo: str, token: str
|
||||
) -> list[str] | None:
|
||||
"""Return filenames changed between two commits, or None if unavailable."""
|
||||
try:
|
||||
comparison = _client(token).get_repo(repo).compare(base, head)
|
||||
return [changed.filename for changed in comparison.files]
|
||||
except GithubException as err:
|
||||
_LOGGER.warning("Could not compare %s...%s: %s", base, head, err)
|
||||
return None
|
||||
|
||||
|
||||
def decide_skip(pr_number: int, head_sha: str, repo: str, token: str) -> GateDecision:
|
||||
"""Decide whether requirements changed since the last comment."""
|
||||
if not head_sha:
|
||||
return GateDecision(False, "No head SHA available; running checks.")
|
||||
prior = extract_prior_sha(fetch_marker_comment_bodies(pr_number, repo, token))
|
||||
if prior is None:
|
||||
return GateDecision(
|
||||
False, "No previous requirements-check comment; running checks."
|
||||
)
|
||||
if prior == head_sha.lower():
|
||||
return GateDecision(
|
||||
True, f"Head {head_sha} unchanged since the last comment; skipping."
|
||||
)
|
||||
changed = compare_changed_files(prior, head_sha, repo, token)
|
||||
if changed is None:
|
||||
return GateDecision(
|
||||
False, f"Could not compare {prior}...{head_sha}; running checks."
|
||||
)
|
||||
tracked = [path for path in changed if is_tracked(path)]
|
||||
if tracked:
|
||||
return GateDecision(
|
||||
False,
|
||||
f"Tracked requirement files changed since {prior}; running checks: "
|
||||
+ ", ".join(tracked),
|
||||
)
|
||||
return GateDecision(
|
||||
True, f"No tracked requirement files changed since {prior}; skipping."
|
||||
)
|
||||
@@ -90,7 +90,6 @@ class CheckRunResult:
|
||||
head_sha: str | None = None
|
||||
packages: list[PackageChange] = field(default_factory=list)
|
||||
rendered_comment: str = ""
|
||||
skip_aw: bool = False
|
||||
|
||||
@property
|
||||
def needs_agent(self) -> bool:
|
||||
@@ -102,7 +101,6 @@ class CheckRunResult:
|
||||
return {
|
||||
"version": 1,
|
||||
"pr_number": self.pr_number,
|
||||
"skip_aw": self.skip_aw,
|
||||
"head_sha": self.head_sha,
|
||||
"needs_agent": self.needs_agent,
|
||||
"packages": [p.to_dict() for p in self.packages],
|
||||
|
||||
@@ -14,7 +14,6 @@ from .models import CheckKind, CheckRunResult, CheckStatus, PackageChange
|
||||
MARKER = "<!-- requirements-check -->"
|
||||
HEADER = "## Check requirements"
|
||||
REPO_URL = "https://github.com/home-assistant/core"
|
||||
COMMIT_PATH = "/commit/"
|
||||
|
||||
# Column / bullet labels per check kind, in display order.
|
||||
_CHECK_DISPLAY: tuple[tuple[CheckKind, str], ...] = (
|
||||
@@ -128,7 +127,7 @@ def _intro(result: CheckRunResult) -> str:
|
||||
"""Marker, header, and the optional commit line the gate reads back."""
|
||||
parts: list[str] = []
|
||||
if result.head_sha:
|
||||
commit = f"[`{result.head_sha[:7]}`]({REPO_URL}{COMMIT_PATH}{result.head_sha})"
|
||||
commit = f"[`{result.head_sha[:7]}`]({REPO_URL}/commit/{result.head_sha})"
|
||||
parts.append(f"Checked at commit {commit}.")
|
||||
return "\n\n".join([f"{MARKER}\n{HEADER}", *parts])
|
||||
|
||||
|
||||
-1
@@ -1,3 +1,2 @@
|
||||
PyGithub==2.9.1
|
||||
requests==2.34.2
|
||||
unidiff==0.7.5
|
||||
|
||||
@@ -165,7 +165,6 @@ INTEGRATIONS_WITHOUT_QUALITY_SCALE_FILE = [
|
||||
"asterisk_mbox",
|
||||
"asuswrt",
|
||||
"atag",
|
||||
"aten_pe",
|
||||
"atome",
|
||||
"august",
|
||||
"aurora",
|
||||
@@ -274,7 +273,6 @@ INTEGRATIONS_WITHOUT_QUALITY_SCALE_FILE = [
|
||||
"doods",
|
||||
"doorbird",
|
||||
"dormakaba_dkey",
|
||||
"dovado",
|
||||
"downloader",
|
||||
"dremel_3d_printer",
|
||||
"drop_connect",
|
||||
@@ -420,7 +418,6 @@ INTEGRATIONS_WITHOUT_QUALITY_SCALE_FILE = [
|
||||
"graphite",
|
||||
"gree",
|
||||
"greeneye_monitor",
|
||||
"greenwave",
|
||||
"group",
|
||||
"gtfs",
|
||||
"guardian",
|
||||
@@ -548,7 +545,6 @@ INTEGRATIONS_WITHOUT_QUALITY_SCALE_FILE = [
|
||||
"local_todo",
|
||||
"location",
|
||||
"locative",
|
||||
"logentries",
|
||||
"logi_circle",
|
||||
"london_air",
|
||||
"london_underground",
|
||||
@@ -913,7 +909,6 @@ INTEGRATIONS_WITHOUT_QUALITY_SCALE_FILE = [
|
||||
"tesla_wall_connector",
|
||||
"thermobeacon",
|
||||
"thermopro",
|
||||
"thermoworks_smoke",
|
||||
"thethingsnetwork",
|
||||
"thingspeak",
|
||||
"thinkingcleaner",
|
||||
@@ -1113,7 +1108,6 @@ INTEGRATIONS_WITHOUT_SCALE = [
|
||||
"asterisk_mbox",
|
||||
"asuswrt",
|
||||
"atag",
|
||||
"aten_pe",
|
||||
"atome",
|
||||
"august",
|
||||
"aurora",
|
||||
@@ -1225,7 +1219,6 @@ INTEGRATIONS_WITHOUT_SCALE = [
|
||||
"doods",
|
||||
"doorbird",
|
||||
"dormakaba_dkey",
|
||||
"dovado",
|
||||
"downloader",
|
||||
"dremel_3d_printer",
|
||||
"drop_connect",
|
||||
@@ -1378,7 +1371,6 @@ INTEGRATIONS_WITHOUT_SCALE = [
|
||||
"graphite",
|
||||
"gree",
|
||||
"greeneye_monitor",
|
||||
"greenwave",
|
||||
"group",
|
||||
"gtfs",
|
||||
"guardian",
|
||||
@@ -1513,7 +1505,6 @@ INTEGRATIONS_WITHOUT_SCALE = [
|
||||
"local_todo",
|
||||
"location",
|
||||
"locative",
|
||||
"logentries",
|
||||
"logi_circle",
|
||||
"london_air",
|
||||
"london_underground",
|
||||
@@ -1896,7 +1887,6 @@ INTEGRATIONS_WITHOUT_SCALE = [
|
||||
"tesla_wall_connector",
|
||||
"thermobeacon",
|
||||
"thermopro",
|
||||
"thermoworks_smoke",
|
||||
"thethingsnetwork",
|
||||
"thingspeak",
|
||||
"thinkingcleaner",
|
||||
@@ -2082,7 +2072,6 @@ NO_QUALITY_SCALE = [
|
||||
"intent_script",
|
||||
"intent",
|
||||
"labs",
|
||||
"llm",
|
||||
"logbook",
|
||||
"logger",
|
||||
"lovelace",
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '123-456-co',
|
||||
'unit_of_measurement': <UnitOfDensity.MICROGRAMS_PER_CUBIC_METER: 'μg/m³'>,
|
||||
'unit_of_measurement': 'μg/m³',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensor[sensor.home_carbon_monoxide-state]
|
||||
@@ -50,7 +50,7 @@
|
||||
'limit': 4000,
|
||||
'percent': 4,
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfDensity.MICROGRAMS_PER_CUBIC_METER: 'μg/m³'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: 'μg/m³',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.home_carbon_monoxide',
|
||||
@@ -157,7 +157,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '123-456-humidity',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensor[sensor.home_humidity-state]
|
||||
@@ -167,7 +167,7 @@
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'humidity',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Home Humidity',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.home_humidity',
|
||||
@@ -216,7 +216,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '123-456-no2',
|
||||
'unit_of_measurement': <UnitOfDensity.MICROGRAMS_PER_CUBIC_METER: 'μg/m³'>,
|
||||
'unit_of_measurement': 'μg/m³',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensor[sensor.home_nitrogen_dioxide-state]
|
||||
@@ -228,7 +228,7 @@
|
||||
'limit': 25,
|
||||
'percent': 64,
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfDensity.MICROGRAMS_PER_CUBIC_METER: 'μg/m³'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: 'μg/m³',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.home_nitrogen_dioxide',
|
||||
@@ -277,7 +277,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '123-456-o3',
|
||||
'unit_of_measurement': <UnitOfDensity.MICROGRAMS_PER_CUBIC_METER: 'μg/m³'>,
|
||||
'unit_of_measurement': 'μg/m³',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensor[sensor.home_ozone-state]
|
||||
@@ -289,7 +289,7 @@
|
||||
'limit': 100,
|
||||
'percent': 42,
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfDensity.MICROGRAMS_PER_CUBIC_METER: 'μg/m³'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: 'μg/m³',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.home_ozone',
|
||||
@@ -338,7 +338,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '123-456-pm1',
|
||||
'unit_of_measurement': <UnitOfDensity.MICROGRAMS_PER_CUBIC_METER: 'μg/m³'>,
|
||||
'unit_of_measurement': 'μg/m³',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensor[sensor.home_pm1-state]
|
||||
@@ -348,7 +348,7 @@
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'pm1',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Home PM1',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfDensity.MICROGRAMS_PER_CUBIC_METER: 'μg/m³'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: 'μg/m³',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.home_pm1',
|
||||
@@ -397,7 +397,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '123-456-pm10',
|
||||
'unit_of_measurement': <UnitOfDensity.MICROGRAMS_PER_CUBIC_METER: 'μg/m³'>,
|
||||
'unit_of_measurement': 'μg/m³',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensor[sensor.home_pm10-state]
|
||||
@@ -409,7 +409,7 @@
|
||||
'limit': 45,
|
||||
'percent': 14,
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfDensity.MICROGRAMS_PER_CUBIC_METER: 'μg/m³'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: 'μg/m³',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.home_pm10',
|
||||
@@ -458,7 +458,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '123-456-pm25',
|
||||
'unit_of_measurement': <UnitOfDensity.MICROGRAMS_PER_CUBIC_METER: 'μg/m³'>,
|
||||
'unit_of_measurement': 'μg/m³',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensor[sensor.home_pm2_5-state]
|
||||
@@ -470,7 +470,7 @@
|
||||
'limit': 15,
|
||||
'percent': 29,
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfDensity.MICROGRAMS_PER_CUBIC_METER: 'μg/m³'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: 'μg/m³',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.home_pm2_5',
|
||||
@@ -578,7 +578,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '123-456-so2',
|
||||
'unit_of_measurement': <UnitOfDensity.MICROGRAMS_PER_CUBIC_METER: 'μg/m³'>,
|
||||
'unit_of_measurement': 'μg/m³',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensor[sensor.home_sulphur_dioxide-state]
|
||||
@@ -590,7 +590,7 @@
|
||||
'limit': 40,
|
||||
'percent': 35,
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfDensity.MICROGRAMS_PER_CUBIC_METER: 'μg/m³'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: 'μg/m³',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.home_sulphur_dioxide',
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': 'aa:bb:cc:dd:ee:ff_113_humidity',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensor_entities_state[sensor.bathroom_rh_humidity-state]
|
||||
@@ -44,7 +44,7 @@
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'humidity',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Bathroom RH Humidity',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.bathroom_rh_humidity',
|
||||
@@ -90,7 +90,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': 'iaq_rh',
|
||||
'unique_id': 'aa:bb:cc:dd:ee:ff_113_iaq_rh',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensor_entities_state[sensor.bathroom_rh_humidity_air_quality_index-state]
|
||||
@@ -98,7 +98,7 @@
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Bathroom RH Humidity air quality index',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.bathroom_rh_humidity_air_quality_index',
|
||||
@@ -144,7 +144,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': 'aa:bb:cc:dd:ee:ff_60_humidity',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensor_entities_state[sensor.bedroom_valve_humidity-state]
|
||||
@@ -153,7 +153,7 @@
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'humidity',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Bedroom valve Humidity',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.bedroom_valve_humidity',
|
||||
@@ -199,7 +199,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': 'iaq_rh',
|
||||
'unique_id': 'aa:bb:cc:dd:ee:ff_60_iaq_rh',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensor_entities_state[sensor.bedroom_valve_humidity_air_quality_index-state]
|
||||
@@ -207,7 +207,7 @@
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Bedroom valve Humidity air quality index',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.bedroom_valve_humidity_air_quality_index',
|
||||
@@ -253,7 +253,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': 'aa:bb:cc:dd:ee:ff_61_co2',
|
||||
'unit_of_measurement': <UnitOfRatio.PARTS_PER_MILLION: 'ppm'>,
|
||||
'unit_of_measurement': 'ppm',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensor_entities_state[sensor.hall_valve_carbon_dioxide-state]
|
||||
@@ -262,7 +262,7 @@
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'carbon_dioxide',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Hall valve Carbon dioxide',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PARTS_PER_MILLION: 'ppm'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: 'ppm',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.hall_valve_carbon_dioxide',
|
||||
@@ -308,7 +308,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': 'iaq_co2',
|
||||
'unique_id': 'aa:bb:cc:dd:ee:ff_61_iaq_co2',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensor_entities_state[sensor.hall_valve_co2_air_quality_index-state]
|
||||
@@ -316,7 +316,7 @@
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Hall valve CO2 air quality index',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.hall_valve_co2_air_quality_index',
|
||||
@@ -362,7 +362,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': 'aa:bb:cc:dd:ee:ff_50_humidity',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensor_entities_state[sensor.kitchen_rh_humidity-state]
|
||||
@@ -371,7 +371,7 @@
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'humidity',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Kitchen RH Humidity',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.kitchen_rh_humidity',
|
||||
@@ -417,7 +417,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': 'iaq_rh',
|
||||
'unique_id': 'aa:bb:cc:dd:ee:ff_50_iaq_rh',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensor_entities_state[sensor.kitchen_rh_humidity_air_quality_index-state]
|
||||
@@ -425,7 +425,7 @@
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Kitchen RH Humidity air quality index',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.kitchen_rh_humidity_air_quality_index',
|
||||
@@ -635,7 +635,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': 'target_flow_level',
|
||||
'unique_id': 'aa:bb:cc:dd:ee:ff_1_target_flow_level',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensor_entities_state[sensor.living_target_flow_level-state]
|
||||
@@ -643,7 +643,7 @@
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Living Target flow level',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.living_target_flow_level',
|
||||
@@ -781,7 +781,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': 'aa:bb:cc:dd:ee:ff_2_co2',
|
||||
'unit_of_measurement': <UnitOfRatio.PARTS_PER_MILLION: 'ppm'>,
|
||||
'unit_of_measurement': 'ppm',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensor_entities_state[sensor.office_co2_carbon_dioxide-state]
|
||||
@@ -790,7 +790,7 @@
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'carbon_dioxide',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Office CO2 Carbon dioxide',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PARTS_PER_MILLION: 'ppm'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: 'ppm',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.office_co2_carbon_dioxide',
|
||||
@@ -836,7 +836,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': 'iaq_co2',
|
||||
'unique_id': 'aa:bb:cc:dd:ee:ff_2_iaq_co2',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensor_entities_state[sensor.office_co2_co2_air_quality_index-state]
|
||||
@@ -844,7 +844,7 @@
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Office CO2 CO2 air quality index',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.office_co2_co2_air_quality_index',
|
||||
@@ -890,7 +890,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': 'aa:bb:cc:dd:ee:ff_62_co2',
|
||||
'unit_of_measurement': <UnitOfRatio.PARTS_PER_MILLION: 'ppm'>,
|
||||
'unit_of_measurement': 'ppm',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensor_entities_state[sensor.study_valve_carbon_dioxide-state]
|
||||
@@ -899,7 +899,7 @@
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'carbon_dioxide',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Study valve Carbon dioxide',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PARTS_PER_MILLION: 'ppm'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: 'ppm',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.study_valve_carbon_dioxide',
|
||||
@@ -945,7 +945,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': 'iaq_co2',
|
||||
'unique_id': 'aa:bb:cc:dd:ee:ff_62_iaq_co2',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensor_entities_state[sensor.study_valve_co2_air_quality_index-state]
|
||||
@@ -953,7 +953,7 @@
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Study valve CO2 air quality index',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.study_valve_co2_air_quality_index',
|
||||
@@ -999,7 +999,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': 'aa:bb:cc:dd:ee:ff_62_humidity',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensor_entities_state[sensor.study_valve_humidity-state]
|
||||
@@ -1008,7 +1008,7 @@
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'humidity',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Study valve Humidity',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.study_valve_humidity',
|
||||
@@ -1054,7 +1054,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': 'iaq_rh',
|
||||
'unique_id': 'aa:bb:cc:dd:ee:ff_62_iaq_rh',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensor_entities_state[sensor.study_valve_humidity_air_quality_index-state]
|
||||
@@ -1062,7 +1062,7 @@
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Study valve Humidity air quality index',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.study_valve_humidity_air_quality_index',
|
||||
|
||||
@@ -13,6 +13,7 @@ from duco_connectivity import (
|
||||
Node,
|
||||
NodeActionItemList,
|
||||
NodeListActionItemList,
|
||||
NodeType,
|
||||
VentilationState,
|
||||
)
|
||||
import pytest
|
||||
@@ -32,6 +33,7 @@ from . import setup_platform_integration
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
_SELECT_ENTITY = "select.living_ventilation_state"
|
||||
_VALVE_SELECT_ENTITY = "select.bedroom_valve_ventilation_state"
|
||||
_UNSUPPORTED_SELECT_ENTITY = "select.office_co2_ventilation_state"
|
||||
|
||||
|
||||
@@ -120,20 +122,55 @@ async def test_select_entity_created_with_dynamic_options(
|
||||
assert hass.states.get(_UNSUPPORTED_SELECT_ENTITY) is None
|
||||
|
||||
|
||||
async def test_select_ignores_non_box_nodes_even_when_actions_exist(
|
||||
@pytest.mark.parametrize(
|
||||
"valve_node_type",
|
||||
[
|
||||
pytest.param(NodeType.VLV, id="vlv"),
|
||||
pytest.param(NodeType.VLVRH, id="vlvrh"),
|
||||
pytest.param(NodeType.VLVVOC, id="vlvvoc"),
|
||||
pytest.param(NodeType.VLVCO2, id="vlvco2"),
|
||||
pytest.param(NodeType.VLVCO2RH, id="vlvco2rh"),
|
||||
pytest.param(NodeType.EAV, id="eav"),
|
||||
pytest.param(NodeType.EAVRH, id="eavrh"),
|
||||
pytest.param(NodeType.EAVVOC, id="eavvoc"),
|
||||
pytest.param(NodeType.EAVCO2, id="eavco2"),
|
||||
],
|
||||
)
|
||||
async def test_select_creates_entities_for_controllable_valve_nodes(
|
||||
hass: HomeAssistant,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
mock_duco_client: AsyncMock,
|
||||
mock_sensor_nodes: list[Node],
|
||||
valve_node_type: NodeType,
|
||||
) -> None:
|
||||
"""Test select discovery ignores non-box nodes that expose the same action."""
|
||||
"""Test select discovery includes valve nodes when they advertise control."""
|
||||
mock_nodes = [
|
||||
replace(
|
||||
mock_sensor_nodes[0],
|
||||
general=replace(mock_sensor_nodes[0].general, node_type=valve_node_type),
|
||||
),
|
||||
*mock_sensor_nodes[1:],
|
||||
]
|
||||
mock_duco_client.async_get_nodes.return_value = mock_nodes
|
||||
mock_duco_client.async_get_node_actions.return_value = _build_multi_node_actions(
|
||||
[1, 2, 50, 113],
|
||||
[node.node_id for node in mock_nodes],
|
||||
options=["AUTO", "CNT1", "CNT2", "CNT3", "MAN1", "MAN2", "MAN3"],
|
||||
)
|
||||
|
||||
await setup_platform_integration(hass, mock_config_entry, [Platform.SELECT])
|
||||
|
||||
assert hass.states.get(_SELECT_ENTITY) is not None
|
||||
valve_state = hass.states.get(_VALVE_SELECT_ENTITY)
|
||||
assert valve_state is not None
|
||||
assert valve_state.attributes[ATTR_OPTIONS] == [
|
||||
"AUTO",
|
||||
"CNT1",
|
||||
"CNT2",
|
||||
"CNT3",
|
||||
"MAN1",
|
||||
"MAN2",
|
||||
"MAN3",
|
||||
]
|
||||
assert hass.states.get(_UNSUPPORTED_SELECT_ENTITY) is None
|
||||
|
||||
|
||||
|
||||
@@ -853,12 +853,11 @@
|
||||
}),
|
||||
]),
|
||||
'envoy_model_data': dict({
|
||||
'ctmeter_consumption': None,
|
||||
'ctmeter_consumption_phases': None,
|
||||
'ctmeter_production': None,
|
||||
'ctmeter_production_phases': None,
|
||||
'ctmeter_storage': None,
|
||||
'ctmeter_storage_phases': None,
|
||||
'acb_inventory': None,
|
||||
'acb_power': None,
|
||||
'battery_aggregate': None,
|
||||
'c6cc': None,
|
||||
'collar': None,
|
||||
'ctmeters': dict({
|
||||
}),
|
||||
'ctmeters_phases': dict({
|
||||
@@ -1768,12 +1767,11 @@
|
||||
}),
|
||||
]),
|
||||
'envoy_model_data': dict({
|
||||
'ctmeter_consumption': None,
|
||||
'ctmeter_consumption_phases': None,
|
||||
'ctmeter_production': None,
|
||||
'ctmeter_production_phases': None,
|
||||
'ctmeter_storage': None,
|
||||
'ctmeter_storage_phases': None,
|
||||
'acb_inventory': None,
|
||||
'acb_power': None,
|
||||
'battery_aggregate': None,
|
||||
'c6cc': None,
|
||||
'collar': None,
|
||||
'ctmeters': dict({
|
||||
}),
|
||||
'ctmeters_phases': dict({
|
||||
@@ -1822,8 +1820,14 @@
|
||||
]),
|
||||
}),
|
||||
'fixtures': dict({
|
||||
'/admin/lib/acb_config': 'Testing request replies.',
|
||||
'/admin/lib/acb_config_log': '{"headers":{"Hello":"World"},"code":200}',
|
||||
'/admin/lib/network_display': 'Testing request replies.',
|
||||
'/admin/lib/network_display_log': '{"headers":{"Hello":"World"},"code":200}',
|
||||
'/admin/lib/tariff': 'Testing request replies.',
|
||||
'/admin/lib/tariff_log': '{"headers":{"Hello":"World"},"code":200}',
|
||||
'/admin/lib/wireless_display': 'Testing request replies.',
|
||||
'/admin/lib/wireless_display_log': '{"headers":{"Hello":"World"},"code":200}',
|
||||
'/api/v1/production': 'Testing request replies.',
|
||||
'/api/v1/production/inverters': 'Testing request replies.',
|
||||
'/api/v1/production/inverters_log': '{"headers":{"Hello":"World"},"code":200}',
|
||||
@@ -1832,6 +1836,8 @@
|
||||
'/home_log': '{"headers":{"Hello":"World"},"code":200}',
|
||||
'/info': 'Testing request replies.',
|
||||
'/info_log': '{"headers":{"Hello":"World"},"code":200}',
|
||||
'/inventory.json?deleted=1': 'Testing request replies.',
|
||||
'/inventory.json?deleted=1_log': '{"headers":{"Hello":"World"},"code":200}',
|
||||
'/ivp/ensemble/dry_contacts': 'Testing request replies.',
|
||||
'/ivp/ensemble/dry_contacts_log': '{"headers":{"Hello":"World"},"code":200}',
|
||||
'/ivp/ensemble/generator': 'Testing request replies.',
|
||||
@@ -1840,18 +1846,26 @@
|
||||
'/ivp/ensemble/inventory_log': '{"headers":{"Hello":"World"},"code":200}',
|
||||
'/ivp/ensemble/power': 'Testing request replies.',
|
||||
'/ivp/ensemble/power_log': '{"headers":{"Hello":"World"},"code":200}',
|
||||
'/ivp/ensemble/relay': 'Testing request replies.',
|
||||
'/ivp/ensemble/relay_log': '{"headers":{"Hello":"World"},"code":200}',
|
||||
'/ivp/ensemble/secctrl': 'Testing request replies.',
|
||||
'/ivp/ensemble/secctrl_log': '{"headers":{"Hello":"World"},"code":200}',
|
||||
'/ivp/ensemble/status': 'Testing request replies.',
|
||||
'/ivp/ensemble/status_log': '{"headers":{"Hello":"World"},"code":200}',
|
||||
'/ivp/livedata/status': 'Testing request replies.',
|
||||
'/ivp/livedata/status_log': '{"headers":{"Hello":"World"},"code":200}',
|
||||
'/ivp/meters': 'Testing request replies.',
|
||||
'/ivp/meters/readings': 'Testing request replies.',
|
||||
'/ivp/meters/readings_log': '{"headers":{"Hello":"World"},"code":200}',
|
||||
'/ivp/meters_log': '{"headers":{"Hello":"World"},"code":200}',
|
||||
'/ivp/pdm/device_data': 'Testing request replies.',
|
||||
'/ivp/pdm/device_data_log': '{"headers":{"Hello":"World"},"code":200}',
|
||||
'/ivp/pdm/energy': 'Testing request replies.',
|
||||
'/ivp/pdm/energy_log': '{"headers":{"Hello":"World"},"code":200}',
|
||||
'/ivp/sc/pvlimit': 'Testing request replies.',
|
||||
'/ivp/sc/pvlimit_log': '{"headers":{"Hello":"World"},"code":200}',
|
||||
'/ivp/sc/sched': 'Testing request replies.',
|
||||
'/ivp/sc/sched_log': '{"headers":{"Hello":"World"},"code":200}',
|
||||
'/ivp/ss/dry_contact_settings': 'Testing request replies.',
|
||||
'/ivp/ss/dry_contact_settings_log': '{"headers":{"Hello":"World"},"code":200}',
|
||||
'/ivp/ss/gen_config': 'Testing request replies.',
|
||||
@@ -2727,12 +2741,11 @@
|
||||
}),
|
||||
]),
|
||||
'envoy_model_data': dict({
|
||||
'ctmeter_consumption': None,
|
||||
'ctmeter_consumption_phases': None,
|
||||
'ctmeter_production': None,
|
||||
'ctmeter_production_phases': None,
|
||||
'ctmeter_storage': None,
|
||||
'ctmeter_storage_phases': None,
|
||||
'acb_inventory': None,
|
||||
'acb_power': None,
|
||||
'battery_aggregate': None,
|
||||
'c6cc': None,
|
||||
'collar': None,
|
||||
'ctmeters': dict({
|
||||
}),
|
||||
'ctmeters_phases': dict({
|
||||
@@ -2781,9 +2794,18 @@
|
||||
]),
|
||||
}),
|
||||
'fixtures': dict({
|
||||
'/admin/lib/acb_config_log': dict({
|
||||
'Error': "EnvoyError('Test')",
|
||||
}),
|
||||
'/admin/lib/network_display_log': dict({
|
||||
'Error': "EnvoyError('Test')",
|
||||
}),
|
||||
'/admin/lib/tariff_log': dict({
|
||||
'Error': "EnvoyError('Test')",
|
||||
}),
|
||||
'/admin/lib/wireless_display_log': dict({
|
||||
'Error': "EnvoyError('Test')",
|
||||
}),
|
||||
'/api/v1/production/inverters_log': dict({
|
||||
'Error': "EnvoyError('Test')",
|
||||
}),
|
||||
@@ -2796,6 +2818,9 @@
|
||||
'/info_log': dict({
|
||||
'Error': "EnvoyError('Test')",
|
||||
}),
|
||||
'/inventory.json?deleted=1_log': dict({
|
||||
'Error': "EnvoyError('Test')",
|
||||
}),
|
||||
'/ivp/ensemble/dry_contacts_log': dict({
|
||||
'Error': "EnvoyError('Test')",
|
||||
}),
|
||||
@@ -2808,12 +2833,18 @@
|
||||
'/ivp/ensemble/power_log': dict({
|
||||
'Error': "EnvoyError('Test')",
|
||||
}),
|
||||
'/ivp/ensemble/relay_log': dict({
|
||||
'Error': "EnvoyError('Test')",
|
||||
}),
|
||||
'/ivp/ensemble/secctrl_log': dict({
|
||||
'Error': "EnvoyError('Test')",
|
||||
}),
|
||||
'/ivp/ensemble/status_log': dict({
|
||||
'Error': "EnvoyError('Test')",
|
||||
}),
|
||||
'/ivp/livedata/status_log': dict({
|
||||
'Error': "EnvoyError('Test')",
|
||||
}),
|
||||
'/ivp/meters/readings_log': dict({
|
||||
'Error': "EnvoyError('Test')",
|
||||
}),
|
||||
@@ -2823,9 +2854,15 @@
|
||||
'/ivp/pdm/device_data_log': dict({
|
||||
'Error': "EnvoyError('Test')",
|
||||
}),
|
||||
'/ivp/pdm/energy_log': dict({
|
||||
'Error': "EnvoyError('Test')",
|
||||
}),
|
||||
'/ivp/sc/pvlimit_log': dict({
|
||||
'Error': "EnvoyError('Test')",
|
||||
}),
|
||||
'/ivp/sc/sched_log': dict({
|
||||
'Error': "EnvoyError('Test')",
|
||||
}),
|
||||
'/ivp/ss/dry_contact_settings_log': dict({
|
||||
'Error': "EnvoyError('Test')",
|
||||
}),
|
||||
@@ -3711,12 +3748,11 @@
|
||||
}),
|
||||
]),
|
||||
'envoy_model_data': dict({
|
||||
'ctmeter_consumption': None,
|
||||
'ctmeter_consumption_phases': None,
|
||||
'ctmeter_production': None,
|
||||
'ctmeter_production_phases': None,
|
||||
'ctmeter_storage': None,
|
||||
'ctmeter_storage_phases': None,
|
||||
'acb_inventory': None,
|
||||
'acb_power': None,
|
||||
'battery_aggregate': None,
|
||||
'c6cc': None,
|
||||
'collar': None,
|
||||
'ctmeters': dict({
|
||||
}),
|
||||
'ctmeters_phases': dict({
|
||||
@@ -19745,59 +19781,16 @@
|
||||
}),
|
||||
]),
|
||||
'envoy_model_data': dict({
|
||||
'ctmeter_consumption': dict({
|
||||
'__type': "<class 'pyenphase.models.meters.EnvoyMeterData'>",
|
||||
'repr': "EnvoyMeterData(eid='100000020', timestamp=1708006120, energy_delivered=21234, energy_received=22345, active_power=101, power_factor=0.21, voltage=112, current=0.3, frequency=50.2, state='enabled', measurement_type='net-consumption', metering_status='normal', status_flags=[])",
|
||||
'acb_inventory': None,
|
||||
'acb_power': None,
|
||||
'battery_aggregate': None,
|
||||
'c6cc': dict({
|
||||
'__type': "<class 'pyenphase.models.c6combiner.EnvoyC6CC'>",
|
||||
'repr': "EnvoyC6CC(admin_state=82, admin_state_str='ENCMN_C6_CC_READY', firmware_loaded_date=1752945451, firmware_version='0.1.20-D1', installed_date=1752945451, last_report_date=1752945451, communicating=True, part_number='800-02403-r08', serial_number='482523040549', dmir_version='0.1.20-D1')",
|
||||
}),
|
||||
'ctmeter_consumption_phases': dict({
|
||||
'L1': dict({
|
||||
'__type': "<class 'pyenphase.models.meters.EnvoyMeterData'>",
|
||||
'repr': "EnvoyMeterData(eid='100000021', timestamp=1708006121, energy_delivered=212341, energy_received=223451, active_power=21, power_factor=0.22, voltage=112, current=0.3, frequency=50.2, state='enabled', measurement_type='net-consumption', metering_status='normal', status_flags=[])",
|
||||
}),
|
||||
'L2': dict({
|
||||
'__type': "<class 'pyenphase.models.meters.EnvoyMeterData'>",
|
||||
'repr': "EnvoyMeterData(eid='100000022', timestamp=1708006122, energy_delivered=212342, energy_received=223452, active_power=31, power_factor=0.23, voltage=112, current=0.3, frequency=50.2, state='enabled', measurement_type='net-consumption', metering_status='normal', status_flags=[])",
|
||||
}),
|
||||
'L3': dict({
|
||||
'__type': "<class 'pyenphase.models.meters.EnvoyMeterData'>",
|
||||
'repr': "EnvoyMeterData(eid='100000023', timestamp=1708006123, energy_delivered=212343, energy_received=223453, active_power=51, power_factor=0.24, voltage=112, current=0.3, frequency=50.2, state='enabled', measurement_type='net-consumption', metering_status='normal', status_flags=[])",
|
||||
}),
|
||||
}),
|
||||
'ctmeter_production': dict({
|
||||
'__type': "<class 'pyenphase.models.meters.EnvoyMeterData'>",
|
||||
'repr': "EnvoyMeterData(eid='100000010', timestamp=1708006110, energy_delivered=11234, energy_received=12345, active_power=100, power_factor=0.11, voltage=111, current=0.2, frequency=50.1, state='enabled', measurement_type='production', metering_status='normal', status_flags=['production-imbalance', 'power-on-unused-phase'])",
|
||||
}),
|
||||
'ctmeter_production_phases': dict({
|
||||
'L1': dict({
|
||||
'__type': "<class 'pyenphase.models.meters.EnvoyMeterData'>",
|
||||
'repr': "EnvoyMeterData(eid='100000011', timestamp=1708006111, energy_delivered=112341, energy_received=123451, active_power=20, power_factor=0.12, voltage=111, current=0.2, frequency=50.1, state='enabled', measurement_type='production', metering_status='normal', status_flags=['production-imbalance'])",
|
||||
}),
|
||||
'L2': dict({
|
||||
'__type': "<class 'pyenphase.models.meters.EnvoyMeterData'>",
|
||||
'repr': "EnvoyMeterData(eid='100000012', timestamp=1708006112, energy_delivered=112342, energy_received=123452, active_power=30, power_factor=0.13, voltage=111, current=0.2, frequency=50.1, state='enabled', measurement_type='production', metering_status='normal', status_flags=['power-on-unused-phase'])",
|
||||
}),
|
||||
'L3': dict({
|
||||
'__type': "<class 'pyenphase.models.meters.EnvoyMeterData'>",
|
||||
'repr': "EnvoyMeterData(eid='100000013', timestamp=1708006113, energy_delivered=112343, energy_received=123453, active_power=50, power_factor=0.14, voltage=111, current=0.2, frequency=50.1, state='enabled', measurement_type='production', metering_status='normal', status_flags=[])",
|
||||
}),
|
||||
}),
|
||||
'ctmeter_storage': dict({
|
||||
'__type': "<class 'pyenphase.models.meters.EnvoyMeterData'>",
|
||||
'repr': "EnvoyMeterData(eid='100000030', timestamp=1708006120, energy_delivered=31234, energy_received=32345, active_power=103, power_factor=0.23, voltage=113, current=0.4, frequency=50.3, state='enabled', measurement_type='storage', metering_status='normal', status_flags=[])",
|
||||
}),
|
||||
'ctmeter_storage_phases': dict({
|
||||
'L1': dict({
|
||||
'__type': "<class 'pyenphase.models.meters.EnvoyMeterData'>",
|
||||
'repr': "EnvoyMeterData(eid='100000031', timestamp=1708006121, energy_delivered=312341, energy_received=323451, active_power=22, power_factor=0.32, voltage=113, current=0.4, frequency=50.3, state='enabled', measurement_type='storage', metering_status='normal', status_flags=[])",
|
||||
}),
|
||||
'L2': dict({
|
||||
'__type': "<class 'pyenphase.models.meters.EnvoyMeterData'>",
|
||||
'repr': "EnvoyMeterData(eid='100000032', timestamp=1708006122, energy_delivered=312342, energy_received=323452, active_power=33, power_factor=0.23, voltage=112, current=0.3, frequency=50.2, state='enabled', measurement_type='storage', metering_status='normal', status_flags=[])",
|
||||
}),
|
||||
'L3': dict({
|
||||
'__type': "<class 'pyenphase.models.meters.EnvoyMeterData'>",
|
||||
'repr': "EnvoyMeterData(eid='100000033', timestamp=1708006123, energy_delivered=312343, energy_received=323453, active_power=53, power_factor=0.24, voltage=112, current=0.3, frequency=50.2, state='enabled', measurement_type='storage', metering_status='normal', status_flags=[])",
|
||||
}),
|
||||
'collar': dict({
|
||||
'__type': "<class 'pyenphase.models.collar.EnvoyCollar'>",
|
||||
'repr': "EnvoyCollar(admin_state=88, admin_state_str='ENCMN_MDE_ON_GRID', firmware_loaded_date=1752939759, firmware_version='3.0.6-D0', installed_date=1752939759, last_report_date=1752939759, communicating=True, mid_state='close', grid_state='on_grid', part_number='865-00400-r22', serial_number='482520020939', temperature=42, temperature_unit='C', control_error=0, collar_state='Installed')",
|
||||
}),
|
||||
'ctmeters': dict({
|
||||
'backfeed': dict({
|
||||
|
||||
@@ -107,12 +107,12 @@ async def test_job_manager_ws_updates(
|
||||
job_data: Job | None = None
|
||||
|
||||
@callback
|
||||
def mock_subcription_callback(job: Job) -> None:
|
||||
def mock_subscription_callback(job: Job) -> None:
|
||||
nonlocal job_data
|
||||
job_data = job
|
||||
|
||||
subscription = JobSubscription(
|
||||
mock_subcription_callback, name="test_job", reference="test"
|
||||
mock_subscription_callback, name="test_job", reference="test"
|
||||
)
|
||||
unsubscribe = data_coordinator.jobs.subscribe(subscription)
|
||||
|
||||
@@ -318,11 +318,11 @@ async def test_job_manager_reload_on_supervisor_restart(
|
||||
job_data: Job | None = None
|
||||
|
||||
@callback
|
||||
def mock_subcription_callback(job: Job) -> None:
|
||||
def mock_subscription_callback(job: Job) -> None:
|
||||
nonlocal job_data
|
||||
job_data = job
|
||||
|
||||
subscription = JobSubscription(mock_subcription_callback, name="test_job")
|
||||
subscription = JobSubscription(mock_subscription_callback, name="test_job")
|
||||
data_coordinator.jobs.subscribe(subscription)
|
||||
|
||||
# Send supervisor restart signal
|
||||
@@ -347,3 +347,78 @@ async def test_job_manager_reload_on_supervisor_restart(
|
||||
assert job_data.reference == "test"
|
||||
assert job_data.done is True
|
||||
assert not data_coordinator.jobs.current_jobs
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("all_setup_requests")
|
||||
async def test_subscribe_returns_unsubscribe_when_job_already_matches(
|
||||
hass: HomeAssistant,
|
||||
jobs_info: AsyncMock,
|
||||
hass_supervisor_ws_client: WebSocketGenerator,
|
||||
) -> None:
|
||||
"""Test subscribe returns a working unsubscribe even if a job already matches."""
|
||||
jobs_info.return_value = JobsInfo(
|
||||
ignore_conditions=[],
|
||||
jobs=[
|
||||
Job(
|
||||
name="test_job",
|
||||
reference="test",
|
||||
uuid=uuid4(),
|
||||
progress=0,
|
||||
stage=None,
|
||||
done=False,
|
||||
errors=[],
|
||||
created=datetime.now(), # pylint: disable=home-assistant-enforce-naive-now
|
||||
extra=None,
|
||||
child_jobs=[],
|
||||
)
|
||||
],
|
||||
)
|
||||
|
||||
result = await async_setup_component(hass, DOMAIN, {})
|
||||
assert result
|
||||
|
||||
client = await hass_supervisor_ws_client()
|
||||
data_coordinator: HassioMainDataUpdateCoordinator = hass.data[MAIN_COORDINATOR]
|
||||
|
||||
received: list[Job] = []
|
||||
|
||||
@callback
|
||||
def mock_subscription_callback(job: Job) -> None:
|
||||
received.append(job)
|
||||
|
||||
subscription = JobSubscription(mock_subscription_callback, name="test_job")
|
||||
unsubscribe = data_coordinator.jobs.subscribe(subscription)
|
||||
|
||||
# Existing matching job is delivered immediately, and a callable unsubscribe
|
||||
# is returned (not the None result of the callback)
|
||||
assert len(received) == 1
|
||||
assert received[0].name == "test_job"
|
||||
assert callable(unsubscribe)
|
||||
|
||||
# After unsubscribing, a new matching job update is no longer delivered
|
||||
unsubscribe()
|
||||
await client.send_json(
|
||||
{
|
||||
"id": 1,
|
||||
"type": "supervisor/event",
|
||||
"data": {
|
||||
"event": "job",
|
||||
"data": {
|
||||
"name": "test_job",
|
||||
"reference": "test",
|
||||
"uuid": uuid4().hex,
|
||||
"progress": 50,
|
||||
"stage": None,
|
||||
"done": False,
|
||||
"errors": [],
|
||||
"created": datetime.now().isoformat(), # pylint: disable=home-assistant-enforce-naive-now
|
||||
"extra": None,
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
msg = await client.receive_json()
|
||||
assert msg["success"]
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert len(received) == 1
|
||||
|
||||
@@ -325,13 +325,13 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00:00:00:00:00:00_1_32896_32900',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
}),
|
||||
'state': dict({
|
||||
'attributes': dict({
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Airversa AP2 1808 Filter lifetime',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'entity_id': 'sensor.airversa_ap2_1808_filter_lifetime',
|
||||
'state': '100.0',
|
||||
@@ -373,14 +373,14 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00:00:00:00:00:00_1_2576_2580',
|
||||
'unit_of_measurement': <UnitOfDensity.MICROGRAMS_PER_CUBIC_METER: 'μg/m³'>,
|
||||
'unit_of_measurement': 'μg/m³',
|
||||
}),
|
||||
'state': dict({
|
||||
'attributes': dict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'pm25',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Airversa AP2 1808 PM2.5 Density',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfDensity.MICROGRAMS_PER_CUBIC_METER: 'μg/m³'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: 'μg/m³',
|
||||
}),
|
||||
'entity_id': 'sensor.airversa_ap2_1808_pm2_5_density',
|
||||
'state': '3.0',
|
||||
@@ -930,7 +930,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00:00:00:00:00:00_4_101',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
}),
|
||||
'state': dict({
|
||||
'attributes': dict({
|
||||
@@ -938,7 +938,7 @@
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'eufyCam2-0000 Battery',
|
||||
<EntityStateAttribute.ICON: 'icon'>: 'mdi:battery-20',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'entity_id': 'sensor.eufycam2_0000_battery',
|
||||
'state': '17',
|
||||
@@ -1192,7 +1192,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00:00:00:00:00:00_2_101',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
}),
|
||||
'state': dict({
|
||||
'attributes': dict({
|
||||
@@ -1200,7 +1200,7 @@
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'eufyCam2-000A Battery',
|
||||
<EntityStateAttribute.ICON: 'icon'>: 'mdi:battery-40',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'entity_id': 'sensor.eufycam2_000a_battery',
|
||||
'state': '38',
|
||||
@@ -1454,7 +1454,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00:00:00:00:00:00_3_101',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
}),
|
||||
'state': dict({
|
||||
'attributes': dict({
|
||||
@@ -1462,7 +1462,7 @@
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'eufyCam2-000A Battery',
|
||||
<EntityStateAttribute.ICON: 'icon'>: 'mdi:battery-alert',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'entity_id': 'sensor.eufycam2_000a_battery_2',
|
||||
'state': '100',
|
||||
@@ -1898,7 +1898,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00:00:00:00:00:00_33_5',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
}),
|
||||
'state': dict({
|
||||
'attributes': dict({
|
||||
@@ -1906,7 +1906,7 @@
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Contact Sensor Battery Sensor',
|
||||
<EntityStateAttribute.ICON: 'icon'>: 'mdi:battery',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'entity_id': 'sensor.contact_sensor_battery_sensor',
|
||||
'state': '100',
|
||||
@@ -2321,7 +2321,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00:00:00:00:00:00_1_5',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
}),
|
||||
'state': dict({
|
||||
'attributes': dict({
|
||||
@@ -2329,7 +2329,7 @@
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Programmable Switch Battery Sensor',
|
||||
<EntityStateAttribute.ICON: 'icon'>: 'mdi:battery',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'entity_id': 'sensor.programmable_switch_battery_sensor',
|
||||
'state': '100',
|
||||
@@ -2655,7 +2655,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00:00:00:00:00:00_1_700',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
}),
|
||||
'state': dict({
|
||||
'attributes': dict({
|
||||
@@ -2663,7 +2663,7 @@
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'ArloBabyA0 Battery',
|
||||
<EntityStateAttribute.ICON: 'icon'>: 'mdi:battery-80',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'entity_id': 'sensor.arlobabya0_battery',
|
||||
'state': '82',
|
||||
@@ -2705,14 +2705,14 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00:00:00:00:00:00_1_900',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
}),
|
||||
'state': dict({
|
||||
'attributes': dict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'humidity',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'ArloBabyA0 Humidity',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'entity_id': 'sensor.arlobabya0_humidity',
|
||||
'state': '60.099998',
|
||||
@@ -3950,14 +3950,14 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00:00:00:00:00:00_1_16_24',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
}),
|
||||
'state': dict({
|
||||
'attributes': dict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'humidity',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'HomeW Current Humidity',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'entity_id': 'sensor.homew_current_humidity',
|
||||
'state': '34',
|
||||
@@ -4573,7 +4573,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00:00:00:00:00:00_4295608960_192',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
}),
|
||||
'state': dict({
|
||||
'attributes': dict({
|
||||
@@ -4581,7 +4581,7 @@
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Basement Battery',
|
||||
<EntityStateAttribute.ICON: 'icon'>: 'mdi:battery',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'entity_id': 'sensor.basement_battery',
|
||||
'state': '100',
|
||||
@@ -4888,7 +4888,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00:00:00:00:00:00_4298360914_192',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
}),
|
||||
'state': dict({
|
||||
'attributes': dict({
|
||||
@@ -4896,7 +4896,7 @@
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Basement Window 1 Battery',
|
||||
<EntityStateAttribute.ICON: 'icon'>: 'mdi:battery',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'entity_id': 'sensor.basement_window_1_battery',
|
||||
'state': '100',
|
||||
@@ -5151,7 +5151,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00:00:00:00:00:00_4298360921_192',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
}),
|
||||
'state': dict({
|
||||
'attributes': dict({
|
||||
@@ -5159,7 +5159,7 @@
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Deck Door Battery',
|
||||
<EntityStateAttribute.ICON: 'icon'>: 'mdi:battery',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'entity_id': 'sensor.deck_door_battery',
|
||||
'state': '100',
|
||||
@@ -5414,7 +5414,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00:00:00:00:00:00_4298527970_192',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
}),
|
||||
'state': dict({
|
||||
'attributes': dict({
|
||||
@@ -5422,7 +5422,7 @@
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Front Door Battery',
|
||||
<EntityStateAttribute.ICON: 'icon'>: 'mdi:battery',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'entity_id': 'sensor.front_door_battery',
|
||||
'state': '100',
|
||||
@@ -5677,7 +5677,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00:00:00:00:00:00_4298527962_192',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
}),
|
||||
'state': dict({
|
||||
'attributes': dict({
|
||||
@@ -5685,7 +5685,7 @@
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Garage Door Battery',
|
||||
<EntityStateAttribute.ICON: 'icon'>: 'mdi:battery',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'entity_id': 'sensor.garage_door_battery',
|
||||
'state': '100',
|
||||
@@ -5895,7 +5895,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00:00:00:00:00:00_4295016858_192',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
}),
|
||||
'state': dict({
|
||||
'attributes': dict({
|
||||
@@ -5903,7 +5903,7 @@
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Living Room Battery',
|
||||
<EntityStateAttribute.ICON: 'icon'>: 'mdi:battery',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'entity_id': 'sensor.living_room_battery',
|
||||
'state': '100',
|
||||
@@ -6210,7 +6210,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00:00:00:00:00:00_4298360712_192',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
}),
|
||||
'state': dict({
|
||||
'attributes': dict({
|
||||
@@ -6218,7 +6218,7 @@
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Living Room Window 1 Battery',
|
||||
<EntityStateAttribute.ICON: 'icon'>: 'mdi:battery',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'entity_id': 'sensor.living_room_window_1_battery',
|
||||
'state': '100',
|
||||
@@ -6473,7 +6473,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00:00:00:00:00:00_4298649931_192',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
}),
|
||||
'state': dict({
|
||||
'attributes': dict({
|
||||
@@ -6481,7 +6481,7 @@
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Loft window Battery',
|
||||
<EntityStateAttribute.ICON: 'icon'>: 'mdi:battery',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'entity_id': 'sensor.loft_window_battery',
|
||||
'state': '100',
|
||||
@@ -6691,7 +6691,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00:00:00:00:00:00_4295608971_192',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
}),
|
||||
'state': dict({
|
||||
'attributes': dict({
|
||||
@@ -6699,7 +6699,7 @@
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Master BR Battery',
|
||||
<EntityStateAttribute.ICON: 'icon'>: 'mdi:battery',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'entity_id': 'sensor.master_br_battery',
|
||||
'state': '100',
|
||||
@@ -7006,7 +7006,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00:00:00:00:00:00_4298584118_192',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
}),
|
||||
'state': dict({
|
||||
'attributes': dict({
|
||||
@@ -7014,7 +7014,7 @@
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Master BR Window Battery',
|
||||
<EntityStateAttribute.ICON: 'icon'>: 'mdi:battery',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'entity_id': 'sensor.master_br_window_battery',
|
||||
'state': '100',
|
||||
@@ -7363,14 +7363,14 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00:00:00:00:00:00_1_16_24',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
}),
|
||||
'state': dict({
|
||||
'attributes': dict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'humidity',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Thermostat Current Humidity',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'entity_id': 'sensor.thermostat_current_humidity',
|
||||
'state': '45.0',
|
||||
@@ -7632,7 +7632,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00:00:00:00:00:00_4295016969_192',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
}),
|
||||
'state': dict({
|
||||
'attributes': dict({
|
||||
@@ -7640,7 +7640,7 @@
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Upstairs BR Battery',
|
||||
<EntityStateAttribute.ICON: 'icon'>: 'mdi:battery',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'entity_id': 'sensor.upstairs_br_battery',
|
||||
'state': '100',
|
||||
@@ -7947,7 +7947,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00:00:00:00:00:00_4298568508_192',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
}),
|
||||
'state': dict({
|
||||
'attributes': dict({
|
||||
@@ -7955,7 +7955,7 @@
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Upstairs BR Window Battery',
|
||||
<EntityStateAttribute.ICON: 'icon'>: 'mdi:battery',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'entity_id': 'sensor.upstairs_br_window_battery',
|
||||
'state': '100',
|
||||
@@ -8394,14 +8394,14 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00:00:00:00:00:00_1_16_24',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
}),
|
||||
'state': dict({
|
||||
'attributes': dict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'humidity',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'HomeW Current Humidity',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'entity_id': 'sensor.homew_current_humidity',
|
||||
'state': '34',
|
||||
@@ -8826,14 +8826,14 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00:00:00:00:00:00_1_16_24',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
}),
|
||||
'state': dict({
|
||||
'attributes': dict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'humidity',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'HomeW Current Humidity',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'entity_id': 'sensor.homew_current_humidity',
|
||||
'state': '34',
|
||||
@@ -9683,14 +9683,14 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00:00:00:00:00:00_1_16_24',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
}),
|
||||
'state': dict({
|
||||
'attributes': dict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'humidity',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'My ecobee Current Humidity',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'entity_id': 'sensor.my_ecobee_current_humidity',
|
||||
'state': '55.0',
|
||||
@@ -10341,7 +10341,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00:00:00:00:00:00_1_17',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
}),
|
||||
'state': dict({
|
||||
'attributes': dict({
|
||||
@@ -10349,7 +10349,7 @@
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Eve Degree AA11 Battery',
|
||||
<EntityStateAttribute.ICON: 'icon'>: 'mdi:battery-60',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'entity_id': 'sensor.eve_degree_aa11_battery',
|
||||
'state': '65',
|
||||
@@ -10391,14 +10391,14 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00:00:00:00:00:00_1_27',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
}),
|
||||
'state': dict({
|
||||
'attributes': dict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'humidity',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Eve Degree AA11 Humidity',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'entity_id': 'sensor.eve_degree_aa11_humidity',
|
||||
'state': '59.4818115234375',
|
||||
@@ -11350,7 +11350,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00:00:00:00:00:00_123016423_162',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
}),
|
||||
'state': dict({
|
||||
'attributes': dict({
|
||||
@@ -11358,7 +11358,7 @@
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Family Room North Battery',
|
||||
<EntityStateAttribute.ICON: 'icon'>: 'mdi:battery',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'entity_id': 'sensor.family_room_north_battery',
|
||||
'state': '100',
|
||||
@@ -11603,7 +11603,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00:00:00:00:00:00_878448248_9',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
}),
|
||||
'state': dict({
|
||||
'attributes': dict({
|
||||
@@ -11611,7 +11611,7 @@
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Kitchen Window Battery',
|
||||
<EntityStateAttribute.ICON: 'icon'>: 'mdi:battery',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'entity_id': 'sensor.kitchen_window_battery',
|
||||
'state': '100',
|
||||
@@ -12255,14 +12255,14 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00:00:00:00:00:00_1233851541_169_180',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
}),
|
||||
'state': dict({
|
||||
'attributes': dict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'humidity',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: '89 Living Room Current Humidity',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'entity_id': 'sensor.89_living_room_current_humidity',
|
||||
'state': '60',
|
||||
@@ -12648,7 +12648,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00:00:00:00:00:00_3982136094_604',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
}),
|
||||
'state': dict({
|
||||
'attributes': dict({
|
||||
@@ -12656,7 +12656,7 @@
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Laundry Smoke ED78 Battery',
|
||||
<EntityStateAttribute.ICON: 'icon'>: 'mdi:battery',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'entity_id': 'sensor.laundry_smoke_ed78_battery',
|
||||
'state': '100',
|
||||
@@ -12827,7 +12827,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00:00:00:00:00:00_123016423_162',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
}),
|
||||
'state': dict({
|
||||
'attributes': dict({
|
||||
@@ -12835,7 +12835,7 @@
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Family Room North Battery',
|
||||
<EntityStateAttribute.ICON: 'icon'>: 'mdi:battery',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'entity_id': 'sensor.family_room_north_battery',
|
||||
'state': '100',
|
||||
@@ -13080,7 +13080,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00:00:00:00:00:00_878448248_9',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
}),
|
||||
'state': dict({
|
||||
'attributes': dict({
|
||||
@@ -13088,7 +13088,7 @@
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Kitchen Window Battery',
|
||||
<EntityStateAttribute.ICON: 'icon'>: 'mdi:battery',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'entity_id': 'sensor.kitchen_window_battery',
|
||||
'state': '100',
|
||||
@@ -13957,14 +13957,14 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00:00:00:00:00:00_1233851541_169_180',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
}),
|
||||
'state': dict({
|
||||
'attributes': dict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'humidity',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: '89 Living Room Current Humidity',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'entity_id': 'sensor.89_living_room_current_humidity',
|
||||
'state': '60',
|
||||
@@ -14358,14 +14358,14 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00:00:00:00:00:00_293334836_8_9',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
}),
|
||||
'state': dict({
|
||||
'attributes': dict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'humidity',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Humidifier 182A Current Humidity',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'entity_id': 'sensor.humidifier_182a_current_humidity',
|
||||
'state': '0',
|
||||
@@ -14629,14 +14629,14 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00:00:00:00:00:00_293334836_8_9',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
}),
|
||||
'state': dict({
|
||||
'attributes': dict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'humidity',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Humidifier 182A Current Humidity',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'entity_id': 'sensor.humidifier_182a_current_humidity',
|
||||
'state': '0',
|
||||
@@ -14902,7 +14902,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00:00:00:00:00:00_3982136094_604',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
}),
|
||||
'state': dict({
|
||||
'attributes': dict({
|
||||
@@ -14910,7 +14910,7 @@
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Laundry Smoke ED78 Battery',
|
||||
<EntityStateAttribute.ICON: 'icon'>: 'mdi:battery',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'entity_id': 'sensor.laundry_smoke_ed78_battery',
|
||||
'state': '100',
|
||||
@@ -16320,7 +16320,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00:00:00:00:00:00_6623462389072572_644245094400',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
}),
|
||||
'state': dict({
|
||||
'attributes': dict({
|
||||
@@ -16328,7 +16328,7 @@
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Hue dimmer switch Battery',
|
||||
<EntityStateAttribute.ICON: 'icon'>: 'mdi:battery',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'entity_id': 'sensor.hue_dimmer_switch_battery',
|
||||
'state': '100',
|
||||
@@ -18122,14 +18122,14 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00:00:00:00:00:00_1_100_107',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
}),
|
||||
'state': dict({
|
||||
'attributes': dict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'humidity',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Lennox Current Humidity',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'entity_id': 'sensor.lennox_current_humidity',
|
||||
'state': '34',
|
||||
@@ -19321,14 +19321,14 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00:00:00:00:00:00_1_20_27',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
}),
|
||||
'state': dict({
|
||||
'attributes': dict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'humidity',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Mysa-85dda9 Current Humidity',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'entity_id': 'sensor.mysa_85dda9_current_humidity',
|
||||
'state': '40',
|
||||
@@ -20323,14 +20323,14 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00:00:00:00:00:00_1_10',
|
||||
'unit_of_measurement': <UnitOfRatio.PARTS_PER_MILLION: 'ppm'>,
|
||||
'unit_of_measurement': 'ppm',
|
||||
}),
|
||||
'state': dict({
|
||||
'attributes': dict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'carbon_dioxide',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Healthy Home Coach Carbon Dioxide sensor',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PARTS_PER_MILLION: 'ppm'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: 'ppm',
|
||||
}),
|
||||
'entity_id': 'sensor.healthy_home_coach_carbon_dioxide_sensor',
|
||||
'state': '804',
|
||||
@@ -20372,14 +20372,14 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00:00:00:00:00:00_1_14',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
}),
|
||||
'state': dict({
|
||||
'attributes': dict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'humidity',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Healthy Home Coach Humidity sensor',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'entity_id': 'sensor.healthy_home_coach_humidity_sensor',
|
||||
'state': '59',
|
||||
@@ -21112,7 +21112,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00:00:00:00:00:00_2_64',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
}),
|
||||
'state': dict({
|
||||
'attributes': dict({
|
||||
@@ -21120,7 +21120,7 @@
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Master Bath South RYSE Shade Battery',
|
||||
<EntityStateAttribute.ICON: 'icon'>: 'mdi:battery',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'entity_id': 'sensor.master_bath_south_ryse_shade_battery',
|
||||
'state': '100',
|
||||
@@ -21365,7 +21365,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00:00:00:00:00:00_3_64',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
}),
|
||||
'state': dict({
|
||||
'attributes': dict({
|
||||
@@ -21373,7 +21373,7 @@
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'RYSE SmartShade RYSE Shade Battery',
|
||||
<EntityStateAttribute.ICON: 'icon'>: 'mdi:battery',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'entity_id': 'sensor.ryse_smartshade_ryse_shade_battery',
|
||||
'state': '100',
|
||||
@@ -21544,7 +21544,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00:00:00:00:00:00_4_64',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
}),
|
||||
'state': dict({
|
||||
'attributes': dict({
|
||||
@@ -21552,7 +21552,7 @@
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'BR Left RYSE Shade Battery',
|
||||
<EntityStateAttribute.ICON: 'icon'>: 'mdi:battery',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'entity_id': 'sensor.br_left_ryse_shade_battery',
|
||||
'state': '100',
|
||||
@@ -21719,7 +21719,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00:00:00:00:00:00_2_64',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
}),
|
||||
'state': dict({
|
||||
'attributes': dict({
|
||||
@@ -21727,7 +21727,7 @@
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'LR Left RYSE Shade Battery',
|
||||
<EntityStateAttribute.ICON: 'icon'>: 'mdi:battery-90',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'entity_id': 'sensor.lr_left_ryse_shade_battery',
|
||||
'state': '89',
|
||||
@@ -21894,7 +21894,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00:00:00:00:00:00_3_64',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
}),
|
||||
'state': dict({
|
||||
'attributes': dict({
|
||||
@@ -21902,7 +21902,7 @@
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'LR Right RYSE Shade Battery',
|
||||
<EntityStateAttribute.ICON: 'icon'>: 'mdi:battery',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'entity_id': 'sensor.lr_right_ryse_shade_battery',
|
||||
'state': '100',
|
||||
@@ -22147,7 +22147,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00:00:00:00:00:00_5_64',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
}),
|
||||
'state': dict({
|
||||
'attributes': dict({
|
||||
@@ -22155,7 +22155,7 @@
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'RZSS RYSE Shade Battery',
|
||||
<EntityStateAttribute.ICON: 'icon'>: 'mdi:battery-alert',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'entity_id': 'sensor.rzss_ryse_shade_battery',
|
||||
'state': '0',
|
||||
@@ -23151,14 +23151,14 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00:00:00:00:00:00_1_14',
|
||||
'unit_of_measurement': <UnitOfRatio.PARTS_PER_MILLION: 'ppm'>,
|
||||
'unit_of_measurement': 'ppm',
|
||||
}),
|
||||
'state': dict({
|
||||
'attributes': dict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'carbon_dioxide',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'VELUX Sensor Carbon Dioxide sensor',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PARTS_PER_MILLION: 'ppm'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: 'ppm',
|
||||
}),
|
||||
'entity_id': 'sensor.velux_sensor_carbon_dioxide_sensor',
|
||||
'state': '1124.0',
|
||||
@@ -23200,14 +23200,14 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00:00:00:00:00:00_1_11',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
}),
|
||||
'state': dict({
|
||||
'attributes': dict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'humidity',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'VELUX Sensor Humidity sensor',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'entity_id': 'sensor.velux_sensor_humidity_sensor',
|
||||
'state': '69.0',
|
||||
@@ -23461,14 +23461,14 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00:00:00:00:00:00_2_14',
|
||||
'unit_of_measurement': <UnitOfRatio.PARTS_PER_MILLION: 'ppm'>,
|
||||
'unit_of_measurement': 'ppm',
|
||||
}),
|
||||
'state': dict({
|
||||
'attributes': dict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'carbon_dioxide',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'VELUX Sensor Carbon Dioxide sensor',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PARTS_PER_MILLION: 'ppm'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: 'ppm',
|
||||
}),
|
||||
'entity_id': 'sensor.velux_sensor_carbon_dioxide_sensor',
|
||||
'state': '400',
|
||||
@@ -23510,14 +23510,14 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00:00:00:00:00:00_2_11',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
}),
|
||||
'state': dict({
|
||||
'attributes': dict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'humidity',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'VELUX Sensor Humidity sensor',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'entity_id': 'sensor.velux_sensor_humidity_sensor',
|
||||
'state': '58',
|
||||
@@ -24267,14 +24267,14 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00:00:00:00:00:00_1_30_33',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
}),
|
||||
'state': dict({
|
||||
'attributes': dict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'humidity',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'VOCOlinc-Flowerbud-0d324b Current Humidity',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'entity_id': 'sensor.vocolinc_flowerbud_0d324b_current_humidity',
|
||||
'state': '45.0',
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
"""Tests for the LLM integration."""
|
||||
@@ -1,121 +0,0 @@
|
||||
"""Tests for the LLM integration."""
|
||||
|
||||
from unittest.mock import Mock
|
||||
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.llm import DATA_PLATFORMS, LLMTools, async_get_tools
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import llm
|
||||
from homeassistant.setup import async_setup_component
|
||||
from homeassistant.util.json import JsonObjectType
|
||||
|
||||
from tests.common import mock_platform
|
||||
|
||||
|
||||
class _StubTool(llm.Tool):
|
||||
"""Minimal tool for registry tests."""
|
||||
|
||||
def __init__(self, name: str) -> None:
|
||||
"""Initialize the stub tool."""
|
||||
self.name = name
|
||||
self.description = f"{name} description"
|
||||
|
||||
async def async_call(
|
||||
self,
|
||||
hass: HomeAssistant,
|
||||
tool_input: llm.ToolInput,
|
||||
llm_context: llm.LLMContext,
|
||||
) -> JsonObjectType:
|
||||
"""Return an empty result."""
|
||||
return {}
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def llm_context() -> llm.LLMContext:
|
||||
"""Return an LLM context."""
|
||||
return llm.LLMContext(
|
||||
platform="test",
|
||||
context=None,
|
||||
language="*",
|
||||
assistant="conversation",
|
||||
device_id=None,
|
||||
)
|
||||
|
||||
|
||||
def _mock_tools_platform(
|
||||
hass: HomeAssistant, domain: str, tools: LLMTools | Exception
|
||||
) -> None:
|
||||
"""Register a mock <integration>/llm.py platform returning the given tools."""
|
||||
if isinstance(tools, Exception):
|
||||
async_get_tools = Mock(side_effect=tools)
|
||||
else:
|
||||
async_get_tools = Mock(return_value=tools)
|
||||
hass.config.components.add(domain)
|
||||
mock_platform(hass, f"{domain}.llm", Mock(async_get_tools=async_get_tools))
|
||||
|
||||
|
||||
async def test_setup(hass: HomeAssistant) -> None:
|
||||
"""Test the integration sets up."""
|
||||
assert await async_setup_component(hass, "llm", {})
|
||||
assert DATA_PLATFORMS in hass.data
|
||||
|
||||
|
||||
async def test_get_tools(hass: HomeAssistant, llm_context: llm.LLMContext) -> None:
|
||||
"""Test that tools from an integration platform are returned."""
|
||||
tool = _StubTool("my_tool")
|
||||
_mock_tools_platform(
|
||||
hass, "test", LLMTools(tools=[tool], prompt="use my_tool wisely")
|
||||
)
|
||||
|
||||
assert await async_setup_component(hass, "llm", {})
|
||||
|
||||
result = await async_get_tools(hass, llm_context)
|
||||
assert result.tools == [tool]
|
||||
assert result.prompt == "use my_tool wisely"
|
||||
|
||||
|
||||
async def test_get_tools_empty(
|
||||
hass: HomeAssistant, llm_context: llm.LLMContext
|
||||
) -> None:
|
||||
"""Test that no platforms yields no tools."""
|
||||
assert await async_setup_component(hass, "llm", {})
|
||||
|
||||
result = await async_get_tools(hass, llm_context)
|
||||
assert result.tools == []
|
||||
assert result.prompt is None
|
||||
|
||||
|
||||
async def test_get_tools_merges_sorted(
|
||||
hass: HomeAssistant, llm_context: llm.LLMContext
|
||||
) -> None:
|
||||
"""Test that tools and prompts are merged in a load-order-independent order."""
|
||||
tool_a = _StubTool("tool_a")
|
||||
tool_b = _StubTool("tool_b")
|
||||
# Register "test_b" before "test_a" to prove the result is sorted by domain.
|
||||
_mock_tools_platform(hass, "test_b", LLMTools(tools=[tool_b], prompt="prompt b"))
|
||||
_mock_tools_platform(hass, "test_a", LLMTools(tools=[tool_a], prompt="prompt a"))
|
||||
|
||||
assert await async_setup_component(hass, "llm", {})
|
||||
|
||||
result = await async_get_tools(hass, llm_context)
|
||||
assert result.tools == [tool_a, tool_b]
|
||||
assert result.prompt == "prompt a\nprompt b"
|
||||
|
||||
|
||||
async def test_get_tools_isolates_failing_platform(
|
||||
hass: HomeAssistant,
|
||||
llm_context: llm.LLMContext,
|
||||
caplog: pytest.LogCaptureFixture,
|
||||
) -> None:
|
||||
"""Test that one failing platform does not drop the others' tools."""
|
||||
tool = _StubTool("good_tool")
|
||||
_mock_tools_platform(hass, "test_bad", ValueError("boom"))
|
||||
_mock_tools_platform(hass, "test_good", LLMTools(tools=[tool], prompt="prompt"))
|
||||
|
||||
assert await async_setup_component(hass, "llm", {})
|
||||
|
||||
result = await async_get_tools(hass, llm_context)
|
||||
assert result.tools == [tool]
|
||||
assert result.prompt == "prompt"
|
||||
assert "Error getting tools from LLM platform test_bad" in caplog.text
|
||||
@@ -1 +0,0 @@
|
||||
"""Tests for the logentries component."""
|
||||
@@ -1,75 +0,0 @@
|
||||
"""The tests for the Logentries component."""
|
||||
|
||||
from unittest.mock import ANY, call, patch
|
||||
|
||||
import pytest
|
||||
|
||||
from homeassistant.components import logentries
|
||||
from homeassistant.const import STATE_OFF, STATE_ON
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.setup import async_setup_component
|
||||
|
||||
|
||||
async def test_setup_config_full(hass: HomeAssistant) -> None:
|
||||
"""Test setup with all data."""
|
||||
config = {"logentries": {"token": "secret"}}
|
||||
assert await async_setup_component(hass, logentries.DOMAIN, config)
|
||||
|
||||
with patch("homeassistant.components.logentries.requests.post") as mock_post:
|
||||
hass.states.async_set("fake.entity", STATE_ON)
|
||||
await hass.async_block_till_done()
|
||||
assert len(mock_post.mock_calls) == 1
|
||||
|
||||
|
||||
async def test_setup_config_defaults(hass: HomeAssistant) -> None:
|
||||
"""Test setup with defaults."""
|
||||
config = {"logentries": {"token": "token"}}
|
||||
assert await async_setup_component(hass, logentries.DOMAIN, config)
|
||||
|
||||
with patch("homeassistant.components.logentries.requests.post") as mock_post:
|
||||
hass.states.async_set("fake.entity", STATE_ON)
|
||||
await hass.async_block_till_done()
|
||||
assert len(mock_post.mock_calls) == 1
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_dump():
|
||||
"""Mock json dumps."""
|
||||
with patch("json.dumps") as mock_dump:
|
||||
yield mock_dump
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_requests():
|
||||
"""Mock requests."""
|
||||
with patch.object(logentries, "requests") as mock_requests:
|
||||
yield mock_requests
|
||||
|
||||
|
||||
async def test_event_listener(hass: HomeAssistant, mock_dump, mock_requests) -> None:
|
||||
"""Test event listener."""
|
||||
mock_dump.side_effect = lambda x: x
|
||||
mock_post = mock_requests.post
|
||||
mock_requests.exceptions.RequestException = Exception
|
||||
config = {"logentries": {"token": "token"}}
|
||||
assert await async_setup_component(hass, logentries.DOMAIN, config)
|
||||
|
||||
valid = {"1": 1, "1.0": 1.0, STATE_ON: 1, STATE_OFF: 0, "foo": "foo"}
|
||||
for in_, out in valid.items():
|
||||
payload = {
|
||||
"host": "https://webhook.logentries.com/noformat/logs/token",
|
||||
"event": [
|
||||
{
|
||||
"domain": "fake",
|
||||
"entity_id": "entity",
|
||||
"attributes": {},
|
||||
"time": ANY,
|
||||
"value": out,
|
||||
}
|
||||
],
|
||||
}
|
||||
hass.states.async_set("fake.entity", in_)
|
||||
await hass.async_block_till_done()
|
||||
assert mock_post.call_count == 1
|
||||
assert mock_post.call_args == call(payload["host"], data=payload, timeout=10)
|
||||
mock_post.reset_mock()
|
||||
@@ -151,7 +151,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': 'be37ca9c47c24498a38bc62c7c711840-sensor2-air_humidity',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
})
|
||||
# ---
|
||||
# name: test_setup[sensor.test_sensor_2-state]
|
||||
@@ -160,7 +160,7 @@
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'humidity',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Test Sensor 2',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.test_sensor_2',
|
||||
|
||||
@@ -103,7 +103,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00000000000004D2-0000000000000001-MatterNodeDevice-1-CarbonDioxideSensor-1037-0',
|
||||
'unit_of_measurement': <UnitOfRatio.PARTS_PER_MILLION: 'ppm'>,
|
||||
'unit_of_measurement': 'ppm',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[air_quality_sensor][sensor.lightfi_aq1_air_quality_sensor_carbon_dioxide-state]
|
||||
@@ -112,7 +112,7 @@
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'carbon_dioxide',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'lightfi-aq1-air-quality-sensor Carbon dioxide',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PARTS_PER_MILLION: 'ppm'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: 'ppm',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.lightfi_aq1_air_quality_sensor_carbon_dioxide',
|
||||
@@ -158,7 +158,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00000000000004D2-0000000000000001-MatterNodeDevice-1-HumiditySensor-1029-0',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[air_quality_sensor][sensor.lightfi_aq1_air_quality_sensor_humidity-state]
|
||||
@@ -167,7 +167,7 @@
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'humidity',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'lightfi-aq1-air-quality-sensor Humidity',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.lightfi_aq1_air_quality_sensor_humidity',
|
||||
@@ -213,7 +213,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00000000000004D2-0000000000000001-MatterNodeDevice-1-NitrogenDioxideSensor-1043-0',
|
||||
'unit_of_measurement': <UnitOfRatio.PARTS_PER_MILLION: 'ppm'>,
|
||||
'unit_of_measurement': 'ppm',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[air_quality_sensor][sensor.lightfi_aq1_air_quality_sensor_nitrogen_dioxide-state]
|
||||
@@ -222,7 +222,7 @@
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'nitrogen_dioxide',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'lightfi-aq1-air-quality-sensor Nitrogen dioxide',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PARTS_PER_MILLION: 'ppm'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: 'ppm',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.lightfi_aq1_air_quality_sensor_nitrogen_dioxide',
|
||||
@@ -268,7 +268,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00000000000004D2-0000000000000001-MatterNodeDevice-1-PM1Sensor-1068-0',
|
||||
'unit_of_measurement': <UnitOfDensity.MICROGRAMS_PER_CUBIC_METER: 'μg/m³'>,
|
||||
'unit_of_measurement': 'μg/m³',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[air_quality_sensor][sensor.lightfi_aq1_air_quality_sensor_pm1-state]
|
||||
@@ -277,7 +277,7 @@
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'pm1',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'lightfi-aq1-air-quality-sensor PM1',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfDensity.MICROGRAMS_PER_CUBIC_METER: 'μg/m³'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: 'μg/m³',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.lightfi_aq1_air_quality_sensor_pm1',
|
||||
@@ -323,7 +323,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00000000000004D2-0000000000000001-MatterNodeDevice-1-PM10Sensor-1069-0',
|
||||
'unit_of_measurement': <UnitOfDensity.MICROGRAMS_PER_CUBIC_METER: 'μg/m³'>,
|
||||
'unit_of_measurement': 'μg/m³',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[air_quality_sensor][sensor.lightfi_aq1_air_quality_sensor_pm10-state]
|
||||
@@ -332,7 +332,7 @@
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'pm10',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'lightfi-aq1-air-quality-sensor PM10',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfDensity.MICROGRAMS_PER_CUBIC_METER: 'μg/m³'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: 'μg/m³',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.lightfi_aq1_air_quality_sensor_pm10',
|
||||
@@ -378,7 +378,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00000000000004D2-0000000000000001-MatterNodeDevice-1-PM25Sensor-1066-0',
|
||||
'unit_of_measurement': <UnitOfDensity.MICROGRAMS_PER_CUBIC_METER: 'μg/m³'>,
|
||||
'unit_of_measurement': 'μg/m³',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[air_quality_sensor][sensor.lightfi_aq1_air_quality_sensor_pm2_5-state]
|
||||
@@ -387,7 +387,7 @@
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'pm25',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'lightfi-aq1-air-quality-sensor PM2.5',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfDensity.MICROGRAMS_PER_CUBIC_METER: 'μg/m³'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: 'μg/m³',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.lightfi_aq1_air_quality_sensor_pm2_5',
|
||||
@@ -598,7 +598,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00000000000004D2-0000000000000001-MatterNodeDevice-1-TotalVolatileOrganicCompoundsSensor-1070-0',
|
||||
'unit_of_measurement': <UnitOfRatio.PARTS_PER_MILLION: 'ppm'>,
|
||||
'unit_of_measurement': 'ppm',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[air_quality_sensor][sensor.lightfi_aq1_air_quality_sensor_volatile_organic_compounds_parts-state]
|
||||
@@ -607,7 +607,7 @@
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'volatile_organic_compounds_parts',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'lightfi-aq1-air-quality-sensor Volatile organic compounds parts',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PARTS_PER_MILLION: 'ppm'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: 'ppm',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.lightfi_aq1_air_quality_sensor_volatile_organic_compounds_parts',
|
||||
@@ -653,7 +653,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00000000000004D2-000000000000005B-MatterNodeDevice-2-PowerSource-47-12',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[aqara_door_window_p2][sensor.aqara_door_and_window_sensor_p2_battery-state]
|
||||
@@ -662,7 +662,7 @@
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'battery',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Aqara Door and Window Sensor P2 Battery',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.aqara_door_and_window_sensor_p2_battery',
|
||||
@@ -993,7 +993,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00000000000004D2-0000000000000053-MatterNodeDevice-3-PowerSource-47-12',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[aqara_motion_p2][sensor.aqara_motion_and_light_sensor_p2_battery-state]
|
||||
@@ -1002,7 +1002,7 @@
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'battery',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Aqara Motion and Light Sensor P2 Battery',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.aqara_motion_and_light_sensor_p2_battery',
|
||||
@@ -1388,7 +1388,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00000000000004D2-000000000000016C-MatterNodeDevice-2-PowerSource-47-12',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[aqara_multi_state_p100][sensor.multi_state_sensor_p100_battery-state]
|
||||
@@ -1397,7 +1397,7 @@
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'battery',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Multi-State Sensor P100 Battery',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.multi_state_sensor_p100_battery',
|
||||
@@ -1900,7 +1900,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00000000000004D2-00000000000000CD-MatterNodeDevice-5-PowerSource-47-12',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[aqara_presence_fp300][sensor.presence_multi_sensor_fp300_1_battery-state]
|
||||
@@ -1909,7 +1909,7 @@
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'battery',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Presence Multi-Sensor FP300 1 Battery',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.presence_multi_sensor_fp300_1_battery',
|
||||
@@ -2136,7 +2136,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00000000000004D2-00000000000000CD-MatterNodeDevice-4-HumiditySensor-1029-0',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[aqara_presence_fp300][sensor.presence_multi_sensor_fp300_1_humidity-state]
|
||||
@@ -2145,7 +2145,7 @@
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'humidity',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Presence Multi-Sensor FP300 1 Humidity',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.presence_multi_sensor_fp300_1_humidity',
|
||||
@@ -2580,7 +2580,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00000000000004D2-000000000000004B-MatterNodeDevice-6-PowerSource-47-12',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[aqara_sensor_w100][sensor.climate_sensor_w100_battery-state]
|
||||
@@ -2589,7 +2589,7 @@
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'battery',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Climate Sensor W100 Battery',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.climate_sensor_w100_battery',
|
||||
@@ -2975,7 +2975,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00000000000004D2-000000000000004B-MatterNodeDevice-2-HumiditySensor-1029-0',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[aqara_sensor_w100][sensor.climate_sensor_w100_humidity-state]
|
||||
@@ -2984,7 +2984,7 @@
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'humidity',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Climate Sensor W100 Humidity',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.climate_sensor_w100_humidity',
|
||||
@@ -3556,7 +3556,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00000000000004D2-0000000000000064-MatterNodeDevice-2-HumiditySensor-1029-0',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[aqara_thermostat_w500][sensor.floor_heating_thermostat_humidity-state]
|
||||
@@ -3565,7 +3565,7 @@
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'humidity',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Floor Heating Thermostat Humidity',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.floor_heating_thermostat_humidity',
|
||||
@@ -3945,7 +3945,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00000000000004D2-0000000000000014-MatterNodeDevice-2-PowerSource-47-12',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[aqara_u200][sensor.aqara_smart_lock_u200_battery-state]
|
||||
@@ -3954,7 +3954,7 @@
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'battery',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Aqara Smart Lock U200 Battery',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.aqara_smart_lock_u200_battery',
|
||||
@@ -4633,14 +4633,14 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': 'pi_heating_demand',
|
||||
'unique_id': '00000000000004D2-0000000000000007-MatterNodeDevice-1-ThermostatPIHeatingDemand-513-8',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[eberle_ute3000][sensor.connected_thermostat_ute_3000_heating_demand-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Connected Thermostat UTE 3000 Heating demand',
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.connected_thermostat_ute_3000_heating_demand',
|
||||
@@ -4852,7 +4852,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00000000000004D2-000000000000002F-MatterNodeDevice-1-PowerSource-47-12',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[ecovacs_deebot][sensor.ecodeebot_battery-state]
|
||||
@@ -4861,7 +4861,7 @@
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'battery',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'ecodeebot Battery',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.ecodeebot_battery',
|
||||
@@ -5539,7 +5539,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00000000000004D2-0000000000000028-MatterNodeDevice-1-PowerSource-47-12',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[eufy_vacuum_omni_e28][sensor.2bavs_ab6031x_44pe_battery-state]
|
||||
@@ -5548,7 +5548,7 @@
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'battery',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: '2BAVS-AB6031X-44PE Battery',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.2bavs_ab6031x_44pe_battery',
|
||||
@@ -5994,7 +5994,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00000000000004D2-0000000000000009-MatterNodeDevice-1-PowerSource-47-12',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[eve_contact_sensor][sensor.eve_door_battery-state]
|
||||
@@ -6003,7 +6003,7 @@
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'battery',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Eve Door Battery',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.eve_door_battery',
|
||||
@@ -7973,14 +7973,14 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': 'window_covering_target_position',
|
||||
'unique_id': '00000000000004D2-0000000000000094-MatterNodeDevice-1-TargetPositionLiftPercent100ths-258-11',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[eve_shutter][sensor.eve_shutter_switch_20eci1701_target_opening_position-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Eve Shutter Switch 20ECI1701 Target opening position',
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.eve_shutter_switch_20eci1701_target_opening_position',
|
||||
@@ -8249,7 +8249,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00000000000004D2-0000000000000021-MatterNodeDevice-0-PowerSource-47-12',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[eve_thermo_v4][sensor.eve_thermo_20ebp1701_battery-state]
|
||||
@@ -8258,7 +8258,7 @@
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'battery',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Eve Thermo 20EBP1701 Battery',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.eve_thermo_20ebp1701_battery',
|
||||
@@ -8697,14 +8697,14 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': 'valve_position',
|
||||
'unique_id': '00000000000004D2-0000000000000021-MatterNodeDevice-1-EveThermoValvePosition-319486977-319422488',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[eve_thermo_v4][sensor.eve_thermo_20ebp1701_valve_position-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Eve Thermo 20EBP1701 Valve position',
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.eve_thermo_20ebp1701_valve_position',
|
||||
@@ -8750,7 +8750,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00000000000004D2-000000000000000C-MatterNodeDevice-0-PowerSource-47-12',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[eve_thermo_v5][sensor.eve_thermo_20ecd1701_battery-state]
|
||||
@@ -8759,7 +8759,7 @@
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'battery',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Eve Thermo 20ECD1701 Battery',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.eve_thermo_20ecd1701_battery',
|
||||
@@ -9137,14 +9137,14 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': 'valve_position',
|
||||
'unique_id': '00000000000004D2-000000000000000C-MatterNodeDevice-1-EveThermoValvePosition-319486977-319422488',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[eve_thermo_v5][sensor.eve_thermo_20ecd1701_valve_position-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Eve Thermo 20ECD1701 Valve position',
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.eve_thermo_20ecd1701_valve_position',
|
||||
@@ -9190,7 +9190,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00000000000004D2-000000000000001D-MatterNodeDevice-0-PowerSource-47-12',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[eve_weather_sensor][sensor.eve_weather_battery-state]
|
||||
@@ -9199,7 +9199,7 @@
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'battery',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Eve Weather Battery',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.eve_weather_battery',
|
||||
@@ -9306,7 +9306,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00000000000004D2-000000000000001D-MatterNodeDevice-2-HumiditySensor-1029-0',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[eve_weather_sensor][sensor.eve_weather_humidity-state]
|
||||
@@ -9315,7 +9315,7 @@
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'humidity',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Eve Weather Humidity',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.eve_weather_humidity',
|
||||
@@ -9991,7 +9991,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00000000000004D2-0000000000000003-MatterNodeDevice-0-PowerSource-47-12',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[haojai_switch][sensor.hjmt_6b_battery-state]
|
||||
@@ -10000,7 +10000,7 @@
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'battery',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'HJMT-6B Battery',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.hjmt_6b_battery',
|
||||
@@ -10771,7 +10771,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00000000000004D2-0000000000000006-MatterNodeDevice-1-PowerSource-47-12',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[heiman_co_sensor][sensor.smart_co_sensor_battery-state]
|
||||
@@ -10780,7 +10780,7 @@
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'battery',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Smart CO sensor Battery',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.smart_co_sensor_battery',
|
||||
@@ -10937,7 +10937,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00000000000004D2-0000000000000006-MatterNodeDevice-1-CarbonMonoxideSensor-1036-0',
|
||||
'unit_of_measurement': <UnitOfRatio.PARTS_PER_MILLION: 'ppm'>,
|
||||
'unit_of_measurement': 'ppm',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[heiman_co_sensor][sensor.smart_co_sensor_carbon_monoxide-state]
|
||||
@@ -10946,7 +10946,7 @@
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'carbon_monoxide',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Smart CO sensor Carbon monoxide',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PARTS_PER_MILLION: 'ppm'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: 'ppm',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.smart_co_sensor_carbon_monoxide',
|
||||
@@ -11329,7 +11329,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00000000000004D2-0000000000000058-MatterNodeDevice-1-PowerSource-47-12',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[heiman_motion_sensor_m1][sensor.smart_motion_sensor_battery-state]
|
||||
@@ -11338,7 +11338,7 @@
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'battery',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Smart motion sensor Battery',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.smart_motion_sensor_battery',
|
||||
@@ -11887,7 +11887,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00000000000004D2-000000000000000B-MatterNodeDevice-1-PowerSource-47-12',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[heiman_smoke_detector][sensor.smoke_sensor_battery-state]
|
||||
@@ -11896,7 +11896,7 @@
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'battery',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Smoke sensor Battery',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.smoke_sensor_battery',
|
||||
@@ -12365,7 +12365,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00000000000004D2-0000000000000025-MatterNodeDevice-1-CarbonDioxideSensor-1037-0',
|
||||
'unit_of_measurement': <UnitOfRatio.PARTS_PER_MILLION: 'ppm'>,
|
||||
'unit_of_measurement': 'ppm',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[ikea_air_quality_monitor][sensor.alpstuga_air_quality_monitor_carbon_dioxide-state]
|
||||
@@ -12374,7 +12374,7 @@
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'carbon_dioxide',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'ALPSTUGA air quality monitor Carbon dioxide',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PARTS_PER_MILLION: 'ppm'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: 'ppm',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.alpstuga_air_quality_monitor_carbon_dioxide',
|
||||
@@ -12420,7 +12420,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00000000000004D2-0000000000000025-MatterNodeDevice-1-HumiditySensor-1029-0',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[ikea_air_quality_monitor][sensor.alpstuga_air_quality_monitor_humidity-state]
|
||||
@@ -12429,7 +12429,7 @@
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'humidity',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'ALPSTUGA air quality monitor Humidity',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.alpstuga_air_quality_monitor_humidity',
|
||||
@@ -12475,7 +12475,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00000000000004D2-0000000000000025-MatterNodeDevice-1-PM25Sensor-1066-0',
|
||||
'unit_of_measurement': <UnitOfDensity.MICROGRAMS_PER_CUBIC_METER: 'μg/m³'>,
|
||||
'unit_of_measurement': 'μg/m³',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[ikea_air_quality_monitor][sensor.alpstuga_air_quality_monitor_pm2_5-state]
|
||||
@@ -12484,7 +12484,7 @@
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'pm25',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'ALPSTUGA air quality monitor PM2.5',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfDensity.MICROGRAMS_PER_CUBIC_METER: 'μg/m³'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: 'μg/m³',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.alpstuga_air_quality_monitor_pm2_5',
|
||||
@@ -12864,7 +12864,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00000000000004D2-0000000000000089-MatterNodeDevice-0-PowerSource-47-12',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[ikea_bilresa_dual_button][sensor.bilresa_dual_button_battery-state]
|
||||
@@ -12873,7 +12873,7 @@
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'battery',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'BILRESA dual button Battery',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.bilresa_dual_button_battery',
|
||||
@@ -13412,7 +13412,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00000000000004D2-0000000000000002-MatterNodeDevice-0-PowerSource-47-12',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[ikea_scroll_wheel][sensor.bilresa_scroll_wheel_battery-state]
|
||||
@@ -13421,7 +13421,7 @@
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'battery',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'BILRESA scroll wheel Battery',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.bilresa_scroll_wheel_battery',
|
||||
@@ -14682,7 +14682,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00000000000004D2-0000000000000100-MatterNodeDevice-8-HumiditySensor-1029-0',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[inovelli_vtm30][sensor.white_series_onoff_switch_humidity-state]
|
||||
@@ -14691,7 +14691,7 @@
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'humidity',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'White Series OnOff Switch Humidity',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.white_series_onoff_switch_humidity',
|
||||
@@ -16043,7 +16043,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': 'activated_carbon_filter_condition',
|
||||
'unique_id': '00000000000004D2-000000000000008F-MatterNodeDevice-1-ActivatedCarbonFilterCondition-114-0',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[mock_air_purifier][sensor.mock_air_purifier_activated_carbon_filter_condition-state]
|
||||
@@ -16051,7 +16051,7 @@
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Mock Air Purifier Activated carbon filter condition',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.mock_air_purifier_activated_carbon_filter_condition',
|
||||
@@ -16235,7 +16235,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00000000000004D2-000000000000008F-MatterNodeDevice-2-CarbonDioxideSensor-1037-0',
|
||||
'unit_of_measurement': <UnitOfRatio.PARTS_PER_MILLION: 'ppm'>,
|
||||
'unit_of_measurement': 'ppm',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[mock_air_purifier][sensor.mock_air_purifier_carbon_dioxide-state]
|
||||
@@ -16244,7 +16244,7 @@
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'carbon_dioxide',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Mock Air Purifier Carbon dioxide',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PARTS_PER_MILLION: 'ppm'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: 'ppm',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.mock_air_purifier_carbon_dioxide',
|
||||
@@ -16290,7 +16290,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00000000000004D2-000000000000008F-MatterNodeDevice-2-CarbonMonoxideSensor-1036-0',
|
||||
'unit_of_measurement': <UnitOfRatio.PARTS_PER_MILLION: 'ppm'>,
|
||||
'unit_of_measurement': 'ppm',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[mock_air_purifier][sensor.mock_air_purifier_carbon_monoxide-state]
|
||||
@@ -16299,7 +16299,7 @@
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'carbon_monoxide',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Mock Air Purifier Carbon monoxide',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PARTS_PER_MILLION: 'ppm'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: 'ppm',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.mock_air_purifier_carbon_monoxide',
|
||||
@@ -16345,7 +16345,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': 'hepa_filter_condition',
|
||||
'unique_id': '00000000000004D2-000000000000008F-MatterNodeDevice-1-HepaFilterCondition-113-0',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[mock_air_purifier][sensor.mock_air_purifier_hepa_filter_condition-state]
|
||||
@@ -16353,7 +16353,7 @@
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Mock Air Purifier HEPA filter condition',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.mock_air_purifier_hepa_filter_condition',
|
||||
@@ -16399,7 +16399,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00000000000004D2-000000000000008F-MatterNodeDevice-4-HumiditySensor-1029-0',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[mock_air_purifier][sensor.mock_air_purifier_humidity-state]
|
||||
@@ -16408,7 +16408,7 @@
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'humidity',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Mock Air Purifier Humidity',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.mock_air_purifier_humidity',
|
||||
@@ -16454,7 +16454,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00000000000004D2-000000000000008F-MatterNodeDevice-2-NitrogenDioxideSensor-1043-0',
|
||||
'unit_of_measurement': <UnitOfRatio.PARTS_PER_MILLION: 'ppm'>,
|
||||
'unit_of_measurement': 'ppm',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[mock_air_purifier][sensor.mock_air_purifier_nitrogen_dioxide-state]
|
||||
@@ -16463,7 +16463,7 @@
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'nitrogen_dioxide',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Mock Air Purifier Nitrogen dioxide',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PARTS_PER_MILLION: 'ppm'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: 'ppm',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.mock_air_purifier_nitrogen_dioxide',
|
||||
@@ -16509,7 +16509,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00000000000004D2-000000000000008F-MatterNodeDevice-2-OzoneConcentrationSensor-1045-0',
|
||||
'unit_of_measurement': <UnitOfRatio.PARTS_PER_MILLION: 'ppm'>,
|
||||
'unit_of_measurement': 'ppm',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[mock_air_purifier][sensor.mock_air_purifier_ozone-state]
|
||||
@@ -16518,7 +16518,7 @@
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'ozone',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Mock Air Purifier Ozone',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PARTS_PER_MILLION: 'ppm'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: 'ppm',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.mock_air_purifier_ozone',
|
||||
@@ -16564,7 +16564,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00000000000004D2-000000000000008F-MatterNodeDevice-2-PM1Sensor-1068-0',
|
||||
'unit_of_measurement': <UnitOfDensity.MICROGRAMS_PER_CUBIC_METER: 'μg/m³'>,
|
||||
'unit_of_measurement': 'μg/m³',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[mock_air_purifier][sensor.mock_air_purifier_pm1-state]
|
||||
@@ -16573,7 +16573,7 @@
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'pm1',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Mock Air Purifier PM1',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfDensity.MICROGRAMS_PER_CUBIC_METER: 'μg/m³'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: 'μg/m³',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.mock_air_purifier_pm1',
|
||||
@@ -16619,7 +16619,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00000000000004D2-000000000000008F-MatterNodeDevice-2-PM10Sensor-1069-0',
|
||||
'unit_of_measurement': <UnitOfDensity.MICROGRAMS_PER_CUBIC_METER: 'μg/m³'>,
|
||||
'unit_of_measurement': 'μg/m³',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[mock_air_purifier][sensor.mock_air_purifier_pm10-state]
|
||||
@@ -16628,7 +16628,7 @@
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'pm10',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Mock Air Purifier PM10',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfDensity.MICROGRAMS_PER_CUBIC_METER: 'μg/m³'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: 'μg/m³',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.mock_air_purifier_pm10',
|
||||
@@ -16674,7 +16674,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00000000000004D2-000000000000008F-MatterNodeDevice-2-PM25Sensor-1066-0',
|
||||
'unit_of_measurement': <UnitOfDensity.MICROGRAMS_PER_CUBIC_METER: 'μg/m³'>,
|
||||
'unit_of_measurement': 'μg/m³',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[mock_air_purifier][sensor.mock_air_purifier_pm2_5-state]
|
||||
@@ -16683,7 +16683,7 @@
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'pm25',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Mock Air Purifier PM2.5',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfDensity.MICROGRAMS_PER_CUBIC_METER: 'μg/m³'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: 'μg/m³',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.mock_air_purifier_pm2_5',
|
||||
@@ -17067,7 +17067,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00000000000004D2-000000000000008F-MatterNodeDevice-2-TotalVolatileOrganicCompoundsSensor-1070-0',
|
||||
'unit_of_measurement': <UnitOfRatio.PARTS_PER_MILLION: 'ppm'>,
|
||||
'unit_of_measurement': 'ppm',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[mock_air_purifier][sensor.mock_air_purifier_volatile_organic_compounds_parts-state]
|
||||
@@ -17076,7 +17076,7 @@
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'volatile_organic_compounds_parts',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Mock Air Purifier Volatile organic compounds parts',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PARTS_PER_MILLION: 'ppm'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: 'ppm',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.mock_air_purifier_volatile_organic_compounds_parts',
|
||||
@@ -17249,7 +17249,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00000000000004D2-0000000000000019-MatterNodeDevice-1-PowerSource-47-12',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[mock_battery_storage][sensor.mock_battery_storage_battery-state]
|
||||
@@ -17258,7 +17258,7 @@
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'battery',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Mock Battery Storage Battery',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.mock_battery_storage_battery',
|
||||
@@ -18815,7 +18815,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': 'activated_carbon_filter_condition',
|
||||
'unique_id': '00000000000004D2-0000000000000049-MatterNodeDevice-1-ActivatedCarbonFilterCondition-114-0',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[mock_extractor_hood][sensor.mock_extractor_hood_activated_carbon_filter_condition-state]
|
||||
@@ -18823,7 +18823,7 @@
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Mock Extractor hood Activated carbon filter condition',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.mock_extractor_hood_activated_carbon_filter_condition',
|
||||
@@ -18939,7 +18939,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': 'hepa_filter_condition',
|
||||
'unique_id': '00000000000004D2-0000000000000049-MatterNodeDevice-1-HepaFilterCondition-113-0',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[mock_extractor_hood][sensor.mock_extractor_hood_hepa_filter_condition-state]
|
||||
@@ -18947,7 +18947,7 @@
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Mock Extractor hood HEPA filter condition',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.mock_extractor_hood_hepa_filter_condition',
|
||||
@@ -19656,7 +19656,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00000000000004D2-0000000000000015-MatterNodeDevice-1-HumiditySensor-1029-0',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[mock_humidity_sensor][sensor.mock_humidity_sensor_humidity-state]
|
||||
@@ -19665,7 +19665,7 @@
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'humidity',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Mock Humidity Sensor Humidity',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.mock_humidity_sensor_humidity',
|
||||
@@ -22707,7 +22707,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00000000000004D2-0000000000000065-MatterNodeDevice-1-SoilMoistureSensor-1072-1',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[mock_soil_sensor][sensor.mock_soil_sensor_moisture-state]
|
||||
@@ -22716,7 +22716,7 @@
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'moisture',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Mock Soil Sensor Moisture',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.mock_soil_sensor_moisture',
|
||||
@@ -23410,14 +23410,14 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': 'pi_heating_demand',
|
||||
'unique_id': '00000000000004D2-0000000000000096-MatterNodeDevice-1-ThermostatPIHeatingDemand-513-8',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[mock_thermostat][sensor.mock_thermostat_heating_demand-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Mock Thermostat Heating demand',
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.mock_thermostat_heating_demand',
|
||||
@@ -24348,14 +24348,14 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': 'window_covering_target_position',
|
||||
'unique_id': '00000000000004D2-0000000000000032-MatterNodeDevice-1-TargetPositionLiftPercent100ths-258-11',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[mock_window_covering_full][sensor.mock_full_window_covering_target_opening_position-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Mock Full Window Covering Target opening position',
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.mock_full_window_covering_target_opening_position',
|
||||
@@ -24685,14 +24685,14 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': 'window_covering_target_position',
|
||||
'unique_id': '00000000000004D2-0000000000000027-MatterNodeDevice-1-TargetPositionLiftPercent100ths-258-11',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[mock_window_covering_pa_lift][sensor.longan_link_wncv_da01_target_opening_position-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Longan link WNCV DA01 Target opening position',
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.longan_link_wncv_da01_target_opening_position',
|
||||
@@ -25451,7 +25451,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00000000000004D2-00000000000000CA-MatterNodeDevice-1-PowerSource-47-12',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[roborock_saros_10][sensor.robotic_vacuum_cleaner_battery-state]
|
||||
@@ -25460,7 +25460,7 @@
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'battery',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Robotic Vacuum Cleaner Battery',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.robotic_vacuum_cleaner_battery',
|
||||
@@ -27905,7 +27905,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': 'evse_soc',
|
||||
'unique_id': '00000000000004D2-0000000000000017-MatterNodeDevice-1-EnergyEvseStateOfCharge-153-48',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[silabs_evse_charging][sensor.evse_state_of_charge-state]
|
||||
@@ -27914,7 +27914,7 @@
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'battery',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'evse State of charge',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.evse_state_of_charge',
|
||||
@@ -30846,7 +30846,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': 'tank_percentage',
|
||||
'unique_id': '00000000000004D2-0000000000000039-MatterNodeDevice-2-WaterHeaterManagementTankPercentage-148-4',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[silabs_water_heater][sensor.water_heater_hot_water_level-state]
|
||||
@@ -30854,7 +30854,7 @@
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Water Heater Hot water level',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.water_heater_hot_water_level',
|
||||
@@ -31775,7 +31775,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00000000000004D2-0000000000000031-MatterNodeDevice-1-HumiditySensor-1029-0',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[tado_smart_radiator_thermostat_x][sensor.smart_radiator_thermostat_x_humidity-state]
|
||||
@@ -31784,7 +31784,7 @@
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'humidity',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Smart Radiator Thermostat X Humidity',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.smart_radiator_thermostat_x_humidity',
|
||||
@@ -32395,7 +32395,7 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00000000000004D2-000000000000007A-MatterNodeDevice-1-PowerSource-47-12',
|
||||
'unit_of_measurement': <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
'unit_of_measurement': '%',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[zemismart_mt25b][sensor.zemismart_mt25b_roller_motor_battery-state]
|
||||
@@ -32404,7 +32404,7 @@
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'battery',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Zemismart MT25B Roller Motor Battery',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfRatio.PERCENTAGE: '%'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '%',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.zemismart_mt25b_roller_motor_battery',
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'sensor',
|
||||
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
|
||||
'entity_category': None,
|
||||
'entity_id': 'sensor.mealie_categories',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
@@ -68,7 +68,7 @@
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'sensor',
|
||||
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
|
||||
'entity_category': None,
|
||||
'entity_id': 'sensor.mealie_recipes',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
@@ -122,7 +122,7 @@
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'sensor',
|
||||
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
|
||||
'entity_category': None,
|
||||
'entity_id': 'sensor.mealie_tags',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
@@ -176,7 +176,7 @@
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'sensor',
|
||||
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
|
||||
'entity_category': None,
|
||||
'entity_id': 'sensor.mealie_tools',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
@@ -230,7 +230,7 @@
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'sensor',
|
||||
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
|
||||
'entity_category': None,
|
||||
'entity_id': 'sensor.mealie_users',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
|
||||
@@ -80,29 +80,6 @@ async def test_missing_sensor_graceful_handling(
|
||||
assert state.state == "Charging"
|
||||
|
||||
|
||||
async def test_websocket_callback_updates_entities(
|
||||
hass: HomeAssistant,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
mock_charger: MagicMock,
|
||||
) -> None:
|
||||
"""Test the websocket callback pushes updates to entity state."""
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("sensor.openevse_mock_config_charging_status")
|
||||
assert state
|
||||
assert state.state == "Charging"
|
||||
|
||||
mock_charger.status = "Sleeping"
|
||||
await mock_charger.callback()
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("sensor.openevse_mock_config_charging_status")
|
||||
assert state
|
||||
assert state.state == "Sleeping"
|
||||
|
||||
|
||||
async def test_sensor_unavailable_on_coordinator_timeout(
|
||||
hass: HomeAssistant,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user