More details about SMS modem (#75694)

This commit is contained in:
Paul Annekov 2022-09-26 04:49:55 +03:00 committed by GitHub
parent 92612c9fe3
commit 1b17c83095
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 115 additions and 88 deletions

View file

@ -1,9 +1,4 @@
"""Constants for sms Component.""" """Constants for sms Component."""
from typing import Final
from homeassistant.components.sensor import SensorDeviceClass, SensorEntityDescription
from homeassistant.const import PERCENTAGE, SIGNAL_STRENGTH_DECIBELS
from homeassistant.helpers.entity import EntityCategory
DOMAIN = "sms" DOMAIN = "sms"
SMS_GATEWAY = "SMS_GATEWAY" SMS_GATEWAY = "SMS_GATEWAY"
@ -38,61 +33,3 @@ DEFAULT_BAUD_SPEEDS = [
{"value": "76800", "label": "76800"}, {"value": "76800", "label": "76800"},
{"value": "115200", "label": "115200"}, {"value": "115200", "label": "115200"},
] ]
SIGNAL_SENSORS: Final[dict[str, SensorEntityDescription]] = {
"SignalStrength": SensorEntityDescription(
key="SignalStrength",
name="Signal Strength",
device_class=SensorDeviceClass.SIGNAL_STRENGTH,
entity_category=EntityCategory.DIAGNOSTIC,
native_unit_of_measurement=SIGNAL_STRENGTH_DECIBELS,
entity_registry_enabled_default=False,
),
"SignalPercent": SensorEntityDescription(
key="SignalPercent",
icon="mdi:signal-cellular-3",
name="Signal Percent",
native_unit_of_measurement=PERCENTAGE,
entity_registry_enabled_default=True,
),
"BitErrorRate": SensorEntityDescription(
key="BitErrorRate",
name="Bit Error Rate",
entity_category=EntityCategory.DIAGNOSTIC,
native_unit_of_measurement=PERCENTAGE,
entity_registry_enabled_default=False,
),
}
NETWORK_SENSORS: Final[dict[str, SensorEntityDescription]] = {
"NetworkName": SensorEntityDescription(
key="NetworkName",
name="Network Name",
entity_category=EntityCategory.DIAGNOSTIC,
entity_registry_enabled_default=False,
),
"State": SensorEntityDescription(
key="State",
name="Network Status",
entity_registry_enabled_default=True,
),
"NetworkCode": SensorEntityDescription(
key="NetworkCode",
name="GSM network code",
entity_category=EntityCategory.DIAGNOSTIC,
entity_registry_enabled_default=False,
),
"CID": SensorEntityDescription(
key="CID",
name="Cell ID",
icon="mdi:radio-tower",
entity_category=EntityCategory.DIAGNOSTIC,
entity_registry_enabled_default=False,
),
"LAC": SensorEntityDescription(
key="LAC",
name="Local Area Code",
entity_category=EntityCategory.DIAGNOSTIC,
entity_registry_enabled_default=False,
),
}

View file

@ -21,10 +21,16 @@ class Gateway:
self._worker.configure(config) self._worker.configure(config)
self._hass = hass self._hass = hass
self._first_pull = True self._first_pull = True
self.manufacturer = None
self.model = None
self.firmware = None
async def init_async(self): async def init_async(self):
"""Initialize the sms gateway asynchronously.""" """Initialize the sms gateway asynchronously. This method is also called in config flow to verify connection."""
await self._worker.init_async() await self._worker.init_async()
self.manufacturer = await self.get_manufacturer_async()
self.model = await self.get_model_async()
self.firmware = await self.get_firmware_async()
def sms_pull(self, state_machine): def sms_pull(self, state_machine):
"""Pull device. """Pull device.
@ -156,7 +162,37 @@ class Gateway:
async def get_network_info_async(self): async def get_network_info_async(self):
"""Get the current network info of the modem.""" """Get the current network info of the modem."""
return await self._worker.get_network_info_async() network_info = await self._worker.get_network_info_async()
# Looks like there is a bug and it's empty for any modem https://github.com/gammu/python-gammu/issues/31, so try workaround
if not network_info["NetworkName"]:
network_info["NetworkName"] = gammu.GSMNetworks.get(
network_info["NetworkCode"]
)
return network_info
async def get_manufacturer_async(self):
"""Get the manufacturer of the modem."""
return await self._worker.get_manufacturer_async()
async def get_model_async(self):
"""Get the model of the modem."""
model = await self._worker.get_model_async()
if not model or not model[0]:
return
display = model[0] # Identification model
if model[1]: # Real model
display = f"{display} ({model[1]})"
return display
async def get_firmware_async(self):
"""Get the firmware information of the modem."""
firmware = await self._worker.get_firmware_async()
if not firmware or not firmware[0]:
return
display = firmware[0] # Version
if firmware[1]: # Date
display = f"{display} ({firmware[1]})"
return display
async def terminate_async(self): async def terminate_async(self):
"""Terminate modem connection.""" """Terminate modem connection."""

View file

@ -1,19 +1,78 @@
"""Support for SMS dongle sensor.""" """Support for SMS dongle sensor."""
from homeassistant.components.sensor import SensorEntity from homeassistant.components.sensor import (
SensorDeviceClass,
SensorEntity,
SensorEntityDescription,
SensorStateClass,
)
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.const import PERCENTAGE, SIGNAL_STRENGTH_DECIBELS
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity import DeviceInfo from homeassistant.helpers.entity import DeviceInfo, EntityCategory
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.update_coordinator import CoordinatorEntity from homeassistant.helpers.update_coordinator import CoordinatorEntity
from .const import ( from .const import DOMAIN, GATEWAY, NETWORK_COORDINATOR, SIGNAL_COORDINATOR, SMS_GATEWAY
DOMAIN,
GATEWAY, SIGNAL_SENSORS = (
NETWORK_COORDINATOR, SensorEntityDescription(
NETWORK_SENSORS, key="SignalStrength",
SIGNAL_COORDINATOR, name="Signal Strength",
SIGNAL_SENSORS, device_class=SensorDeviceClass.SIGNAL_STRENGTH,
SMS_GATEWAY, entity_category=EntityCategory.DIAGNOSTIC,
native_unit_of_measurement=SIGNAL_STRENGTH_DECIBELS,
entity_registry_enabled_default=False,
state_class=SensorStateClass.MEASUREMENT,
),
SensorEntityDescription(
key="SignalPercent",
icon="mdi:signal-cellular-3",
name="Signal Percent",
native_unit_of_measurement=PERCENTAGE,
entity_registry_enabled_default=True,
state_class=SensorStateClass.MEASUREMENT,
),
SensorEntityDescription(
key="BitErrorRate",
name="Bit Error Rate",
entity_category=EntityCategory.DIAGNOSTIC,
native_unit_of_measurement=PERCENTAGE,
entity_registry_enabled_default=False,
state_class=SensorStateClass.MEASUREMENT,
),
)
NETWORK_SENSORS = (
SensorEntityDescription(
key="NetworkName",
name="Network Name",
entity_category=EntityCategory.DIAGNOSTIC,
entity_registry_enabled_default=False,
),
SensorEntityDescription(
key="State",
name="Network Status",
entity_registry_enabled_default=True,
),
SensorEntityDescription(
key="NetworkCode",
name="GSM network code",
entity_category=EntityCategory.DIAGNOSTIC,
entity_registry_enabled_default=False,
),
SensorEntityDescription(
key="CID",
name="Cell ID",
icon="mdi:radio-tower",
entity_category=EntityCategory.DIAGNOSTIC,
entity_registry_enabled_default=False,
),
SensorEntityDescription(
key="LAC",
name="Local Area Code",
entity_category=EntityCategory.DIAGNOSTIC,
entity_registry_enabled_default=False,
),
) )
@ -29,21 +88,13 @@ async def async_setup_entry(
gateway = sms_data[GATEWAY] gateway = sms_data[GATEWAY]
unique_id = str(await gateway.get_imei_async()) unique_id = str(await gateway.get_imei_async())
entities = [] entities = []
for description in SIGNAL_SENSORS.values(): for description in SIGNAL_SENSORS:
entities.append( entities.append(
DeviceSensor( DeviceSensor(signal_coordinator, description, unique_id, gateway)
signal_coordinator,
description,
unique_id,
)
) )
for description in NETWORK_SENSORS.values(): for description in NETWORK_SENSORS:
entities.append( entities.append(
DeviceSensor( DeviceSensor(network_coordinator, description, unique_id, gateway)
network_coordinator,
description,
unique_id,
)
) )
async_add_entities(entities, True) async_add_entities(entities, True)
@ -51,12 +102,15 @@ async def async_setup_entry(
class DeviceSensor(CoordinatorEntity, SensorEntity): class DeviceSensor(CoordinatorEntity, SensorEntity):
"""Implementation of a device sensor.""" """Implementation of a device sensor."""
def __init__(self, coordinator, description, unique_id): def __init__(self, coordinator, description, unique_id, gateway):
"""Initialize the device sensor.""" """Initialize the device sensor."""
super().__init__(coordinator) super().__init__(coordinator)
self._attr_device_info = DeviceInfo( self._attr_device_info = DeviceInfo(
identifiers={(DOMAIN, unique_id)}, identifiers={(DOMAIN, unique_id)},
name="SMS Gateway", name="SMS Gateway",
manufacturer=gateway.manufacturer,
model=gateway.model,
sw_version=gateway.firmware,
) )
self._attr_unique_id = f"{unique_id}_{description.key}" self._attr_unique_id = f"{unique_id}_{description.key}"
self.entity_description = description self.entity_description = description