separate PVInfo from serve code

This commit is contained in:
2021-02-13 12:17:07 +00:00
parent 8892b1f320
commit bca92d0ff7
3 changed files with 101 additions and 94 deletions

View File

@ -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
View 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]

View File

@ -1,5 +0,0 @@
def typename(obj):
return type(obj).__name__