-
-
Notifications
You must be signed in to change notification settings - Fork 36k
add teltonika integration #157539
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
add teltonika integration #157539
Conversation
add basic integration with sensor device class
This includes only the licensing under Apache 2.0
2988a2a to
31e29e5
Compare
mentions license properly in the pyproject.toml
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR adds a new integration for Teltonika routers and modems with sensor support for monitoring modem status (signal strength, temperature, operator, connection type).
Key Changes
- Implements config flow with user setup, reauth, and DHCP discovery
- Creates coordinator-based data updates with 30-second polling interval
- Adds 7 sensor types: RSSI, RSRP, RSRQ, SINR, temperature, operator, and connection type
- Includes comprehensive test coverage and diagnostics support
Reviewed changes
Copilot reviewed 24 out of 27 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
homeassistant/components/teltonika/__init__.py |
Entry point with async setup, device registration, and protocol fallback handling |
homeassistant/components/teltonika/config_flow.py |
Config flow with user, reauth, and DHCP discovery flows |
homeassistant/components/teltonika/coordinator.py |
Data update coordinator for fetching modem status |
homeassistant/components/teltonika/sensor.py |
Sensor platform with 7 sensor types for modem monitoring |
homeassistant/components/teltonika/diagnostics.py |
Diagnostics support with data serialization |
homeassistant/components/teltonika/util.py |
Helper functions for URL construction |
homeassistant/components/teltonika/const.py |
Domain and constant definitions |
homeassistant/components/teltonika/strings.json |
User-facing translations for config flow and entities |
homeassistant/components/teltonika/manifest.json |
Integration metadata with DHCP discovery configuration |
homeassistant/components/teltonika/quality_scale.yaml |
Quality scale rule tracking |
tests/components/teltonika/ |
Comprehensive test suite with config flow, init, sensor, diagnostics, and utility tests |
requirements_all.txt, requirements_test_all.txt |
Added teltasync==0.1.3 dependency |
CODEOWNERS |
Added @karlbeecken as code owner |
| Generated files | Updated integration registry, DHCP matchers, and config flows list |
| try: | ||
| await candidate_client.get_device_info() | ||
| system_info_response = await candidate_client.get_system_info() | ||
| except TeltonikaConnectionError as err: | ||
| last_error = err | ||
| await candidate_client.close() | ||
| except TeltonikaAuthenticationError as err: | ||
| await candidate_client.close() | ||
| raise ConfigEntryAuthFailed(f"Authentication failed: {err}") from err | ||
| except ContentTypeError as err: | ||
| # Device returned HTML instead of JSON - likely auth failure | ||
| await candidate_client.close() | ||
| if err.status == 403: | ||
| raise ConfigEntryAuthFailed( | ||
| f"Access denied - check credentials: {err}" | ||
| ) from err | ||
| last_error = err | ||
| except ClientResponseError as err: | ||
| await candidate_client.close() | ||
| if err.status in (401, 403): | ||
| raise ConfigEntryAuthFailed( | ||
| f"Authentication failed (HTTP {err.status}): {err.message}" | ||
| ) from err | ||
| last_error = err | ||
| except Exception as err: # pylint: disable=broad-except | ||
| await candidate_client.close() | ||
| # Check if error message indicates authentication issues | ||
| error_str = str(err).lower() | ||
| if any( | ||
| keyword in error_str | ||
| for keyword in ("auth", "unauthorized", "forbidden", "credentials") | ||
| ): | ||
| raise ConfigEntryAuthFailed(f"Authentication failed: {err}") from err | ||
| last_error = err | ||
| else: | ||
| return candidate_client, candidate, system_info_response |
Copilot
AI
Nov 29, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] The _try_connect function processes data outside the try/except blocks but doesn't follow the recommended pattern. After catching exceptions, the code should not continue to process the response. Line 102 returns system_info_response from inside the else block, which is correct. However, the try block should only contain the code that can throw exceptions (lines 68-69) for clarity and best practices.
|
|
||
| # Return only modems which are online | ||
| modem_data = {} | ||
| if modems_response.data: | ||
| for modem in modems_response.data: | ||
| if Modems.is_online(modem): | ||
| modem_data[modem.id] = modem | ||
|
|
||
| except TeltonikaConnectionError as err: | ||
| raise UpdateFailed(f"Error communicating with device: {err}") from err | ||
| except Exception as err: | ||
| raise UpdateFailed(f"Unexpected error: {err}") from err | ||
| else: | ||
| return modem_data |
Copilot
AI
Nov 29, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The try/except/else pattern here violates the recommended error handling approach. Lines 48-52 should be outside the try block because they process data and don't throw exceptions. Only lines 44-45 should be in the try block. The else clause should be removed and the return statement should be outside the try/except block.
Better pattern:
try:
modems = Modems(self.client.auth)
modems_response = await modems.get_status()
except TeltonikaConnectionError as err:
raise UpdateFailed(f"Error communicating with device: {err}") from err
except Exception as err:
raise UpdateFailed(f"Unexpected error: {err}") from err
# Process data outside try block
modem_data = {}
if modems_response.data:
for modem in modems_response.data:
if Modems.is_online(modem):
modem_data[modem.id] = modem
return modem_data| # Return only modems which are online | |
| modem_data = {} | |
| if modems_response.data: | |
| for modem in modems_response.data: | |
| if Modems.is_online(modem): | |
| modem_data[modem.id] = modem | |
| except TeltonikaConnectionError as err: | |
| raise UpdateFailed(f"Error communicating with device: {err}") from err | |
| except Exception as err: | |
| raise UpdateFailed(f"Unexpected error: {err}") from err | |
| else: | |
| return modem_data | |
| except TeltonikaConnectionError as err: | |
| raise UpdateFailed(f"Error communicating with device: {err}") from err | |
| except Exception as err: | |
| raise UpdateFailed(f"Unexpected error: {err}") from err | |
| # Return only modems which are online | |
| modem_data = {} | |
| if modems_response.data: | |
| for modem in modems_response.data: | |
| if Modems.is_online(modem): | |
| modem_data[modem.id] = modem | |
| return modem_data |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 24 out of 27 changed files in this pull request and generated 5 comments.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 24 out of 27 changed files in this pull request and generated no new comments.
This PR is to add a basic integration (containing only the sensor device class) for Teltonika routers and modems.
Breaking change
Proposed change
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: