separate PVInfo from serve code
This commit is contained in:
100
morioc/morioc.py
100
morioc/morioc.py
@ -2,10 +2,10 @@ from time import sleep
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
from pcaspy import SimpleServer, Driver
|
from pcaspy import SimpleServer, Driver
|
||||||
from pcaspy.driver import manager, _ait_d as AIT_D
|
from pcaspy.driver import manager
|
||||||
|
|
||||||
from context import Context
|
from context import Context
|
||||||
from utils import typename
|
from pvinfo import make_pvinfos, make_pvdb, make_values
|
||||||
|
|
||||||
|
|
||||||
INITIAL_PVDB = { #TODO make wait_time caput-able
|
INITIAL_PVDB = { #TODO make wait_time caput-able
|
||||||
@ -14,15 +14,6 @@ INITIAL_PVDB = { #TODO make wait_time caput-able
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
D_AIT = {v:k for k, v in AIT_D.items()}
|
|
||||||
|
|
||||||
#PV data type: enum, string, char, float or int
|
|
||||||
DTYPES = {
|
|
||||||
str: "string",
|
|
||||||
float: "float",
|
|
||||||
int: "int"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class DefaultDriver(Driver): #TODO: caget on START_TIME crashes without this subclass?!
|
class DefaultDriver(Driver): #TODO: caget on START_TIME crashes without this subclass?!
|
||||||
@ -49,6 +40,7 @@ class MorIOC(Context):
|
|||||||
self.driver.setParam("START_TIME", str(now))
|
self.driver.setParam("START_TIME", str(now))
|
||||||
self.driver.updatePVs()
|
self.driver.updatePVs()
|
||||||
|
|
||||||
|
self.running = False
|
||||||
self.thread = Thread(target=self.run, daemon=True)
|
self.thread = Thread(target=self.run, daemon=True)
|
||||||
self.thread.start()
|
self.thread.start()
|
||||||
|
|
||||||
@ -65,14 +57,16 @@ class MorIOC(Context):
|
|||||||
|
|
||||||
|
|
||||||
def serve(self, **kwargs):
|
def serve(self, **kwargs):
|
||||||
ts, vs = make_mappings(kwargs, parse_string=False)
|
pvis = make_pvinfos(kwargs, parse_string=False)
|
||||||
pvdb = make_pvdb(ts)
|
pvdb = make_pvdb(pvis)
|
||||||
self.createPV(pvdb)
|
self.createPV(pvdb)
|
||||||
self.setParams(**vs)
|
pvvs = make_values(pvis)
|
||||||
|
self.setParams(**pvvs)
|
||||||
|
|
||||||
|
|
||||||
def host(self, **kwargs):
|
def host(self, **kwargs):
|
||||||
ts, _vs = make_mappings(kwargs, parse_string=True)
|
pvis = make_pvinfos(kwargs, parse_string=True)
|
||||||
pvdb = make_pvdb(ts)
|
pvdb = make_pvdb(pvis)
|
||||||
self.createPV(pvdb)
|
self.createPV(pvdb)
|
||||||
|
|
||||||
|
|
||||||
@ -81,7 +75,7 @@ class MorIOC(Context):
|
|||||||
return
|
return
|
||||||
print("new PVs", pvdb)
|
print("new PVs", pvdb)
|
||||||
current_pvdb = self.driver.pvDB #TODO crash due to keyerror otherwise
|
current_pvdb = self.driver.pvDB #TODO crash due to keyerror otherwise
|
||||||
self.server.createPV(self.prefix, pvdb)
|
self.server.createPV(self.prefix, pvdb) #TODO if pv name already contains ":", don't prepend self.prefix?!
|
||||||
self.driver = self.DriverClass()
|
self.driver = self.DriverClass()
|
||||||
self.driver.pvDB.update(current_pvdb)
|
self.driver.pvDB.update(current_pvdb)
|
||||||
|
|
||||||
@ -111,75 +105,3 @@ class MorIOC(Context):
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
def make_mappings(name_to_dtype_or_value, *args, **kwargs):
|
|
||||||
name_to_dtype = {}
|
|
||||||
name_to_value = {}
|
|
||||||
|
|
||||||
for name, type_or_value in name_to_dtype_or_value.items():
|
|
||||||
name = name.upper()
|
|
||||||
dtype, value = infer_type(type_or_value, *args, **kwargs)
|
|
||||||
|
|
||||||
name_to_dtype[name] = dtype
|
|
||||||
name_to_value[name] = value
|
|
||||||
|
|
||||||
return name_to_dtype, name_to_value
|
|
||||||
|
|
||||||
|
|
||||||
def infer_type(value, parse_string=True): #TODO arrays? strings?
|
|
||||||
# str -> "string", ""
|
|
||||||
# "test" -> "string", "test"
|
|
||||||
|
|
||||||
#TODO parse_string, when?
|
|
||||||
# "string" -> "string", ""
|
|
||||||
# "float" -> "float", 0.0
|
|
||||||
# or
|
|
||||||
# "string" -> "string", "string"
|
|
||||||
# "float" -> "string", "float"
|
|
||||||
|
|
||||||
if isinstance(value, type):
|
|
||||||
dtype = value
|
|
||||||
value = dtype()
|
|
||||||
else:
|
|
||||||
dtype = type(value)
|
|
||||||
|
|
||||||
if parse_string and isinstance(value, str):
|
|
||||||
if value in DTYPES.values():
|
|
||||||
dtype = value
|
|
||||||
value = ""
|
|
||||||
|
|
||||||
if not isinstance(dtype, str):
|
|
||||||
dtype = DTYPES.get(dtype, "string") #TODO default?
|
|
||||||
|
|
||||||
return dtype, value
|
|
||||||
|
|
||||||
|
|
||||||
def make_pvdb(name_to_dtype):
|
|
||||||
pvdb = {}
|
|
||||||
for name, dtype in name_to_dtype.items():
|
|
||||||
if not pv_is_managed(name):
|
|
||||||
print("will create", name)
|
|
||||||
pvdb[name] = {"type": dtype}
|
|
||||||
else:
|
|
||||||
pv_type = get_managed_pv_type(name)
|
|
||||||
if pv_type != dtype:
|
|
||||||
print(f"type for {name} changed:", pv_type, "->", dtype) #TODO what should be done if this happens?
|
|
||||||
# self.deletePV(name)
|
|
||||||
# pvdb[name] = {"type": dtype}
|
|
||||||
return pvdb
|
|
||||||
|
|
||||||
|
|
||||||
def pv_is_managed(name):
|
|
||||||
managed_pvs = manager.pvs["default"]
|
|
||||||
return name in managed_pvs
|
|
||||||
|
|
||||||
def get_managed_pv_type(name):
|
|
||||||
managed_pvs = manager.pvs["default"]
|
|
||||||
pv = managed_pvs[name]
|
|
||||||
pv_type = pv.info.type
|
|
||||||
return D_AIT[pv_type]
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#TODO:
|
|
||||||
# - if pv name already contains ":", don't prepend prefix?!
|
|
||||||
|
|
||||||
|
90
morioc/pvinfo.py
Normal file
90
morioc/pvinfo.py
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
from pcaspy.driver import manager, _ait_d as AIT_D
|
||||||
|
|
||||||
|
|
||||||
|
D_AIT = {v:k for k, v in AIT_D.items()}
|
||||||
|
|
||||||
|
#PV data type: enum, string, char, float or int
|
||||||
|
DTYPES = {
|
||||||
|
str: "string",
|
||||||
|
float: "float",
|
||||||
|
int: "int"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def make_values(pvinfos):
|
||||||
|
return {pvi.name: pvi.value for pvi in pvinfos}
|
||||||
|
|
||||||
|
|
||||||
|
def make_pvinfos(kwargs, parse_string=True):
|
||||||
|
return [PVInfo(*args, parse_string=parse_string) for args in kwargs.items()]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class PVInfo:
|
||||||
|
|
||||||
|
def __init__(self, name, data, parse_string=True):
|
||||||
|
self.name = name.upper()
|
||||||
|
self.dtype, self.value = infer_type(data, parse_string=parse_string)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def infer_type(value, parse_string=True): #TODO arrays? strings?
|
||||||
|
# str -> "string", ""
|
||||||
|
# "test" -> "string", "test"
|
||||||
|
|
||||||
|
#TODO parse_string, when?
|
||||||
|
# "string" -> "string", ""
|
||||||
|
# "float" -> "float", 0.0
|
||||||
|
# or
|
||||||
|
# "string" -> "string", "string"
|
||||||
|
# "float" -> "string", "float"
|
||||||
|
|
||||||
|
if isinstance(value, type):
|
||||||
|
dtype = value
|
||||||
|
value = dtype()
|
||||||
|
else:
|
||||||
|
dtype = type(value)
|
||||||
|
|
||||||
|
if parse_string and isinstance(value, str):
|
||||||
|
if value in DTYPES.values():
|
||||||
|
dtype = value
|
||||||
|
value = ""
|
||||||
|
|
||||||
|
if not isinstance(dtype, str):
|
||||||
|
dtype = DTYPES.get(dtype, "string") #TODO default?
|
||||||
|
|
||||||
|
return dtype, value
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def make_pvdb(pvinfos):
|
||||||
|
pvdb = {}
|
||||||
|
for pvi in pvinfos:
|
||||||
|
name, dtype = pvi.name, pvi.dtype
|
||||||
|
|
||||||
|
if not pv_is_managed(name):
|
||||||
|
print("will create", name)
|
||||||
|
pvdb[name] = {"type": dtype}
|
||||||
|
else:
|
||||||
|
pv_type = get_managed_pv_type(name)
|
||||||
|
if pv_type != dtype:
|
||||||
|
print(f"type for {name} changed:", pv_type, "->", dtype) #TODO what should be done if this happens?
|
||||||
|
# self.deletePV(name)
|
||||||
|
# pvdb[name] = {"type": dtype}
|
||||||
|
|
||||||
|
return pvdb
|
||||||
|
|
||||||
|
|
||||||
|
def pv_is_managed(name):
|
||||||
|
managed_pvs = manager.pvs["default"]
|
||||||
|
return name in managed_pvs
|
||||||
|
|
||||||
|
def get_managed_pv_type(name):
|
||||||
|
managed_pvs = manager.pvs["default"]
|
||||||
|
pv = managed_pvs[name]
|
||||||
|
pv_type = pv.info.type
|
||||||
|
return D_AIT[pv_type]
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
|||||||
|
|
||||||
def typename(obj):
|
|
||||||
return type(obj).__name__
|
|
||||||
|
|
||||||
|
|
Reference in New Issue
Block a user