1 """AVM FRITZ!Box binary sensors."""
3 from __future__
import annotations
5 from collections.abc
import Callable
6 from dataclasses
import dataclass
7 from datetime
import datetime, timedelta
10 from fritzconnection.lib.fritzstatus
import FritzStatus
15 SensorEntityDescription,
20 SIGNAL_STRENGTH_DECIBELS,
30 from .const
import DOMAIN, DSL_CONNECTION, UPTIME_DEVIATION
31 from .coordinator
import AvmWrapper, ConnectionInfo
32 from .entity
import FritzBoxBaseCoordinatorEntity, FritzEntityDescription
34 _LOGGER = logging.getLogger(__name__)
38 """Calculate uptime with deviation."""
43 or abs((delta_uptime - last_value).total_seconds()) > UPTIME_DEVIATION
51 status: FritzStatus, last_value: datetime
53 """Return uptime from device."""
58 status: FritzStatus, last_value: datetime |
None
60 """Return uptime from connection."""
65 """Return external ip from device."""
66 return status.external_ip
70 """Return external ipv6 from device."""
71 return str(status.external_ipv6)
75 """Return upload transmission rate."""
76 return round(status.transmission_rate[0] / 1000, 1)
80 """Return download transmission rate."""
81 return round(status.transmission_rate[1] / 1000, 1)
85 """Return upload max transmission rate."""
86 return round(status.max_bit_rate[0] / 1000, 1)
90 """Return download max transmission rate."""
91 return round(status.max_bit_rate[1] / 1000, 1)
95 """Return upload total data."""
96 return round(status.bytes_sent / 1000 / 1000 / 1000, 1)
100 """Return download total data."""
101 return round(status.bytes_received / 1000 / 1000 / 1000, 1)
105 """Return upload link rate."""
106 return round(status.max_linked_bit_rate[0] / 1000, 1)
110 """Return download link rate."""
111 return round(status.max_linked_bit_rate[1] / 1000, 1)
115 status: FritzStatus, last_value: str
117 """Return upload noise margin."""
118 return status.noise_margin[0] / 10
122 status: FritzStatus, last_value: str
124 """Return download noise margin."""
125 return status.noise_margin[1] / 10
129 status: FritzStatus, last_value: str
131 """Return upload line attenuation."""
132 return status.attenuation[0] / 10
136 status: FritzStatus, last_value: str
138 """Return download line attenuation."""
139 return status.attenuation[1] / 10
142 @dataclass(frozen=True, kw_only=True)
144 """Describes Fritz sensor entity."""
146 is_suitable: Callable[[ConnectionInfo], bool] =
lambda info: info.wan_enabled
149 SENSOR_TYPES: tuple[FritzSensorEntityDescription, ...] = (
152 translation_key=
"external_ip",
153 value_fn=_retrieve_external_ip_state,
157 translation_key=
"external_ipv6",
158 value_fn=_retrieve_external_ipv6_state,
159 is_suitable=
lambda info: info.ipv6_active,
163 translation_key=
"device_uptime",
164 device_class=SensorDeviceClass.TIMESTAMP,
165 entity_category=EntityCategory.DIAGNOSTIC,
166 value_fn=_retrieve_device_uptime_state,
167 is_suitable=
lambda info:
True,
170 key=
"connection_uptime",
171 translation_key=
"connection_uptime",
172 device_class=SensorDeviceClass.TIMESTAMP,
173 entity_category=EntityCategory.DIAGNOSTIC,
174 value_fn=_retrieve_connection_uptime_state,
178 translation_key=
"kb_s_sent",
179 state_class=SensorStateClass.MEASUREMENT,
180 native_unit_of_measurement=UnitOfDataRate.KILOBYTES_PER_SECOND,
181 device_class=SensorDeviceClass.DATA_RATE,
182 value_fn=_retrieve_kb_s_sent_state,
186 translation_key=
"kb_s_received",
187 state_class=SensorStateClass.MEASUREMENT,
188 native_unit_of_measurement=UnitOfDataRate.KILOBYTES_PER_SECOND,
189 device_class=SensorDeviceClass.DATA_RATE,
190 value_fn=_retrieve_kb_s_received_state,
194 translation_key=
"max_kb_s_sent",
195 native_unit_of_measurement=UnitOfDataRate.KILOBITS_PER_SECOND,
196 device_class=SensorDeviceClass.DATA_RATE,
197 entity_category=EntityCategory.DIAGNOSTIC,
198 value_fn=_retrieve_max_kb_s_sent_state,
201 key=
"max_kb_s_received",
202 translation_key=
"max_kb_s_received",
203 native_unit_of_measurement=UnitOfDataRate.KILOBITS_PER_SECOND,
204 device_class=SensorDeviceClass.DATA_RATE,
205 entity_category=EntityCategory.DIAGNOSTIC,
206 value_fn=_retrieve_max_kb_s_received_state,
210 translation_key=
"gb_sent",
211 state_class=SensorStateClass.TOTAL_INCREASING,
212 native_unit_of_measurement=UnitOfInformation.GIGABYTES,
213 device_class=SensorDeviceClass.DATA_SIZE,
214 value_fn=_retrieve_gb_sent_state,
218 translation_key=
"gb_received",
219 state_class=SensorStateClass.TOTAL_INCREASING,
220 native_unit_of_measurement=UnitOfInformation.GIGABYTES,
221 device_class=SensorDeviceClass.DATA_SIZE,
222 value_fn=_retrieve_gb_received_state,
225 key=
"link_kb_s_sent",
226 translation_key=
"link_kb_s_sent",
227 native_unit_of_measurement=UnitOfDataRate.KILOBITS_PER_SECOND,
228 device_class=SensorDeviceClass.DATA_RATE,
229 value_fn=_retrieve_link_kb_s_sent_state,
232 key=
"link_kb_s_received",
233 translation_key=
"link_kb_s_received",
234 native_unit_of_measurement=UnitOfDataRate.KILOBITS_PER_SECOND,
235 device_class=SensorDeviceClass.DATA_RATE,
236 value_fn=_retrieve_link_kb_s_received_state,
239 key=
"link_noise_margin_sent",
240 translation_key=
"link_noise_margin_sent",
241 native_unit_of_measurement=SIGNAL_STRENGTH_DECIBELS,
242 value_fn=_retrieve_link_noise_margin_sent_state,
243 is_suitable=
lambda info: info.wan_enabled
and info.connection == DSL_CONNECTION,
246 key=
"link_noise_margin_received",
247 translation_key=
"link_noise_margin_received",
248 native_unit_of_measurement=SIGNAL_STRENGTH_DECIBELS,
249 value_fn=_retrieve_link_noise_margin_received_state,
250 is_suitable=
lambda info: info.wan_enabled
and info.connection == DSL_CONNECTION,
253 key=
"link_attenuation_sent",
254 translation_key=
"link_attenuation_sent",
255 native_unit_of_measurement=SIGNAL_STRENGTH_DECIBELS,
256 value_fn=_retrieve_link_attenuation_sent_state,
257 is_suitable=
lambda info: info.wan_enabled
and info.connection == DSL_CONNECTION,
260 key=
"link_attenuation_received",
261 translation_key=
"link_attenuation_received",
262 native_unit_of_measurement=SIGNAL_STRENGTH_DECIBELS,
263 value_fn=_retrieve_link_attenuation_received_state,
264 is_suitable=
lambda info: info.wan_enabled
and info.connection == DSL_CONNECTION,
270 hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
273 _LOGGER.debug(
"Setting up FRITZ!Box sensors")
274 avm_wrapper: AvmWrapper = hass.data[DOMAIN][entry.entry_id]
276 connection_info = await avm_wrapper.async_get_connection_info()
280 for description
in SENSOR_TYPES
281 if description.is_suitable(connection_info)
288 """Define FRITZ!Box connectivity class."""
290 entity_description: FritzSensorEntityDescription
294 """Return the value reported by the sensor."""
StateType native_value(self)
web.Response get(self, web.Request request, str config_key)
float _retrieve_kb_s_sent_state(FritzStatus status, str last_value)
float _retrieve_max_kb_s_received_state(FritzStatus status, str last_value)
float _retrieve_link_noise_margin_received_state(FritzStatus status, str last_value)
None async_setup_entry(HomeAssistant hass, ConfigEntry entry, AddEntitiesCallback async_add_entities)
str _retrieve_external_ipv6_state(FritzStatus status, str last_value)
float _retrieve_gb_sent_state(FritzStatus status, str last_value)
float _retrieve_link_attenuation_received_state(FritzStatus status, str last_value)
str _retrieve_external_ip_state(FritzStatus status, str last_value)
float _retrieve_max_kb_s_sent_state(FritzStatus status, str last_value)
float _retrieve_link_noise_margin_sent_state(FritzStatus status, str last_value)
float _retrieve_gb_received_state(FritzStatus status, str last_value)
float _retrieve_kb_s_received_state(FritzStatus status, str last_value)
datetime _retrieve_connection_uptime_state(FritzStatus status, datetime|None last_value)
float _retrieve_link_attenuation_sent_state(FritzStatus status, str last_value)
datetime _retrieve_device_uptime_state(FritzStatus status, datetime last_value)
float _retrieve_link_kb_s_received_state(FritzStatus status, str last_value)
float _retrieve_link_kb_s_sent_state(FritzStatus status, str last_value)
datetime _uptime_calculation(float seconds_uptime, datetime|None last_value)