added custom config and started developing roon trigger
This commit is contained in:
@@ -4,16 +4,18 @@ from pathlib import Path
|
|||||||
from lxml import etree
|
from lxml import etree
|
||||||
from functools import cached_property, lru_cache
|
from functools import cached_property, lru_cache
|
||||||
from arguments import ArgumentsParser
|
from arguments import ArgumentsParser
|
||||||
from typing import NamedTuple, Optional
|
from typing import NamedTuple, Optional, Any
|
||||||
|
from collections import OrderedDict
|
||||||
|
import xmltodict
|
||||||
|
|
||||||
class TriggerTuple(NamedTuple):
|
class TriggerTuple(NamedTuple):
|
||||||
name: str
|
name: str
|
||||||
interval_in_seconds: int
|
interval_in_seconds: int
|
||||||
governor: str
|
governor: str
|
||||||
|
custom_config: OrderedDict[str, Any]
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self) -> str:
|
||||||
return f"{self.name}, interval: {self.interval_in_seconds}, governor: {self.governor}"
|
return f"{self.name}, interval: {self.interval_in_seconds}, governor: {self.governor}, custom_config: {self.custom_config}"
|
||||||
|
|
||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
@@ -68,10 +70,17 @@ class Config:
|
|||||||
name = self._get_single_text_value_from_xpath('name', trigger_elem)
|
name = self._get_single_text_value_from_xpath('name', trigger_elem)
|
||||||
interval_in_seconds = self._get_single_text_value_from_xpath('intervalInSeconds', trigger_elem)
|
interval_in_seconds = self._get_single_text_value_from_xpath('intervalInSeconds', trigger_elem)
|
||||||
governor = self._get_single_text_value_from_xpath('governor', trigger_elem)
|
governor = self._get_single_text_value_from_xpath('governor', trigger_elem)
|
||||||
|
try:
|
||||||
|
custom_config_elem = self._get_single_element_by_xpath('customConfig', trigger_elem)
|
||||||
|
custom_config = xmltodict.parse(etree.tostring(custom_config_elem))['customConfig']
|
||||||
|
except AssertionError:
|
||||||
|
self.log.debug("Trigger %s has no custom config", name)
|
||||||
|
custom_config = OrderedDict({})
|
||||||
_new_trigger = TriggerTuple(
|
_new_trigger = TriggerTuple(
|
||||||
name=name,
|
name=name,
|
||||||
interval_in_seconds=int(interval_in_seconds),
|
interval_in_seconds=int(interval_in_seconds),
|
||||||
governor=governor
|
governor=governor,
|
||||||
|
custom_config=custom_config
|
||||||
)
|
)
|
||||||
ret_val.append(_new_trigger)
|
ret_val.append(_new_trigger)
|
||||||
self.log.info("Loaded trigger: %s", _new_trigger)
|
self.log.info("Loaded trigger: %s", _new_trigger)
|
||||||
|
|||||||
@@ -17,6 +17,15 @@
|
|||||||
<name>roon</name>
|
<name>roon</name>
|
||||||
<intervalInSeconds>2</intervalInSeconds>
|
<intervalInSeconds>2</intervalInSeconds>
|
||||||
<governor>performance</governor>
|
<governor>performance</governor>
|
||||||
|
<customConfig>
|
||||||
|
<extensionId>cpu_governor_auto_adjust_for_roon</extensionId>
|
||||||
|
<displayName>CPU Governor Auto Adjust for Roon</displayName>
|
||||||
|
<displayVersion>1.0.0</displayVersion>
|
||||||
|
<publisher>Martin Reurekas</publisher>
|
||||||
|
<email>martin@semrks.nl</email>
|
||||||
|
<coreIdFilePath>/home/martin/dev/cpu_governor_auto_adjust/triggers/.data/core_id_file</coreIdFilePath>
|
||||||
|
<tokenFilePath>/home/martin/dev/cpu_governor_auto_adjust/triggers/.data/token_file</tokenFilePath>
|
||||||
|
</customConfig>
|
||||||
</trigger>
|
</trigger>
|
||||||
</triggers>
|
</triggers>
|
||||||
</cpuGovernorAutoAdjust>
|
</cpuGovernorAutoAdjust>
|
||||||
|
|||||||
@@ -14,10 +14,10 @@ def getLogger(name: str = 'root', loglevel: str = 'INFO') -> Logger:
|
|||||||
# if logger 'name' does not already exist, create it and attach handlers
|
# if logger 'name' does not already exist, create it and attach handlers
|
||||||
else:
|
else:
|
||||||
# set logLevel to loglevel or to INFO if requested level is incorrect
|
# set logLevel to loglevel or to INFO if requested level is incorrect
|
||||||
loglevel = getattr(logging, loglevel.upper(), "INFO")
|
loglevel = getattr(logging, loglevel.upper())
|
||||||
logger.setLevel(loglevel)
|
logger.setLevel(loglevel)
|
||||||
if loglevel == logging.DEBUG:
|
if loglevel == logging.DEBUG:
|
||||||
fmt = '%(asctime)s %(levelname)-8s %(message)s (%(filename)s)'
|
fmt = '%(asctime)s %(levelname)-8s %(message)s (%(filename)s:%(lineno)d)'
|
||||||
else:
|
else:
|
||||||
fmt = '%(asctime)s %(levelname)-8s %(message)s'
|
fmt = '%(asctime)s %(levelname)-8s %(message)s'
|
||||||
fmt_date = '%Y-%m-%dT%T'
|
fmt_date = '%Y-%m-%dT%T'
|
||||||
|
|||||||
+1
-1
@@ -1,2 +1,2 @@
|
|||||||
cpufreq==0.3.5
|
cpufreq==0.3.5
|
||||||
lxml==5.3.0
|
roonapi==0.1.6
|
||||||
|
|||||||
+1
-1
@@ -13,7 +13,7 @@ class TriggerScheduler(AppClass):
|
|||||||
async def trigger(self, _trigger: Trigger) -> None:
|
async def trigger(self, _trigger: Trigger) -> None:
|
||||||
"""Run a trigger with a specific name at a given interval."""
|
"""Run a trigger with a specific name at a given interval."""
|
||||||
while True:
|
while True:
|
||||||
self.log.info("Trigger %s is running", _trigger.name)
|
self.log.debug("Trigger %s is running", _trigger.name)
|
||||||
_trigger.run()
|
_trigger.run()
|
||||||
await asyncio.sleep(_trigger.config.interval_in_seconds)
|
await asyncio.sleep(_trigger.config.interval_in_seconds)
|
||||||
|
|
||||||
|
|||||||
+73
-1
@@ -1,11 +1,83 @@
|
|||||||
from trigger import Trigger
|
from trigger import Trigger
|
||||||
from config import Config
|
from config import Config
|
||||||
|
from roonapi import RoonApi, RoonDiscovery # type: ignore
|
||||||
|
from functools import cached_property
|
||||||
|
from typing import Any, NamedTuple
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
class RoonServer(NamedTuple):
|
||||||
|
ip: str
|
||||||
|
port: str
|
||||||
|
|
||||||
|
def __repr__(self) -> str:
|
||||||
|
return f"RoonServer: ip: {self.ip}, port: {self.port}"
|
||||||
|
|
||||||
class RoonTrigger(Trigger):
|
class RoonTrigger(Trigger):
|
||||||
def __init__(self, _config: Config) -> None:
|
def __init__(self, _config: Config) -> None:
|
||||||
super().__init__(_config)
|
super().__init__(_config)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def playing(self) -> bool:
|
||||||
|
return False
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def appinfo(self) -> dict[str, Any]:
|
||||||
|
_appinfo = {
|
||||||
|
"extension_id": self.config.custom_config['extensionId'],
|
||||||
|
"display_name": self.config.custom_config['displayName'],
|
||||||
|
"display_version": self.config.custom_config['displayVersion'],
|
||||||
|
"publisher": self.config.custom_config['publisher'],
|
||||||
|
"email": self.config.custom_config['email'],
|
||||||
|
}
|
||||||
|
self.log.debug("appinfo: %s", _appinfo)
|
||||||
|
return _appinfo
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def core_id(self) -> str:
|
||||||
|
_core_id_path = Path(self.config.custom_config['coreIdFilePath'])
|
||||||
|
if not _core_id_path.exists():
|
||||||
|
raise FileExistsError(f'unable to open {_core_id_path}')
|
||||||
|
_core_id = _core_id_path.read_text()
|
||||||
|
self.log.debug('roon core id: %s', _core_id)
|
||||||
|
return _core_id
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def token(self) -> str:
|
||||||
|
_token_path = Path(self.config.custom_config['tokenFilePath'])
|
||||||
|
if not _token_path.exists():
|
||||||
|
raise FileExistsError(f'unable to open {_token_path}')
|
||||||
|
_token = _token_path.read_text()
|
||||||
|
self.log.debug('roon token: %s', _token)
|
||||||
|
return _token
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def discover(self) -> RoonDiscovery:
|
||||||
|
return RoonDiscovery(self.core_id)
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def server(self) -> RoonServer:
|
||||||
|
_server = self.discover.first()
|
||||||
|
assert isinstance(_server, tuple) and len(_server) == 2, "failed to discover roon server"
|
||||||
|
self.discover.stop()
|
||||||
|
roon_server = RoonServer(_server[0], _server[1])
|
||||||
|
self.log.info("found %s", roon_server)
|
||||||
|
return roon_server
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def roonapi(self) -> RoonApi:
|
||||||
|
_roonapi = RoonApi(self.appinfo, self.token, self.server.ip, self.server.port, True)
|
||||||
|
return _roonapi
|
||||||
|
|
||||||
|
def my_state_callback(self, event, changed_ids):
|
||||||
|
"""Call when something changes in roon."""
|
||||||
|
self.log.info("my_state_callback event:%s changed_ids: %s" % (event, changed_ids))
|
||||||
|
for zone_id in changed_ids:
|
||||||
|
zone = self.roonapi.zones[zone_id]
|
||||||
|
self.log.info("zone_id:%s zone_info: %s" % (zone_id, zone))
|
||||||
|
|
||||||
def run(self) -> bool:
|
def run(self) -> bool:
|
||||||
self.log.info("run check code")
|
self.roonapi.register_state_callback(self.my_state_callback)
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
Reference in New Issue
Block a user