Skip to content

Commit

Permalink
Merge pull request #2528 from alandtse/dev
Browse files Browse the repository at this point in the history
  • Loading branch information
alandtse authored Sep 16, 2024
2 parents 6dcba6e + 5464724 commit 4acabd7
Show file tree
Hide file tree
Showing 5 changed files with 348 additions and 13 deletions.
5 changes: 3 additions & 2 deletions custom_components/alexa_media/alexa_entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -350,10 +350,11 @@ def parse_temperature_from_coordinator(
coordinator: DataUpdateCoordinator, entity_id: str
) -> Optional[str]:
"""Get the temperature of an entity from the coordinator data."""
value = parse_value_from_coordinator(
temperature = parse_value_from_coordinator(
coordinator, entity_id, "Alexa.TemperatureSensor", "temperature"
)
return value.get("value") if value and "value" in value else None
_LOGGER.debug("parse_temperature_from_coordinator: %s", temperature)
return temperature


def parse_air_quality_from_coordinator(
Expand Down
174 changes: 174 additions & 0 deletions custom_components/alexa_media/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,3 +139,177 @@
ALEXA_ICON_DEFAULT = "mdi:molecule"

UPLOAD_PATH = "www/alexa_tts"

# Note: Some of these are likely wrong
MODEL_IDS = {
"A10A33FOX2NUBK": "Echo Spot",
"A10L5JEZTKKCZ8": "Vobot Bunny",
"A11QM4H9HGV71H": "Echo Show 5 (Gen3)",
"A12GXV8XMS007S": "Fire TV (Gen1)",
"A12IZU8NMHSY5U": "Generic Device",
"A132LT22WVG6X5": "Samsung Soundbar Q700A",
"A13B2WB920IZ7X": "Samsung HW-Q70T Soundbar",
"A13W6HQIHKEN3Z": "Echo Auto",
"A14ZH95E6SE9Z1": "Bose Home Speaker 300",
"A15996VY63BQ2D": "Echo Show 8 (Gen2)",
"A15ERDAKK5HQQG": "Sonos",
"A15QWUTQ6FSMYX": "Echo Buds (Gen2)",
"A16MZVIFVHX6P6": "Generic Echo",
"A17LGWINFBUTZZ": "Anker Roav Viva",
"A18BI6KPKDOEI4": "Ecobee4",
"A18O6U1UQFJ0XK": "Echo Plus (Gen2)",
"A18TCD9FP10WJ9": "Orbi Voice",
"A18X8OBWBCSLD8": "Samsung Soundbar",
"A195TXHV1M5D4A": "Echo Auto",
"A1C66CX2XD756O": "Fire Tablet HD",
"A1EIANJ7PNB0Q7": "Echo Show 15 (Gen1)",
"A1ENT81UXFMNNO": "Unknown",
"A1ETW4IXK2PYBP": "Talk to Alexa",
"A1F1F76XIW4DHQ": "Unknown TV",
"A1F8D55J0FWDTN": "Fire TV (Toshiba)",
"A1H0CMF1XM0ZP4": "Bose SoundTouch 30",
"A1J16TEDOYCZTN": "Fire Tablet",
"A1JJ0KFC4ZPNJ3": "Echo Input",
"A1L4KDRIILU6N9": "Sony Speaker",
"A1LOQ8ZHF4G510": "Samsung Soundbar Q990B",
"A1M0A9L9HDBID3": "One-Link Safe and Sound",
"A1MUORL8FP149X": "Unknown",
"A1N9SW0I0LUX5Y": "Ford/Lincoln Alexa App",
"A1NL4BVLQ4L3N3": "Echo Show (Gen1)",
"A1NQ0LXWBGVQS9": "2021 Samsung QLED TV",
"A1P31Q3MOWSHOD": "Zolo Halo Speaker",
"A1P7E7V3FCZKU6": "Fire TV (Gen3)",
"A1Q69AKRWLJC0F": "TV",
"A1Q7QCGNMXAKYW": "Generic Tablet",
"A1QKZ9D0IJY332": "Samsung TV 2020-U",
"A1RABVCI4QCIKC": "Echo Dot (Gen3)",
"A1RTAM01W29CUP": "Windows App",
"A1SCI5MODUBAT1": "Pioneer DMH-W466NEX",
"A1TD5Z1R8IWBHA": "Tablet",
"A1VGB7MHSIEYFK": "Fire TV Cube Gen3",
"A1W2YILXTG9HA7": "Nextbase 522GW Dashcam",
"A1W46V57KES4B5": "Cable TV box Brazil",
"A1WZKXFLI43K86": "Fire TV Stick MAX",
"A1XWJRHALS1REP": "Echo Show 5 (Gen2)",
"A1Z88NGR2BK6A2": "Echo Show 8 (Gen1)",
"A25EC4GIHFOCSG": "Unrecognized Media Player",
"A25OJWHZA1MWNB": "2021 Samsung QLED TV",
"A265XOI9586NML": "Fire TV Stick",
"A27VEYGQBW3YR5": "Echo Link",
"A2A3XFQ1AVYLHZ": "SONY WF-1000XM5",
"A2BRQDVMSZD13S": "SURE Universal Remote",
"A2C8J6UHV0KFCV": "Alexa Gear",
"A2DS1Q2TPDJ48U": "Echo Dot Clock (Gen5)",
"A2E0SNTXJVT7WK": "Fire TV (Gen2)",
"A2E5N6DMWCW8MZ": "Brilliant Smart Switch",
"A2EZ3TS0L1S2KV": "Sonos Beam",
"A2GFL5ZMWNE0PX": "Fire TV (Gen3)",
"A2H4LV5GIZ1JFT": "Echo Dot Clock (Gen4)",
"A2HZENIFNYTXZD": "Facebook Portal",
"A2I0SCCU3561Y8": "Samsung Soundbar Q800A",
"A2IS7199CJBT71": "TV",
"A2IVLV5VM2W81": "Alexa Mobile Voice iOS",
"A2J0R2SD7G9LPA": "Lenovo SmartTab M10",
"A2JKHJ0PX4J3L3": "Fire TV Cube (Gen2)",
"A2LH725P8DQR2A": "Fabriq Riff",
"A2LWARUGJLBYEW": "Fire TV Stick (Gen2)",
"A2M35JJZWCQOMZ": "Echo Plus (Gen1)",
"A2M4YX06LWP8WI": "Fire Tablet",
"A2N49KXGVA18AR": "Fire Tablet HD 10 Plus",
"A2OSP3UA4VC85F": "Sonos",
"A2R2GLZH1DFYQO": "Zolo Halo Speaker",
"A2RU4B77X9R9NZ": "Echo Link Amp",
"A2TF17PFR55MTB": "Alexa Mobile Voice Android",
"A2TTLILJHVNI9X": "LG TV",
"A2U21SRK4QGSE1": "Echo Dot Clock (Gen4)",
"A2UONLFQW0PADH": "Echo Show 8 (Gen3)",
"A2V9UEGZ82H4KZ": "Fire Tablet HD 10",
"A2VAXZ7UNGY4ZH": "Wyze Headphones",
"A2WFDCBDEXOXR8": "Bose Soundbar 700",
"A2WN1FJ2HG09UN": "Ultimate Alexa App",
"A2X8WT9JELC577": "Ecobee5",
"A2XPGY5LRKB9BE": "Fitbit Versa 2",
"A2Y04QPFCANLPQ": "Bose QuietComfort 35 II",
"A303PJF6ISQ7IC": "Echo Auto",
"A30YDR2MK8HMRV": "Echo (Gen3)",
"A31DTMEEVDDOIV": "Fire TV Stick Lite",
"A324YMIUSWQDGE": "Samsung 8K TV",
"A32DDESGESSHZA": "Echo Dot (Gen3)",
"A32DOYMUN6DTXA": "Echo Dot (Gen3)",
"A339L426Y220I4": "Teufel Radio",
"A347G2JC8I4HC7": "Roav Car Charger Pro",
"A37CFAHI1O0CXT": "Logitech Blast",
"A37M7RU8Z6ZFB": "Garmin Speak",
"A37SHHQ3NUL7B5": "Bose Home Speaker 500",
"A38949IHXHRQ5P": "Echo Tap",
"A38BPK7OW001EX": "Raspberry Alexa",
"A38EHHIB10L47V": "Fire Tablet HD 8",
"A39BU42XNMN516": "Generic Device",
"A3B50IC5QPZPWP": "Polk Command Bar",
"A3B5K1G3EITBIF": "Facebook Portal",
"A3BRT6REMPQWA8": "Bose Home Speaker 450",
"A3BW5ZVFHRCQPO": "BMW Alexa Integration",
"A3C9PE6TNYLTCH": "Speaker Group",
"A3CY98NH016S5F": "Facebook Portal Mini",
"A3D4YURNTARP5K": "Facebook Portal TV",
"A3EVMLQTU6WL1W": "Fire TV (GenX)",
"A3F1S88NTZZXS9": "Dash Wand",
"A3FX4UWTP28V1P": "Echo (Gen3)",
"A3GFRGUNIGG1I5": "Samsung TV QN50Q60CAGXZD",
"A3HF4YRA2L7XGC": "Fire TV Cube",
"A3IYPH06PH1HRA": "Echo Frames",
"A3K69RS3EIMXPI": "Hisense Smart TV",
"A3KULB3NQN7Z1F": "Unknown TV",
"A3L0T0VL9A921N": "Fire Tablet HD 8",
"A3NPD82ABCPIDP": "Sonos Beam",
"A3QPPX1R9W5RJV": "Fabriq Chorus",
"A3QS1XP2U6UJX9": "SONY WF-1000XM4",
"A3R9S4ZZECZ6YL": "Fire Tablet HD 10",
"A3RBAYBE7VM004": "Echo Studio",
"A3RCTOK2V0A4ZG": "LG TV",
"A3RMGO6LYLH7YN": "Echo Dot (Gen4)",
"A3S5BH2HU6VAYF": "Echo Dot (Gen2)",
"A3SSG6GR8UU7SN": "Echo Sub",
"A3SSWQ04XYPXBH": "Generic Tablet",
"A3TCJ8RTT3NVI7": "Alexa Listens",
"A3VRME03NAXFUB": "Echo Flex",
"A4ZP7ZC4PI6TO": "Echo Show 5 (Gen1)",
"A4ZXE0RM7LQ7A": "Echo Dot (Gen5)",
"A52ARKF0HM2T4": "Facebook Portal+",
"A6SIQKETF3L2E": "Unknown Device",
"A7WXQPH584YP": "Echo (Gen2)",
"A81PNL0A63P93": "Home Remote",
"A8DM4FYR6D3HT": "TV",
"AA1IN44SS3X6O": "Ecobee Thermostat Premium",
"AB72C64C86AW2": "Echo (Gen1)",
"ABJ2EHL7HQT4L": "Unknown Amplifier",
"ADVBD696BHNV5": "Fire TV Stick (Gen1)",
"AE7X7Z227NFNS": "HiMirror Mini",
"AF473ZSOIRKFJ": "Onkyo VC-PX30",
"AFF50AL5E3DIU": "Fire TV (Insignia)",
"AFF5OAL5E3DIU": "Fire TV",
"AGHZIK8D6X7QR": "Fire TV",
"AHJYKVA63YCAQ": "Sonos",
"AIPK7MM90V7TB": "Echo Show 10 (Gen3)",
"AKKLQD9FZWWQS": "Jabra Elite",
"AKNO1N0KSFN8L": "Echo Dot (Gen1)",
"AKO51L5QAQKL2": "Alexa Jams",
"AKPGW064GI9HE": "Fire TV Stick 4K (Gen3)",
"ALT9P69K6LORD": "Echo Auto",
"AMCZ48H33RCDF": "Samsung HW-Q910B 9.1.2 ch Soundbar",
"AN630UQPG2CA4": "Fire TV (Toshiba)",
"AO6HHP9UE6EOF": "Unknown Media Device",
"AP1F6KUH00XPV": "Stereo/Subwoofer Pair",
"AP4RS91ZQ0OOI": "Fire TV (Toshiba)",
"APHEAY6LX7T13": "Samsung Smart Refrigerator",
"AQCGW9PSYWRF": "TV",
"AR6X0XNIME80V": "Unknown TV",
"ASQZWP4GPYUT7": "Echo Pop",
"ATNLRCEBX3W4P": "Generic Tablet",
"AUPUQSVCVHXP0": "Ecobee Switch+",
"AVD3HM0HOJAAL": "Sonos",
"AVE5HX13UR5NO": "Logitech Zero Touch",
"AVN2TMX8MU2YM": "Bose Home Speaker 500",
"AVU7CPPF2ZRAS": "Fire Tablet HD 8",
"AWZZ5CVHX2CD": "Echo Show (Gen2)",
}
25 changes: 21 additions & 4 deletions custom_components/alexa_media/media_player.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
DEPENDENT_ALEXA_COMPONENTS,
MIN_TIME_BETWEEN_FORCED_SCANS,
MIN_TIME_BETWEEN_SCANS,
MODEL_IDS,
PLAY_SCAN_INTERVAL,
UPLOAD_PATH,
)
Expand Down Expand Up @@ -180,9 +181,14 @@ async def async_setup_entry(hass, config_entry, async_add_devices):
_LOGGER.debug(
"%s: Loading config entry for %s", hide_email(account), component
)
await hass.config_entries.async_forward_entry_setups(
config_entry, [component]
)
try:
await hass.config_entries.async_forward_entry_setups(
config_entry, [component]
)
except (asyncio.TimeoutError, TimeoutException) as ex:
raise ConfigEntryNotReady(
f"Timeout while loading config entry for {component}"
) from ex
return True
raise ConfigEntryNotReady

Expand Down Expand Up @@ -412,6 +418,15 @@ async def _refresh_if_no_audiopush(already_refreshed=False):
self.hass.data[DATA_ALEXAMEDIA]["accounts"][email]["http2"]
)
self.async_schedule_update_ha_state(force_refresh=force_refresh)
if self._last_called:
self.hass.bus.async_fire(
"alexa_media_last_called_event",
{
"last_called": self.device_serial_number,
"timestamp": self._last_called_timestamp,
"summary": self._last_called_summary,
},
)
elif "bluetooth_change" in event:
if event_serial == self.device_serial_number:
_LOGGER.debug(
Expand Down Expand Up @@ -1607,7 +1622,9 @@ def device_info(self):
"identifiers": {(ALEXA_DOMAIN, self.unique_id)},
"name": self.name,
"manufacturer": "Amazon",
"model": f"{self._device_family} {self._device_type}",
"model": MODEL_IDS.get(
self._device_type, f"{self._device_family} {self._device_type}"
),
"sw_version": self._software_version,
}

