Skip to content

Commit

Permalink
feat: Support multiple Android TV instances (#35)
Browse files Browse the repository at this point in the history
Closes #14

---------

Co-authored-by: Markus Zehnder <markus.z@unfoldedcircle.com>
  • Loading branch information
albaintor and zehnm authored Mar 29, 2024
1 parent 2cb4885 commit 842bf46
Show file tree
Hide file tree
Showing 5 changed files with 254 additions and 65 deletions.
5 changes: 3 additions & 2 deletions driver.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,13 @@
"label": {
"en": "Setup process",
"de": "Setup Fortschritt",
"fr": "Progrès de la configuration"
"fr": "Progression de la configuration"
},
"field": {
"label": {
"value": {
"en": "The integration will discover your Android TV on your network. Only devices running the [Android TV Remote Service](https://play.google.com/store/apps/details?id=com.google.android.tv.remote.service) are supported.\nDuring the process, you might need to enter a PIN that is shown on your Android TV. Please make sure that your Android TV is powered on and that no old pairing request is shown.\nIf pairing continuously fails, reboot your Android TV device and try again."
"en": "The integration will discover your Android TV on your network. Only devices running the [Android TV Remote Service](https://play.google.com/store/apps/details?id=com.google.android.tv.remote.service) are supported.\nDuring the process, you might need to enter a PIN that is shown on your Android TV. Please make sure that your Android TV is powered on and that no old pairing request is shown.\nIf pairing continuously fails, reboot your Android TV device and try again.",
"fr": "L'intégration découvrira votre Android TV sur votre réseau. Seuls les appareils faisant tourner le [Android TV Remote Service](https://play.google.com/store/apps/details?id=com.google.android.tv.remote.service) sont supportés.\nDurant la procédure, vous devrez saisir un code PIN qui sera affiché sur votre Android TV. Assurez-vous que votre Android TV est allumée et qu'aucune ancienne requête d'apparaige est affichée.\nSi l'appairage échoue systématiquement, redémarrez votre Android TV et réessayez"
}
}
}
Expand Down
52 changes: 37 additions & 15 deletions intg-androidtv/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,12 +76,25 @@ def contains(self, atv_id: str) -> bool:
return True
return False

def add(self, atv: AtvDevice) -> None:
"""Add a new configured Android TV device."""
# TODO duplicate check
self._config.append(atv)
if self._add_handler is not None:
self._add_handler(atv)
def contains_address(self, address: str) -> bool:
"""Check if there's a device with the given device identifier."""
for item in self._config:
if item.address == address:
return True
return False

def add_or_update(self, atv: AtvDevice) -> None:
"""
Add a new configured Android TV device and persist configuration.
The device is updated if it already exists in the configuration.
"""
# duplicate check
if not self.update(atv):
self._config.append(atv)
self.store()
if self._add_handler is not None:
self._add_handler(atv)

def get(self, atv_id: str) -> AtvDevice | None:
"""Get device configuration for given identifier."""
Expand All @@ -106,6 +119,7 @@ def remove(self, atv_id: str) -> bool:
if atv is None:
return False
try:
self.remove_files(atv_id)
self._config.remove(atv)
if self._remove_handler is not None:
self._remove_handler(atv)
Expand All @@ -114,22 +128,30 @@ def remove(self, atv_id: str) -> bool:
pass
return False

def remove_files(self, atv_id: str) -> bool:
"""Remove the certificate and key files of a given Android TV instance."""
for item in self._config:
if item.id == atv_id:
android_tv = AndroidTv(self.data_path, item.address, item.name, item.id)
pem_file = android_tv.certfile
if os.path.exists(pem_file):
os.remove(pem_file)
pem_file = android_tv.keyfile
if os.path.exists(pem_file):
os.remove(pem_file)
return True
return False

def clear(self) -> None:
"""Remove the configuration file and device certificates."""
for item in self._config:
self.remove_files(item.id)

self._config = []

if os.path.exists(self._cfg_file_path):
os.remove(self._cfg_file_path)

# FIXME #14 does not work for multi-device support
pem_file = os.path.join(self._data_path, "androidtv_remote_cert.pem")
if os.path.exists(pem_file):
os.remove(pem_file)

pem_file = os.path.join(self._data_path, "androidtv_remote_key.pem")
if os.path.exists(pem_file):
os.remove(pem_file)

if self._remove_handler is not None:
self._remove_handler(None)

Expand Down
13 changes: 13 additions & 0 deletions intg-androidtv/driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,19 @@ async def main():
await config.devices.migrate()
# and register them as available devices.
for device in config.devices.all():
# Migration of certificate/key files with identifier in name
_android_tv = tv.AndroidTv(api.config_dir_path, device.address, device.name, device.id)
if not os.path.exists(_android_tv.certfile):
current_certfile = os.path.join(api.config_dir_path, "androidtv_remote_cert.pem")
current_keyfile = os.path.join(api.config_dir_path, "androidtv_remote_key.pem")
try:
_LOG.info("Rename certificate file %s to %s", current_certfile, _android_tv.certfile)
os.rename(current_certfile, _android_tv.certfile)
_LOG.info("Rename key file %s to %s", current_keyfile, _android_tv.keyfile)
os.rename(current_keyfile, _android_tv.keyfile)
except OSError as ex:
_LOG.error("Error while migrating certificate files: %s", ex)

_add_configured_android_tv(device, connect=False)

await api.init("driver.json", setup_flow.driver_setup_handler)
Expand Down
Loading

0 comments on commit 842bf46

Please sign in to comment.