Add Fully Kiosk Browser switch platform (#76931)

This commit is contained in:
Charles Garwood 2022-08-17 10:30:20 -04:00 committed by GitHub
parent eec0f3351a
commit 79ab13d118
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 534 additions and 1 deletions

View File

@ -6,7 +6,7 @@ from homeassistant.core import HomeAssistant
from .const import DOMAIN
from .coordinator import FullyKioskDataUpdateCoordinator
PLATFORMS = [Platform.BINARY_SENSOR, Platform.BUTTON, Platform.SENSOR]
PLATFORMS = [Platform.BINARY_SENSOR, Platform.BUTTON, Platform.SENSOR, Platform.SWITCH]
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:

View File

@ -0,0 +1,117 @@
"""Fully Kiosk Browser switch."""
from __future__ import annotations
from collections.abc import Callable
from dataclasses import dataclass
from typing import Any
from fullykiosk import FullyKiosk
from homeassistant.components.switch import SwitchEntity, SwitchEntityDescription
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity import EntityCategory
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .const import DOMAIN
from .coordinator import FullyKioskDataUpdateCoordinator
from .entity import FullyKioskEntity
@dataclass
class FullySwitchEntityDescriptionMixin:
"""Fully Kiosk Browser switch entity description mixin."""
on_action: Callable[[FullyKiosk], Any]
off_action: Callable[[FullyKiosk], Any]
is_on_fn: Callable[[dict[str, Any]], Any]
@dataclass
class FullySwitchEntityDescription(
SwitchEntityDescription, FullySwitchEntityDescriptionMixin
):
"""Fully Kiosk Browser switch entity description."""
SWITCHES: tuple[FullySwitchEntityDescription, ...] = (
FullySwitchEntityDescription(
key="screensaver",
name="Screensaver",
on_action=lambda fully: fully.startScreensaver(),
off_action=lambda fully: fully.stopScreensaver(),
is_on_fn=lambda data: data.get("isInScreensaver"),
),
FullySwitchEntityDescription(
key="maintenance",
name="Maintenance mode",
entity_category=EntityCategory.CONFIG,
on_action=lambda fully: fully.enableLockedMode(),
off_action=lambda fully: fully.disableLockedMode(),
is_on_fn=lambda data: data.get("maintenanceMode"),
),
FullySwitchEntityDescription(
key="kiosk",
name="Kiosk lock",
entity_category=EntityCategory.CONFIG,
on_action=lambda fully: fully.lockKiosk(),
off_action=lambda fully: fully.unlockKiosk(),
is_on_fn=lambda data: data.get("kioskLocked"),
),
FullySwitchEntityDescription(
key="motion-detection",
name="Motion detection",
entity_category=EntityCategory.CONFIG,
on_action=lambda fully: fully.enableMotionDetection(),
off_action=lambda fully: fully.disableMotionDetection(),
is_on_fn=lambda data: data["settings"].get("motionDetection"),
),
)
async def async_setup_entry(
hass: HomeAssistant,
config_entry: ConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up the Fully Kiosk Browser switch."""
coordinator: FullyKioskDataUpdateCoordinator = hass.data[DOMAIN][
config_entry.entry_id
]
async_add_entities(
FullySwitchEntity(coordinator, description) for description in SWITCHES
)
class FullySwitchEntity(FullyKioskEntity, SwitchEntity):
"""Fully Kiosk Browser switch entity."""
entity_description: FullySwitchEntityDescription
def __init__(
self,
coordinator: FullyKioskDataUpdateCoordinator,
description: FullySwitchEntityDescription,
) -> None:
"""Initialize the Fully Kiosk Browser switch entity."""
super().__init__(coordinator)
self.entity_description = description
self._attr_unique_id = f"{coordinator.data['deviceID']}-{description.key}"
@property
def is_on(self) -> bool | None:
"""Return true if the entity is on."""
if self.entity_description.is_on_fn(self.coordinator.data) is not None:
return bool(self.entity_description.is_on_fn(self.coordinator.data))
return None
async def async_turn_on(self, **kwargs: Any) -> None:
"""Turn the entity on."""
await self.entity_description.on_action(self.coordinator.fully)
await self.coordinator.async_refresh()
async def async_turn_off(self, **kwargs: Any) -> None:
"""Turn the entity off."""
await self.entity_description.off_action(self.coordinator.fully)
await self.coordinator.async_refresh()

View File

@ -65,6 +65,9 @@ def mock_fully_kiosk() -> Generator[MagicMock, None, None]:
client.getDeviceInfo.return_value = json.loads(
load_fixture("deviceinfo.json", DOMAIN)
)
client.getSettings.return_value = json.loads(
load_fixture("listsettings.json", DOMAIN)
)
yield client

View File

@ -0,0 +1,332 @@
{
"tapsToPinDialogInSingleAppMode": "7",
"mdmSystemUpdatePolicy": "0",
"showMenuHint": true,
"movementBeaconList": "",
"authUsername": "",
"motionSensitivity": "90",
"remoteAdminPassword": "admin_password",
"launchOnBoot": true,
"kioskAppBlacklist": "",
"folderCleanupTime": "",
"preventSleepWhileScreenOff": false,
"touchInteraction": true,
"showBackButton": true,
"volumeLimits": "",
"addressBarBgColor": -2236963,
"mdmSystemAppsToEnable": "",
"rebootTime": "",
"kioskWifiPin": "",
"appLauncherTextColor": -16777216,
"wifiSSID": "",
"keepSleepingIfUnplugged": false,
"microphoneAccess": false,
"barcodeScanBroadcastExtra": "",
"cacheMode": "-1",
"disableOutgoingCalls": false,
"knoxDisableUsbDebugging": false,
"screensaverBrightness": "0",
"thirdPartyCookies": true,
"desktopMode": false,
"protectedContent": false,
"knoxDisableBluetoothTethering": false,
"safeBrowsing": false,
"mqttBrokerPassword": "mqtt_password",
"screensaverOtherAppIntent": "",
"disablePowerButton": true,
"inUseWhileKeyboardVisible": false,
"screensaverFullscreen": true,
"actionBarTitle": "Fully Kiosk Browser",
"pageTransitions": false,
"urlBlacklist": "",
"appBlockReturnIntent": "",
"playAlarmSoundUntilPin": false,
"enableQrScan": false,
"knoxDisableBackup": false,
"appLauncherScaling": "100",
"showAppLauncherOnStart": false,
"appToRunInForegroundOnStart": "",
"usageStatistics": true,
"restartOnCrash": true,
"tabsFgColor": -16777216,
"knoxDisableGoogleAccountsAutoSync": false,
"appToRunOnStart": "",
"knoxDisableDeveloperMode": false,
"sleepOnPowerDisconnect": false,
"remotePdfFileMode": "0",
"keepOnWhileFullscreen": true,
"mainWebAutomation": "",
"mdmMinimumPasswordLength": "5",
"deleteHistoryOnReload": false,
"showQrScanButton": false,
"mdmApkToInstall": "",
"autoplayVideos": false,
"loadOverview": false,
"startURL": "https://homeassistant.local/",
"screensaverOtherApp": false,
"showNewTabButton": false,
"advancedKioskProtection": false,
"mdmDisableKeyguard": false,
"searchProviderUrl": "https://www.google.com/search?q=",
"defaultWebviewBackgroundColor": -1,
"motionDetectionAcoustic": false,
"reloadOnScreenOn": false,
"knoxDisableMultiUser": false,
"enableBackButton": true,
"mdmDisableUsbStorage": false,
"actionBarBgUrl": "",
"lockSafeMode": false,
"setWifiWakelock": false,
"knoxHideStatusBar": false,
"ignoreMotionWhenScreensaverOnOff": false,
"kioskWifiPinCustomIntent": "",
"showTabCloseButtons": true,
"knoxDisablePowerSavingMode": false,
"killOtherApps": false,
"knoxDisableMtp": false,
"deleteWebstorageOnReload": false,
"knoxDisablePowerOff": false,
"knoxDisableGoogleCrashReport": false,
"barcodeScanIntent": "",
"mdmAppsToDisable": "",
"barcodeScanTargetUrl": "",
"knoxDisablePowerButton": false,
"actionBarFgColor": -1,
"fadeInOutDuration": "200",
"audioRecordUploads": false,
"autoplayAudio": false,
"remoteAdminCamshot": true,
"showPrintButton": false,
"knoxDisableTaskManager": false,
"kioskExitGesture": "2",
"remoteAdminScreenshot": true,
"kioskAppWhitelist": "de.badaix.snapcast",
"enableVersionInfo": true,
"removeStatusBar": false,
"knoxDisableCellularData": false,
"showShareButton": false,
"recreateTabsOnReload": false,
"injectJsCode": "",
"screensaverWallpaperURL": "fully://color#000000",
"removeNavigationBar": false,
"forceScreenOrientation": "0",
"showStatusBar": false,
"knoxDisableWiFi": false,
"inUseWhileAnotherAppInForeground": false,
"appLauncherBackgroundColor": -1,
"mdmAppLockTaskWhitelist": "",
"webcamAccess": false,
"knoxDisableClipboard": false,
"playAlarmSoundOnMovement": false,
"loadContentZipFileUrl": "",
"forceImmersive": false,
"forceShowKeyboard": false,
"keepScreenOn": true,
"pauseMotionInBackground": false,
"showCamPreview": false,
"timeToScreenOffV2": "0",
"softKeyboard": true,
"statusBarColor": 0,
"mqttBrokerUsername": "mqtt",
"fileUploads": false,
"rootEnable": true,
"knoxDisableUsbTethering": false,
"screensaverPlaylist": "",
"showNavigationBar": false,
"launcherApps": "[\n {\n \"label\": \"Plex\",\n \"component\": \"com.plexapp.android\\/com.plexapp.plex.activities.SplashActivity\"\n },\n {\n \"label\": \"Spotify\",\n \"component\": \"com.spotify.music\\/com.spotify.music.MainActivity\"\n }\n]",
"autoImportSettings": true,
"motionDetection": false,
"cloudService": false,
"webviewDarkMode": "1",
"killAppsBeforeStartingList": "",
"websiteIntegration": true,
"clientCaPassword": "",
"deleteCookiesOnReload": false,
"errorURL": "",
"knoxDisableFactoryReset": false,
"knoxDisableCamera": false,
"knoxEnabled": false,
"playMedia": true,
"stopScreensaverOnMotion": true,
"redirectBlocked": false,
"mdmDisableADB": true,
"showTabs": false,
"restartAfterUpdate": true,
"mqttEventTopic": "$appId/event/$event/$deviceId",
"fontSize": "100",
"clearCacheEach": false,
"mdmDisableVolumeButtons": false,
"knoxDisableVpn": false,
"confirmExit": true,
"ignoreSSLerrors": true,
"mqttClientId": "",
"setRemoveSystemUI": false,
"wifiKey": "",
"screenOffInDarkness": false,
"knoxDisableWifiDirect": false,
"inactiveTabsBgColor": -4144960,
"useWideViewport": true,
"forceSwipeUnlock": false,
"geoLocationAccess": false,
"graphicsAccelerationMode": "2",
"barcodeScanBroadcastAction": "",
"authPassword": "",
"tabsBgColor": -2236963,
"loadCurrentPageOnReload": false,
"skipReloadIfStartUrlShowing": false,
"enablePullToRefresh": false,
"motionSensitivityAcoustic": "90",
"wifiMode": "0",
"ignoreMotionWhenMoving": false,
"knoxDisableAirViewMode": false,
"actionBarCustomButtonUrl": "",
"kioskHomeStartURL": true,
"environmentSensorsEnabled": true,
"mdmRuntimePermissionPolicy": "0",
"disableCamera": false,
"knoxDisableRecentTaskButton": false,
"knoxDisableAirCommandMode": false,
"remoteAdminSingleAppExit": false,
"mqttDeviceInfoTopic": "$appId/deviceInfo/$deviceId",
"darknessLevel": "10",
"actionBarInSettings": false,
"remoteAdminLan": true,
"knoxDisableSDCardWrite": false,
"movementBeaconDistance": "5",
"forceSleepIfUnplugged": false,
"swipeTabs": false,
"alarmSoundFileUrl": "",
"knoxDisableStatusBar": false,
"reloadOnInternet": false,
"knoxDisableNonMarketApps": false,
"knoxDisableSettingsChanges": false,
"barcodeScanListenKeys": false,
"mdmLockTask": false,
"timeToScreensaverV2": "900",
"movementDetection": true,
"clientCaUrl": "",
"sleepOnPowerConnect": false,
"resumeVideoAudio": true,
"addXffHeader": false,
"readNfcTag": false,
"swipeNavigation": false,
"knoxDisableVolumeButtons": false,
"screenOnOnMovement": true,
"knoxHideNavigationBar": false,
"timeToClearSingleAppData": "0",
"timeToGoBackground": "0",
"timeToShutdownOnPowerDisconnect": "0",
"webviewDragging": true,
"timeToRegainFocus": "600",
"pauseWebviewOnPause": false,
"knoxDisableUsbHostStorage": false,
"folderCleanupList": "",
"movementWhenUnplugged": false,
"actionBarBgColor": -15906911,
"enableZoom": false,
"resetZoomEach": false,
"knoxDisableAndroidBeam": false,
"reloadOnWifiOn": true,
"compassSensitivity": "50",
"touchesOtherAppsBreakIdle": true,
"reloadPageFailure": "300",
"knoxDisableBackButton": false,
"actionBarIconUrl": "",
"initialScale": "0",
"knoxDisableMicrophoneState": false,
"remoteAdminFileManagement": true,
"knoxDisableFirmwareRecovery": false,
"errorUrlOnDisconnection": "0",
"addRefererHeader": true,
"showHomeButton": true,
"reloadEachSeconds": "0",
"accelerometerSensitivity": "80",
"knoxDisableScreenCapture": false,
"knoxDisableWifiTethering": false,
"knoxDisableEdgeScreen": false,
"forceScreenOrientationGlobal": false,
"mqttBrokerUrl": "tcp://192.168.1.2:1883",
"wakeupOnPowerConnect": false,
"knoxDisableClipboardShare": false,
"forceScreenUnlock": true,
"knoxDisableAirplaneMode": false,
"barcodeScanInsertInputField": false,
"waitInternetOnReload": true,
"forceOpenByAppUrl": "",
"disableVolumeButtons": true,
"disableStatusBar": true,
"kioskPin": "1234",
"screensaverDaydream": false,
"detectIBeacons": false,
"kioskWifiPinAction": "0",
"stopScreensaverOnMovement": true,
"videoCaptureUploads": false,
"disableIncomingCalls": false,
"motionCameraId": "",
"knoxDisableSafeMode": false,
"webHostFilter": false,
"urlWhitelist": "",
"disableOtherApps": true,
"progressBarColor": -13611010,
"enableTapSound": true,
"volumeLicenseKey": "",
"showActionBar": false,
"ignoreJustOnceLauncher": false,
"remoteAdmin": true,
"launcherBgUrl": "",
"mdmDisableSafeModeBoot": true,
"launcherInjectCode": "",
"cameraCaptureUploads": false,
"disableNotifications": false,
"sleepSchedule": "",
"knoxDisableAudioRecord": false,
"setCpuWakelock": false,
"enablePopups": false,
"mqttEnabled": true,
"knoxDisableOtaUpgrades": false,
"mdmDisableStatusBar": false,
"lastVersionInfo": "1.39",
"textSelection": false,
"jsAlerts": true,
"knoxActiveByKiosk": false,
"disableHomeButton": true,
"webviewDebugging": true,
"mdmDisableAppsFromUnknownSources": true,
"knoxDisableBluetooth": false,
"showAddressBar": false,
"batteryWarning": "20",
"playerCacheImages": true,
"localPdfFileMode": "0",
"resendFormData": false,
"mdmDisableScreenCapture": false,
"kioskMode": true,
"singleAppMode": false,
"mdmPasswordQuality": "0",
"enableUrlOtherApps": true,
"navigationBarColor": 0,
"isRunning": true,
"knoxDisableHomeButton": false,
"webviewScrolling": true,
"motionFps": "5",
"enableLocalhost": false,
"reloadOnScreensaverStop": false,
"customUserAgent": "",
"screenBrightness": "9",
"knoxDisableVideoRecord": false,
"showProgressBar": true,
"formAutoComplete": true,
"showRefreshButton": false,
"knoxDisableHeadphoneState": false,
"showForwardButton": true,
"timeToClearLauncherAppData": "0",
"bluetoothMode": "0",
"enableFullscreenVideos": true,
"remoteFileMode": "0",
"barcodeScanSubmitInputField": false,
"knoxDisableMultiWindowMode": false,
"singleAppIntent": "",
"userAgent": "0",
"runInForeground": true,
"deleteCacheOnReload": false,
"screenOnOnMotion": true
}

View File

@ -0,0 +1,81 @@
"""Test the Fully Kiosk Browser switches."""
from unittest.mock import MagicMock
from homeassistant.components.fully_kiosk.const import DOMAIN
import homeassistant.components.switch as switch
from homeassistant.const import ATTR_ENTITY_ID
from homeassistant.core import HomeAssistant
from homeassistant.helpers import device_registry as dr, entity_registry as er
from tests.common import MockConfigEntry
async def test_switches(
hass: HomeAssistant, mock_fully_kiosk: MagicMock, init_integration: MockConfigEntry
) -> None:
"""Test Fully Kiosk switches."""
entity_registry = er.async_get(hass)
device_registry = dr.async_get(hass)
entity = hass.states.get("switch.amazon_fire_screensaver")
assert entity
assert entity.state == "off"
entry = entity_registry.async_get("switch.amazon_fire_screensaver")
assert entry
assert entry.unique_id == "abcdef-123456-screensaver"
await call_service(hass, "turn_on", "switch.amazon_fire_screensaver")
assert len(mock_fully_kiosk.startScreensaver.mock_calls) == 1
await call_service(hass, "turn_off", "switch.amazon_fire_screensaver")
assert len(mock_fully_kiosk.stopScreensaver.mock_calls) == 1
entity = hass.states.get("switch.amazon_fire_maintenance_mode")
assert entity
assert entity.state == "off"
entry = entity_registry.async_get("switch.amazon_fire_maintenance_mode")
assert entry
assert entry.unique_id == "abcdef-123456-maintenance"
await call_service(hass, "turn_on", "switch.amazon_fire_maintenance_mode")
assert len(mock_fully_kiosk.enableLockedMode.mock_calls) == 1
await call_service(hass, "turn_off", "switch.amazon_fire_maintenance_mode")
assert len(mock_fully_kiosk.disableLockedMode.mock_calls) == 1
entity = hass.states.get("switch.amazon_fire_kiosk_lock")
assert entity
assert entity.state == "on"
entry = entity_registry.async_get("switch.amazon_fire_kiosk_lock")
assert entry
assert entry.unique_id == "abcdef-123456-kiosk"
await call_service(hass, "turn_off", "switch.amazon_fire_kiosk_lock")
assert len(mock_fully_kiosk.unlockKiosk.mock_calls) == 1
await call_service(hass, "turn_on", "switch.amazon_fire_kiosk_lock")
assert len(mock_fully_kiosk.lockKiosk.mock_calls) == 1
entity = hass.states.get("switch.amazon_fire_motion_detection")
assert entity
assert entity.state == "off"
entry = entity_registry.async_get("switch.amazon_fire_motion_detection")
assert entry
assert entry.unique_id == "abcdef-123456-motion-detection"
await call_service(hass, "turn_on", "switch.amazon_fire_motion_detection")
assert len(mock_fully_kiosk.enableMotionDetection.mock_calls) == 1
await call_service(hass, "turn_off", "switch.amazon_fire_motion_detection")
assert len(mock_fully_kiosk.disableMotionDetection.mock_calls) == 1
assert entry.device_id
device_entry = device_registry.async_get(entry.device_id)
assert device_entry
assert device_entry.configuration_url == "http://192.168.1.234:2323"
assert device_entry.entry_type is None
assert device_entry.hw_version is None
assert device_entry.identifiers == {(DOMAIN, "abcdef-123456")}
assert device_entry.manufacturer == "amzn"
assert device_entry.model == "KFDOWI"
assert device_entry.name == "Amazon Fire"
assert device_entry.sw_version == "1.42.5"
def call_service(hass, service, entity_id):
"""Call any service on entity."""
return hass.services.async_call(
switch.DOMAIN, service, {ATTR_ENTITY_ID: entity_id}, blocking=True
)