Expand Down
51 changes: 44 additions & 7 deletions custom_components/alexa_media/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,9 +182,10 @@ async def create_temperature_sensors(account_dict, temperature_entities):
coordinator = account_dict["coordinator"]
for temp in temperature_entities:
_LOGGER.debug(
"Creating entity %s for a temperature sensor with name %s",
"Creating entity %s for a temperature sensor with name %s (%s)",
temp["id"],
temp["name"],
temp,
)
serial = temp["device_serial"]
device_info = lookup_device_info(account_dict, serial)
Expand Down Expand Up @@ -254,16 +255,25 @@ def __init__(self, coordinator, entity_id, name, media_player_device_id):
"""Initialize temperature sensor."""
super().__init__(coordinator)
self.alexa_entity_id = entity_id
# Need to append "+temperature" because the Alexa entityId is for a physical device
# and a single physical device can have multiple HA entities
self._attr_unique_id = entity_id + "_temperature"
self._attr_name = name + " Temperature"
self._attr_device_class = SensorDeviceClass.TEMPERATURE
self._attr_state_class = SensorStateClass.MEASUREMENT
self._attr_native_value: Optional[datetime.datetime] = (
value_and_scale: Optional[datetime.datetime] = (
parse_temperature_from_coordinator(coordinator, entity_id)
)
self._attr_native_unit_of_measurement: Optional[str] = UnitOfTemperature.CELSIUS
# This includes "_temperature" because the Alexa entityId is for a physical device
# A single physical device could have multiple HA entities
self._attr_unique_id = entity_id + "_temperature"
self._attr_native_value = self._get_temperature_value(value_and_scale)
self._attr_native_unit_of_measurement = self._get_temperature_scale(
value_and_scale
)
_LOGGER.debug(
"Coordinator init: %s: %s %s",
self._attr_name,
self._attr_native_value,
self._attr_native_unit_of_measurement,
)
self._attr_device_info = (
{
"identifiers": {media_player_device_id},
Expand All @@ -276,11 +286,38 @@ def __init__(self, coordinator, entity_id, name, media_player_device_id):
@callback
def _handle_coordinator_update(self) -> None:
"""Handle updated data from the coordinator."""
self._attr_native_value = parse_temperature_from_coordinator(
value_and_scale = parse_temperature_from_coordinator(
self.coordinator, self.alexa_entity_id
)
self._attr_native_value = self._get_temperature_value(value_and_scale)
self._attr_native_unit_of_measurement = self._get_temperature_scale(
value_and_scale
)
_LOGGER.debug(
"Coordinator update: %s: %s %s",
self._attr_name,
self._attr_native_value,
self._attr_native_unit_of_measurement,
)
super()._handle_coordinator_update()

def _get_temperature_value(self, value):
if value and "value" in value:
_LOGGER.debug("TemperatureSensor value: %s", value.get("value"))
return value.get("value")
return None

def _get_temperature_scale(self, value):
if value and "scale" in value:
_LOGGER.debug("TemperatureSensor scale: %s", value.get("scale"))
if value.get("scale") == "CELSIUS":
return UnitOfTemperature.CELSIUS
if value.get("scale") == "FAHRENHEIT":
return UnitOfTemperature.FAHRENHEIT
if value.get("scale") == "KELVIN":
return UnitOfTemperature.KELVIN
return None


class AirQualitySensor(SensorEntity, CoordinatorEntity):
"""A air quality sensor reported by an Amazon indoor air quality monitor."""
Expand Down
Loading

0 comments on commit 4acabd7

Please sign in to comment.