Add hardware revision support to homekit (#63336)
This commit is contained in:
parent
7c6297db86
commit
5c8271552a
|
@ -26,6 +26,7 @@ from homeassistant.const import (
|
|||
ATTR_BATTERY_LEVEL,
|
||||
ATTR_DEVICE_ID,
|
||||
ATTR_ENTITY_ID,
|
||||
ATTR_HW_VERSION,
|
||||
ATTR_MANUFACTURER,
|
||||
ATTR_MODEL,
|
||||
ATTR_SW_VERSION,
|
||||
|
@ -911,6 +912,8 @@ class HomeKit:
|
|||
config[ATTR_MODEL] = device_entry.model
|
||||
if device_entry.sw_version:
|
||||
config[ATTR_SW_VERSION] = device_entry.sw_version
|
||||
if device_entry.hw_version:
|
||||
config[ATTR_HW_VERSION] = device_entry.hw_version
|
||||
if device_entry.config_entries:
|
||||
first_entry = list(device_entry.config_entries)[0]
|
||||
if entry := self.hass.config_entries.async_get_entry(first_entry):
|
||||
|
|
|
@ -15,6 +15,7 @@ from homeassistant.const import (
|
|||
ATTR_BATTERY_LEVEL,
|
||||
ATTR_DEVICE_CLASS,
|
||||
ATTR_ENTITY_ID,
|
||||
ATTR_HW_VERSION,
|
||||
ATTR_MANUFACTURER,
|
||||
ATTR_MODEL,
|
||||
ATTR_SERVICE,
|
||||
|
@ -43,6 +44,7 @@ from .const import (
|
|||
BRIDGE_SERIAL_NUMBER,
|
||||
CHAR_BATTERY_LEVEL,
|
||||
CHAR_CHARGING_STATE,
|
||||
CHAR_HARDWARE_REVISION,
|
||||
CHAR_STATUS_LOW_BATTERY,
|
||||
CONF_FEATURE_LIST,
|
||||
CONF_LINKED_BATTERY_CHARGING_SENSOR,
|
||||
|
@ -59,6 +61,7 @@ from .const import (
|
|||
MAX_MODEL_LENGTH,
|
||||
MAX_SERIAL_LENGTH,
|
||||
MAX_VERSION_LENGTH,
|
||||
SERV_ACCESSORY_INFO,
|
||||
SERV_BATTERY_SERVICE,
|
||||
SERVICE_HOMEKIT_RESET_ACCESSORY,
|
||||
TYPE_FAUCET,
|
||||
|
@ -74,7 +77,7 @@ from .util import (
|
|||
async_show_setup_message,
|
||||
cleanup_name_for_homekit,
|
||||
convert_to_float,
|
||||
format_sw_version,
|
||||
format_version,
|
||||
validate_media_player_features,
|
||||
)
|
||||
|
||||
|
@ -256,7 +259,7 @@ class HomeAccessory(Accessory):
|
|||
domain = split_entity_id(entity_id)[0].replace("_", " ")
|
||||
|
||||
if self.config.get(ATTR_MANUFACTURER) is not None:
|
||||
manufacturer = self.config[ATTR_MANUFACTURER]
|
||||
manufacturer = str(self.config[ATTR_MANUFACTURER])
|
||||
elif self.config.get(ATTR_INTEGRATION) is not None:
|
||||
manufacturer = self.config[ATTR_INTEGRATION].replace("_", " ").title()
|
||||
elif domain:
|
||||
|
@ -264,16 +267,19 @@ class HomeAccessory(Accessory):
|
|||
else:
|
||||
manufacturer = MANUFACTURER
|
||||
if self.config.get(ATTR_MODEL) is not None:
|
||||
model = self.config[ATTR_MODEL]
|
||||
model = str(self.config[ATTR_MODEL])
|
||||
elif domain:
|
||||
model = domain.title()
|
||||
else:
|
||||
model = MANUFACTURER
|
||||
sw_version = None
|
||||
if self.config.get(ATTR_SW_VERSION) is not None:
|
||||
sw_version = format_sw_version(self.config[ATTR_SW_VERSION])
|
||||
sw_version = format_version(self.config[ATTR_SW_VERSION])
|
||||
if sw_version is None:
|
||||
sw_version = __version__
|
||||
hw_version = None
|
||||
if self.config.get(ATTR_HW_VERSION) is not None:
|
||||
hw_version = format_version(self.config[ATTR_HW_VERSION])
|
||||
|
||||
self.set_info_service(
|
||||
manufacturer=manufacturer[:MAX_MANUFACTURER_LENGTH],
|
||||
|
@ -281,6 +287,13 @@ class HomeAccessory(Accessory):
|
|||
serial_number=serial_number[:MAX_SERIAL_LENGTH],
|
||||
firmware_revision=sw_version[:MAX_VERSION_LENGTH],
|
||||
)
|
||||
if hw_version:
|
||||
serv_info = self.get_service(SERV_ACCESSORY_INFO)
|
||||
char = self.driver.loader.get_char(CHAR_HARDWARE_REVISION)
|
||||
serv_info.add_characteristic(char)
|
||||
serv_info.configure_char(CHAR_HARDWARE_REVISION, value=hw_version)
|
||||
self.iid_manager.assign(char)
|
||||
char.broker = self
|
||||
|
||||
self.category = category
|
||||
self.entity_id = entity_id
|
||||
|
|
|
@ -166,6 +166,7 @@ CHAR_CONTACT_SENSOR_STATE = "ContactSensorState"
|
|||
CHAR_COOLING_THRESHOLD_TEMPERATURE = "CoolingThresholdTemperature"
|
||||
CHAR_CURRENT_AMBIENT_LIGHT_LEVEL = "CurrentAmbientLightLevel"
|
||||
CHAR_CURRENT_DOOR_STATE = "CurrentDoorState"
|
||||
CHAR_CURRENT_FAN_STATE = "CurrentFanState"
|
||||
CHAR_CURRENT_HEATING_COOLING = "CurrentHeatingCoolingState"
|
||||
CHAR_CURRENT_HUMIDIFIER_DEHUMIDIFIER = "CurrentHumidifierDehumidifierState"
|
||||
CHAR_CURRENT_POSITION = "CurrentPosition"
|
||||
|
@ -176,6 +177,7 @@ CHAR_CURRENT_TILT_ANGLE = "CurrentHorizontalTiltAngle"
|
|||
CHAR_CURRENT_VISIBILITY_STATE = "CurrentVisibilityState"
|
||||
CHAR_DEHUMIDIFIER_THRESHOLD_HUMIDITY = "RelativeHumidityDehumidifierThreshold"
|
||||
CHAR_FIRMWARE_REVISION = "FirmwareRevision"
|
||||
CHAR_HARDWARE_REVISION = "HardwareRevision"
|
||||
CHAR_HEATING_THRESHOLD_TEMPERATURE = "HeatingThresholdTemperature"
|
||||
CHAR_HUE = "Hue"
|
||||
CHAR_HUMIDIFIER_THRESHOLD_HUMIDITY = "RelativeHumidityHumidifierThreshold"
|
||||
|
|
|
@ -92,6 +92,11 @@ from .const import (
|
|||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
NUMBERS_ONLY_RE = re.compile(r"[^\d.]+")
|
||||
VERSION_RE = re.compile(r"([0-9]+)(\.[0-9]+)?(\.[0-9]+)?")
|
||||
|
||||
|
||||
MAX_PORT = 65535
|
||||
VALID_VIDEO_CODECS = [VIDEO_CODEC_LIBX264, VIDEO_CODEC_H264_OMX, AUDIO_CODEC_COPY]
|
||||
VALID_AUDIO_CODECS = [AUDIO_CODEC_OPUS, VIDEO_CODEC_COPY]
|
||||
|
@ -412,9 +417,11 @@ def get_aid_storage_fullpath_for_entry_id(hass: HomeAssistant, entry_id: str):
|
|||
)
|
||||
|
||||
|
||||
def format_sw_version(version):
|
||||
def format_version(version):
|
||||
"""Extract the version string in a format homekit can consume."""
|
||||
match = re.search(r"([0-9]+)(\.[0-9]+)?(\.[0-9]+)?", str(version).replace("-", "."))
|
||||
split_ver = str(version).replace("-", ".")
|
||||
num_only = NUMBERS_ONLY_RE.sub("", split_ver)
|
||||
match = VERSION_RE.search(num_only)
|
||||
if match:
|
||||
return match.group(0)
|
||||
return None
|
||||
|
|
|
@ -19,6 +19,7 @@ from homeassistant.components.homekit.const import (
|
|||
BRIDGE_NAME,
|
||||
BRIDGE_SERIAL_NUMBER,
|
||||
CHAR_FIRMWARE_REVISION,
|
||||
CHAR_HARDWARE_REVISION,
|
||||
CHAR_MANUFACTURER,
|
||||
CHAR_MODEL,
|
||||
CHAR_NAME,
|
||||
|
@ -33,6 +34,7 @@ from homeassistant.const import (
|
|||
ATTR_BATTERY_CHARGING,
|
||||
ATTR_BATTERY_LEVEL,
|
||||
ATTR_ENTITY_ID,
|
||||
ATTR_HW_VERSION,
|
||||
ATTR_MANUFACTURER,
|
||||
ATTR_MODEL,
|
||||
ATTR_SERVICE,
|
||||
|
@ -215,6 +217,36 @@ async def test_accessory_with_missing_basic_service_info(hass, hk_driver):
|
|||
assert serv.get_characteristic(CHAR_MODEL).value == "Sensor"
|
||||
assert serv.get_characteristic(CHAR_SERIAL_NUMBER).value == entity_id
|
||||
assert serv.get_characteristic(CHAR_FIRMWARE_REVISION).value == hass_version
|
||||
assert isinstance(acc.to_HAP(), dict)
|
||||
|
||||
|
||||
async def test_accessory_with_hardware_revision(hass, hk_driver):
|
||||
"""Test HomeAccessory class with hardware revision."""
|
||||
entity_id = "sensor.accessory"
|
||||
hass.states.async_set(entity_id, "on")
|
||||
acc = HomeAccessory(
|
||||
hass,
|
||||
hk_driver,
|
||||
"Home Accessory",
|
||||
entity_id,
|
||||
3,
|
||||
{
|
||||
ATTR_MODEL: None,
|
||||
ATTR_MANUFACTURER: None,
|
||||
ATTR_SW_VERSION: None,
|
||||
ATTR_HW_VERSION: "1.2.3",
|
||||
ATTR_INTEGRATION: None,
|
||||
},
|
||||
)
|
||||
acc.driver = hk_driver
|
||||
serv = acc.get_service(SERV_ACCESSORY_INFO)
|
||||
assert serv.get_characteristic(CHAR_NAME).value == "Home Accessory"
|
||||
assert serv.get_characteristic(CHAR_MANUFACTURER).value == "Home Assistant Sensor"
|
||||
assert serv.get_characteristic(CHAR_MODEL).value == "Sensor"
|
||||
assert serv.get_characteristic(CHAR_SERIAL_NUMBER).value == entity_id
|
||||
assert serv.get_characteristic(CHAR_FIRMWARE_REVISION).value == hass_version
|
||||
assert serv.get_characteristic(CHAR_HARDWARE_REVISION).value == "1.2.3"
|
||||
assert isinstance(acc.to_HAP(), dict)
|
||||
|
||||
|
||||
async def test_battery_service(hass, hk_driver, caplog):
|
||||
|
|
|
@ -1104,6 +1104,7 @@ async def test_homekit_finds_linked_batteries(
|
|||
device_entry = device_reg.async_get_or_create(
|
||||
config_entry_id=config_entry.entry_id,
|
||||
sw_version="0.16.0",
|
||||
hw_version="2.34",
|
||||
model="Powerwall 2",
|
||||
manufacturer="Tesla",
|
||||
connections={(device_registry.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
|
||||
|
@ -1152,6 +1153,7 @@ async def test_homekit_finds_linked_batteries(
|
|||
"manufacturer": "Tesla",
|
||||
"model": "Powerwall 2",
|
||||
"sw_version": "0.16.0",
|
||||
"hw_version": "2.34",
|
||||
"platform": "test",
|
||||
"linked_battery_charging_sensor": "binary_sensor.powerwall_battery_charging",
|
||||
"linked_battery_sensor": "sensor.powerwall_battery",
|
||||
|
|
|
@ -32,7 +32,7 @@ from homeassistant.components.homekit.util import (
|
|||
cleanup_name_for_homekit,
|
||||
convert_to_float,
|
||||
density_to_air_quality,
|
||||
format_sw_version,
|
||||
format_version,
|
||||
state_needs_accessory_mode,
|
||||
temperature_to_homekit,
|
||||
temperature_to_states,
|
||||
|
@ -343,13 +343,17 @@ async def test_port_is_available_skips_existing_entries(hass):
|
|||
async_find_next_available_port(hass, 65530)
|
||||
|
||||
|
||||
async def test_format_sw_version():
|
||||
"""Test format_sw_version method."""
|
||||
assert format_sw_version("soho+3.6.8+soho-release-rt120+10") == "3.6.8"
|
||||
assert format_sw_version("undefined-undefined-1.6.8") == "1.6.8"
|
||||
assert format_sw_version("56.0-76060") == "56.0.76060"
|
||||
assert format_sw_version(3.6) == "3.6"
|
||||
assert format_sw_version("unknown") is None
|
||||
async def test_format_version():
|
||||
"""Test format_version method."""
|
||||
assert format_version("soho+3.6.8+soho-release-rt120+10") == "3.6.8"
|
||||
assert format_version("undefined-undefined-1.6.8") == "1.6.8"
|
||||
assert format_version("56.0-76060") == "56.0.76060"
|
||||
assert format_version(3.6) == "3.6"
|
||||
assert format_version("AK001-ZJ100") == "001.100"
|
||||
assert format_version("HF-LPB100-") == "100"
|
||||
assert format_version("AK001-ZJ2149") == "001.2149"
|
||||
assert format_version("0.1") == "0.1"
|
||||
assert format_version("unknown") is None
|
||||
|
||||
|
||||
async def test_accessory_friendly_name():
|
||||
|
|
Loading…
Reference in New Issue