11from collections .abc import Callable
2- from dataclasses import dataclass
2+ from dataclasses import asdict , dataclass
33from types import MethodType
44from typing import Any , Literal
55
1515 enum_value_to_index ,
1616)
1717from fastcs .controller import BaseController
18- from fastcs .datatypes import Bool , Float , Int , String , T
18+ from fastcs .datatypes import Bool , DataType , Float , Int , String , T
1919from fastcs .exceptions import FastCSException
2020from fastcs .mapping import Mapping
2121
@@ -27,6 +27,25 @@ class EpicsIOCOptions:
2727 terminal : bool = True
2828
2929
30+ DATATYPE_NAME_TO_RECORD_FIELD = {
31+ "prec" : "PREC" ,
32+ "units" : "EGU" ,
33+ "min" : "DRVL" ,
34+ "max" : "DRVH" ,
35+ "min_alarm" : "LOPR" ,
36+ "max_alarm" : "HOPR" ,
37+ "znam" : "ZNAM" ,
38+ "onam" : "ONAM" ,
39+ }
40+
41+
42+ def datatype_to_epics_fields (datatype : DataType ) -> dict [str , Any ]:
43+ return {
44+ DATATYPE_NAME_TO_RECORD_FIELD [field ]: value
45+ for field , value in asdict (datatype ).items ()
46+ }
47+
48+
3049class EpicsIOC :
3150 def __init__ (self , pv_prefix : str , mapping : Mapping ):
3251 _add_pvi_info (f"{ pv_prefix } :PVI" )
@@ -184,36 +203,38 @@ def _get_input_record(pv: str, attribute: AttrR) -> RecordWrapper:
184203 return builder .mbbIn (pv , ** state_keys , ** attribute_fields )
185204
186205 match attribute .datatype :
187- case Bool (znam , onam ):
188- return builder .boolIn (pv , ZNAM = znam , ONAM = onam , ** attribute_fields )
189- case Int (units , min , max , min_alarm , max_alarm ):
190- return builder .longIn (
206+ case Bool ():
207+ record = builder .boolIn (
208+ pv , ** datatype_to_epics_fields (attribute .datatype ), ** attribute_fields
209+ )
210+ case Int ():
211+ record = builder .longIn (
191212 pv ,
192- EGU = units ,
193- DRVL = min ,
194- DRVH = max ,
195- LOPR = min_alarm ,
196- HOPR = max_alarm ,
213+ ** datatype_to_epics_fields (attribute .datatype ),
197214 ** attribute_fields ,
198215 )
199- case Float (prec , units , min , max , min_alarm , max_alarm ):
200- return builder .aIn (
216+ case Float ():
217+ record = builder .aIn (
201218 pv ,
202- PREC = prec ,
203- EGU = units ,
204- DRVL = min ,
205- DRVH = max ,
206- LOPR = min_alarm ,
207- HOPR = max_alarm ,
219+ ** datatype_to_epics_fields (attribute .datatype ),
208220 ** attribute_fields ,
209221 )
210222 case String ():
211- return builder .longStringIn (pv , ** attribute_fields )
223+ record = builder .longStringIn (
224+ pv , ** datatype_to_epics_fields (attribute .datatype ), ** attribute_fields
225+ )
212226 case _:
213227 raise FastCSException (
214228 f"Unsupported type { type (attribute .datatype )} : { attribute .datatype } "
215229 )
216230
231+ def datatype_updater (datatype : DataType ):
232+ for name , value in datatype_to_epics_fields (datatype ).items ():
233+ record .set_field (name , value )
234+
235+ attribute .add_update_datatype_callback (datatype_updater )
236+ return record
237+
217238
218239def _create_and_link_write_pv (
219240 pv_prefix : str , pv_name : str , attr_name : str , attribute : AttrW [T ]
@@ -262,48 +283,45 @@ def _get_output_record(pv: str, attribute: AttrW, on_update: Callable) -> Any:
262283 )
263284
264285 match attribute .datatype :
265- case Bool (znam , onam ):
266- return builder .boolOut (
286+ case Bool ():
287+ record = builder .boolOut (
267288 pv ,
268- ZNAM = znam ,
269- ONAM = onam ,
289+ ** datatype_to_epics_fields (attribute .datatype ),
270290 always_update = True ,
271291 on_update = on_update ,
272292 )
273- case Int (units , min , max , min_alarm , max_alarm ):
274- return builder .longOut (
293+ case Int ():
294+ record = builder .longOut (
275295 pv ,
276296 always_update = True ,
277297 on_update = on_update ,
278- EGU = units ,
279- DRVL = min ,
280- DRVH = max ,
281- LOPR = min_alarm ,
282- HOPR = max_alarm ,
298+ ** datatype_to_epics_fields (attribute .datatype ),
283299 ** attribute_fields ,
284300 )
285- case Float (prec , units , min , max , min_alarm , max_alarm ):
286- return builder .aOut (
301+ case Float ():
302+ record = builder .aOut (
287303 pv ,
288304 always_update = True ,
289305 on_update = on_update ,
290- PREC = prec ,
291- EGU = units ,
292- DRVL = min ,
293- DRVH = max ,
294- LOPR = min_alarm ,
295- HOPR = max_alarm ,
306+ ** datatype_to_epics_fields (attribute .datatype ),
296307 ** attribute_fields ,
297308 )
298309 case String ():
299- return builder .longStringOut (
310+ record = builder .longStringOut (
300311 pv , always_update = True , on_update = on_update , ** attribute_fields
301312 )
302313 case _:
303314 raise FastCSException (
304315 f"Unsupported type { type (attribute .datatype )} : { attribute .datatype } "
305316 )
306317
318+ def datatype_updater (datatype : DataType ):
319+ for name , value in datatype_to_epics_fields (datatype ).items ():
320+ record .set_field (name , value )
321+
322+ attribute .add_update_datatype_callback (datatype_updater )
323+ return record
324+
307325
308326def _create_and_link_command_pvs (pv_prefix : str , mapping : Mapping ) -> None :
309327 for single_mapping in mapping .get_controller_mappings ():
0 commit comments