sdk/server/plugin: python sample

This commit is contained in:
Koushik Dutta
2021-11-13 16:15:19 -08:00
parent f7bdfb82c1
commit 78eb5a5e71
28 changed files with 879 additions and 319 deletions

View File

@@ -1,5 +1,6 @@
from __future__ import annotations
from collections.abc import Mapping
from rpc import RpcPeer, readLoop, RpcSerializer
from python.rpc import RpcPeer, readLoop, RpcSerializer
import asyncio
from asyncio.events import AbstractEventLoop
import json
@@ -8,8 +9,72 @@ import os
from typing import TypedDict
import base64
from os import sys
import time
import zipfile
import subprocess
from typing import Any
more = os.path.join(os.getcwd(), 'node_modules/@scrypted/sdk')
sys.path.insert(0, more)
import scrypted_python.scrypted_sdk
from scrypted_python.scrypted_sdk.types import ScryptedInterfaceProperty
class SystemDeviceState(TypedDict):
lastEventTime: int
stateTime: int
value: any
class SystemManager(scrypted_python.scrypted_sdk.SystemManager):
def __init__(self, api: Any, systemState: Mapping[str, Mapping[str, SystemDeviceState]]) -> None:
super().__init__()
self.api = api
self.systemState = systemState
class DeviceState(scrypted_python.scrypted_sdk.DeviceState):
def __init__(self, id: str, nativeId: str, systemManager: SystemManager, deviceManager: scrypted_python.scrypted_sdk.DeviceManager) -> None:
super().__init__()
self._id = id
self.nativeId = nativeId
self.deviceManager = deviceManager
self.systemManager = systemManager
def getScryptedProperty(self, property: str) -> Any:
deviceState = getattr(self.systemManager.systemState, self.nativeId, None)
if not deviceState:
print("missing nativeId id %s" % self.nativeId)
return None
return getattr(deviceState, property, None)
def setScryptedProperty(self, property: str, value: Any):
if property == ScryptedInterfaceProperty.id.value:
raise Exception("id is read only");
if property == ScryptedInterfaceProperty.mixins.value:
raise Exception("mixins is read only");
if property == ScryptedInterfaceProperty.interfaces.value:
raise Exception("interfaces is a read only post-mixin computed property, use providedInterfaces");
now = int(time.time() * 1000)
self.systemManager.systemState[self._id][property] = {
"lastEventTime": now,
"stateTime": now,
"value": value
}
self.systemManager.api.setState(self.nativeId, property, value)
class DeviceManager(scrypted_python.scrypted_sdk.DeviceManager):
def __init__(self, nativeIds: Mapping[str, DeviceStorage], systemManager: SystemManager) -> None:
super().__init__()
self.nativeIds = nativeIds
self.systemManager = systemManager
def getDeviceState(self, nativeId: str) -> DeviceState:
id = self.nativeIds[nativeId].id
return DeviceState(id, nativeId, self.systemManager, self)
class BufferSerializer(RpcSerializer):
def serialize(self, value):
@@ -19,12 +84,6 @@ class BufferSerializer(RpcSerializer):
return base64.b64decode(value)
class SystemDeviceState(TypedDict):
lastEventTime: int
stateTime: int
value: any
class DeviceStorage:
id: str
nativeId: str
@@ -48,31 +107,38 @@ class PluginRemote:
f.close()
zip = zipfile.ZipFile(zipPath)
requirements = zip.open('requirements.txt').read()
python_modules = os.path.join(os.environ.get('SCRYPTED_PLUGIN_VOLUME'), 'python', 'modules')
if not os.path.exists(python_modules):
os.makedirs(python_modules)
requirementstxt = os.path.join(python_modules, 'requirements.txt')
f = open(requirementstxt, 'wb')
f.write(requirements)
f.close()
if 'requirements.txt' in zip.namelist():
requirements = zip.open('requirements.txt').read()
# os.system('pip install -r %s --target %s' % (requirementstxt, python_modules))
result = subprocess.check_output(['pip', 'install', '-r', requirementstxt, '--target', python_modules], stderr=subprocess.STDOUT, text=True)
print(result)
requirementstxt = os.path.join(python_modules, 'requirements.txt')
f = open(requirementstxt, 'wb')
f.write(requirements)
f.close()
# os.system('pip install -r %s --target %s' % (requirementstxt, python_modules))
result = subprocess.check_output(['pip', 'install', '-r', requirementstxt, '--target', python_modules], stderr=subprocess.STDOUT, text=True)
print(result)
sys.path.insert(0, zipPath)
sys.path.insert(0, python_modules)
from main import plugin_main
plugin_main()
from scrypted_sdk import sdk_init # type: ignore
self.systemManager = SystemManager(self.api, self.systemState)
self.deviceManager = DeviceManager(self.nativeIds, self.systemManager)
sdk_init(self.systemManager, self.deviceManager)
from main import create_scrypted_plugin # type: ignore
return create_scrypted_plugin()
async def setSystemState(self, state):
self.systemState = state
async def setNativeId(self, nativeId, id, storage):
if nativeId:
if id:
ds = DeviceStorage()
ds.id = id
ds.storage = storage