Conversation
There was a problem hiding this comment.
Pull request overview
Adds a new Home Assistant Core integration for Threema Gateway, enabling secure outbound messaging via a dedicated threema.send_message service and providing a QR-code image entity for gateway identity verification.
Changes:
- Introduces the
threemaintegration (config flow, runtime client, service registration, and image platform). - Adds translations, service metadata, icons, and quality scale declaration for the integration.
- Adds full test suite coverage and registers new dependencies + strict typing configuration.
Reviewed changes
Copilot reviewed 21 out of 23 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
homeassistant/components/threema/__init__.py |
Integration setup/unload and send_message service handler |
homeassistant/components/threema/client.py |
Threema Gateway SDK wrapper client + key generation |
homeassistant/components/threema/config_flow.py |
Multi-step config flow including key generation + reauth |
homeassistant/components/threema/const.py |
Integration constants |
homeassistant/components/threema/image.py |
QR code ImageEntity implementation |
homeassistant/components/threema/icons.json |
Service icon metadata |
homeassistant/components/threema/manifest.json |
Integration manifest + requirements |
homeassistant/components/threema/quality_scale.yaml |
Declared quality scale status |
homeassistant/components/threema/services.yaml |
Service schema/selector metadata |
homeassistant/components/threema/strings.json |
Config flow/service/exception translations |
homeassistant/components/threema/README.md |
Developer-focused integration documentation |
tests/components/threema/__init__.py |
Test package marker |
tests/components/threema/conftest.py |
Shared fixtures and mocks for Threema tests |
tests/components/threema/test_config_flow.py |
Config flow + reauth tests |
tests/components/threema/test_image.py |
QR image entity tests |
tests/components/threema/test_init.py |
Setup/unload + service behavior tests |
requirements_all.txt |
Adds runtime dependencies for the integration |
requirements_test_all.txt |
Adds test environment dependencies |
mypy.ini |
Enables strict mypy checks for homeassistant.components.threema.* |
.strict-typing |
Marks integration as strict-typing |
homeassistant/generated/config_flows.py |
Registers config flow domain |
homeassistant/generated/integrations.json |
Adds generated integration metadata |
CODEOWNERS |
Adds code ownership entries for the new integration and tests |
You can also share your feedback on Copilot code review. Take the survey.
Add new integration for Threema Gateway messaging service. Supports E2E encrypted and simple text messaging, key pair generation, QR code identity verification, and reauthentication. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
good catch. Co-authored-by: Norbert Rittel <norbert@rittel.de>
Co-authored-by: Norbert Rittel <norbert@rittel.de>
There was a problem hiding this comment.
Pull request overview
Adds a new Home Assistant Core integration for the Threema Gateway, enabling automations to send Threema messages (simple transport or E2E) and exposing a QR-code image entity for gateway identity verification.
Changes:
- Implement Threema integration core: config flow (including key generation + reauth), runtime client wrapper, and
threema.send_messageservice. - Add image platform entity that renders the gateway public key as a PNG QR code.
- Add full test suite plus dependency pins, strict typing config, and generated metadata updates.
Reviewed changes
Copilot reviewed 21 out of 23 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| homeassistant/components/threema/init.py | Registers service, sets up config entries, forwards to image platform |
| homeassistant/components/threema/client.py | Wraps threema.gateway SDK for validation and message sending + key generation |
| homeassistant/components/threema/config_flow.py | Multi-step config flow (existing/new gateway), validation, and reauth |
| homeassistant/components/threema/const.py | Domain and config key constants |
| homeassistant/components/threema/image.py | ImageEntity that generates/stores QR code PNG bytes |
| homeassistant/components/threema/manifest.json | Declares integration metadata, requirements, logging, quality scale |
| homeassistant/components/threema/ गुणवत्ता_scale.yaml | Quality scale status declarations for the new integration |
| homeassistant/components/threema/services.yaml | Service selectors/field requirements for send_message |
| homeassistant/components/threema/strings.json | Config flow/service/entity/exception translations |
| homeassistant/components/threema/icons.json | Service icon mapping |
| homeassistant/components/threema/README.md | Developer-facing integration architecture/decisions notes |
| tests/components/threema/init.py | Test package marker for the integration |
| tests/components/threema/conftest.py | Shared fixtures for config entries and SDK patching |
| tests/components/threema/test_config_flow.py | Config flow test coverage (new/existing/reauth/error paths) |
| tests/components/threema/test_init.py | Setup/unload + service behavior tests |
| tests/components/threema/test_image.py | QR image entity creation/availability tests |
| requirements_all.txt | Adds runtime dependency pins for Threema + QR generation |
| requirements_test_all.txt | Adds test dependency pins for Threema + QR generation |
| mypy.ini | Enables strict mypy settings for homeassistant.components.threema.* |
| .strict-typing | Adds the integration to strict typing enforcement list |
| homeassistant/generated/integrations.json | Registers the new integration in generated metadata |
| homeassistant/generated/config_flows.py | Registers config flow domain in generated list |
| CODEOWNERS | Adds code ownership for integration + tests |
You can also share your feedback on Copilot code review. Take the survey.
joostlek
left a comment
There was a problem hiding this comment.
Hello 👋🏻,
So I would love to know a few things:
- I know Threema as a chat app, what is the gateway qr code supposed to do?
- Please make sure you either include a platform or services, not both. But preferrably a platform as that shows how state is handled in the integration
- The current service has a recipient and a message, I would strongly consider to look at a notify entity. A benefit of using the notify entity is that you can group them and for example send a message to both telegram and threema with a group of notify entities, or send it to alexa if you want to. You would likely have to look into subentries for this one, given that we need to know the recipients before we can create the entity.
- What's the idea behind the client.py? Ideally we have all device specific logic in a library hosted on pypi, and not in the integration
|
Please take a look at the requested changes, and use the Ready for review button when you are done, thanks 👍 |
QR Code displays the gateway's public key in Threema's 3mid: verification format. Users scan it with the Threema app to verify the gateway's identity — the three green dots confirming authenticity. Same verification mechanism as Threema's contact verification.
Platform vs Service / Notify Entity: I originally used a service because I'm planning to extend this with image/file support. Now that you mentioned it, I could also go the Telegram way and use 'data'
The SDK (threema.gateway) handles all API communication — HTTP requests, encryption, key management, and the Threema protocol. client.py is essentially glue code: it maps SDK exceptions to HA-specific exception types and manages the connection context. Happy to extract it into a separate PyPI package if you feel that's necessary, but the actual device/service logic lives in the SDK already. |
I believe data is for the old notify service, which is different In any case, I think we should limit the initial scope, and I think a notify entity would make sense right of the bat, I would like to have more opinions on the image entity, so I think we can get it in a mergable state faster with notify entities and leave the other discussions for a later PR. (as in, I need to double check we like the qe code dependency in its current form as its not in a library) |
There was a problem hiding this comment.
Pull request overview
Adds a new Home Assistant Threema Gateway integration (service-based) to enable sending Threema messages from automations, including an optional QR-code image entity for gateway identity verification.
Changes:
- Introduces the
threemaintegration with config flow (including key generation + reauth) and athreema.send_messageservice. - Adds an image platform entity that generates a QR code from the gateway public key.
- Adds dependencies, typing config, generated integration metadata, and comprehensive tests.
Reviewed changes
Copilot reviewed 21 out of 23 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
homeassistant/components/threema/__init__.py |
Registers send_message service; sets up/unloads config entries and forwards to image platform. |
homeassistant/components/threema/client.py |
Implements ThreemaAPIClient wrapper and keypair generation helper. |
homeassistant/components/threema/config_flow.py |
Implements multi-step config flow (existing/new setup, credential validation, reauth). |
homeassistant/components/threema/const.py |
Defines integration constants and config keys. |
homeassistant/components/threema/image.py |
Adds QR-code ImageEntity for gateway identity verification. |
homeassistant/components/threema/manifest.json |
Declares integration metadata and requirements. |
homeassistant/components/threema/quality_scale.yaml |
Declares quality-scale compliance status for the new integration. |
homeassistant/components/threema/services.yaml |
Defines UI selectors/fields for threema.send_message. |
homeassistant/components/threema/strings.json |
Adds translations for config flow, service fields, and raised exceptions. |
homeassistant/components/threema/icons.json |
Adds service icon mapping. |
homeassistant/components/threema/README.md |
Adds developer-facing integration documentation/architecture notes. |
tests/components/threema/__init__.py |
Adds test package marker for the integration tests. |
tests/components/threema/conftest.py |
Provides fixtures for config entries, connection mocks, and message mocks. |
tests/components/threema/test_config_flow.py |
Tests config flow paths (existing/new, validation errors, reauth). |
tests/components/threema/test_image.py |
Tests QR-code image entity creation and availability. |
tests/components/threema/test_init.py |
Tests setup/unload and send_message service behavior & errors. |
requirements_all.txt |
Adds runtime requirements (qrcode, threema.gateway). |
requirements_test_all.txt |
Adds test requirements (qrcode, threema.gateway). |
.strict-typing |
Enables strict typing for the new integration module. |
mypy.ini |
Adds a strict mypy section for homeassistant.components.threema.*. |
homeassistant/generated/integrations.json |
Registers generated integration metadata entry for threema. |
homeassistant/generated/config_flows.py |
Registers threema in the generated config flow list. |
CODEOWNERS |
Assigns code ownership for the new integration and its tests. |
You can also share your feedback on Copilot code review. Take the survey.
Already working on it.
It's already used by e.g. the PSN Integration afaik and I recommend strongly to include a QR code (whatever lib to use ;) ) to implement full verification in the first shot. Ideas? |
|
Well we still want to limit to a single platform in the initial PR, so you'd have to pick anyhow :) |
There was a problem hiding this comment.
Pull request overview
Adds a new Home Assistant Core integration for the Threema Gateway, enabling sending messages (including optional E2E mode) and exposing a QR-code image entity for gateway identity verification. This fits into HA’s integrations ecosystem as a config-entry based “service” integration with notify + image platforms and full config flow support.
Changes:
- Introduce the new
threemaintegration (config flow, client wrapper, notify entity per recipient subentry, QR-code image entity). - Add comprehensive test coverage for config flow, setup/unload, notify behavior, and QR image entity.
- Register new dependencies and integration metadata (manifest, generated integration/config flow registries, strict typing/mypy configuration, CODEOWNERS).
Reviewed changes
Copilot reviewed 21 out of 23 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
homeassistant/components/threema/__init__.py |
Config entry setup/unload; runtime client creation; forwards to image/notify platforms. |
homeassistant/components/threema/client.py |
Threema Gateway SDK wrapper: credential validation, sending messages, keypair generation, error mapping. |
homeassistant/components/threema/config_flow.py |
User config flow (existing/new w/ keygen), reauth handling, and recipient subentry flow. |
homeassistant/components/threema/const.py |
Integration constants (domain, config keys, subentry type). |
homeassistant/components/threema/image.py |
QR-code ImageEntity for gateway public key verification. |
homeassistant/components/threema/notify.py |
NotifyEntity per recipient subentry; sends messages via runtime client. |
homeassistant/components/threema/manifest.json |
Integration metadata and pinned requirements. |
homeassistant/components/threema/strings.json |
Config flow, subentry flow, entity, and exception translations. |
homeassistant/components/threema/icons.json |
Icon translation file (empty mapping). |
homeassistant/components/threema/quality_scale.yaml |
Declares quality scale status (silver) and exemptions/todos. |
homeassistant/components/threema/README.md |
Developer-focused integration notes/architecture and roadmap. |
tests/components/threema/__init__.py |
Test package marker for the integration. |
tests/components/threema/conftest.py |
Shared fixtures for config entries and SDK mocking. |
tests/components/threema/test_config_flow.py |
Tests for config flow, reauth, and recipient subentry flow. |
tests/components/threema/test_init.py |
Tests for integration setup, retry behavior, auth failures, and unload. |
tests/components/threema/test_image.py |
Tests for QR-code image entity creation/availability. |
tests/components/threema/test_notify.py |
Tests for notify entity creation and send behavior (simple/E2E and error paths). |
requirements_all.txt |
Adds integration runtime dependencies. |
requirements_test_all.txt |
Adds dependencies to the test requirements set. |
homeassistant/generated/integrations.json |
Registers the new integration for HA’s generated metadata. |
homeassistant/generated/config_flows.py |
Adds threema to generated config flow registry. |
mypy.ini |
Enables strict mypy settings for homeassistant.components.threema.*. |
.strict-typing |
Adds homeassistant.components.threema.* to strict typing set. |
CODEOWNERS |
Assigns ownership for integration and its tests. |
You can also share your feedback on Copilot code review. Take the survey.
The security expert in me cries, but moved to: feature/threema-qr |
There was a problem hiding this comment.
Pull request overview
Adds a new Home Assistant Core integration for sending Threema Gateway messages, implemented as a config-entry driven service integration with per-recipient notify entities backed by Threema Gateway SDK calls.
Changes:
- Introduces the
threemaintegration (config flow, client wrapper, notify platform, translations, and quality scale metadata). - Adds comprehensive tests for config flow, setup/unload, and notify send/error handling.
- Registers the new dependency and enables strict typing/mypy coverage for the integration.
Reviewed changes
Copilot reviewed 19 out of 21 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| homeassistant/components/threema/init.py | Config entry setup/unload, runtime client creation, platform forwarding, update listener. |
| homeassistant/components/threema/client.py | Threema Gateway SDK wrapper for credential validation and sending messages (E2E vs simple). |
| homeassistant/components/threema/config_flow.py | Config flow for gateway credentials + optional key generation; subentry flow for recipients. |
| homeassistant/components/threema/const.py | Integration constants (domain + config keys + subentry type). |
| homeassistant/components/threema/manifest.json | Integration manifest (domain, docs link, requirements, quality scale, codeowners). |
| homeassistant/components/threema/notify.py | NotifyEntity implementation for sending messages to configured recipients. |
| homeassistant/components/threema/quality_scale.yaml | Quality scale declaration for the new integration. |
| homeassistant/components/threema/strings.json | UI strings for config flow, subentries, and exception translations. |
| homeassistant/components/threema/README.md | Developer-focused architecture/roadmap documentation for the integration. |
| homeassistant/generated/integrations.json | Registers the threema integration metadata (generated file). |
| homeassistant/generated/config_flows.py | Adds threema to the generated config flows registry. |
| requirements_all.txt | Adds threema.gateway==8.0.0 to core requirements aggregation. |
| requirements_test_all.txt | Adds threema.gateway==8.0.0 to test requirements aggregation. |
| mypy.ini | Enables strict mypy settings for homeassistant.components.threema.*. |
| .strict-typing | Marks homeassistant.components.threema.* as strict-typing. |
| CODEOWNERS | Adds code ownership entries for the new integration and its tests. |
| tests/components/threema/init.py | Test package marker for the integration’s tests. |
| tests/components/threema/conftest.py | Shared fixtures for Threema integration tests (mock config entries, SDK patches). |
| tests/components/threema/test_config_flow.py | Tests user flow, key generation path, reauth, and recipient subentry flow. |
| tests/components/threema/test_init.py | Tests config entry setup/unload and setup error states. |
| tests/components/threema/test_notify.py | Tests notify entity creation from subentries and send/error paths. |
You can also share your feedback on Copilot code review. Take the survey.
|
So, all refactored to one platform only and improved with |
There was a problem hiding this comment.
Pull request overview
Adds a new Home Assistant Core integration for sending messages via Threema Gateway. The integration is implemented as a config-entry based service integration with a notify platform and recipient management via config subentries.
Changes:
- Introduce the
threemaintegration (config flow + runtime client + notify platform). - Add recipient subentry flow and notify entity per recipient.
- Add tests and register new dependency (
threema.gateway==8.0.0) plus generated/ownership metadata updates.
Reviewed changes
Copilot reviewed 19 out of 21 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| homeassistant/components/threema/init.py | Sets up/unloads the config entry, creates and validates the API client, reloads on updates. |
| homeassistant/components/threema/client.py | Wraps the Threema Gateway SDK; maps SDK errors into integration-specific exceptions. |
| homeassistant/components/threema/config_flow.py | Implements initial setup + key generation + reauth + recipient subentry flow. |
| homeassistant/components/threema/notify.py | Provides NotifyEntity per recipient subentry to send messages. |
| homeassistant/components/threema/const.py | Integration constants (domain, config keys, subentry type). |
| homeassistant/components/threema/manifest.json | Declares integration metadata and runtime requirement. |
| homeassistant/components/threema/strings.json | Config flow, subentry flow, and exception translations. |
| homeassistant/components/threema/quality_scale.yaml | Declares quality scale status and exemptions. |
| homeassistant/components/threema/README.md | Developer-facing architecture/design notes and roadmap. |
| tests/components/threema/* | Test coverage for config flow, setup/unload, and notify behavior. |
| requirements_all.txt | Adds the threema.gateway dependency to the full requirements set. |
| requirements_test_all.txt | Adds the threema.gateway dependency for tests that import SDK exceptions. |
| mypy.ini | Enables strict mypy settings for the new integration module. |
| .strict-typing | Adds the integration to strict typing enforcement. |
| homeassistant/generated/integrations.json | Registers the new integration in generated metadata. |
| homeassistant/generated/config_flows.py | Registers the integration as having a config flow. |
| CODEOWNERS | Assigns code ownership for integration and tests. |
| self._gateway_id = gateway_id | ||
| self._api_secret = user_input[CONF_API_SECRET] | ||
|
|
||
| if user_input.get(CONF_PRIVATE_KEY): | ||
| self._private_key = user_input[CONF_PRIVATE_KEY] | ||
| if user_input.get(CONF_PUBLIC_KEY): | ||
| self._public_key = user_input[CONF_PUBLIC_KEY] |
There was a problem hiding this comment.
gateway_id is normalized via strip().upper(), but api_secret (and the optional key inputs) are persisted without trimming. Leading/trailing whitespace from copy/paste is a common cause of hard-to-debug auth failures; it would help to strip() these values (and normalize empty strings to None where appropriate) before validation and storing them in the entry.
| schema = vol.Schema( | ||
| { | ||
| vol.Required(CONF_GATEWAY_ID): str, | ||
| vol.Required(CONF_API_SECRET): str, | ||
| vol.Optional(CONF_PRIVATE_KEY, default=self._private_key or ""): str, | ||
| vol.Optional(CONF_PUBLIC_KEY, default=self._public_key or ""): str, | ||
| } |
There was a problem hiding this comment.
The config flow currently defines api_secret / private_key fields as plain str in the vol.Schema, which means the UI will render them as normal text inputs (exposing secrets on screen and not benefiting from password-manager/autocomplete behavior). Consider switching these fields to TextSelector(TextSelectorConfig(type=PASSWORD, autocomplete=...)) (as done in other cloud/service integrations) for the credentials and reauth steps (and optionally the key-generation step).
| try: | ||
| async with self._get_connection() as conn: | ||
| if self.private_key: | ||
| _LOGGER.debug("Sending E2E encrypted message to %s", recipient_id) | ||
| message = TextMessage( | ||
| connection=conn, | ||
| to_id=recipient_id, | ||
| text=text, | ||
| ) | ||
| else: | ||
| _LOGGER.debug("Sending simple message to %s", recipient_id) | ||
| message = SimpleTextMessage( | ||
| connection=conn, | ||
| to_id=recipient_id, | ||
| text=text, | ||
| ) | ||
|
|
||
| message_id: str = await message.send() | ||
| _LOGGER.debug("Message sent to %s (ID: %s)", recipient_id, message_id) | ||
| return message_id | ||
| except GatewayServerError as err: |
There was a problem hiding this comment.
Ideally we only have things in the try block that can raise, so i am wondering if we can keep things out like the message object creation
| except Exception as err: | ||
| raise ThreemaSendError( | ||
| f"Failed to send message to {recipient_id}: {err}" | ||
| ) from err |
There was a problem hiding this comment.
Ideally we don't catch raw exceptions outside of the config flow
| """Handle a config flow for Threema Gateway.""" | ||
|
|
||
| VERSION = 1 | ||
| MINOR_VERSION = 2 |
There was a problem hiding this comment.
we start at version 1 and minor version 1
| async def async_step_reauth( | ||
| self, entry_data: Mapping[str, Any] | ||
| ) -> ConfigFlowResult: | ||
| """Handle reauth if credentials become invalid.""" | ||
| return await self.async_step_reauth_confirm() | ||
|
|
||
| async def async_step_reauth_confirm( | ||
| self, user_input: dict[str, Any] | None = None | ||
| ) -> ConfigFlowResult: | ||
| """Handle reauth confirmation.""" | ||
| errors: dict[str, str] = {} | ||
|
|
||
| if user_input is not None: |
There was a problem hiding this comment.
Can we keep reauth out of this PR to make it more manageable?
| async def async_step_user( | ||
| self, user_input: dict[str, Any] | None = None | ||
| ) -> ConfigFlowResult: | ||
| """Handle the initial step - choose setup type.""" | ||
| if user_input is not None: | ||
| if user_input.get("setup_type") == "new": | ||
| return await self.async_step_setup_new() | ||
| return await self.async_step_credentials() | ||
|
|
||
| return self.async_show_form( | ||
| step_id="user", | ||
| data_schema=vol.Schema( | ||
| { | ||
| vol.Required("setup_type", default="existing"): vol.In( | ||
| ["existing", "new"] | ||
| ), | ||
| } | ||
| ), | ||
| ) |
There was a problem hiding this comment.
Why does one pick or why pick existing?
| gateway_id = entry.data[CONF_GATEWAY_ID] | ||
|
|
||
| self._attr_unique_id = f"{gateway_id}_{subentry_id}" | ||
| self._attr_name = subentry.title |
There was a problem hiding this comment.
we need to have _attr_has_entity_name = True instead, maybe check on how telegram does this
| text = f"*{title}*\n{message}" if title else message | ||
| client = self._entry.runtime_data |
There was a problem hiding this comment.
I am wondering if this title is a real title or just one that we pretend is a title. As in, I don't think this is a title title, but more a title in a message
| _LOGGER.warning( | ||
| "Authentication failed sending message; check your Gateway credentials" | ||
| ) | ||
| raise HomeAssistantError( | ||
| translation_domain=DOMAIN, | ||
| translation_key="send_error", | ||
| translation_placeholders={"error": str(err)}, | ||
| ) from err |
There was a problem hiding this comment.
We shouldn't have a readme on integration level
Proposed change
My first core PR 🥳
Reopened as a clean PR after the previous one (#165787) was closed due to force-push noise affecting other contributors. Apologies for the disruption.
Privacy matters. Threema is one of the few messengers that doesn't require a phone number, is fully end-to-end encrypted by default, and is open source. With over 12 million users — especially popular in the DACH region — it's a natural fit for Home Assistant
This integration brings Threema Gateway support to HA Core, enabling users to send secure text messages from their automations. It supports both E2E encrypted and simple transport modes, key pair generation during setup, and a QR code entity for identity verification — staying true to Threema's security-first philosophy.
What's included:
threema.send_message service (E2E encrypted or simple mode)notify entityQR code image entity for gateway identity verificationfuture releaseWhat's not included (intentionally)
Additional developer related info is added to the readme.md, including a small roadmap.
Type of change
Additional information
Checklist
ruff format homeassistant tests)If user exposed functionality or configuration variables are added/changed:
If the code communicates with devices, web services, or third-party tools:
Updated and included derived files by running:
python3 -m script.hassfest.requirements_all.txt.Updated by running
python3 -m script.gen_requirements_all.To help with the load of incoming pull requests: