From ac137afe076494acc2bd8fb526eac31ba52570f9 Mon Sep 17 00:00:00 2001 From: Ingmar Stein Date: Fri, 21 Feb 2025 16:22:46 +0100 Subject: [PATCH] Make the API endpoint configurable This allows using API-compatible servers to be used instead of Tidbyt's, for example tavdog/tronbyt-server. --- README.md | 16 +++++++-- custom_components/tidbytassistant/__init__.py | 35 +++++++++++-------- custom_components/tidbytassistant/const.py | 3 ++ custom_components/tidbytassistant/light.py | 10 +++--- custom_components/tidbytassistant/switch.py | 10 +++--- 5 files changed, 47 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index 6201636..83cf732 100644 --- a/README.md +++ b/README.md @@ -117,15 +117,25 @@ The integration will expose each devices' sceen as a light entity. The autodim f #### Pushing your own files 1. Create a folder in your **/config** directory called **tidbyt**. -2. Place your .star file(s) in this folder. -3. Select the radio button for *Custom*. In the *Custom Content* text box, enter the file name minus the '.star'. Example: If your file is named *custom.star*, you will enter *custom* in the field. +2. Place your `.star` file(s) into a subdirectory of this folder. +3. Select the radio button for *Custom*. In the *Custom Content* text box, enter the name of the app directory. Example: If your files is named */config/tidbyt/myapp/custom.star*, you will enter *myapp* in the field. 4. You can also pass in arguments as key=value pairs. in the *Arguments* box you can enter these pairs like this, separated with a semi-colon (;): ***key=value;key2=value 2***. (Scroll down to **Passing arguments** to see an example of how this works) 5. Select your device(s) and run the action to see it displayed on your Tidbyt. + +### Pushing a Tidbyt Community app + +1. Create a folder in your **/config** directory called **tidbyt**, if it doesn't exist already. +2. Clone the Tidbyt Community repository into this directory: `git clone --depth=1 https://github.com/tidbyt/community`. +3. Set up a push action using as a custom content using the name `community/apps/myapp`. +4. You can also pass in arguments as key=value pairs. in the *Arguments* box you can enter these pairs like this, separated with a semi-colon (;): ***key=value;key2=value 2***. (Scroll down to **Passing arguments** to see an example of how this works) +5. Select your device(s) and run the action to see it displayed on your Tidbyt. + +Note: community apps which store credentials in the Tidbyt cloud will not have access to them and likely not work as expected. ### TidbytAssistant: Text 1. Select the radio buttom for *Text* 2. In the *Content* box, enter the text you want displayed. You can also select from the avaialble fonts and colors as well as static text or scrolling. -4. Select your device(s) and run the action. You should see your text on the screen. +3. Select your device(s) and run the action. You should see your text on the screen. ### TidbytAssistant: Delete 1. Enter the content ID of the app you published and device name. diff --git a/custom_components/tidbytassistant/__init__.py b/custom_components/tidbytassistant/__init__.py index f92f674..84a9cd2 100644 --- a/custom_components/tidbytassistant/__init__.py +++ b/custom_components/tidbytassistant/__init__.py @@ -17,6 +17,7 @@ CONF_HOST, CONF_NAME, CONF_EXTERNALADDON, + CONF_API_URL, ATTR_CONTENT, ATTR_CONTENT_ID, ATTR_DEVICENANME, @@ -33,7 +34,8 @@ ATTR_BRIGHTNESS, ATTR_AUTODIM, ATTR_LANG, - ADDON_MIN_VERSION + ADDON_MIN_VERSION, + DEFAULT_API_URL ) from homeassistant.core import HomeAssistant, ServiceCall, callback from homeassistant.helpers.typing import ConfigType @@ -78,8 +80,8 @@ extra=vol.ALLOW_EXTRA, ) -async def getdevicename(deviceid, token) -> str: - url = f"https://api.tidbyt.com/v0/devices/{deviceid}" +async def getdevicename(endpoint, deviceid, token) -> str: + url = f"{endpoint}/v0/devices/{deviceid}" header = { "Authorization": f"Bearer {token}", "Content-Type": "application/json", @@ -154,13 +156,17 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: config = yaml.safe_load(content) devicelist = [] - for item in conf[CONF_DEVICE]: - if CONF_NAME in item: - devicelist.append(item[CONF_NAME]) + for device in conf[CONF_DEVICE]: + if CONF_NAME in device: + devicelist.append(device[CONF_NAME]) else: - retrievedname = await getdevicename(item[CONF_ID],item[CONF_TOKEN]) + retrievedname = await getdevicename( + device.get(CONF_API_URL, DEFAULT_API_URL), + device[CONF_ID], + device[CONF_TOKEN] + ) devicelist.append(retrievedname) - item[CONF_NAME] = retrievedname + device[CONF_NAME] = retrievedname device_name_options = [{"label": name, "value": name} for name in devicelist] @@ -188,8 +194,8 @@ async def validateid(input): pattern = r'^[A-Za-z0-9]+$' return bool(re.match(pattern, input)) - async def getinstalledapps(deviceid, token): - url = f"https://api.tidbyt.com/v0/devices/{deviceid}/installations" + async def getinstalledapps(endpoint, deviceid, token): + url = f"{endpoint}/v0/devices/{deviceid}/installations" header = { "Authorization": f"Bearer {token}", "Content-Type": "application/json", @@ -302,13 +308,14 @@ async def pixlet_delete(call: ServiceCall) -> None: if item[CONF_NAME] == device: token = item[CONF_TOKEN] deviceid = item[CONF_ID] - - validids = await getinstalledapps(deviceid, token) + base_url = item.get(CONF_API_URL, DEFAULT_API_URL) + + validids = await getinstalledapps(base_url, deviceid, token) if contentid not in validids: _LOGGER.error(f"The Content ID you entered is not an installed app on {device}. Currently installed apps are: {validids}") - raise HomeAssistantError(f"The Contend ID you entered is not an installed app on {device}. Currently installed apps are: {validids}") + raise HomeAssistantError(f"The Content ID you entered is not an installed app on {device}. Currently installed apps are: {validids}") - url = f"https://api.tidbyt.com/v0/devices/{deviceid}/installations/{contentid}" + url = f"{base_url}/v0/devices/{deviceid}/installations/{contentid}" header = { "Authorization": f"Bearer {token}", "Content-Type": "application/json", diff --git a/custom_components/tidbytassistant/const.py b/custom_components/tidbytassistant/const.py index 57e93e8..992c9ef 100644 --- a/custom_components/tidbytassistant/const.py +++ b/custom_components/tidbytassistant/const.py @@ -7,6 +7,7 @@ CONF_NAME = "name" CONF_DEVICE = "device" CONF_EXTERNALADDON = "external_addon" +CONF_API_URL = "apiurl" ATTR_CONTENT = "content" ATTR_DEVICENANME = "devicename" ATTR_CONT_TYPE = "contenttype" @@ -25,3 +26,5 @@ ATTR_LANG = "language" ADDON_SLUG = "d8f2112a_tidbytassistant" ADDON_MIN_VERSION = "1.0.15" +ATTR_LANG = "language" +DEFAULT_API_URL = "https://api.tidbyt.com" diff --git a/custom_components/tidbytassistant/light.py b/custom_components/tidbytassistant/light.py index f6c23f0..d3e832a 100644 --- a/custom_components/tidbytassistant/light.py +++ b/custom_components/tidbytassistant/light.py @@ -17,7 +17,7 @@ BRIGHTNESS_SCALE = (1, 100) -from .const import DOMAIN, CONF_DEVICE, CONF_NAME, CONF_TOKEN, CONF_ID +from .const import DOMAIN, CONF_DEVICE, CONF_NAME, CONF_TOKEN, CONF_ID, CONF_API_URL, DEFAULT_API_URL _LOGGER = logging.getLogger(__name__) @@ -34,11 +34,11 @@ class TidbytLight(LightEntity): _attr_supported_color_modes = {ColorMode.BRIGHTNESS} def __init__(self, tidbyt): - self._name = tidbyt["name"] - self._deviceid = tidbyt["deviceid"] - self._token = tidbyt["token"] + self._name = tidbyt[CONF_NAME] + self._deviceid = tidbyt[CONF_ID] + self._token = tidbyt[CONF_TOKEN] self._is_on = True - self._url = f"https://api.tidbyt.com/v0/devices/{self._deviceid}" + self._url = f"{tidbyt.get(CONF_API_URL, DEFAULT_API_URL)}/v0/devices/{self._deviceid}" self._header = { "Authorization": f"Bearer {self._token}", diff --git a/custom_components/tidbytassistant/switch.py b/custom_components/tidbytassistant/switch.py index 0e76c87..933b107 100644 --- a/custom_components/tidbytassistant/switch.py +++ b/custom_components/tidbytassistant/switch.py @@ -10,7 +10,7 @@ from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType from homeassistant.helpers.entity_platform import AddEntitiesCallback -from .const import DOMAIN, CONF_DEVICE, CONF_NAME, CONF_TOKEN, CONF_ID +from .const import DOMAIN, CONF_DEVICE, CONF_NAME, CONF_TOKEN, CONF_ID, CONF_API_URL, DEFAULT_API_URL _LOGGER = logging.getLogger(__name__) @@ -24,14 +24,14 @@ async def async_setup_platform(hass: HomeAssistant, config: ConfigType, add_enti class TidbytSwitch(SwitchEntity): def __init__(self, tidbyt): - self._name = tidbyt["name"] - self._deviceid = tidbyt["deviceid"] - self._token = tidbyt["token"] + self._name = tidbyt[CONF_NAME] + self._deviceid = tidbyt[CONF_ID] + self._token = tidbyt[CONF_TOKEN] append = self._deviceid.split('-') self._entity_id = f"switch.{self._name.replace(" ","_")}_{append[3]}" - self._url = f"https://api.tidbyt.com/v0/devices/{self._deviceid}" + self._url = f"{tidbyt.get(CONF_API_URL, DEFAULT_API_URL)}/v0/devices/{self._deviceid}" self._header = { "Authorization": f"Bearer {self._token}", "Content-Type": "application/json",