Source code for lvmnps.switch.powerswitchbase
# -*- coding: utf-8 -*-
#
# @Author: Florian Briegel (briegel@mpia.de), Changgon Kim
# @Date: 2021-06-24
# @Filename: lvmnps/switch/powerswitchbase.py
# @License: BSD 3-clause (http://www.opensource.org/licenses/BSD-3-Clause)
from abc import abstractmethod
from sdsstools.logger import SDSSLogger
from lvmnps.switch.outlet import Outlet
__all__ = ["PowerSwitchBase"]
[docs]class PowerSwitchBase(object):
"""PowerswitchBase class for multiple power switches from different manufacturers
The Powerswitch classes will inherit the PowerSwitchBase class.
Parameters
----------
name
A name identifying the power switch.
'DLI Controller' for Dli switch
config
The configuration defined on the .yaml file under /etc/lvmnps.yml
log
The logger for logging
"""
def __init__(self, name: str, config: [], log: SDSSLogger):
self.name = name
self.log = log
self.config = config
self.numports = self.config_get("ports.number_of_ports", 8)
self.outlets = [
Outlet(
name,
self.config_get(f"ports.{portnum}.name"),
portnum,
self.config_get(f"ports.{portnum}.desc"),
-1,
)
for portnum in range(1, self.numports + 1)
]
self.log.debug(f"{self.outlets}")
self.onlyusedones = self.config_get("ouo", True)
self.log.debug(f"Only used ones: {self.onlyusedones}")
[docs] def config_get(self, key, default=None):
"""Read the configuration and extract the data as a structure that we want.
Notice: DOESNT work for keys with dots !!!
Parameters
----------
key
The tree structure as a string to extract the data.
For example, if the configuration structure is
ports;
1;
desc; "Hg-Ar spectral callibration lamp"
You can input the key as
"ports.1.desc" to take the information "Hg-Ar spectral callibration lamp"
"""
def g(config, key, d=None):
"""Internal function for parsing the key from the configuration.
Parameters
----------
config
config from the class member, which is saved from the class instance
key
The tree structure as a string to extract the data.
For example, if the configuration structure is
ports:
num:1
1:
desc: "Hg-Ar spectral callibration lamp"
You can input the key as
"ports.1.desc" to take the information "Hg-Ar spectral callibration lamp"
"""
k = key.split(".", maxsplit=1)
c = config.get(
k[0] if not k[0].isnumeric() else int(k[0])
) # keys can be numeric
return (
d
if c is None
else c
if len(k) < 2
else g(c, k[1], d)
if type(c) is dict
else d
)
return g(self.config, key, default)
[docs] def findOutletByName(self, name: str):
"""Find the outlet by the name, comparing with the name from the Outlet object.
Parameters
----------
name
The string to compare with the name in Outlet instance.
"""
for o in self.outlets:
if o.name == name:
return o
[docs] def collectOutletsByNameAndPort(self, name: str, portnum: int = 0):
"""Collects the outlet by the name and ports,
comparing with the name and ports from the Outlet object.
Parameters
----------
name
The string to compare with the name in Outlet instance.
portnum
The integer for indicating each Outlet instances
"""
if not name or name == self.name:
if portnum:
if portnum > self.numports:
return []
return [self.outlets[portnum - 1]]
else:
outlets = []
self.log.debug(str(self.onlyusedones))
for o in self.outlets:
if o.inuse or not self.onlyusedones:
outlets.append(o)
return outlets
else:
o = self.findOutletByName(name)
if o:
return [o]
return []
[docs] async def setState(self, state, name: str = "", portnum: int = 0):
"""Set the state of the Outlet instance to On/Off. (On = 1, Off = 0)
Parameters
----------
state
The boolian value (True, False) to set the state inside the Outlet object.
name
The string to compare with the name in Outlet instance.
portnum
The integer for indicating each Outlet instances
"""
if portnum > self.numports:
return []
return await self.switch(
Outlet.parse(state), self.collectOutletsByNameAndPort(name, portnum)
)
[docs] async def statusAsDict(self, name: str = "", portnum: int = 0):
"""Get the status of the Outlets by dictionary.
Parameters
----------
name
The string to compare with the name in Outlet instance.
'name' can be a switch or an outlet name.
portnum
The integer for indicating each Outlet instances
"""
outlets = self.collectOutletsByNameAndPort(name, portnum)
await self.update(outlets)
status = {}
for o in outlets:
status[f"{o.name}"] = o.toDict()
return status
[docs] @abstractmethod
async def start(self):
pass
[docs] @abstractmethod
async def stop(self):
pass
[docs] @abstractmethod
async def isReachable(self):
"""Verify we can reach the switch, returns true if ok"""
pass
[docs] @abstractmethod
async def update(self, outlets):
pass
[docs] @abstractmethod
async def switch(self, state, outlets):
pass