Compare commits
110 Commits
Author | SHA1 | Date | |
---|---|---|---|
4c71e44cd2 | |||
5d0c980e22 | |||
f1bbdec2b3 | |||
2bdf9c6542 | |||
1fba0fad42 | |||
0a5de1ebc2 | |||
92c53ad3ba | |||
802d4e0c99 | |||
ee040ce98a | |||
b1f9c74269 | |||
63210c9924 | |||
47c5e297d4 | |||
6cd83eabcc | |||
caaefec6db | |||
6dfb3bcee8 | |||
d492f7326f | |||
7929c37027 | |||
76349e38f9 | |||
647d87f70f | |||
798c268eb4 | |||
9467f5233c | |||
a7ff73a34d | |||
bf018e74ba | |||
801f80af7f | |||
26fa5371e9 | |||
2bad1ffee5 | |||
b2b77c70ea | |||
192cde605e | |||
c7d23e40e9 | |||
2561e82086 | |||
55c96ffe4f | |||
17a44ef42a | |||
fcdee8e3ec | |||
dddf74df9e | |||
ac251ea515 | |||
9e4f9b7b95 | |||
4f65ae7e46 | |||
a73b7e7d88 | |||
76a78871b4 | |||
118e22ee44 | |||
c63f98f3cb | |||
6514a1b2ee | |||
aeec940659 | |||
4571af8534 | |||
adfb561308 | |||
70a31b5cae | |||
8ee97ade63 | |||
1715f95dd4 | |||
db29776dd5 | |||
a2905d9fbc | |||
16b826394f | |||
ea8570d422 | |||
1169e0cd09 | |||
7d02498b3d | |||
694b121c01 | |||
0f50de9a7f | |||
b454f47a12 | |||
6e7be6b4c7 | |||
af28511403 | |||
9d9d31693b | |||
3a7fff713d | |||
2acab33faa | |||
8c589cc138 | |||
2b42e3fa0a | |||
5b0da3ba98 | |||
c80b4ac5fb | |||
8cb9154bb5 | |||
813d1b76ef | |||
183709b7ce | |||
2cdf1fc58e | |||
ffaa9c83bd | |||
f9a0fdf7e4 | |||
7dfb2ff4e3 | |||
84c0017c03 | |||
2126956160 | |||
4cdd3b0709 | |||
15d38d7cc1 | |||
9904d31f0b | |||
b07d2ae8a3 | |||
7d7cb02f17 | |||
1017925ca0 | |||
bb14d02884 | |||
4c499cf048 | |||
e403396941 | |||
5b42df4a5e | |||
841ef224f6 | |||
8142ba746d | |||
5358412b7a | |||
010f0747e1 | |||
047c52b5a5 | |||
f846c5cb31 | |||
0e4a427bc3 | |||
2d8b609a3c | |||
6e3865b345 | |||
0004dc7620 | |||
158477792f | |||
fd0e762d18 | |||
a16ec6cc91 | |||
777a2cb6a9 | |||
cb3e98f86d | |||
a8bafde64e | |||
36c512d50b | |||
17b7a01ce1 | |||
be66faa591 | |||
e27b4f72b5 | |||
bc7922f5c8 | |||
99a58933ec | |||
9e000528d2 | |||
4a2ce62dd8 | |||
9e6699dd1e |
@ -1,6 +1,5 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# pylint: disable=invalid-name
|
# pylint: disable=invalid-name
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
# *****************************************************************************
|
# *****************************************************************************
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify it under
|
# This program is free software; you can redistribute it and/or modify it under
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
# *****************************************************************************
|
# *****************************************************************************
|
||||||
# Copyright (c) 2015-2016 by the authors, see LICENSE
|
# Copyright (c) 2015-2016 by the authors, see LICENSE
|
||||||
#
|
#
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# pylint: disable=invalid-name
|
# pylint: disable=invalid-name
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
# *****************************************************************************
|
# *****************************************************************************
|
||||||
# Copyright (c) 2015-2016 by the authors, see LICENSE
|
# Copyright (c) 2015-2016 by the authors, see LICENSE
|
||||||
#
|
#
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
# *****************************************************************************
|
# *****************************************************************************
|
||||||
# Copyright (c) 2015-2016 by the authors, see LICENSE
|
# Copyright (c) 2015-2016 by the authors, see LICENSE
|
||||||
#
|
#
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
# *****************************************************************************
|
# *****************************************************************************
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify it under
|
# This program is free software; you can redistribute it and/or modify it under
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# pylint: disable=invalid-name
|
# pylint: disable=invalid-name
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
# *****************************************************************************
|
# *****************************************************************************
|
||||||
# This program is free software; you can redistribute it and/or modify it under
|
# This program is free software; you can redistribute it and/or modify it under
|
||||||
# the terms of the GNU General Public License as published by the Free Software
|
# the terms of the GNU General Public License as published by the Free Software
|
||||||
|
22
calibtest.py
Normal file
22
calibtest.py
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import sys
|
||||||
|
import os
|
||||||
|
from glob import glob
|
||||||
|
from frappy_psi.calcurve import CalCurve
|
||||||
|
|
||||||
|
os.chdir('/Users/zolliker/gitpsi/calcurves')
|
||||||
|
|
||||||
|
if len(sys.argv) > 1:
|
||||||
|
calib = sys.argv[1]
|
||||||
|
c = CalCurve(calib)
|
||||||
|
else:
|
||||||
|
for file in sorted(glob('*.*')):
|
||||||
|
if file.endswith('.md') or file.endswith('.std'):
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
c = CalCurve(file)
|
||||||
|
xy = c.export()
|
||||||
|
print('%9.4g %12.7g %9.4g %9.4g %s' % (tuple(c.extx) + tuple(c.exty) + (file,)))
|
||||||
|
except Exception as e:
|
||||||
|
print(file, e)
|
||||||
|
calib = file
|
||||||
|
|
@ -24,6 +24,7 @@ Mod('ts_low',
|
|||||||
minrange=13,
|
minrange=13,
|
||||||
range=22,
|
range=22,
|
||||||
tolerance = 0.1,
|
tolerance = 0.1,
|
||||||
|
vexc = 3,
|
||||||
htrrng=4,
|
htrrng=4,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -32,7 +33,8 @@ Mod('ts_high',
|
|||||||
'sample Cernox',
|
'sample Cernox',
|
||||||
channel = 1,
|
channel = 1,
|
||||||
switcher = 'lsc_channel',
|
switcher = 'lsc_channel',
|
||||||
minrange=9,
|
minrange=11,
|
||||||
|
vexc = 5,
|
||||||
range=22,
|
range=22,
|
||||||
tolerance = 0.1,
|
tolerance = 0.1,
|
||||||
htrrng=5,
|
htrrng=5,
|
||||||
@ -45,6 +47,8 @@ Mod('ts',
|
|||||||
value=Param(unit='K'),
|
value=Param(unit='K'),
|
||||||
low='ts_low',
|
low='ts_low',
|
||||||
high='ts_high',
|
high='ts_high',
|
||||||
|
#min_high=0.6035,
|
||||||
|
#max_low=1.6965,
|
||||||
min_high=0.6,
|
min_high=0.6,
|
||||||
max_low=1.7,
|
max_low=1.7,
|
||||||
tolerance=0.1,
|
tolerance=0.1,
|
||||||
|
@ -74,10 +74,10 @@ Mod('currentsource',
|
|||||||
Mod('mf',
|
Mod('mf',
|
||||||
'frappy_mlz.amagnet.GarfieldMagnet',
|
'frappy_mlz.amagnet.GarfieldMagnet',
|
||||||
'magnetic field module, handling polarity switching and stuff',
|
'magnetic field module, handling polarity switching and stuff',
|
||||||
subdev_currentsource = 'currentsource',
|
currentsource = 'currentsource',
|
||||||
subdev_enable = 'enable',
|
enable = 'enable',
|
||||||
subdev_polswitch = 'polarity',
|
polswitch = 'polarity',
|
||||||
subdev_symmetry = 'symmetry',
|
symmetry = 'symmetry',
|
||||||
target = Param(unit='T'),
|
target = Param(unit='T'),
|
||||||
value = Param(unit='T'),
|
value = Param(unit='T'),
|
||||||
userlimits = (-0.35, 0.35),
|
userlimits = (-0.35, 0.35),
|
||||||
|
19
cfg/attocube_cfg.py
Normal file
19
cfg/attocube_cfg.py
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
Node('attocube_test.psi.ch',
|
||||||
|
'a single attocube axis',
|
||||||
|
interface='tcp://5000',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('r',
|
||||||
|
'frappy_psi.attocube.Axis',
|
||||||
|
'ANRv220-F3-02882',
|
||||||
|
axis = 1,
|
||||||
|
value = Param(unit='deg'),
|
||||||
|
tolerance = 0.1,
|
||||||
|
target_min = 0,
|
||||||
|
target_max = 360,
|
||||||
|
steps_fwd = 45,
|
||||||
|
steps_bwd = 85,
|
||||||
|
step_mode = True,
|
||||||
|
# gear = 1.2,
|
||||||
|
)
|
||||||
|
|
@ -41,6 +41,6 @@ Mod('label',
|
|||||||
'frappy_demo.modules.Label',
|
'frappy_demo.modules.Label',
|
||||||
'some label indicating the state of the magnet `mf`.',
|
'some label indicating the state of the magnet `mf`.',
|
||||||
system = 'Cryomagnet MX15',
|
system = 'Cryomagnet MX15',
|
||||||
subdev_mf = 'mf',
|
mf = 'mf',
|
||||||
subdev_ts = 'ts',
|
ts = 'ts',
|
||||||
)
|
)
|
||||||
|
231
cfg/dilsc_cfg.py
Normal file
231
cfg/dilsc_cfg.py
Normal file
@ -0,0 +1,231 @@
|
|||||||
|
Node('cfg/dilsc1.cfg',
|
||||||
|
'triton test',
|
||||||
|
interface='5000',
|
||||||
|
name='dilsc1',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('triton',
|
||||||
|
'frappy_psi.mercury.IO',
|
||||||
|
'connection to triton software',
|
||||||
|
uri='tcp://192.168.2.33:33576',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('T_mix',
|
||||||
|
'frappy_psi.triton.TemperatureSensor',
|
||||||
|
'mix. chamber temperature',
|
||||||
|
slot='T8',
|
||||||
|
io='triton',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('T_pt2head',
|
||||||
|
'frappy_psi.triton.TemperatureSensor',
|
||||||
|
'PTR2 head temperature',
|
||||||
|
slot='T1',
|
||||||
|
io='triton',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('T_pt2plate',
|
||||||
|
'frappy_psi.triton.TemperatureSensor',
|
||||||
|
'PTR2 plate temperature',
|
||||||
|
slot='T2',
|
||||||
|
io='triton',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('T_still',
|
||||||
|
'frappy_psi.triton.TemperatureSensor',
|
||||||
|
'still temperature',
|
||||||
|
slot='T3',
|
||||||
|
io='triton',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('htr_still',
|
||||||
|
'frappy_psi.triton.HeaterOutput',
|
||||||
|
'still heater',
|
||||||
|
slot='H2',
|
||||||
|
io='triton',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('T_coldpl',
|
||||||
|
'frappy_psi.triton.TemperatureSensor',
|
||||||
|
'cold plate temperature',
|
||||||
|
slot='T4',
|
||||||
|
io='triton',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('T_mixcx',
|
||||||
|
'frappy_psi.triton.TemperatureSensor',
|
||||||
|
'mix. chamber cernox',
|
||||||
|
slot='T5',
|
||||||
|
io='triton',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('T_pt1head',
|
||||||
|
'frappy_psi.triton.TemperatureSensor',
|
||||||
|
'PTR1 head temperature',
|
||||||
|
slot='T6',
|
||||||
|
io='triton',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('T_pt1plate',
|
||||||
|
'frappy_psi.triton.TemperatureSensor',
|
||||||
|
'PTR1 plate temperature',
|
||||||
|
slot='T7',
|
||||||
|
io='triton',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('T_pucksensor',
|
||||||
|
'frappy_psi.triton.TemperatureLoop',
|
||||||
|
'puck sensor temperature',
|
||||||
|
output_module='htr_pucksensor',
|
||||||
|
slot='TA',
|
||||||
|
io='triton',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('htr_pucksensor',
|
||||||
|
'frappy_psi.triton.HeaterOutputWithRange',
|
||||||
|
'mix. chamber heater',
|
||||||
|
slot='H1,TA',
|
||||||
|
io='triton',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('T_magnet',
|
||||||
|
'frappy_psi.triton.TemperatureSensor',
|
||||||
|
'magnet temperature',
|
||||||
|
slot='T13',
|
||||||
|
io='triton',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('action',
|
||||||
|
'frappy_psi.triton.Action',
|
||||||
|
'higher level scripts',
|
||||||
|
io='triton',
|
||||||
|
slot='DR',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('p_dump',
|
||||||
|
'frappy_psi.mercury.PressureSensor',
|
||||||
|
'dump pressure',
|
||||||
|
slot='P1',
|
||||||
|
io='triton',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('p_cond',
|
||||||
|
'frappy_psi.mercury.PressureSensor',
|
||||||
|
'condenser pressure',
|
||||||
|
slot='P2',
|
||||||
|
io='triton',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('p_still',
|
||||||
|
'frappy_psi.mercury.PressureSensor',
|
||||||
|
'still pressure',
|
||||||
|
slot='P3',
|
||||||
|
io='triton',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('p_fore',
|
||||||
|
'frappy_psi.mercury.PressureSensor',
|
||||||
|
'pressure on the pump side',
|
||||||
|
slot='P5',
|
||||||
|
io='triton',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('p_back',
|
||||||
|
'frappy_psi.mercury.PressureSensor',
|
||||||
|
'pressure on the back side of the pump',
|
||||||
|
slot='P4',
|
||||||
|
io='triton',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('p_ovc',
|
||||||
|
'frappy_psi.mercury.PressureSensor',
|
||||||
|
'outer vacuum pressure',
|
||||||
|
slot='P6',
|
||||||
|
io='triton',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('V1',
|
||||||
|
'frappy_psi.triton.Valve',
|
||||||
|
'valve V1',
|
||||||
|
slot='V1',
|
||||||
|
io='triton',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('V2',
|
||||||
|
'frappy_psi.triton.Valve',
|
||||||
|
'valve V2',
|
||||||
|
slot='V2',
|
||||||
|
io='triton',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('V4',
|
||||||
|
'frappy_psi.triton.Valve',
|
||||||
|
'valve V4',
|
||||||
|
slot='V4',
|
||||||
|
io='triton',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('V5',
|
||||||
|
'frappy_psi.triton.Valve',
|
||||||
|
'valve V5',
|
||||||
|
slot='V5',
|
||||||
|
io='triton',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('V9',
|
||||||
|
'frappy_psi.triton.Valve',
|
||||||
|
'valve V9',
|
||||||
|
slot='V9',
|
||||||
|
io='triton',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('ips',
|
||||||
|
'frappy_psi.mercury.IO',
|
||||||
|
'IPS for magnet',
|
||||||
|
uri='192.168.127.254:3001',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('mf',
|
||||||
|
'frappy_psi.dilsc.VectorField',
|
||||||
|
'vector field',
|
||||||
|
x='mfx',
|
||||||
|
y='mfy',
|
||||||
|
z='mfz',
|
||||||
|
sphere_radius=0.6,
|
||||||
|
cylinders=((0.23, 5.2), (0.45, 0.8)),
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('mfx',
|
||||||
|
'frappy_psi.ips_mercury.SimpleField',
|
||||||
|
'magnetic field, x-axis',
|
||||||
|
slot='GRPX',
|
||||||
|
io='ips',
|
||||||
|
tolerance=0.0001,
|
||||||
|
wait_stable_field=0.0,
|
||||||
|
nunits=2,
|
||||||
|
target=Param(max=0.6),
|
||||||
|
ramp=0.225,
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('mfy',
|
||||||
|
'frappy_psi.ips_mercury.SimpleField',
|
||||||
|
'magnetic field, y axis',
|
||||||
|
slot='GRPY',
|
||||||
|
io='ips',
|
||||||
|
tolerance=0.0001,
|
||||||
|
wait_stable_field=0.0,
|
||||||
|
nunits=2,
|
||||||
|
target=Param(max=0.6),
|
||||||
|
ramp=0.225,
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('mfz',
|
||||||
|
'frappy_psi.ips_mercury.Field',
|
||||||
|
'magnetic field, z-axis',
|
||||||
|
slot='GRPZ',
|
||||||
|
io='ips',
|
||||||
|
tolerance=0.0001,
|
||||||
|
target=Param(max=5.2),
|
||||||
|
mode='DRIVEN',
|
||||||
|
ramp=0.52,
|
||||||
|
)
|
27
cfg/drums_cfg.py
Normal file
27
cfg/drums_cfg.py
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
Node('relais.psi.ch',
|
||||||
|
'relais test',
|
||||||
|
'tcp://5000',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('rl',
|
||||||
|
'frappy_psi.ionopimax.DigitalOutput',
|
||||||
|
'left relais',
|
||||||
|
addr = 'o1',
|
||||||
|
value = 0, # start with relais off
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('rr',
|
||||||
|
'frappy_psi.ionopimax.DigitalOutput',
|
||||||
|
'right relais',
|
||||||
|
addr = 'o2',
|
||||||
|
value = 0, # start with relais off
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('drummer',
|
||||||
|
'frappy_psi.drums.Drums',
|
||||||
|
'drummer',
|
||||||
|
target = 150,
|
||||||
|
pattern='l2L2rl1R1L2',
|
||||||
|
left='rl',
|
||||||
|
right='rr',
|
||||||
|
)
|
52
cfg/flowsas_cfg.py
Normal file
52
cfg/flowsas_cfg.py
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
Node('flowsas.psi.ch',
|
||||||
|
'flowsas test motors',
|
||||||
|
'tcp://5000',
|
||||||
|
)
|
||||||
|
|
||||||
|
#Mod('mot_io',
|
||||||
|
# 'frappy_psi.phytron.PhytronIO',
|
||||||
|
# 'io for motor control',
|
||||||
|
# uri = 'serial:///dev/ttyUSB0',
|
||||||
|
# )
|
||||||
|
|
||||||
|
#Mod('hmot',
|
||||||
|
# 'frappy_psi.phytron.Motor',
|
||||||
|
# 'horizontal axis',
|
||||||
|
# axis = 'X',
|
||||||
|
# io = 'mot_io',
|
||||||
|
# encoder_mode= 'NO',
|
||||||
|
# )
|
||||||
|
|
||||||
|
#Mod('vmot',
|
||||||
|
# 'frappy_psi.phytron.Motor',
|
||||||
|
# 'vertical axis',
|
||||||
|
# axis = 'Y',
|
||||||
|
# io = 'mot_io',
|
||||||
|
# encoder_mode= 'NO',
|
||||||
|
# )
|
||||||
|
|
||||||
|
Mod('syr_io',
|
||||||
|
'frappy_psi.cetoni_pump.LabCannBus',
|
||||||
|
'Module for bus',
|
||||||
|
deviceconfig = "/home/l_samenv/frappy/cetoniSDK/CETONI_SDK_Raspi_64bit_v20220627/config/dual_pumps",
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('syr1',
|
||||||
|
'frappy_psi.cetoni_pump.SyringePump',
|
||||||
|
'First syringe pump',
|
||||||
|
io='syr_io',
|
||||||
|
pump_name = "Nemesys_S_1_Pump",
|
||||||
|
valve_name = "Nemesys_S_1_Valve",
|
||||||
|
inner_diameter_set = 10,
|
||||||
|
piston_stroke_set = 60,
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('syr2',
|
||||||
|
'frappy_psi.cetoni_pump.SyringePump',
|
||||||
|
'Second syringe pump',
|
||||||
|
io='syr_io',
|
||||||
|
pump_name = "Nemesys_S_2_Pump",
|
||||||
|
valve_name = "Nemesys_S_2_Valve",
|
||||||
|
inner_diameter_set = 1,
|
||||||
|
piston_stroke_set = 60,
|
||||||
|
)
|
@ -3,3 +3,5 @@
|
|||||||
logdir = ./log
|
logdir = ./log
|
||||||
piddir = ./pid
|
piddir = ./pid
|
||||||
confdir = ./cfg
|
confdir = ./cfg
|
||||||
|
comlog = True
|
||||||
|
|
||||||
|
16
cfg/lockin70_cfg.py
Normal file
16
cfg/lockin70_cfg.py
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
Node('lockin70test.psi.ch',
|
||||||
|
'lockin70 test',
|
||||||
|
'tcp://5000',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('io',
|
||||||
|
'frappy_psi.SR.SR_IO',
|
||||||
|
'lockin communication',
|
||||||
|
uri='10105266.psi.ch:50000',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('XY',
|
||||||
|
'frappy_psi.SR.XY70',
|
||||||
|
'XY channels',
|
||||||
|
io='io',
|
||||||
|
)
|
24
cfg/main/fw_cfg.py
Normal file
24
cfg/main/fw_cfg.py
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
Node('ft.config.sea.psi.ch',
|
||||||
|
'FW ILL furnace with W5 thermnocouple (1800 K), old power rack',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('sea_main',
|
||||||
|
'frappy_psi.sea.SeaClient',
|
||||||
|
'main sea connection for fw.config',
|
||||||
|
config='fw.config',
|
||||||
|
service='main',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('ts',
|
||||||
|
'frappy_psi.sea.SeaDrivable', '',
|
||||||
|
io='sea_main',
|
||||||
|
sea_object='tt',
|
||||||
|
rel_paths=['.', 'ts'],
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('t2',
|
||||||
|
'frappy_psi.sea.SeaReadable', '',
|
||||||
|
io='sea_main',
|
||||||
|
sea_object='tt',
|
||||||
|
rel_paths=['t2'],
|
||||||
|
)
|
@ -83,4 +83,5 @@ Mod('om',
|
|||||||
target_min = -180,
|
target_min = -180,
|
||||||
target_max = 360,
|
target_max = 360,
|
||||||
encoder_mode='READ',
|
encoder_mode='READ',
|
||||||
|
backlash=-1,
|
||||||
)
|
)
|
||||||
|
101
cfg/main/ma10heat_cfg.py
Normal file
101
cfg/main/ma10heat_cfg.py
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
Node('ma10.config.sea.psi.ch',
|
||||||
|
'10 Tesla vertical cryomagnet',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('sea_main',
|
||||||
|
'frappy_psi.sea.SeaClient',
|
||||||
|
'main sea connection for ma10.config',
|
||||||
|
config='ma10heat.config',
|
||||||
|
service='main',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('ts',
|
||||||
|
'frappy_psi.sea.SeaDrivable', '',
|
||||||
|
io='sea_main',
|
||||||
|
sea_object='tt',
|
||||||
|
rel_paths=['ts', 'set']
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('tm',
|
||||||
|
'frappy_psi.sea.SeaReadable', '',
|
||||||
|
io='sea_main',
|
||||||
|
sea_object='tt',
|
||||||
|
rel_paths=['tm', 'setvti']
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('ts2',
|
||||||
|
'frappy_psi.sea.SeaReadable', '',
|
||||||
|
io='sea_main',
|
||||||
|
sea_object='tt',
|
||||||
|
rel_paths=['ts_2']
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('cc',
|
||||||
|
'frappy_psi.sea.SeaReadable', '',
|
||||||
|
io='sea_main',
|
||||||
|
sea_object='cc',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('nv',
|
||||||
|
'frappy_psi.sea.SeaWritable', '',
|
||||||
|
io='sea_main',
|
||||||
|
sea_object='nv',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('hepump',
|
||||||
|
'frappy_psi.sea.SeaWritable', '',
|
||||||
|
io='sea_main',
|
||||||
|
sea_object='hepump',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('hemot',
|
||||||
|
'frappy_psi.sea.SeaDrivable', '',
|
||||||
|
io='sea_main',
|
||||||
|
sea_object='hemot',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('mf',
|
||||||
|
'frappy_psi.sea.SeaDrivable', '',
|
||||||
|
io='sea_main',
|
||||||
|
sea_object='mf',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('lev',
|
||||||
|
'frappy_psi.sea.SeaReadable', '',
|
||||||
|
io='sea_main',
|
||||||
|
sea_object='lev',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('ln2fill',
|
||||||
|
'frappy_psi.sea.SeaWritable', '',
|
||||||
|
io='sea_main',
|
||||||
|
sea_object='ln2fill',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('hefill',
|
||||||
|
'frappy_psi.sea.SeaWritable', '',
|
||||||
|
io='sea_main',
|
||||||
|
sea_object='hefill',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('table',
|
||||||
|
'frappy_psi.sea.SeaReadable', '',
|
||||||
|
io='sea_main',
|
||||||
|
sea_object='table',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('om_io',
|
||||||
|
'frappy_psi.phytron.PhytronIO',
|
||||||
|
'dom motor IO',
|
||||||
|
uri='ma10-ts.psi.ch:3004',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('om',
|
||||||
|
'frappy_psi.phytron.Motor',
|
||||||
|
'stick rotation, typically used for omega',
|
||||||
|
io='om_io',
|
||||||
|
sign=-1,
|
||||||
|
target_min = -180,
|
||||||
|
target_max = 360,
|
||||||
|
encoder_mode='READ',
|
||||||
|
)
|
108
cfg/main/ma10high_t_cfg.py
Normal file
108
cfg/main/ma10high_t_cfg.py
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
Node('ma10.config.sea.psi.ch',
|
||||||
|
'10 Tesla vertical cryomagnet',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('sea_main',
|
||||||
|
'frappy_psi.sea.SeaClient',
|
||||||
|
'main sea connection for ma10.config',
|
||||||
|
config='ma10high_t.config',
|
||||||
|
service='main',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('th',
|
||||||
|
'frappy_psi.sea.SeaReadable',
|
||||||
|
'sample heater temperature',
|
||||||
|
io='sea_main',
|
||||||
|
sea_object='tt',
|
||||||
|
rel_paths=['ts', 'setsamp']
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('tm',
|
||||||
|
'frappy_psi.sea.SeaDrivable', '',
|
||||||
|
io='sea_main',
|
||||||
|
sea_object='tt',
|
||||||
|
rel_paths=['tm', 'set']
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('ts',
|
||||||
|
'frappy_psi.parmod.Converging',
|
||||||
|
'test for parmod',
|
||||||
|
unit='K',
|
||||||
|
read='th.value',
|
||||||
|
write='th.setsamp',
|
||||||
|
meaning=['temperature', 20],
|
||||||
|
settling_time=20,
|
||||||
|
tolerance=1,
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('ts2',
|
||||||
|
'frappy_psi.sea.SeaReadable', '',
|
||||||
|
io='sea_main',
|
||||||
|
sea_object='tt',
|
||||||
|
rel_paths=['ts_2']
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('cc',
|
||||||
|
'frappy_psi.sea.SeaReadable', '',
|
||||||
|
io='sea_main',
|
||||||
|
sea_object='cc',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('nv',
|
||||||
|
'frappy_psi.sea.SeaWritable', '',
|
||||||
|
io='sea_main',
|
||||||
|
sea_object='nv',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('hepump',
|
||||||
|
'frappy_psi.sea.SeaWritable', '',
|
||||||
|
io='sea_main',
|
||||||
|
sea_object='hepump',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('hemot',
|
||||||
|
'frappy_psi.sea.SeaDrivable', '',
|
||||||
|
io='sea_main',
|
||||||
|
sea_object='hemot',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('mf',
|
||||||
|
'frappy_psi.sea.SeaDrivable', '',
|
||||||
|
io='sea_main',
|
||||||
|
sea_object='mf',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('lev',
|
||||||
|
'frappy_psi.sea.SeaReadable', '',
|
||||||
|
io='sea_main',
|
||||||
|
sea_object='lev',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('ln2fill',
|
||||||
|
'frappy_psi.sea.SeaWritable', '',
|
||||||
|
io='sea_main',
|
||||||
|
sea_object='ln2fill',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('hefill',
|
||||||
|
'frappy_psi.sea.SeaWritable', '',
|
||||||
|
io='sea_main',
|
||||||
|
sea_object='hefill',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('om_io',
|
||||||
|
'frappy_psi.phytron.PhytronIO',
|
||||||
|
'dom motor IO',
|
||||||
|
uri='ma10-ts.psi.ch:3004',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('om',
|
||||||
|
'frappy_psi.phytron.Motor',
|
||||||
|
'stick rotation, typically used for omega',
|
||||||
|
io='om_io',
|
||||||
|
sign=-1,
|
||||||
|
target_min = -180,
|
||||||
|
target_max = 360,
|
||||||
|
encoder_mode='READ',
|
||||||
|
)
|
||||||
|
|
@ -13,7 +13,7 @@ Mod('tt',
|
|||||||
'frappy_psi.sea.SeaDrivable', '',
|
'frappy_psi.sea.SeaDrivable', '',
|
||||||
io='sea_main',
|
io='sea_main',
|
||||||
sea_object='tt',
|
sea_object='tt',
|
||||||
rel_paths=['.', 'tm'],
|
rel_paths=['tm', 'set', 'dblctrl'],
|
||||||
)
|
)
|
||||||
|
|
||||||
Mod('cc',
|
Mod('cc',
|
||||||
|
107
cfg/main/ma7_piezo_cfg.py
Normal file
107
cfg/main/ma7_piezo_cfg.py
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
Node('ma7.config.sea.psi.ch',
|
||||||
|
'6.8 Tesla horizontal cryomagnet',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('sea_main',
|
||||||
|
'frappy_psi.sea.SeaClient',
|
||||||
|
'main sea connection for ma7.config',
|
||||||
|
config='ma7_piezo.config',
|
||||||
|
service='main',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('tt',
|
||||||
|
'frappy_psi.sea.SeaDrivable', '',
|
||||||
|
io='sea_main',
|
||||||
|
sea_object='tt',
|
||||||
|
rel_paths=['tm', 'set', 'dblctrl', 'voltage'],
|
||||||
|
extra_modules=['manualpower'],
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('cc',
|
||||||
|
'frappy_psi.sea.SeaReadable', '',
|
||||||
|
io='sea_main',
|
||||||
|
sea_object='cc',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('nv',
|
||||||
|
'frappy_psi.sea.SeaWritable', '',
|
||||||
|
io='sea_main',
|
||||||
|
sea_object='nv',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('hefill',
|
||||||
|
'frappy_psi.sea.SeaWritable', '',
|
||||||
|
io='sea_main',
|
||||||
|
sea_object='hefill',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('hepump',
|
||||||
|
'frappy_psi.sea.SeaWritable', '',
|
||||||
|
io='sea_main',
|
||||||
|
sea_object='hepump',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('hemot',
|
||||||
|
'frappy_psi.sea.SeaDrivable', '',
|
||||||
|
io='sea_main',
|
||||||
|
sea_object='hemot',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('ln2fill',
|
||||||
|
'frappy_psi.sea.SeaWritable', '',
|
||||||
|
io='sea_main',
|
||||||
|
sea_object='ln2fill',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('mf',
|
||||||
|
'frappy_psi.sea.SeaDrivable', '',
|
||||||
|
io='sea_main',
|
||||||
|
sea_object='mf',
|
||||||
|
value=Param(unit='T'),
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('lev',
|
||||||
|
'frappy_psi.sea.SeaReadable', '',
|
||||||
|
io='sea_main',
|
||||||
|
sea_object='lev',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('tcoil1',
|
||||||
|
'frappy_psi.sea.SeaReadable', '',
|
||||||
|
io='sea_main',
|
||||||
|
sea_object='tcoil',
|
||||||
|
rel_paths=['ta'],
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('tcoil2',
|
||||||
|
'frappy_psi.sea.SeaReadable', '',
|
||||||
|
io='sea_main',
|
||||||
|
sea_object='tcoil',
|
||||||
|
rel_paths=['tb'],
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('table',
|
||||||
|
'frappy_psi.sea.SeaReadable', '',
|
||||||
|
io='sea_main',
|
||||||
|
sea_object='table',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('stick_io',
|
||||||
|
'frappy_psi.phytron.PhytronIO',
|
||||||
|
'dom motor IO',
|
||||||
|
uri='ma7-ts.psi.ch:3007',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('stickrot',
|
||||||
|
'frappy_psi.phytron.Motor',
|
||||||
|
'stick rotation, typically not used as omega',
|
||||||
|
io='stick_io',
|
||||||
|
encoder_mode='CHECK',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('V',
|
||||||
|
'frappy_psi.sea.SeaWritable',
|
||||||
|
'voltage',
|
||||||
|
io='sea_main',
|
||||||
|
single_module='tt.manualpower',
|
||||||
|
)
|
@ -36,8 +36,8 @@ Mod('ts',
|
|||||||
'frappy_psi.parmod.Converging',
|
'frappy_psi.parmod.Converging',
|
||||||
'test for parmod',
|
'test for parmod',
|
||||||
unit='K',
|
unit='K',
|
||||||
read='th.value',
|
value_param='th.value',
|
||||||
write='th.setsamp',
|
target_param='th.setsamp',
|
||||||
meaning=['temperature', 20],
|
meaning=['temperature', 20],
|
||||||
settling_time=20,
|
settling_time=20,
|
||||||
tolerance=1,
|
tolerance=1,
|
||||||
|
128
cfg/main/ma7_thermalc_cfg.py
Normal file
128
cfg/main/ma7_thermalc_cfg.py
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
Node('ma7_thermalc.config.sea.psi.ch',
|
||||||
|
'''6.8 Tesla horizontal cryomagnet for thrermalcond''',
|
||||||
|
)
|
||||||
|
Mod('sea_main',
|
||||||
|
'frappy_psi.sea.SeaClient',
|
||||||
|
'main sea connection for ma7_thermalc.config',
|
||||||
|
config = 'ma7_thermalc.config',
|
||||||
|
service = 'main',
|
||||||
|
)
|
||||||
|
#Mod('tt',
|
||||||
|
# 'frappy_psi.sea.SeaDrivable', '',
|
||||||
|
# io='sea_main',
|
||||||
|
# sea_object='tt',
|
||||||
|
# rel_paths=['.', 'tm'],
|
||||||
|
#)
|
||||||
|
|
||||||
|
Mod('tt',
|
||||||
|
'frappy_psi.sea.SeaDrivable', '',
|
||||||
|
io='sea_main',
|
||||||
|
sea_object='tt',
|
||||||
|
rel_paths=['tm', 'set'],
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('th',
|
||||||
|
'frappy_psi.sea.SeaReadable',
|
||||||
|
'sample heater temperature',
|
||||||
|
io='sea_main',
|
||||||
|
sea_object='tt',
|
||||||
|
rel_paths=['ts', 'setsamp']
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('ts',
|
||||||
|
'frappy_psi.parmod.Converging',
|
||||||
|
'test for parmod',
|
||||||
|
unit='K',
|
||||||
|
value_param='th.value',
|
||||||
|
target_param='th.setsamp',
|
||||||
|
meaning=['temperature', 20],
|
||||||
|
settling_time=20,
|
||||||
|
tolerance=1,
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('samph',
|
||||||
|
'frappy_psi.sea.SeaWritable', '',
|
||||||
|
io='sea_main',
|
||||||
|
sea_object='tt',
|
||||||
|
rel_paths=['setsamp','power'],
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
Mod('cc',
|
||||||
|
'frappy_psi.sea.SeaReadable', '',
|
||||||
|
io = 'sea_main',
|
||||||
|
sea_object = 'cc',
|
||||||
|
)
|
||||||
|
Mod('nv',
|
||||||
|
'frappy_psi.sea.SeaWritable', '',
|
||||||
|
io = 'sea_main',
|
||||||
|
sea_object = 'nv',
|
||||||
|
)
|
||||||
|
Mod('hefill',
|
||||||
|
'frappy_psi.sea.SeaWritable', '',
|
||||||
|
io = 'sea_main',
|
||||||
|
sea_object = 'hefill',
|
||||||
|
)
|
||||||
|
Mod('hepump',
|
||||||
|
'frappy_psi.sea.SeaWritable', '',
|
||||||
|
io = 'sea_main',
|
||||||
|
sea_object = 'hepump',
|
||||||
|
)
|
||||||
|
Mod('hemot',
|
||||||
|
'frappy_psi.sea.SeaDrivable', '',
|
||||||
|
io = 'sea_main',
|
||||||
|
sea_object = 'hemot',
|
||||||
|
)
|
||||||
|
Mod('nvflow',
|
||||||
|
'frappy_psi.sea.SeaReadable', '',
|
||||||
|
io = 'sea_main',
|
||||||
|
sea_object = 'nvflow',
|
||||||
|
)
|
||||||
|
Mod('ln2fill',
|
||||||
|
'frappy_psi.sea.SeaWritable', '',
|
||||||
|
io = 'sea_main',
|
||||||
|
sea_object = 'ln2fill',
|
||||||
|
)
|
||||||
|
Mod('mf',
|
||||||
|
'frappy_psi.sea.SeaDrivable', '',
|
||||||
|
io = 'sea_main',
|
||||||
|
sea_object = 'mf',
|
||||||
|
)
|
||||||
|
Mod('lev',
|
||||||
|
'frappy_psi.sea.SeaReadable', '',
|
||||||
|
io = 'sea_main',
|
||||||
|
sea_object = 'lev',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('tcoil1',
|
||||||
|
'frappy_psi.sea.SeaReadable', '',
|
||||||
|
io='sea_main',
|
||||||
|
sea_object='tcoil',
|
||||||
|
rel_paths=['ta'],
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('tcoil2',
|
||||||
|
'frappy_psi.sea.SeaReadable', '',
|
||||||
|
io='sea_main',
|
||||||
|
sea_object='tcoil',
|
||||||
|
rel_paths=['tb'],
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('table',
|
||||||
|
'frappy_psi.sea.SeaReadable', '',
|
||||||
|
io = 'sea_main',
|
||||||
|
sea_object = 'table',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('stick_io',
|
||||||
|
'frappy_psi.phytron.PhytronIO',
|
||||||
|
'dom motor IO',
|
||||||
|
uri='ma7-ts.psi.ch:3007',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('stickrot',
|
||||||
|
'frappy_psi.phytron.Motor',
|
||||||
|
'stick rotation, typically not used as omega',
|
||||||
|
io='stick_io',
|
||||||
|
encoder_mode='CHECK',
|
||||||
|
)
|
16
cfg/phoenix_cfg.py
Normal file
16
cfg/phoenix_cfg.py
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
Node('phoenixtest.psi.ch',
|
||||||
|
'phoenix test',
|
||||||
|
'tcp://5000',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('io',
|
||||||
|
'frappy_psi.haake.HaakeIO',
|
||||||
|
'connection for Thermo Haake',
|
||||||
|
uri='tcp://ldmprep7-ts:3005',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('T',
|
||||||
|
'frappy_psi.haake.TemperatureLoop',
|
||||||
|
'holder temperature',
|
||||||
|
io='io',
|
||||||
|
)
|
139
cfg/razorbillUC220T_cfg.py
Normal file
139
cfg/razorbillUC220T_cfg.py
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
# call $ bin/frappy-server razorbillUC220T
|
||||||
|
# in frappy directory, with python with frappy libraries installed.
|
||||||
|
|
||||||
|
Node('UC220T.psi.ch',
|
||||||
|
'A Razorbill UC220T controlled by a RP100 high voltage powersupply and a ACM1219 (AD7746) capacitance meter',
|
||||||
|
interface='tcp://3000')
|
||||||
|
|
||||||
|
Mod('io1',
|
||||||
|
'frappy_psi.RP100.RP100IO',
|
||||||
|
'communication',
|
||||||
|
uri='serial:///dev/ttyACM1?baudrate=9600+bytesize=8+parity=none+stopbits=1',
|
||||||
|
visibility=2)
|
||||||
|
Mod('Tension',
|
||||||
|
'frappy_psi.RP100.VoltageChannel',
|
||||||
|
'Voltage Channel 1',
|
||||||
|
temp='T',
|
||||||
|
io='io1',
|
||||||
|
target=Param(min=-200, max=200),
|
||||||
|
max_target=120,
|
||||||
|
min_target=-20,
|
||||||
|
slew_rate=5,
|
||||||
|
channel=1)
|
||||||
|
Mod('Compression',
|
||||||
|
'frappy_psi.RP100.VoltageChannel',
|
||||||
|
'Voltage Channel 2',
|
||||||
|
temp='T',
|
||||||
|
io='io1',
|
||||||
|
target=Param(min=-200, max=200),
|
||||||
|
max_target=120,
|
||||||
|
min_target=-20,
|
||||||
|
slew_rate=5,
|
||||||
|
channel=2)
|
||||||
|
|
||||||
|
Mod('io2',
|
||||||
|
'frappy_psi.ACM1219.ACM1219IO',
|
||||||
|
'communication',
|
||||||
|
uri='serial:///dev/ttyUSB1?baudrate=9600+bytesize=8+parity=none+stopbits=1',
|
||||||
|
visibility=2)
|
||||||
|
Mod('C1',
|
||||||
|
'frappy_psi.ACM1219.OneChannel',
|
||||||
|
'channel 1',
|
||||||
|
channel_enabled=True,
|
||||||
|
channel=1,
|
||||||
|
io='io2',
|
||||||
|
group='cap')
|
||||||
|
|
||||||
|
Mod('io3',
|
||||||
|
'frappy_psi.ACM1219.ACM1219IO',
|
||||||
|
'communication',
|
||||||
|
uri='serial:///dev/ttyUSB2?baudrate=9600+bytesize=8+parity=none+stopbits=1',
|
||||||
|
visibility=2)
|
||||||
|
Mod('C2',
|
||||||
|
'frappy_psi.ACM1219.OneChannel',
|
||||||
|
'channel 1',
|
||||||
|
channel_enabled=True,
|
||||||
|
channel=1,
|
||||||
|
io='io3',
|
||||||
|
group='cap')
|
||||||
|
|
||||||
|
# Mod('C1',
|
||||||
|
# 'frappy_psi.ACM1219.Channel',
|
||||||
|
# 'channel 1',
|
||||||
|
# group='cap')
|
||||||
|
# Mod('C2',
|
||||||
|
# 'frappy_psi.ACM1219.Channel',
|
||||||
|
# 'channel 2',
|
||||||
|
# group='cap')
|
||||||
|
# Mod('C1C2',
|
||||||
|
# 'frappy_psi.ACM1219.BothChannels',
|
||||||
|
# 'Capacitance channels 1 and 2',
|
||||||
|
# chan1='C1',
|
||||||
|
# chan2='C2',
|
||||||
|
# channels_enabled=True,
|
||||||
|
# io='io2',
|
||||||
|
# group='cap')
|
||||||
|
Mod('d',
|
||||||
|
'frappy_psi.razorbill.Displacement',
|
||||||
|
'razorbill displacement from capacitance',
|
||||||
|
cap='C1',
|
||||||
|
alpha290K=56.710,
|
||||||
|
d0=95.443,
|
||||||
|
Cp=0.01883,
|
||||||
|
d0_curve={'a':4.21,'b':-0.00157,'c':-3.38e-5,'d':5.28e-8,'e':-6.93e-11},
|
||||||
|
temp='T')
|
||||||
|
Mod('strain',
|
||||||
|
'frappy_psi.razorbill.Strain',
|
||||||
|
'Sample strain from force',
|
||||||
|
displacement='d',
|
||||||
|
L=3,
|
||||||
|
)
|
||||||
|
Mod('F',
|
||||||
|
'frappy_psi.razorbill.Force',
|
||||||
|
'razorbill force from capacitance',
|
||||||
|
cap='C2',
|
||||||
|
alpha290K=374.23,
|
||||||
|
f0=315.63,
|
||||||
|
Cp=0.0755,
|
||||||
|
f0_curve={'a':38.9,'b':-0.0147,'c':-0.000346,'d':8.96e-7,'e':-1.58e-9},
|
||||||
|
temp='T')
|
||||||
|
Mod('stress',
|
||||||
|
'frappy_psi.razorbill.Stress',
|
||||||
|
'Sample stress from force',
|
||||||
|
force='F',
|
||||||
|
area=0.1,
|
||||||
|
)
|
||||||
|
Mod('YM',
|
||||||
|
'frappy_psi.razorbill.YoungsModulus',
|
||||||
|
'Sample youngs modulus from stress and strain',
|
||||||
|
stress='stress',
|
||||||
|
strain='strain',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('T',
|
||||||
|
'frappy_psi.razorbill.Temp',
|
||||||
|
'dummy T written from client',
|
||||||
|
target=Param(value=300, min=1, max=325),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
Mod('io4',
|
||||||
|
'frappy_psi.ls372.StringIO',
|
||||||
|
'the communication device',
|
||||||
|
uri='tcp://192.168.3.3:7777',
|
||||||
|
visibility=2
|
||||||
|
)
|
||||||
|
Mod('lsswitcher',
|
||||||
|
'frappy_psi.ls372.Switcher',
|
||||||
|
'Switcher control of Lsc controller',
|
||||||
|
uri='tcp://192.168.3.3:7777',
|
||||||
|
io='io4',
|
||||||
|
)
|
||||||
|
Mod('res',
|
||||||
|
'frappy_psi.ls372.ResChannel',
|
||||||
|
'resistivity',
|
||||||
|
iexc='100uA',
|
||||||
|
range='63.2mOhm',
|
||||||
|
channel=1,
|
||||||
|
switcher='lsswitcher',
|
||||||
|
)
|
@ -1,10 +1,10 @@
|
|||||||
Node('ori7.config.sea.psi.ch',
|
Node('ccrpe.config.sea.psi.ch',
|
||||||
'''orange cryostat with 50 mm sample space for ULT''',
|
'''4 K closed cycle cryostat (PE cell)''',
|
||||||
)
|
)
|
||||||
Mod('sea_main',
|
Mod('sea_main',
|
||||||
'frappy_psi.sea.SeaClient',
|
'frappy_psi.sea.SeaClient',
|
||||||
'main sea connection for ori7.config',
|
'main sea connection for ccrpe.config',
|
||||||
config = 'ori7.config',
|
config = 'ccrpe.config',
|
||||||
service = 'main',
|
service = 'main',
|
||||||
)
|
)
|
||||||
Mod('tt',
|
Mod('tt',
|
||||||
@ -22,16 +22,6 @@ Mod('nv',
|
|||||||
io = 'sea_main',
|
io = 'sea_main',
|
||||||
sea_object = 'nv',
|
sea_object = 'nv',
|
||||||
)
|
)
|
||||||
Mod('ln2fill',
|
|
||||||
'frappy_psi.sea.SeaWritable', '',
|
|
||||||
io = 'sea_main',
|
|
||||||
sea_object = 'ln2fill',
|
|
||||||
)
|
|
||||||
Mod('hefill',
|
|
||||||
'frappy_psi.sea.SeaWritable', '',
|
|
||||||
io = 'sea_main',
|
|
||||||
sea_object = 'hefill',
|
|
||||||
)
|
|
||||||
Mod('hepump',
|
Mod('hepump',
|
||||||
'frappy_psi.sea.SeaWritable', '',
|
'frappy_psi.sea.SeaWritable', '',
|
||||||
io = 'sea_main',
|
io = 'sea_main',
|
||||||
@ -47,8 +37,13 @@ Mod('nvflow',
|
|||||||
io = 'sea_main',
|
io = 'sea_main',
|
||||||
sea_object = 'nvflow',
|
sea_object = 'nvflow',
|
||||||
)
|
)
|
||||||
Mod('table',
|
Mod('warmup',
|
||||||
|
'frappy_psi.sea.SeaDrivable', '',
|
||||||
|
io = 'sea_main',
|
||||||
|
sea_object = 'warmup',
|
||||||
|
)
|
||||||
|
Mod('p',
|
||||||
'frappy_psi.sea.SeaReadable', '',
|
'frappy_psi.sea.SeaReadable', '',
|
||||||
io = 'sea_main',
|
io = 'sea_main',
|
||||||
sea_object = 'table',
|
sea_object = 'p',
|
||||||
)
|
)
|
@ -72,8 +72,7 @@
|
|||||||
{"path": "min_cpl", "type": "float", "readonly": false, "cmd": "pauto min_cpl"},
|
{"path": "min_cpl", "type": "float", "readonly": false, "cmd": "pauto min_cpl"},
|
||||||
{"path": "max_cpl", "type": "float", "readonly": false, "cmd": "pauto max_cpl"},
|
{"path": "max_cpl", "type": "float", "readonly": false, "cmd": "pauto max_cpl"},
|
||||||
{"path": "fact_cpl", "type": "float", "readonly": false, "cmd": "pauto fact_cpl"},
|
{"path": "fact_cpl", "type": "float", "readonly": false, "cmd": "pauto fact_cpl"},
|
||||||
{"path": "max_ramp", "type": "float", "readonly": false, "cmd": "pauto max_ramp"},
|
{"path": "max_ramp", "type": "float", "readonly": false, "cmd": "pauto max_ramp"}]},
|
||||||
{"path": "target", "type": "float"}]},
|
|
||||||
|
|
||||||
"tc": {"base": "/tc", "params": [
|
"tc": {"base": "/tc", "params": [
|
||||||
{"path": "", "type": "float", "readonly": false, "cmd": "run tc", "description": "tc", "kids": 15},
|
{"path": "", "type": "float", "readonly": false, "cmd": "run tc", "description": "tc", "kids": 15},
|
||||||
|
395
cfg/sea/ma10heat.config.json
Normal file
395
cfg/sea/ma10heat.config.json
Normal file
@ -0,0 +1,395 @@
|
|||||||
|
{"tt": {"base": "/tt", "params": [
|
||||||
|
{"path": "", "type": "float", "readonly": false, "cmd": "run tt", "description": "tt", "kids": 18},
|
||||||
|
{"path": "send", "type": "text", "readonly": false, "cmd": "tt send", "visibility": 3},
|
||||||
|
{"path": "status", "type": "text", "visibility": 3},
|
||||||
|
{"path": "is_running", "type": "int", "readonly": false, "cmd": "tt is_running", "visibility": 3},
|
||||||
|
{"path": "mainloop", "type": "text", "readonly": false, "cmd": "tt mainloop", "visibility": 3},
|
||||||
|
{"path": "target", "type": "float"},
|
||||||
|
{"path": "running", "type": "int"},
|
||||||
|
{"path": "tolerance", "type": "float", "readonly": false, "cmd": "tt tolerance"},
|
||||||
|
{"path": "maxwait", "type": "float", "readonly": false, "cmd": "tt maxwait"},
|
||||||
|
{"path": "settle", "type": "float", "readonly": false, "cmd": "tt settle"},
|
||||||
|
{"path": "log", "type": "text", "readonly": false, "cmd": "tt log", "visibility": 3, "kids": 4},
|
||||||
|
{"path": "log/mean", "type": "float", "visibility": 3},
|
||||||
|
{"path": "log/m2", "type": "float", "visibility": 3},
|
||||||
|
{"path": "log/stddev", "type": "float", "visibility": 3},
|
||||||
|
{"path": "log/n", "type": "float", "visibility": 3},
|
||||||
|
{"path": "dblctrl", "type": "bool", "readonly": false, "cmd": "tt dblctrl", "kids": 9},
|
||||||
|
{"path": "dblctrl/tshift", "type": "float", "readonly": false, "cmd": "tt dblctrl/tshift"},
|
||||||
|
{"path": "dblctrl/mode", "type": "enum", "enum": {"disabled": -1, "inactive": 0, "stable": 1, "up": 2, "down": 3}, "readonly": false, "cmd": "tt dblctrl/mode"},
|
||||||
|
{"path": "dblctrl/shift_up", "type": "float"},
|
||||||
|
{"path": "dblctrl/shift_lo", "type": "float"},
|
||||||
|
{"path": "dblctrl/t_min", "type": "float"},
|
||||||
|
{"path": "dblctrl/t_max", "type": "float"},
|
||||||
|
{"path": "dblctrl/int2", "type": "float", "readonly": false, "cmd": "tt dblctrl/int2"},
|
||||||
|
{"path": "dblctrl/prop_up", "type": "float", "readonly": false, "cmd": "tt dblctrl/prop_up"},
|
||||||
|
{"path": "dblctrl/prop_lo", "type": "float", "readonly": false, "cmd": "tt dblctrl/prop_lo"},
|
||||||
|
{"path": "tm", "type": "float", "kids": 4},
|
||||||
|
{"path": "tm/curve", "type": "text", "readonly": false, "cmd": "tt tm/curve", "kids": 1},
|
||||||
|
{"path": "tm/curve/points", "type": "floatvarar", "readonly": false, "cmd": "tt tm/curve/points", "visibility": 3},
|
||||||
|
{"path": "tm/alarm", "type": "float", "readonly": false, "cmd": "tt tm/alarm"},
|
||||||
|
{"path": "tm/stddev", "type": "float"},
|
||||||
|
{"path": "tm/raw", "type": "float"},
|
||||||
|
{"path": "ts", "type": "float", "kids": 4},
|
||||||
|
{"path": "ts/curve", "type": "text", "readonly": false, "cmd": "tt ts/curve", "kids": 1},
|
||||||
|
{"path": "ts/curve/points", "type": "floatvarar", "readonly": false, "cmd": "tt ts/curve/points", "visibility": 3},
|
||||||
|
{"path": "ts/alarm", "type": "float", "readonly": false, "cmd": "tt ts/alarm"},
|
||||||
|
{"path": "ts/stddev", "type": "float"},
|
||||||
|
{"path": "ts/raw", "type": "float"},
|
||||||
|
{"path": "ts_2", "type": "float", "kids": 4},
|
||||||
|
{"path": "ts_2/curve", "type": "text", "readonly": false, "cmd": "tt ts_2/curve", "kids": 1},
|
||||||
|
{"path": "ts_2/curve/points", "type": "floatvarar", "readonly": false, "cmd": "tt ts_2/curve/points", "visibility": 3},
|
||||||
|
{"path": "ts_2/alarm", "type": "float", "readonly": false, "cmd": "tt ts_2/alarm"},
|
||||||
|
{"path": "ts_2/stddev", "type": "float"},
|
||||||
|
{"path": "ts_2/raw", "type": "float"},
|
||||||
|
{"path": "set", "type": "float", "readonly": false, "cmd": "tt set", "kids": 18},
|
||||||
|
{"path": "set/mode", "type": "enum", "enum": {"disabled": -1, "off": 0, "controlling": 1, "manual": 2}, "readonly": false, "cmd": "tt set/mode"},
|
||||||
|
{"path": "set/reg", "type": "float"},
|
||||||
|
{"path": "set/ramp", "type": "float", "readonly": false, "cmd": "tt set/ramp", "description": "maximum ramp in K/min (0: ramp off)"},
|
||||||
|
{"path": "set/wramp", "type": "float", "readonly": false, "cmd": "tt set/wramp"},
|
||||||
|
{"path": "set/smooth", "type": "float", "readonly": false, "cmd": "tt set/smooth", "description": "smooth time (minutes)"},
|
||||||
|
{"path": "set/channel", "type": "text", "readonly": false, "cmd": "tt set/channel"},
|
||||||
|
{"path": "set/limit", "type": "float", "readonly": false, "cmd": "tt set/limit"},
|
||||||
|
{"path": "set/resist", "type": "float", "readonly": false, "cmd": "tt set/resist"},
|
||||||
|
{"path": "set/maxheater", "type": "text", "readonly": false, "cmd": "tt set/maxheater", "description": "maximum heater limit, units should be given without space: W, mW, A, mA"},
|
||||||
|
{"path": "set/linearpower", "type": "float", "readonly": false, "cmd": "tt set/linearpower", "description": "when not 0, it is the maximum effective power, and the power is linear to the heater output"},
|
||||||
|
{"path": "set/maxpowerlim", "type": "float", "description": "the maximum power limit (before any booster or converter)"},
|
||||||
|
{"path": "set/maxpower", "type": "float", "readonly": false, "cmd": "tt set/maxpower", "description": "maximum power [W]"},
|
||||||
|
{"path": "set/maxcurrent", "type": "float", "description": "the maximum current before any booster or converter"},
|
||||||
|
{"path": "set/manualpower", "type": "float", "readonly": false, "cmd": "tt set/manualpower"},
|
||||||
|
{"path": "set/power", "type": "float"},
|
||||||
|
{"path": "set/prop", "type": "float", "readonly": false, "cmd": "tt set/prop", "description": "bigger means more gain"},
|
||||||
|
{"path": "set/integ", "type": "float", "readonly": false, "cmd": "tt set/integ", "description": "bigger means faster"},
|
||||||
|
{"path": "set/deriv", "type": "float", "readonly": false, "cmd": "tt set/deriv"},
|
||||||
|
{"path": "setvti", "type": "float", "readonly": false, "cmd": "tt setvti", "kids": 18},
|
||||||
|
{"path": "setvti/mode", "type": "enum", "enum": {"disabled": -1, "off": 0, "controlling": 1, "manual": 2}, "readonly": false, "cmd": "tt setvti/mode"},
|
||||||
|
{"path": "setvti/reg", "type": "float"},
|
||||||
|
{"path": "setvti/ramp", "type": "float", "readonly": false, "cmd": "tt setvti/ramp", "description": "maximum ramp in K/min (0: ramp off)"},
|
||||||
|
{"path": "setvti/wramp", "type": "float", "readonly": false, "cmd": "tt setvti/wramp"},
|
||||||
|
{"path": "setvti/smooth", "type": "float", "readonly": false, "cmd": "tt setvti/smooth", "description": "smooth time (minutes)"},
|
||||||
|
{"path": "setvti/channel", "type": "text", "readonly": false, "cmd": "tt setvti/channel"},
|
||||||
|
{"path": "setvti/limit", "type": "float", "readonly": false, "cmd": "tt setvti/limit"},
|
||||||
|
{"path": "setvti/resist", "type": "float", "readonly": false, "cmd": "tt setvti/resist"},
|
||||||
|
{"path": "setvti/maxheater", "type": "text", "readonly": false, "cmd": "tt setvti/maxheater", "description": "maximum heater limit, units should be given without space: W, mW, A, mA"},
|
||||||
|
{"path": "setvti/linearpower", "type": "float", "readonly": false, "cmd": "tt setvti/linearpower", "description": "when not 0, it is the maximum effective power, and the power is linear to the heater output"},
|
||||||
|
{"path": "setvti/maxpowerlim", "type": "float", "description": "the maximum power limit (before any booster or converter)"},
|
||||||
|
{"path": "setvti/maxpower", "type": "float", "readonly": false, "cmd": "tt setvti/maxpower", "description": "maximum power [W]"},
|
||||||
|
{"path": "setvti/maxcurrent", "type": "float", "description": "the maximum current before any booster or converter"},
|
||||||
|
{"path": "setvti/manualpower", "type": "float", "readonly": false, "cmd": "tt setvti/manualpower"},
|
||||||
|
{"path": "setvti/power", "type": "float"},
|
||||||
|
{"path": "setvti/prop", "type": "float", "readonly": false, "cmd": "tt setvti/prop", "description": "bigger means more gain"},
|
||||||
|
{"path": "setvti/integ", "type": "float", "readonly": false, "cmd": "tt setvti/integ", "description": "bigger means faster"},
|
||||||
|
{"path": "setvti/deriv", "type": "float", "readonly": false, "cmd": "tt setvti/deriv"},
|
||||||
|
{"path": "display", "type": "text", "readonly": false, "cmd": "tt display"},
|
||||||
|
{"path": "remote", "type": "bool"}]},
|
||||||
|
|
||||||
|
"cc": {"base": "/cc", "params": [
|
||||||
|
{"path": "", "type": "bool", "kids": 96},
|
||||||
|
{"path": "send", "type": "text", "readonly": false, "cmd": "cc send", "visibility": 3},
|
||||||
|
{"path": "status", "type": "text", "visibility": 3},
|
||||||
|
{"path": "autodevice", "type": "bool", "readonly": false, "cmd": "cc autodevice"},
|
||||||
|
{"path": "fav", "type": "bool", "readonly": false, "cmd": "cc fav"},
|
||||||
|
{"path": "f", "type": "float"},
|
||||||
|
{"path": "fs", "type": "enum", "enum": {"ok": 0, "no_sens": 1}, "readonly": false, "cmd": "cc fs"},
|
||||||
|
{"path": "mav", "type": "bool", "readonly": false, "cmd": "cc mav"},
|
||||||
|
{"path": "fm", "type": "enum", "enum": {"idle": 0, "opening": 1, "closing": 2, "opened": 3, "closed": 4, "no_motor": 5}},
|
||||||
|
{"path": "fa", "type": "enum", "enum": {"fixed": 0, "controlled": 1, "automatic": 2, "offline": 3}, "readonly": false, "cmd": "cc fa"},
|
||||||
|
{"path": "mp", "type": "float", "readonly": false, "cmd": "cc mp"},
|
||||||
|
{"path": "msp", "type": "float"},
|
||||||
|
{"path": "mmp", "type": "float"},
|
||||||
|
{"path": "mc", "type": "float", "readonly": false, "cmd": "cc mc"},
|
||||||
|
{"path": "mfc", "type": "float", "readonly": false, "cmd": "cc mfc"},
|
||||||
|
{"path": "moc", "type": "float", "readonly": false, "cmd": "cc moc"},
|
||||||
|
{"path": "mtc", "type": "float", "readonly": false, "cmd": "cc mtc"},
|
||||||
|
{"path": "mtl", "type": "float"},
|
||||||
|
{"path": "mft", "type": "float", "readonly": false, "cmd": "cc mft"},
|
||||||
|
{"path": "mt", "type": "float"},
|
||||||
|
{"path": "mo", "type": "float"},
|
||||||
|
{"path": "mcr", "type": "float"},
|
||||||
|
{"path": "mot", "type": "float"},
|
||||||
|
{"path": "mw", "type": "float", "readonly": false, "cmd": "cc mw", "description": "correction pulse after automatic open"},
|
||||||
|
{"path": "hav", "type": "bool", "readonly": false, "cmd": "cc hav"},
|
||||||
|
{"path": "h", "type": "float"},
|
||||||
|
{"path": "hr", "type": "float"},
|
||||||
|
{"path": "hc", "type": "float"},
|
||||||
|
{"path": "hu", "type": "float"},
|
||||||
|
{"path": "hh", "type": "float", "readonly": false, "cmd": "cc hh"},
|
||||||
|
{"path": "hl", "type": "float", "readonly": false, "cmd": "cc hl"},
|
||||||
|
{"path": "htf", "type": "float", "readonly": false, "cmd": "cc htf", "description": "meas. period in fast mode"},
|
||||||
|
{"path": "hts", "type": "float", "readonly": false, "cmd": "cc hts", "description": "meas. period in slow mode"},
|
||||||
|
{"path": "hd", "type": "float", "readonly": false, "cmd": "cc hd"},
|
||||||
|
{"path": "hwr", "type": "float", "readonly": false, "cmd": "cc hwr"},
|
||||||
|
{"path": "hem", "type": "float", "readonly": false, "cmd": "cc hem", "description": "sensor length in mm from top to empty pos."},
|
||||||
|
{"path": "hfu", "type": "float", "readonly": false, "cmd": "cc hfu", "description": "sensor length in mm from top to full pos."},
|
||||||
|
{"path": "hcd", "type": "enum", "enum": {"stop": 0, "fill": 1, "off": 2, "auto": 3, "manual": 7}, "readonly": false, "cmd": "cc hcd"},
|
||||||
|
{"path": "hv", "type": "enum", "enum": {"fill_valve_off": 0, "filling": 1, "no_fill_valve": 2, "timeout": 3, "timeout1": 4}},
|
||||||
|
{"path": "hsf", "type": "enum", "enum": {"sens_ok": 0, "sens_warm": 1, "no_sens": 2, "timeout": 3, "not_yet_read": 4, "disabled": 5}},
|
||||||
|
{"path": "ha", "type": "bool", "readonly": false, "cmd": "cc ha"},
|
||||||
|
{"path": "hm", "type": "bool"},
|
||||||
|
{"path": "hf", "type": "enum", "enum": {"slow": 0, "fast": 1}, "readonly": false, "cmd": "cc hf"},
|
||||||
|
{"path": "hbe", "type": "bool", "readonly": false, "cmd": "cc hbe"},
|
||||||
|
{"path": "hmf", "type": "float"},
|
||||||
|
{"path": "hms", "type": "float"},
|
||||||
|
{"path": "hit", "type": "float", "readonly": false, "cmd": "cc hit"},
|
||||||
|
{"path": "hft", "type": "int", "readonly": false, "cmd": "cc hft"},
|
||||||
|
{"path": "hea", "type": "enum", "enum": {"0": 0, "1": 1, "6": 6}, "readonly": false, "cmd": "cc hea"},
|
||||||
|
{"path": "hch", "type": "int", "readonly": false, "cmd": "cc hch", "visibility": 3},
|
||||||
|
{"path": "hwr0", "type": "float", "readonly": false, "cmd": "cc hwr0", "visibility": 3},
|
||||||
|
{"path": "hem0", "type": "float", "readonly": false, "cmd": "cc hem0", "description": "sensor length in mm from top to empty pos.", "visibility": 3},
|
||||||
|
{"path": "hfu0", "type": "float", "readonly": false, "cmd": "cc hfu0", "description": "sensor length in mm from top to full pos.", "visibility": 3},
|
||||||
|
{"path": "hd0", "type": "float", "readonly": false, "cmd": "cc hd0", "description": "external sensor drive current (mA)", "visibility": 3},
|
||||||
|
{"path": "h0", "type": "float", "visibility": 3},
|
||||||
|
{"path": "hs0", "type": "enum", "enum": {"sens_ok": 0, "sens_warm": 1, "no_sens": 2, "timeout": 3, "not_yet_read": 4, "disabled": 5}, "visibility": 3},
|
||||||
|
{"path": "h1", "type": "float", "visibility": 3},
|
||||||
|
{"path": "hs1", "type": "enum", "enum": {"sens_ok": 0, "sens_warm": 1, "no_sens": 2, "timeout": 3, "not_yet_read": 4, "disabled": 5}, "visibility": 3},
|
||||||
|
{"path": "h2", "type": "float", "visibility": 3},
|
||||||
|
{"path": "hs2", "type": "enum", "enum": {"sens_ok": 0, "sens_warm": 1, "no_sens": 2, "timeout": 3, "not_yet_read": 4, "disabled": 5}, "visibility": 3},
|
||||||
|
{"path": "h3", "type": "float", "visibility": 3},
|
||||||
|
{"path": "hs3", "type": "enum", "enum": {"sens_ok": 0, "sens_warm": 1, "no_sens": 2, "timeout": 3, "not_yet_read": 4, "disabled": 5}, "visibility": 3},
|
||||||
|
{"path": "h4", "type": "float", "visibility": 3},
|
||||||
|
{"path": "hs4", "type": "enum", "enum": {"sens_ok": 0, "sens_warm": 1, "no_sens": 2, "timeout": 3, "not_yet_read": 4, "disabled": 5}, "visibility": 3},
|
||||||
|
{"path": "h5", "type": "float", "visibility": 3},
|
||||||
|
{"path": "hs5", "type": "enum", "enum": {"sens_ok": 0, "sens_warm": 1, "no_sens": 2, "timeout": 3, "not_yet_read": 4, "disabled": 5}, "visibility": 3},
|
||||||
|
{"path": "hfb", "type": "float"},
|
||||||
|
{"path": "nav", "type": "bool", "readonly": false, "cmd": "cc nav"},
|
||||||
|
{"path": "nu", "type": "float"},
|
||||||
|
{"path": "nl", "type": "float"},
|
||||||
|
{"path": "nth", "type": "float", "readonly": false, "cmd": "cc nth"},
|
||||||
|
{"path": "ntc", "type": "float", "readonly": false, "cmd": "cc ntc"},
|
||||||
|
{"path": "ntm", "type": "float", "readonly": false, "cmd": "cc ntm"},
|
||||||
|
{"path": "ns", "type": "enum", "enum": {"sens_ok": 0, "no_sens": 1, "short_circuit": 2, "upside_down": 3, "sens_warm": 4, "empty": 5}},
|
||||||
|
{"path": "na", "type": "bool", "readonly": false, "cmd": "cc na"},
|
||||||
|
{"path": "nv", "type": "enum", "enum": {"fill_valve_off": 0, "filling": 1, "no_fill_valve": 2, "timeout": 3, "timeout1": 4, "boost": 5}},
|
||||||
|
{"path": "nc", "type": "enum", "enum": {"stop": 0, "fill": 1, "off": 2, "auto": 3}, "readonly": false, "cmd": "cc nc"},
|
||||||
|
{"path": "nfb", "type": "float"},
|
||||||
|
{"path": "cda", "type": "float"},
|
||||||
|
{"path": "cdb", "type": "float"},
|
||||||
|
{"path": "cba", "type": "float"},
|
||||||
|
{"path": "cbb", "type": "float"},
|
||||||
|
{"path": "cvs", "type": "int"},
|
||||||
|
{"path": "csp", "type": "int"},
|
||||||
|
{"path": "cdv", "type": "text", "readonly": false, "cmd": "cc cdv"},
|
||||||
|
{"path": "cic", "type": "text", "readonly": false, "cmd": "cc cic"},
|
||||||
|
{"path": "cin", "type": "text"},
|
||||||
|
{"path": "cds", "type": "enum", "enum": {"local": 0, "remote": 1, "loading": 2, "by_code": 3, "by_touch": 4}, "readonly": false, "cmd": "cc cds"},
|
||||||
|
{"path": "timing", "type": "bool", "readonly": false, "cmd": "cc timing"},
|
||||||
|
{"path": "tc", "type": "float", "visibility": 3},
|
||||||
|
{"path": "tn", "type": "float", "visibility": 3},
|
||||||
|
{"path": "th", "type": "float", "visibility": 3},
|
||||||
|
{"path": "tf", "type": "float", "visibility": 3},
|
||||||
|
{"path": "tm", "type": "float", "visibility": 3},
|
||||||
|
{"path": "tv", "type": "float", "visibility": 3},
|
||||||
|
{"path": "tq", "type": "float", "visibility": 3},
|
||||||
|
{"path": "bdl", "type": "float", "readonly": false, "cmd": "cc bdl"}]},
|
||||||
|
|
||||||
|
"nv": {"base": "/nv", "params": [
|
||||||
|
{"path": "", "type": "enum", "enum": {"fixed": 0, "controlled": 1, "automatic": 2, "close": 3, "open": 4}, "readonly": false, "cmd": "nv", "kids": 11},
|
||||||
|
{"path": "send", "type": "text", "readonly": false, "cmd": "nv send", "visibility": 3},
|
||||||
|
{"path": "status", "type": "text", "visibility": 3},
|
||||||
|
{"path": "motstat", "type": "enum", "enum": {"idle": 0, "opening": 1, "closing": 2, "opened": 3, "closed": 4, "no_motor": 5}},
|
||||||
|
{"path": "flow", "type": "float"},
|
||||||
|
{"path": "set", "type": "float", "readonly": false, "cmd": "nv set"},
|
||||||
|
{"path": "flowmax", "type": "float", "readonly": false, "cmd": "nv flowmax"},
|
||||||
|
{"path": "flowp", "type": "float"},
|
||||||
|
{"path": "span", "type": "float"},
|
||||||
|
{"path": "ctrl", "type": "none", "kids": 13},
|
||||||
|
{"path": "ctrl/regtext", "type": "text"},
|
||||||
|
{"path": "ctrl/prop_o", "type": "float", "readonly": false, "cmd": "nv ctrl/prop_o", "description": "prop [sec/mbar] when opening. above 4 mbar a 10 times lower value is used"},
|
||||||
|
{"path": "ctrl/prop_c", "type": "float", "readonly": false, "cmd": "nv ctrl/prop_c", "description": "prop [sec/mbar] when closing. above 4 mbar a 10 times lower value is used"},
|
||||||
|
{"path": "ctrl/deriv_o", "type": "float", "readonly": false, "cmd": "nv ctrl/deriv_o", "description": "convergence target time [sec] when opening"},
|
||||||
|
{"path": "ctrl/deriv_c", "type": "float", "readonly": false, "cmd": "nv ctrl/deriv_c", "description": "convergence target time [sec] when closing"},
|
||||||
|
{"path": "ctrl/minpulse_o", "type": "float", "readonly": false, "cmd": "nv ctrl/minpulse_o", "description": "minimum close pulse [sec]"},
|
||||||
|
{"path": "ctrl/minpulse_c", "type": "float", "readonly": false, "cmd": "nv ctrl/minpulse_c", "description": "standard close pulse [sec]"},
|
||||||
|
{"path": "ctrl/hystpulse_o", "type": "float", "readonly": false, "cmd": "nv ctrl/hystpulse_o", "description": "motor pulse to overcome hysteresis when opening"},
|
||||||
|
{"path": "ctrl/hystpulse_c", "type": "float", "readonly": false, "cmd": "nv ctrl/hystpulse_c", "description": "motor pulse to overcome hysteresis when closing"},
|
||||||
|
{"path": "ctrl/tol", "type": "float", "readonly": false, "cmd": "nv ctrl/tol", "description": "valid below 3 mbar"},
|
||||||
|
{"path": "ctrl/tolhigh", "type": "float", "readonly": false, "cmd": "nv ctrl/tolhigh", "description": "valid above 4 mbar"},
|
||||||
|
{"path": "ctrl/openpulse", "type": "float", "readonly": false, "cmd": "nv ctrl/openpulse", "description": "time to open from completely closed to a significant opening"},
|
||||||
|
{"path": "ctrl/adjust_minpulse", "type": "bool", "readonly": false, "cmd": "nv ctrl/adjust_minpulse", "description": "adjust minpulse automatically"},
|
||||||
|
{"path": "autoflow", "type": "none", "kids": 24},
|
||||||
|
{"path": "autoflow/suspended", "type": "bool", "readonly": false, "cmd": "nv autoflow/suspended"},
|
||||||
|
{"path": "autoflow/prop", "type": "float", "readonly": false, "cmd": "nv autoflow/prop"},
|
||||||
|
{"path": "autoflow/flowstd", "type": "float", "readonly": false, "cmd": "nv autoflow/flowstd"},
|
||||||
|
{"path": "autoflow/flowlim", "type": "float", "readonly": false, "cmd": "nv autoflow/flowlim"},
|
||||||
|
{"path": "autoflow/smooth", "type": "float", "readonly": false, "cmd": "nv autoflow/smooth"},
|
||||||
|
{"path": "autoflow/difSize", "type": "float", "readonly": false, "cmd": "nv autoflow/difSize"},
|
||||||
|
{"path": "autoflow/difRange", "type": "float", "readonly": false, "cmd": "nv autoflow/difRange"},
|
||||||
|
{"path": "autoflow/flowSize", "type": "float", "readonly": false, "cmd": "nv autoflow/flowSize"},
|
||||||
|
{"path": "autoflow/convTime", "type": "float", "readonly": false, "cmd": "nv autoflow/convTime"},
|
||||||
|
{"path": "autoflow/Tmin", "type": "float", "readonly": false, "cmd": "nv autoflow/Tmin"},
|
||||||
|
{"path": "autoflow/script", "type": "text", "readonly": false, "cmd": "nv autoflow/script"},
|
||||||
|
{"path": "autoflow/getTemp", "type": "text", "readonly": false, "cmd": "nv autoflow/getTemp"},
|
||||||
|
{"path": "autoflow/getTset", "type": "text", "readonly": false, "cmd": "nv autoflow/getTset"},
|
||||||
|
{"path": "autoflow/getFlow", "type": "text", "readonly": false, "cmd": "nv autoflow/getFlow"},
|
||||||
|
{"path": "autoflow/difBuf", "type": "text"},
|
||||||
|
{"path": "autoflow/flowBuf", "type": "text"},
|
||||||
|
{"path": "autoflow/flowset", "type": "float"},
|
||||||
|
{"path": "autoflow/flowmin", "type": "float"},
|
||||||
|
{"path": "autoflow/flowmax", "type": "float"},
|
||||||
|
{"path": "autoflow/difmin", "type": "float"},
|
||||||
|
{"path": "autoflow/difmax", "type": "float"},
|
||||||
|
{"path": "autoflow/setmin", "type": "float"},
|
||||||
|
{"path": "autoflow/setmax", "type": "float"},
|
||||||
|
{"path": "autoflow/flowtarget", "type": "float"},
|
||||||
|
{"path": "calib", "type": "none", "kids": 2},
|
||||||
|
{"path": "calib/ln_per_min_per_mbar", "type": "float", "readonly": false, "cmd": "nv calib/ln_per_min_per_mbar"},
|
||||||
|
{"path": "calib/mbar_offset", "type": "float", "readonly": false, "cmd": "nv calib/mbar_offset"}]},
|
||||||
|
|
||||||
|
"hepump": {"base": "/hepump", "params": [
|
||||||
|
{"path": "", "type": "enum", "enum": {"xds35_auto": 0, "xds35_manual": 1, "sv65": 2, "other": 3, "no": -1}, "readonly": false, "cmd": "hepump", "description": "xds35: scroll pump, sv65: leybold", "kids": 10},
|
||||||
|
{"path": "send", "type": "text", "readonly": false, "cmd": "hepump send", "visibility": 3},
|
||||||
|
{"path": "status", "type": "text", "visibility": 3},
|
||||||
|
{"path": "running", "type": "bool", "readonly": false, "cmd": "hepump running"},
|
||||||
|
{"path": "eco", "type": "bool", "readonly": false, "cmd": "hepump eco"},
|
||||||
|
{"path": "auto", "type": "bool", "readonly": false, "cmd": "hepump auto"},
|
||||||
|
{"path": "valve", "type": "enum", "enum": {"closed": 0, "closing": 1, "opening": 2, "opened": 3, "undefined": 4}, "readonly": false, "cmd": "hepump valve"},
|
||||||
|
{"path": "eco_t_lim", "type": "float", "readonly": false, "cmd": "hepump eco_t_lim", "description": "switch off eco mode when T_set < eco_t_lim and T < eco_t_lim * 2"},
|
||||||
|
{"path": "calib", "type": "float", "readonly": false, "cmd": "hepump calib", "visibility": 3},
|
||||||
|
{"path": "health", "type": "float"}]},
|
||||||
|
|
||||||
|
"hemot": {"base": "/hepump/hemot", "params": [
|
||||||
|
{"path": "", "type": "float", "readonly": false, "cmd": "run hemot", "kids": 30},
|
||||||
|
{"path": "send", "type": "text", "readonly": false, "cmd": "hemot send", "visibility": 3},
|
||||||
|
{"path": "status", "type": "text", "visibility": 3},
|
||||||
|
{"path": "is_running", "type": "int", "readonly": false, "cmd": "hemot is_running", "visibility": 3},
|
||||||
|
{"path": "pos", "type": "float"},
|
||||||
|
{"path": "encoder", "type": "float"},
|
||||||
|
{"path": "zero", "type": "float", "readonly": false, "cmd": "hemot zero"},
|
||||||
|
{"path": "lowerlimit", "type": "float", "readonly": false, "cmd": "hemot lowerlimit"},
|
||||||
|
{"path": "upperlimit", "type": "float", "readonly": false, "cmd": "hemot upperlimit"},
|
||||||
|
{"path": "disablelimits", "type": "bool", "readonly": false, "cmd": "hemot disablelimits"},
|
||||||
|
{"path": "verbose", "type": "bool", "readonly": false, "cmd": "hemot verbose"},
|
||||||
|
{"path": "target", "type": "float"},
|
||||||
|
{"path": "runstate", "type": "enum", "enum": {"idle": 0, "running": 1, "finished": 2, "error": 3}},
|
||||||
|
{"path": "precision", "type": "float", "readonly": false, "cmd": "hemot precision"},
|
||||||
|
{"path": "maxencdif", "type": "float", "readonly": false, "cmd": "hemot maxencdif"},
|
||||||
|
{"path": "id", "type": "float", "readonly": false, "cmd": "hemot id"},
|
||||||
|
{"path": "pump_number", "type": "float", "readonly": false, "cmd": "hemot pump_number"},
|
||||||
|
{"path": "init", "type": "float", "readonly": false, "cmd": "hemot init"},
|
||||||
|
{"path": "maxspeed", "type": "float", "readonly": false, "cmd": "hemot maxspeed"},
|
||||||
|
{"path": "acceleration", "type": "float", "readonly": false, "cmd": "hemot acceleration"},
|
||||||
|
{"path": "maxcurrent", "type": "float", "readonly": false, "cmd": "hemot maxcurrent"},
|
||||||
|
{"path": "standbycurrent", "type": "float", "readonly": false, "cmd": "hemot standbycurrent"},
|
||||||
|
{"path": "freewheeling", "type": "bool", "readonly": false, "cmd": "hemot freewheeling"},
|
||||||
|
{"path": "output0", "type": "bool", "readonly": false, "cmd": "hemot output0"},
|
||||||
|
{"path": "output1", "type": "bool", "readonly": false, "cmd": "hemot output1"},
|
||||||
|
{"path": "input3", "type": "bool"},
|
||||||
|
{"path": "pullup", "type": "float", "readonly": false, "cmd": "hemot pullup"},
|
||||||
|
{"path": "nopumpfeedback", "type": "bool", "readonly": false, "cmd": "hemot nopumpfeedback"},
|
||||||
|
{"path": "eeprom", "type": "enum", "enum": {"ok": 0, "dirty": 1, "save": 2, "load": 3}, "readonly": false, "cmd": "hemot eeprom"},
|
||||||
|
{"path": "customadr", "type": "text", "readonly": false, "cmd": "hemot customadr"},
|
||||||
|
{"path": "custompar", "type": "float", "readonly": false, "cmd": "hemot custompar"}]},
|
||||||
|
|
||||||
|
"nvflow": {"base": "/nvflow", "params": [
|
||||||
|
{"path": "", "type": "float", "kids": 7},
|
||||||
|
{"path": "send", "type": "text", "readonly": false, "cmd": "nvflow send", "visibility": 3},
|
||||||
|
{"path": "status", "type": "text", "visibility": 3},
|
||||||
|
{"path": "stddev", "type": "float"},
|
||||||
|
{"path": "nsamples", "type": "int", "readonly": false, "cmd": "nvflow nsamples"},
|
||||||
|
{"path": "offset", "type": "float", "readonly": false, "cmd": "nvflow offset"},
|
||||||
|
{"path": "scale", "type": "float", "readonly": false, "cmd": "nvflow scale"},
|
||||||
|
{"path": "save", "type": "bool", "readonly": false, "cmd": "nvflow save", "description": "unchecked: current calib is not saved. set checked: save calib"}]},
|
||||||
|
|
||||||
|
"mf": {"base": "/mf", "params": [
|
||||||
|
{"path": "", "type": "float", "readonly": false, "cmd": "run mf", "kids": 8},
|
||||||
|
{"path": "send", "type": "text", "readonly": false, "cmd": "mf send", "visibility": 3},
|
||||||
|
{"path": "status", "type": "text", "visibility": 3},
|
||||||
|
{"path": "is_running", "type": "int", "readonly": false, "cmd": "mf is_running", "visibility": 3},
|
||||||
|
{"path": "statustext", "type": "text"},
|
||||||
|
{"path": "ramp", "type": "float", "readonly": false, "cmd": "mf ramp"},
|
||||||
|
{"path": "persistent_mode", "type": "enum", "enum": {"forever_off": -1, "off": 0, "on": 1}, "readonly": false, "cmd": "mf persistent_mode", "description": "hidden mode -1: completely off"},
|
||||||
|
{"path": "gen", "type": "none", "kids": 13},
|
||||||
|
{"path": "gen/persistent_delay", "type": "float", "readonly": false, "cmd": "mf gen/persistent_delay", "description": "timeout for going automatically into persistent mode"},
|
||||||
|
{"path": "gen/tolerance", "type": "float", "readonly": false, "cmd": "mf gen/tolerance"},
|
||||||
|
{"path": "gen/wait_switch_on", "type": "float", "readonly": false, "cmd": "mf gen/wait_switch_on"},
|
||||||
|
{"path": "gen/wait_switch_off", "type": "float", "readonly": false, "cmd": "mf gen/wait_switch_off"},
|
||||||
|
{"path": "gen/wait_stable_leads", "type": "float", "readonly": false, "cmd": "mf gen/wait_stable_leads"},
|
||||||
|
{"path": "gen/wait_stable_field", "type": "float", "readonly": false, "cmd": "mf gen/wait_stable_field"},
|
||||||
|
{"path": "gen/expectend", "type": "text"},
|
||||||
|
{"path": "gen/trained_pos", "type": "float", "readonly": false, "cmd": "mf gen/trained_pos"},
|
||||||
|
{"path": "gen/trained_neg", "type": "float", "readonly": false, "cmd": "mf gen/trained_neg"},
|
||||||
|
{"path": "gen/profile", "type": "text", "readonly": false, "cmd": "mf gen/profile", "description": "syntax: <field1>:<ramp1> <field2>:<ramp2> ... (<ramp2> is the ramp limit from <field1> to <field2>)"},
|
||||||
|
{"path": "gen/profile_training", "type": "text", "readonly": false, "cmd": "mf gen/profile_training", "description": "syntax: <field1>:<ramp1> <field2>:<ramp2> ... (<ramp2> is the ramp limit from <field1> to <field2>)"},
|
||||||
|
{"path": "gen/limit", "type": "float", "readonly": false, "cmd": "mf gen/limit"},
|
||||||
|
{"path": "gen/bipolar", "type": "bool", "readonly": false, "cmd": "mf gen/bipolar"},
|
||||||
|
{"path": "ips", "type": "float", "kids": 17},
|
||||||
|
{"path": "ips/ramp_slow", "type": "float", "readonly": false, "cmd": "mf ips/ramp_slow", "description": "ramp rate for coils Tesla/min."},
|
||||||
|
{"path": "ips/ramp_fast", "type": "float", "description": "ramp rate for leads Tesla/min."},
|
||||||
|
{"path": "ips/set_field", "type": "float", "readonly": false, "cmd": "mf ips/set_field"},
|
||||||
|
{"path": "ips/heater", "type": "bool", "readonly": false, "cmd": "mf ips/heater"},
|
||||||
|
{"path": "ips/ramp_state", "type": "enum", "enum": {"hold": 0, "to_zero": 1, "to_set": 2, "clamp": 3}, "readonly": false, "cmd": "mf ips/ramp_state"},
|
||||||
|
{"path": "ips/leads_set", "type": "float", "description": "calculated current in the leads, converted to Tesla"},
|
||||||
|
{"path": "ips/show_internals", "type": "bool", "readonly": false, "cmd": "mf ips/show_internals"},
|
||||||
|
{"path": "ips/leads_meas", "type": "float", "description": "measured current in the leads, converted to Tesla"},
|
||||||
|
{"path": "ips/slave1", "type": "float"},
|
||||||
|
{"path": "ips/slave2", "type": "float"},
|
||||||
|
{"path": "ips/slave3", "type": "float"},
|
||||||
|
{"path": "ips/volt", "type": "float"},
|
||||||
|
{"path": "ips/symode", "type": "text"},
|
||||||
|
{"path": "ips/engineering_password", "type": "text", "readonly": false, "cmd": "mf ips/engineering_password"},
|
||||||
|
{"path": "ips/atob", "type": "float", "readonly": false, "cmd": "mf ips/atob", "description": "Amp/Tesla"},
|
||||||
|
{"path": "ips/inductance", "type": "float", "readonly": false, "cmd": "mf ips/inductance", "description": "henries"},
|
||||||
|
{"path": "ips/switch_heater_current", "type": "float", "readonly": false, "cmd": "mf ips/switch_heater_current", "description": "switch heater current [mA]"}]},
|
||||||
|
|
||||||
|
"lev": {"base": "/lev", "params": [
|
||||||
|
{"path": "", "type": "float", "kids": 4},
|
||||||
|
{"path": "send", "type": "text", "readonly": false, "cmd": "lev send", "visibility": 3},
|
||||||
|
{"path": "status", "type": "text", "visibility": 3},
|
||||||
|
{"path": "mode", "type": "enum", "enum": {"slow": 0, "fast": 1}, "readonly": false, "cmd": "lev mode"},
|
||||||
|
{"path": "n2", "type": "float"}]},
|
||||||
|
|
||||||
|
"ln2fill": {"base": "/ln2fill", "params": [
|
||||||
|
{"path": "", "type": "enum", "enum": {"watching": 0, "filling": 1, "inactive": 2, "manualfill": 3}, "readonly": false, "cmd": "ln2fill", "kids": 14},
|
||||||
|
{"path": "send", "type": "text", "readonly": false, "cmd": "ln2fill send", "visibility": 3},
|
||||||
|
{"path": "status", "type": "text", "visibility": 3},
|
||||||
|
{"path": "state", "type": "text"},
|
||||||
|
{"path": "readlevel", "type": "text", "readonly": false, "cmd": "ln2fill readlevel", "visibility": 3},
|
||||||
|
{"path": "lowlevel", "type": "float", "readonly": false, "cmd": "ln2fill lowlevel"},
|
||||||
|
{"path": "highlevel", "type": "float", "readonly": false, "cmd": "ln2fill highlevel"},
|
||||||
|
{"path": "smooth", "type": "float"},
|
||||||
|
{"path": "minfillminutes", "type": "float", "readonly": false, "cmd": "ln2fill minfillminutes"},
|
||||||
|
{"path": "maxfillminutes", "type": "float", "readonly": false, "cmd": "ln2fill maxfillminutes"},
|
||||||
|
{"path": "minholdhours", "type": "float", "readonly": false, "cmd": "ln2fill minholdhours"},
|
||||||
|
{"path": "maxholdhours", "type": "float", "readonly": false, "cmd": "ln2fill maxholdhours"},
|
||||||
|
{"path": "tolerance", "type": "float", "readonly": false, "cmd": "ln2fill tolerance"},
|
||||||
|
{"path": "badreadingminutes", "type": "float", "readonly": false, "cmd": "ln2fill badreadingminutes"},
|
||||||
|
{"path": "tubecoolingminutes", "type": "float", "readonly": false, "cmd": "ln2fill tubecoolingminutes"}]},
|
||||||
|
|
||||||
|
"hefill": {"base": "/hefill", "params": [
|
||||||
|
{"path": "", "type": "enum", "enum": {"watching": 0, "filling": 1, "inactive": 2, "manualfill": 3}, "readonly": false, "cmd": "hefill", "kids": 16},
|
||||||
|
{"path": "send", "type": "text", "readonly": false, "cmd": "hefill send", "visibility": 3},
|
||||||
|
{"path": "status", "type": "text", "visibility": 3},
|
||||||
|
{"path": "state", "type": "text"},
|
||||||
|
{"path": "readlevel", "type": "text", "readonly": false, "cmd": "hefill readlevel", "visibility": 3},
|
||||||
|
{"path": "lowlevel", "type": "float", "readonly": false, "cmd": "hefill lowlevel"},
|
||||||
|
{"path": "highlevel", "type": "float", "readonly": false, "cmd": "hefill highlevel"},
|
||||||
|
{"path": "smooth", "type": "float"},
|
||||||
|
{"path": "minfillminutes", "type": "float", "readonly": false, "cmd": "hefill minfillminutes"},
|
||||||
|
{"path": "maxfillminutes", "type": "float", "readonly": false, "cmd": "hefill maxfillminutes"},
|
||||||
|
{"path": "minholdhours", "type": "float", "readonly": false, "cmd": "hefill minholdhours"},
|
||||||
|
{"path": "maxholdhours", "type": "float", "readonly": false, "cmd": "hefill maxholdhours"},
|
||||||
|
{"path": "tolerance", "type": "float", "readonly": false, "cmd": "hefill tolerance"},
|
||||||
|
{"path": "badreadingminutes", "type": "float", "readonly": false, "cmd": "hefill badreadingminutes"},
|
||||||
|
{"path": "tubecoolingminutes", "type": "float", "readonly": false, "cmd": "hefill tubecoolingminutes"},
|
||||||
|
{"path": "vessellimit", "type": "float", "readonly": false, "cmd": "hefill vessellimit"},
|
||||||
|
{"path": "vext", "type": "float"}]},
|
||||||
|
|
||||||
|
"table": {"base": "/table", "params": [
|
||||||
|
{"path": "", "type": "none", "kids": 17},
|
||||||
|
{"path": "send", "type": "text", "readonly": false, "cmd": "table send", "visibility": 3},
|
||||||
|
{"path": "status", "type": "text", "visibility": 3},
|
||||||
|
{"path": "fix_tt_set_prop", "type": "bool", "readonly": false, "cmd": "table fix_tt_set_prop"},
|
||||||
|
{"path": "val_tt_set_prop", "type": "float"},
|
||||||
|
{"path": "tbl_tt_set_prop", "type": "text", "readonly": false, "cmd": "table tbl_tt_set_prop", "description": "enter value pair separated with colon T1:par1 T2:par2 ..."},
|
||||||
|
{"path": "fix_tt_set_integ", "type": "bool", "readonly": false, "cmd": "table fix_tt_set_integ"},
|
||||||
|
{"path": "val_tt_set_integ", "type": "float"},
|
||||||
|
{"path": "tbl_tt_set_integ", "type": "text", "readonly": false, "cmd": "table tbl_tt_set_integ", "description": "enter value pair separated with colon T1:par1 T2:par2 ..."},
|
||||||
|
{"path": "fix_tt_dblctrl_int2", "type": "bool", "readonly": false, "cmd": "table fix_tt_dblctrl_int2"},
|
||||||
|
{"path": "val_tt_dblctrl_int2", "type": "float"},
|
||||||
|
{"path": "tbl_tt_dblctrl_int2", "type": "text", "readonly": false, "cmd": "table tbl_tt_dblctrl_int2", "description": "enter value pair separated with colon T1:par1 T2:par2 ..."},
|
||||||
|
{"path": "fix_tt_dblctrl_prop_up", "type": "bool", "readonly": false, "cmd": "table fix_tt_dblctrl_prop_up"},
|
||||||
|
{"path": "val_tt_dblctrl_prop_up", "type": "float"},
|
||||||
|
{"path": "tbl_tt_dblctrl_prop_up", "type": "text", "readonly": false, "cmd": "table tbl_tt_dblctrl_prop_up", "description": "enter value pair separated with colon T1:par1 T2:par2 ..."},
|
||||||
|
{"path": "fix_tt_dblctrl_prop_lo", "type": "bool", "readonly": false, "cmd": "table fix_tt_dblctrl_prop_lo"},
|
||||||
|
{"path": "val_tt_dblctrl_prop_lo", "type": "float"},
|
||||||
|
{"path": "tbl_tt_dblctrl_prop_lo", "type": "text", "readonly": false, "cmd": "table tbl_tt_dblctrl_prop_lo", "description": "enter value pair separated with colon T1:par1 T2:par2 ..."}]}}
|
395
cfg/sea/ma10high_t.config.json
Normal file
395
cfg/sea/ma10high_t.config.json
Normal file
@ -0,0 +1,395 @@
|
|||||||
|
{"tt": {"base": "/tt", "params": [
|
||||||
|
{"path": "", "type": "float", "readonly": false, "cmd": "run tt", "description": "tt", "kids": 18},
|
||||||
|
{"path": "send", "type": "text", "readonly": false, "cmd": "tt send", "visibility": 3},
|
||||||
|
{"path": "status", "type": "text", "visibility": 3},
|
||||||
|
{"path": "is_running", "type": "int", "readonly": false, "cmd": "tt is_running", "visibility": 3},
|
||||||
|
{"path": "mainloop", "type": "text", "readonly": false, "cmd": "tt mainloop", "visibility": 3},
|
||||||
|
{"path": "target", "type": "float"},
|
||||||
|
{"path": "running", "type": "int"},
|
||||||
|
{"path": "tolerance", "type": "float", "readonly": false, "cmd": "tt tolerance"},
|
||||||
|
{"path": "maxwait", "type": "float", "readonly": false, "cmd": "tt maxwait"},
|
||||||
|
{"path": "settle", "type": "float", "readonly": false, "cmd": "tt settle"},
|
||||||
|
{"path": "log", "type": "text", "readonly": false, "cmd": "tt log", "visibility": 3, "kids": 4},
|
||||||
|
{"path": "log/mean", "type": "float", "visibility": 3},
|
||||||
|
{"path": "log/m2", "type": "float", "visibility": 3},
|
||||||
|
{"path": "log/stddev", "type": "float", "visibility": 3},
|
||||||
|
{"path": "log/n", "type": "float", "visibility": 3},
|
||||||
|
{"path": "dblctrl", "type": "bool", "readonly": false, "cmd": "tt dblctrl", "kids": 9},
|
||||||
|
{"path": "dblctrl/tshift", "type": "float", "readonly": false, "cmd": "tt dblctrl/tshift"},
|
||||||
|
{"path": "dblctrl/mode", "type": "enum", "enum": {"disabled": -1, "inactive": 0, "stable": 1, "up": 2, "down": 3}, "readonly": false, "cmd": "tt dblctrl/mode"},
|
||||||
|
{"path": "dblctrl/shift_up", "type": "float"},
|
||||||
|
{"path": "dblctrl/shift_lo", "type": "float"},
|
||||||
|
{"path": "dblctrl/t_min", "type": "float"},
|
||||||
|
{"path": "dblctrl/t_max", "type": "float"},
|
||||||
|
{"path": "dblctrl/int2", "type": "float", "readonly": false, "cmd": "tt dblctrl/int2"},
|
||||||
|
{"path": "dblctrl/prop_up", "type": "float", "readonly": false, "cmd": "tt dblctrl/prop_up"},
|
||||||
|
{"path": "dblctrl/prop_lo", "type": "float", "readonly": false, "cmd": "tt dblctrl/prop_lo"},
|
||||||
|
{"path": "tm", "type": "float", "kids": 4},
|
||||||
|
{"path": "tm/curve", "type": "text", "readonly": false, "cmd": "tt tm/curve", "kids": 1},
|
||||||
|
{"path": "tm/curve/points", "type": "floatvarar", "readonly": false, "cmd": "tt tm/curve/points", "visibility": 3},
|
||||||
|
{"path": "tm/alarm", "type": "float", "readonly": false, "cmd": "tt tm/alarm"},
|
||||||
|
{"path": "tm/stddev", "type": "float"},
|
||||||
|
{"path": "tm/raw", "type": "float"},
|
||||||
|
{"path": "ts", "type": "float", "kids": 4},
|
||||||
|
{"path": "ts/curve", "type": "text", "readonly": false, "cmd": "tt ts/curve", "kids": 1},
|
||||||
|
{"path": "ts/curve/points", "type": "floatvarar", "readonly": false, "cmd": "tt ts/curve/points", "visibility": 3},
|
||||||
|
{"path": "ts/alarm", "type": "float", "readonly": false, "cmd": "tt ts/alarm"},
|
||||||
|
{"path": "ts/stddev", "type": "float"},
|
||||||
|
{"path": "ts/raw", "type": "float"},
|
||||||
|
{"path": "ts_2", "type": "float", "kids": 4},
|
||||||
|
{"path": "ts_2/curve", "type": "text", "readonly": false, "cmd": "tt ts_2/curve", "kids": 1},
|
||||||
|
{"path": "ts_2/curve/points", "type": "floatvarar", "readonly": false, "cmd": "tt ts_2/curve/points", "visibility": 3},
|
||||||
|
{"path": "ts_2/alarm", "type": "float", "readonly": false, "cmd": "tt ts_2/alarm"},
|
||||||
|
{"path": "ts_2/stddev", "type": "float"},
|
||||||
|
{"path": "ts_2/raw", "type": "float"},
|
||||||
|
{"path": "setsamp", "type": "float", "readonly": false, "cmd": "tt setsamp", "kids": 18},
|
||||||
|
{"path": "setsamp/mode", "type": "enum", "enum": {"disabled": -1, "off": 0, "controlling": 1, "manual": 2}, "readonly": false, "cmd": "tt setsamp/mode"},
|
||||||
|
{"path": "setsamp/reg", "type": "float"},
|
||||||
|
{"path": "setsamp/ramp", "type": "float", "readonly": false, "cmd": "tt setsamp/ramp", "description": "maximum ramp in K/min (0: ramp off)"},
|
||||||
|
{"path": "setsamp/wramp", "type": "float", "readonly": false, "cmd": "tt setsamp/wramp"},
|
||||||
|
{"path": "setsamp/smooth", "type": "float", "readonly": false, "cmd": "tt setsamp/smooth", "description": "smooth time (minutes)"},
|
||||||
|
{"path": "setsamp/channel", "type": "text", "readonly": false, "cmd": "tt setsamp/channel"},
|
||||||
|
{"path": "setsamp/limit", "type": "float", "readonly": false, "cmd": "tt setsamp/limit"},
|
||||||
|
{"path": "setsamp/resist", "type": "float", "readonly": false, "cmd": "tt setsamp/resist"},
|
||||||
|
{"path": "setsamp/maxheater", "type": "text", "readonly": false, "cmd": "tt setsamp/maxheater", "description": "maximum heater limit, units should be given without space: W, mW, A, mA"},
|
||||||
|
{"path": "setsamp/linearpower", "type": "float", "readonly": false, "cmd": "tt setsamp/linearpower", "description": "when not 0, it is the maximum effective power, and the power is linear to the heater output"},
|
||||||
|
{"path": "setsamp/maxpowerlim", "type": "float", "description": "the maximum power limit (before any booster or converter)"},
|
||||||
|
{"path": "setsamp/maxpower", "type": "float", "readonly": false, "cmd": "tt setsamp/maxpower", "description": "maximum power [W]"},
|
||||||
|
{"path": "setsamp/maxcurrent", "type": "float", "description": "the maximum current before any booster or converter"},
|
||||||
|
{"path": "setsamp/manualpower", "type": "float", "readonly": false, "cmd": "tt setsamp/manualpower"},
|
||||||
|
{"path": "setsamp/power", "type": "float"},
|
||||||
|
{"path": "setsamp/prop", "type": "float", "readonly": false, "cmd": "tt setsamp/prop", "description": "bigger means more gain"},
|
||||||
|
{"path": "setsamp/integ", "type": "float", "readonly": false, "cmd": "tt setsamp/integ", "description": "bigger means faster"},
|
||||||
|
{"path": "setsamp/deriv", "type": "float", "readonly": false, "cmd": "tt setsamp/deriv"},
|
||||||
|
{"path": "set", "type": "float", "readonly": false, "cmd": "tt set", "kids": 18},
|
||||||
|
{"path": "set/mode", "type": "enum", "enum": {"disabled": -1, "off": 0, "controlling": 1, "manual": 2}, "readonly": false, "cmd": "tt set/mode"},
|
||||||
|
{"path": "set/reg", "type": "float"},
|
||||||
|
{"path": "set/ramp", "type": "float", "readonly": false, "cmd": "tt set/ramp", "description": "maximum ramp in K/min (0: ramp off)"},
|
||||||
|
{"path": "set/wramp", "type": "float", "readonly": false, "cmd": "tt set/wramp"},
|
||||||
|
{"path": "set/smooth", "type": "float", "readonly": false, "cmd": "tt set/smooth", "description": "smooth time (minutes)"},
|
||||||
|
{"path": "set/channel", "type": "text", "readonly": false, "cmd": "tt set/channel"},
|
||||||
|
{"path": "set/limit", "type": "float", "readonly": false, "cmd": "tt set/limit"},
|
||||||
|
{"path": "set/resist", "type": "float", "readonly": false, "cmd": "tt set/resist"},
|
||||||
|
{"path": "set/maxheater", "type": "text", "readonly": false, "cmd": "tt set/maxheater", "description": "maximum heater limit, units should be given without space: W, mW, A, mA"},
|
||||||
|
{"path": "set/linearpower", "type": "float", "readonly": false, "cmd": "tt set/linearpower", "description": "when not 0, it is the maximum effective power, and the power is linear to the heater output"},
|
||||||
|
{"path": "set/maxpowerlim", "type": "float", "description": "the maximum power limit (before any booster or converter)"},
|
||||||
|
{"path": "set/maxpower", "type": "float", "readonly": false, "cmd": "tt set/maxpower", "description": "maximum power [W]"},
|
||||||
|
{"path": "set/maxcurrent", "type": "float", "description": "the maximum current before any booster or converter"},
|
||||||
|
{"path": "set/manualpower", "type": "float", "readonly": false, "cmd": "tt set/manualpower"},
|
||||||
|
{"path": "set/power", "type": "float"},
|
||||||
|
{"path": "set/prop", "type": "float", "readonly": false, "cmd": "tt set/prop", "description": "bigger means more gain"},
|
||||||
|
{"path": "set/integ", "type": "float", "readonly": false, "cmd": "tt set/integ", "description": "bigger means faster"},
|
||||||
|
{"path": "set/deriv", "type": "float", "readonly": false, "cmd": "tt set/deriv"},
|
||||||
|
{"path": "display", "type": "text", "readonly": false, "cmd": "tt display"},
|
||||||
|
{"path": "remote", "type": "bool"}]},
|
||||||
|
|
||||||
|
"cc": {"base": "/cc", "params": [
|
||||||
|
{"path": "", "type": "bool", "kids": 96},
|
||||||
|
{"path": "send", "type": "text", "readonly": false, "cmd": "cc send", "visibility": 3},
|
||||||
|
{"path": "status", "type": "text", "visibility": 3},
|
||||||
|
{"path": "autodevice", "type": "bool", "readonly": false, "cmd": "cc autodevice"},
|
||||||
|
{"path": "fav", "type": "bool", "readonly": false, "cmd": "cc fav"},
|
||||||
|
{"path": "f", "type": "float"},
|
||||||
|
{"path": "fs", "type": "enum", "enum": {"ok": 0, "no_sens": 1}, "readonly": false, "cmd": "cc fs"},
|
||||||
|
{"path": "mav", "type": "bool", "readonly": false, "cmd": "cc mav"},
|
||||||
|
{"path": "fm", "type": "enum", "enum": {"idle": 0, "opening": 1, "closing": 2, "opened": 3, "closed": 4, "no_motor": 5}},
|
||||||
|
{"path": "fa", "type": "enum", "enum": {"fixed": 0, "controlled": 1, "automatic": 2, "offline": 3}, "readonly": false, "cmd": "cc fa"},
|
||||||
|
{"path": "mp", "type": "float", "readonly": false, "cmd": "cc mp"},
|
||||||
|
{"path": "msp", "type": "float"},
|
||||||
|
{"path": "mmp", "type": "float"},
|
||||||
|
{"path": "mc", "type": "float", "readonly": false, "cmd": "cc mc"},
|
||||||
|
{"path": "mfc", "type": "float", "readonly": false, "cmd": "cc mfc"},
|
||||||
|
{"path": "moc", "type": "float", "readonly": false, "cmd": "cc moc"},
|
||||||
|
{"path": "mtc", "type": "float", "readonly": false, "cmd": "cc mtc"},
|
||||||
|
{"path": "mtl", "type": "float"},
|
||||||
|
{"path": "mft", "type": "float", "readonly": false, "cmd": "cc mft"},
|
||||||
|
{"path": "mt", "type": "float"},
|
||||||
|
{"path": "mo", "type": "float"},
|
||||||
|
{"path": "mcr", "type": "float"},
|
||||||
|
{"path": "mot", "type": "float"},
|
||||||
|
{"path": "mw", "type": "float", "readonly": false, "cmd": "cc mw", "description": "correction pulse after automatic open"},
|
||||||
|
{"path": "hav", "type": "bool", "readonly": false, "cmd": "cc hav"},
|
||||||
|
{"path": "h", "type": "float"},
|
||||||
|
{"path": "hr", "type": "float"},
|
||||||
|
{"path": "hc", "type": "float"},
|
||||||
|
{"path": "hu", "type": "float"},
|
||||||
|
{"path": "hh", "type": "float", "readonly": false, "cmd": "cc hh"},
|
||||||
|
{"path": "hl", "type": "float", "readonly": false, "cmd": "cc hl"},
|
||||||
|
{"path": "htf", "type": "float", "readonly": false, "cmd": "cc htf", "description": "meas. period in fast mode"},
|
||||||
|
{"path": "hts", "type": "float", "readonly": false, "cmd": "cc hts", "description": "meas. period in slow mode"},
|
||||||
|
{"path": "hd", "type": "float", "readonly": false, "cmd": "cc hd"},
|
||||||
|
{"path": "hwr", "type": "float", "readonly": false, "cmd": "cc hwr"},
|
||||||
|
{"path": "hem", "type": "float", "readonly": false, "cmd": "cc hem", "description": "sensor length in mm from top to empty pos."},
|
||||||
|
{"path": "hfu", "type": "float", "readonly": false, "cmd": "cc hfu", "description": "sensor length in mm from top to full pos."},
|
||||||
|
{"path": "hcd", "type": "enum", "enum": {"stop": 0, "fill": 1, "off": 2, "auto": 3, "manual": 7}, "readonly": false, "cmd": "cc hcd"},
|
||||||
|
{"path": "hv", "type": "enum", "enum": {"fill_valve_off": 0, "filling": 1, "no_fill_valve": 2, "timeout": 3, "timeout1": 4}},
|
||||||
|
{"path": "hsf", "type": "enum", "enum": {"sens_ok": 0, "sens_warm": 1, "no_sens": 2, "timeout": 3, "not_yet_read": 4, "disabled": 5}},
|
||||||
|
{"path": "ha", "type": "bool", "readonly": false, "cmd": "cc ha"},
|
||||||
|
{"path": "hm", "type": "bool"},
|
||||||
|
{"path": "hf", "type": "enum", "enum": {"slow": 0, "fast": 1}, "readonly": false, "cmd": "cc hf"},
|
||||||
|
{"path": "hbe", "type": "bool", "readonly": false, "cmd": "cc hbe"},
|
||||||
|
{"path": "hmf", "type": "float"},
|
||||||
|
{"path": "hms", "type": "float"},
|
||||||
|
{"path": "hit", "type": "float", "readonly": false, "cmd": "cc hit"},
|
||||||
|
{"path": "hft", "type": "int", "readonly": false, "cmd": "cc hft"},
|
||||||
|
{"path": "hea", "type": "enum", "enum": {"0": 0, "1": 1, "6": 6}, "readonly": false, "cmd": "cc hea"},
|
||||||
|
{"path": "hch", "type": "int", "readonly": false, "cmd": "cc hch", "visibility": 3},
|
||||||
|
{"path": "hwr0", "type": "float", "readonly": false, "cmd": "cc hwr0", "visibility": 3},
|
||||||
|
{"path": "hem0", "type": "float", "readonly": false, "cmd": "cc hem0", "description": "sensor length in mm from top to empty pos.", "visibility": 3},
|
||||||
|
{"path": "hfu0", "type": "float", "readonly": false, "cmd": "cc hfu0", "description": "sensor length in mm from top to full pos.", "visibility": 3},
|
||||||
|
{"path": "hd0", "type": "float", "readonly": false, "cmd": "cc hd0", "description": "external sensor drive current (mA)", "visibility": 3},
|
||||||
|
{"path": "h0", "type": "float", "visibility": 3},
|
||||||
|
{"path": "hs0", "type": "enum", "enum": {"sens_ok": 0, "sens_warm": 1, "no_sens": 2, "timeout": 3, "not_yet_read": 4, "disabled": 5}, "visibility": 3},
|
||||||
|
{"path": "h1", "type": "float", "visibility": 3},
|
||||||
|
{"path": "hs1", "type": "enum", "enum": {"sens_ok": 0, "sens_warm": 1, "no_sens": 2, "timeout": 3, "not_yet_read": 4, "disabled": 5}, "visibility": 3},
|
||||||
|
{"path": "h2", "type": "float", "visibility": 3},
|
||||||
|
{"path": "hs2", "type": "enum", "enum": {"sens_ok": 0, "sens_warm": 1, "no_sens": 2, "timeout": 3, "not_yet_read": 4, "disabled": 5}, "visibility": 3},
|
||||||
|
{"path": "h3", "type": "float", "visibility": 3},
|
||||||
|
{"path": "hs3", "type": "enum", "enum": {"sens_ok": 0, "sens_warm": 1, "no_sens": 2, "timeout": 3, "not_yet_read": 4, "disabled": 5}, "visibility": 3},
|
||||||
|
{"path": "h4", "type": "float", "visibility": 3},
|
||||||
|
{"path": "hs4", "type": "enum", "enum": {"sens_ok": 0, "sens_warm": 1, "no_sens": 2, "timeout": 3, "not_yet_read": 4, "disabled": 5}, "visibility": 3},
|
||||||
|
{"path": "h5", "type": "float", "visibility": 3},
|
||||||
|
{"path": "hs5", "type": "enum", "enum": {"sens_ok": 0, "sens_warm": 1, "no_sens": 2, "timeout": 3, "not_yet_read": 4, "disabled": 5}, "visibility": 3},
|
||||||
|
{"path": "hfb", "type": "float"},
|
||||||
|
{"path": "nav", "type": "bool", "readonly": false, "cmd": "cc nav"},
|
||||||
|
{"path": "nu", "type": "float"},
|
||||||
|
{"path": "nl", "type": "float"},
|
||||||
|
{"path": "nth", "type": "float", "readonly": false, "cmd": "cc nth"},
|
||||||
|
{"path": "ntc", "type": "float", "readonly": false, "cmd": "cc ntc"},
|
||||||
|
{"path": "ntm", "type": "float", "readonly": false, "cmd": "cc ntm"},
|
||||||
|
{"path": "ns", "type": "enum", "enum": {"sens_ok": 0, "no_sens": 1, "short_circuit": 2, "upside_down": 3, "sens_warm": 4, "empty": 5}},
|
||||||
|
{"path": "na", "type": "bool", "readonly": false, "cmd": "cc na"},
|
||||||
|
{"path": "nv", "type": "enum", "enum": {"fill_valve_off": 0, "filling": 1, "no_fill_valve": 2, "timeout": 3, "timeout1": 4, "boost": 5}},
|
||||||
|
{"path": "nc", "type": "enum", "enum": {"stop": 0, "fill": 1, "off": 2, "auto": 3}, "readonly": false, "cmd": "cc nc"},
|
||||||
|
{"path": "nfb", "type": "float"},
|
||||||
|
{"path": "cda", "type": "float"},
|
||||||
|
{"path": "cdb", "type": "float"},
|
||||||
|
{"path": "cba", "type": "float"},
|
||||||
|
{"path": "cbb", "type": "float"},
|
||||||
|
{"path": "cvs", "type": "int"},
|
||||||
|
{"path": "csp", "type": "int"},
|
||||||
|
{"path": "cdv", "type": "text", "readonly": false, "cmd": "cc cdv"},
|
||||||
|
{"path": "cic", "type": "text", "readonly": false, "cmd": "cc cic"},
|
||||||
|
{"path": "cin", "type": "text"},
|
||||||
|
{"path": "cds", "type": "enum", "enum": {"local": 0, "remote": 1, "loading": 2, "by_code": 3, "by_touch": 4}, "readonly": false, "cmd": "cc cds"},
|
||||||
|
{"path": "timing", "type": "bool", "readonly": false, "cmd": "cc timing"},
|
||||||
|
{"path": "tc", "type": "float", "visibility": 3},
|
||||||
|
{"path": "tn", "type": "float", "visibility": 3},
|
||||||
|
{"path": "th", "type": "float", "visibility": 3},
|
||||||
|
{"path": "tf", "type": "float", "visibility": 3},
|
||||||
|
{"path": "tm", "type": "float", "visibility": 3},
|
||||||
|
{"path": "tv", "type": "float", "visibility": 3},
|
||||||
|
{"path": "tq", "type": "float", "visibility": 3},
|
||||||
|
{"path": "bdl", "type": "float", "readonly": false, "cmd": "cc bdl"}]},
|
||||||
|
|
||||||
|
"nv": {"base": "/nv", "params": [
|
||||||
|
{"path": "", "type": "enum", "enum": {"fixed": 0, "controlled": 1, "automatic": 2, "close": 3, "open": 4}, "readonly": false, "cmd": "nv", "kids": 11},
|
||||||
|
{"path": "send", "type": "text", "readonly": false, "cmd": "nv send", "visibility": 3},
|
||||||
|
{"path": "status", "type": "text", "visibility": 3},
|
||||||
|
{"path": "motstat", "type": "enum", "enum": {"idle": 0, "opening": 1, "closing": 2, "opened": 3, "closed": 4, "no_motor": 5}},
|
||||||
|
{"path": "flow", "type": "float"},
|
||||||
|
{"path": "set", "type": "float", "readonly": false, "cmd": "nv set"},
|
||||||
|
{"path": "flowmax", "type": "float", "readonly": false, "cmd": "nv flowmax"},
|
||||||
|
{"path": "flowp", "type": "float"},
|
||||||
|
{"path": "span", "type": "float"},
|
||||||
|
{"path": "ctrl", "type": "none", "kids": 13},
|
||||||
|
{"path": "ctrl/regtext", "type": "text"},
|
||||||
|
{"path": "ctrl/prop_o", "type": "float", "readonly": false, "cmd": "nv ctrl/prop_o", "description": "prop [sec/mbar] when opening. above 4 mbar a 10 times lower value is used"},
|
||||||
|
{"path": "ctrl/prop_c", "type": "float", "readonly": false, "cmd": "nv ctrl/prop_c", "description": "prop [sec/mbar] when closing. above 4 mbar a 10 times lower value is used"},
|
||||||
|
{"path": "ctrl/deriv_o", "type": "float", "readonly": false, "cmd": "nv ctrl/deriv_o", "description": "convergence target time [sec] when opening"},
|
||||||
|
{"path": "ctrl/deriv_c", "type": "float", "readonly": false, "cmd": "nv ctrl/deriv_c", "description": "convergence target time [sec] when closing"},
|
||||||
|
{"path": "ctrl/minpulse_o", "type": "float", "readonly": false, "cmd": "nv ctrl/minpulse_o", "description": "minimum close pulse [sec]"},
|
||||||
|
{"path": "ctrl/minpulse_c", "type": "float", "readonly": false, "cmd": "nv ctrl/minpulse_c", "description": "standard close pulse [sec]"},
|
||||||
|
{"path": "ctrl/hystpulse_o", "type": "float", "readonly": false, "cmd": "nv ctrl/hystpulse_o", "description": "motor pulse to overcome hysteresis when opening"},
|
||||||
|
{"path": "ctrl/hystpulse_c", "type": "float", "readonly": false, "cmd": "nv ctrl/hystpulse_c", "description": "motor pulse to overcome hysteresis when closing"},
|
||||||
|
{"path": "ctrl/tol", "type": "float", "readonly": false, "cmd": "nv ctrl/tol", "description": "valid below 3 mbar"},
|
||||||
|
{"path": "ctrl/tolhigh", "type": "float", "readonly": false, "cmd": "nv ctrl/tolhigh", "description": "valid above 4 mbar"},
|
||||||
|
{"path": "ctrl/openpulse", "type": "float", "readonly": false, "cmd": "nv ctrl/openpulse", "description": "time to open from completely closed to a significant opening"},
|
||||||
|
{"path": "ctrl/adjust_minpulse", "type": "bool", "readonly": false, "cmd": "nv ctrl/adjust_minpulse", "description": "adjust minpulse automatically"},
|
||||||
|
{"path": "autoflow", "type": "none", "kids": 24},
|
||||||
|
{"path": "autoflow/suspended", "type": "bool", "readonly": false, "cmd": "nv autoflow/suspended"},
|
||||||
|
{"path": "autoflow/prop", "type": "float", "readonly": false, "cmd": "nv autoflow/prop"},
|
||||||
|
{"path": "autoflow/flowstd", "type": "float", "readonly": false, "cmd": "nv autoflow/flowstd"},
|
||||||
|
{"path": "autoflow/flowlim", "type": "float", "readonly": false, "cmd": "nv autoflow/flowlim"},
|
||||||
|
{"path": "autoflow/smooth", "type": "float", "readonly": false, "cmd": "nv autoflow/smooth"},
|
||||||
|
{"path": "autoflow/difSize", "type": "float", "readonly": false, "cmd": "nv autoflow/difSize"},
|
||||||
|
{"path": "autoflow/difRange", "type": "float", "readonly": false, "cmd": "nv autoflow/difRange"},
|
||||||
|
{"path": "autoflow/flowSize", "type": "float", "readonly": false, "cmd": "nv autoflow/flowSize"},
|
||||||
|
{"path": "autoflow/convTime", "type": "float", "readonly": false, "cmd": "nv autoflow/convTime"},
|
||||||
|
{"path": "autoflow/Tmin", "type": "float", "readonly": false, "cmd": "nv autoflow/Tmin"},
|
||||||
|
{"path": "autoflow/script", "type": "text", "readonly": false, "cmd": "nv autoflow/script"},
|
||||||
|
{"path": "autoflow/getTemp", "type": "text", "readonly": false, "cmd": "nv autoflow/getTemp"},
|
||||||
|
{"path": "autoflow/getTset", "type": "text", "readonly": false, "cmd": "nv autoflow/getTset"},
|
||||||
|
{"path": "autoflow/getFlow", "type": "text", "readonly": false, "cmd": "nv autoflow/getFlow"},
|
||||||
|
{"path": "autoflow/difBuf", "type": "text"},
|
||||||
|
{"path": "autoflow/flowBuf", "type": "text"},
|
||||||
|
{"path": "autoflow/flowset", "type": "float"},
|
||||||
|
{"path": "autoflow/flowmin", "type": "float"},
|
||||||
|
{"path": "autoflow/flowmax", "type": "float"},
|
||||||
|
{"path": "autoflow/difmin", "type": "float"},
|
||||||
|
{"path": "autoflow/difmax", "type": "float"},
|
||||||
|
{"path": "autoflow/setmin", "type": "float"},
|
||||||
|
{"path": "autoflow/setmax", "type": "float"},
|
||||||
|
{"path": "autoflow/flowtarget", "type": "float"},
|
||||||
|
{"path": "calib", "type": "none", "kids": 2},
|
||||||
|
{"path": "calib/ln_per_min_per_mbar", "type": "float", "readonly": false, "cmd": "nv calib/ln_per_min_per_mbar"},
|
||||||
|
{"path": "calib/mbar_offset", "type": "float", "readonly": false, "cmd": "nv calib/mbar_offset"}]},
|
||||||
|
|
||||||
|
"hepump": {"base": "/hepump", "params": [
|
||||||
|
{"path": "", "type": "enum", "enum": {"xds35_auto": 0, "xds35_manual": 1, "sv65": 2, "other": 3, "no": -1}, "readonly": false, "cmd": "hepump", "description": "xds35: scroll pump, sv65: leybold", "kids": 10},
|
||||||
|
{"path": "send", "type": "text", "readonly": false, "cmd": "hepump send", "visibility": 3},
|
||||||
|
{"path": "status", "type": "text", "visibility": 3},
|
||||||
|
{"path": "running", "type": "bool", "readonly": false, "cmd": "hepump running"},
|
||||||
|
{"path": "eco", "type": "bool", "readonly": false, "cmd": "hepump eco"},
|
||||||
|
{"path": "auto", "type": "bool", "readonly": false, "cmd": "hepump auto"},
|
||||||
|
{"path": "valve", "type": "enum", "enum": {"closed": 0, "closing": 1, "opening": 2, "opened": 3, "undefined": 4}, "readonly": false, "cmd": "hepump valve"},
|
||||||
|
{"path": "eco_t_lim", "type": "float", "readonly": false, "cmd": "hepump eco_t_lim", "description": "switch off eco mode when T_set < eco_t_lim and T < eco_t_lim * 2"},
|
||||||
|
{"path": "calib", "type": "float", "readonly": false, "cmd": "hepump calib", "visibility": 3},
|
||||||
|
{"path": "health", "type": "float"}]},
|
||||||
|
|
||||||
|
"hemot": {"base": "/hepump/hemot", "params": [
|
||||||
|
{"path": "", "type": "float", "readonly": false, "cmd": "run hemot", "kids": 30},
|
||||||
|
{"path": "send", "type": "text", "readonly": false, "cmd": "hemot send", "visibility": 3},
|
||||||
|
{"path": "status", "type": "text", "visibility": 3},
|
||||||
|
{"path": "is_running", "type": "int", "readonly": false, "cmd": "hemot is_running", "visibility": 3},
|
||||||
|
{"path": "pos", "type": "float"},
|
||||||
|
{"path": "encoder", "type": "float"},
|
||||||
|
{"path": "zero", "type": "float", "readonly": false, "cmd": "hemot zero"},
|
||||||
|
{"path": "lowerlimit", "type": "float", "readonly": false, "cmd": "hemot lowerlimit"},
|
||||||
|
{"path": "upperlimit", "type": "float", "readonly": false, "cmd": "hemot upperlimit"},
|
||||||
|
{"path": "disablelimits", "type": "bool", "readonly": false, "cmd": "hemot disablelimits"},
|
||||||
|
{"path": "verbose", "type": "bool", "readonly": false, "cmd": "hemot verbose"},
|
||||||
|
{"path": "target", "type": "float"},
|
||||||
|
{"path": "runstate", "type": "enum", "enum": {"idle": 0, "running": 1, "finished": 2, "error": 3}},
|
||||||
|
{"path": "precision", "type": "float", "readonly": false, "cmd": "hemot precision"},
|
||||||
|
{"path": "maxencdif", "type": "float", "readonly": false, "cmd": "hemot maxencdif"},
|
||||||
|
{"path": "id", "type": "float", "readonly": false, "cmd": "hemot id"},
|
||||||
|
{"path": "pump_number", "type": "float", "readonly": false, "cmd": "hemot pump_number"},
|
||||||
|
{"path": "init", "type": "float", "readonly": false, "cmd": "hemot init"},
|
||||||
|
{"path": "maxspeed", "type": "float", "readonly": false, "cmd": "hemot maxspeed"},
|
||||||
|
{"path": "acceleration", "type": "float", "readonly": false, "cmd": "hemot acceleration"},
|
||||||
|
{"path": "maxcurrent", "type": "float", "readonly": false, "cmd": "hemot maxcurrent"},
|
||||||
|
{"path": "standbycurrent", "type": "float", "readonly": false, "cmd": "hemot standbycurrent"},
|
||||||
|
{"path": "freewheeling", "type": "bool", "readonly": false, "cmd": "hemot freewheeling"},
|
||||||
|
{"path": "output0", "type": "bool", "readonly": false, "cmd": "hemot output0"},
|
||||||
|
{"path": "output1", "type": "bool", "readonly": false, "cmd": "hemot output1"},
|
||||||
|
{"path": "input3", "type": "bool"},
|
||||||
|
{"path": "pullup", "type": "float", "readonly": false, "cmd": "hemot pullup"},
|
||||||
|
{"path": "nopumpfeedback", "type": "bool", "readonly": false, "cmd": "hemot nopumpfeedback"},
|
||||||
|
{"path": "eeprom", "type": "enum", "enum": {"ok": 0, "dirty": 1, "save": 2, "load": 3}, "readonly": false, "cmd": "hemot eeprom"},
|
||||||
|
{"path": "customadr", "type": "text", "readonly": false, "cmd": "hemot customadr"},
|
||||||
|
{"path": "custompar", "type": "float", "readonly": false, "cmd": "hemot custompar"}]},
|
||||||
|
|
||||||
|
"nvflow": {"base": "/nvflow", "params": [
|
||||||
|
{"path": "", "type": "float", "kids": 7},
|
||||||
|
{"path": "send", "type": "text", "readonly": false, "cmd": "nvflow send", "visibility": 3},
|
||||||
|
{"path": "status", "type": "text", "visibility": 3},
|
||||||
|
{"path": "stddev", "type": "float"},
|
||||||
|
{"path": "nsamples", "type": "int", "readonly": false, "cmd": "nvflow nsamples"},
|
||||||
|
{"path": "offset", "type": "float", "readonly": false, "cmd": "nvflow offset"},
|
||||||
|
{"path": "scale", "type": "float", "readonly": false, "cmd": "nvflow scale"},
|
||||||
|
{"path": "save", "type": "bool", "readonly": false, "cmd": "nvflow save", "description": "unchecked: current calib is not saved. set checked: save calib"}]},
|
||||||
|
|
||||||
|
"mf": {"base": "/mf", "params": [
|
||||||
|
{"path": "", "type": "float", "readonly": false, "cmd": "run mf", "kids": 8},
|
||||||
|
{"path": "send", "type": "text", "readonly": false, "cmd": "mf send", "visibility": 3},
|
||||||
|
{"path": "status", "type": "text", "visibility": 3},
|
||||||
|
{"path": "is_running", "type": "int", "readonly": false, "cmd": "mf is_running", "visibility": 3},
|
||||||
|
{"path": "statustext", "type": "text"},
|
||||||
|
{"path": "ramp", "type": "float", "readonly": false, "cmd": "mf ramp"},
|
||||||
|
{"path": "persistent_mode", "type": "enum", "enum": {"forever_off": -1, "off": 0, "on": 1}, "readonly": false, "cmd": "mf persistent_mode", "description": "hidden mode -1: completely off"},
|
||||||
|
{"path": "gen", "type": "none", "kids": 13},
|
||||||
|
{"path": "gen/persistent_delay", "type": "float", "readonly": false, "cmd": "mf gen/persistent_delay", "description": "timeout for going automatically into persistent mode"},
|
||||||
|
{"path": "gen/tolerance", "type": "float", "readonly": false, "cmd": "mf gen/tolerance"},
|
||||||
|
{"path": "gen/wait_switch_on", "type": "float", "readonly": false, "cmd": "mf gen/wait_switch_on"},
|
||||||
|
{"path": "gen/wait_switch_off", "type": "float", "readonly": false, "cmd": "mf gen/wait_switch_off"},
|
||||||
|
{"path": "gen/wait_stable_leads", "type": "float", "readonly": false, "cmd": "mf gen/wait_stable_leads"},
|
||||||
|
{"path": "gen/wait_stable_field", "type": "float", "readonly": false, "cmd": "mf gen/wait_stable_field"},
|
||||||
|
{"path": "gen/expectend", "type": "text"},
|
||||||
|
{"path": "gen/trained_pos", "type": "float", "readonly": false, "cmd": "mf gen/trained_pos"},
|
||||||
|
{"path": "gen/trained_neg", "type": "float", "readonly": false, "cmd": "mf gen/trained_neg"},
|
||||||
|
{"path": "gen/profile", "type": "text", "readonly": false, "cmd": "mf gen/profile", "description": "syntax: <field1>:<ramp1> <field2>:<ramp2> ... (<ramp2> is the ramp limit from <field1> to <field2>)"},
|
||||||
|
{"path": "gen/profile_training", "type": "text", "readonly": false, "cmd": "mf gen/profile_training", "description": "syntax: <field1>:<ramp1> <field2>:<ramp2> ... (<ramp2> is the ramp limit from <field1> to <field2>)"},
|
||||||
|
{"path": "gen/limit", "type": "float", "readonly": false, "cmd": "mf gen/limit"},
|
||||||
|
{"path": "gen/bipolar", "type": "bool", "readonly": false, "cmd": "mf gen/bipolar"},
|
||||||
|
{"path": "ips", "type": "float", "kids": 17},
|
||||||
|
{"path": "ips/ramp_slow", "type": "float", "readonly": false, "cmd": "mf ips/ramp_slow", "description": "ramp rate for coils Tesla/min."},
|
||||||
|
{"path": "ips/ramp_fast", "type": "float", "description": "ramp rate for leads Tesla/min."},
|
||||||
|
{"path": "ips/set_field", "type": "float", "readonly": false, "cmd": "mf ips/set_field"},
|
||||||
|
{"path": "ips/heater", "type": "bool", "readonly": false, "cmd": "mf ips/heater"},
|
||||||
|
{"path": "ips/ramp_state", "type": "enum", "enum": {"hold": 0, "to_zero": 1, "to_set": 2, "clamp": 3}, "readonly": false, "cmd": "mf ips/ramp_state"},
|
||||||
|
{"path": "ips/leads_set", "type": "float", "description": "calculated current in the leads, converted to Tesla"},
|
||||||
|
{"path": "ips/show_internals", "type": "bool", "readonly": false, "cmd": "mf ips/show_internals"},
|
||||||
|
{"path": "ips/leads_meas", "type": "float", "description": "measured current in the leads, converted to Tesla"},
|
||||||
|
{"path": "ips/slave1", "type": "float"},
|
||||||
|
{"path": "ips/slave2", "type": "float"},
|
||||||
|
{"path": "ips/slave3", "type": "float"},
|
||||||
|
{"path": "ips/volt", "type": "float"},
|
||||||
|
{"path": "ips/symode", "type": "text"},
|
||||||
|
{"path": "ips/engineering_password", "type": "text", "readonly": false, "cmd": "mf ips/engineering_password"},
|
||||||
|
{"path": "ips/atob", "type": "float", "readonly": false, "cmd": "mf ips/atob", "description": "Amp/Tesla"},
|
||||||
|
{"path": "ips/inductance", "type": "float", "readonly": false, "cmd": "mf ips/inductance", "description": "henries"},
|
||||||
|
{"path": "ips/switch_heater_current", "type": "float", "readonly": false, "cmd": "mf ips/switch_heater_current", "description": "switch heater current [mA]"}]},
|
||||||
|
|
||||||
|
"lev": {"base": "/lev", "params": [
|
||||||
|
{"path": "", "type": "float", "kids": 4},
|
||||||
|
{"path": "send", "type": "text", "readonly": false, "cmd": "lev send", "visibility": 3},
|
||||||
|
{"path": "status", "type": "text", "visibility": 3},
|
||||||
|
{"path": "mode", "type": "enum", "enum": {"slow": 0, "fast": 1}, "readonly": false, "cmd": "lev mode"},
|
||||||
|
{"path": "n2", "type": "float"}]},
|
||||||
|
|
||||||
|
"ln2fill": {"base": "/ln2fill", "params": [
|
||||||
|
{"path": "", "type": "enum", "enum": {"watching": 0, "filling": 1, "inactive": 2, "manualfill": 3}, "readonly": false, "cmd": "ln2fill", "kids": 14},
|
||||||
|
{"path": "send", "type": "text", "readonly": false, "cmd": "ln2fill send", "visibility": 3},
|
||||||
|
{"path": "status", "type": "text", "visibility": 3},
|
||||||
|
{"path": "state", "type": "text"},
|
||||||
|
{"path": "readlevel", "type": "text", "readonly": false, "cmd": "ln2fill readlevel", "visibility": 3},
|
||||||
|
{"path": "lowlevel", "type": "float", "readonly": false, "cmd": "ln2fill lowlevel"},
|
||||||
|
{"path": "highlevel", "type": "float", "readonly": false, "cmd": "ln2fill highlevel"},
|
||||||
|
{"path": "smooth", "type": "float"},
|
||||||
|
{"path": "minfillminutes", "type": "float", "readonly": false, "cmd": "ln2fill minfillminutes"},
|
||||||
|
{"path": "maxfillminutes", "type": "float", "readonly": false, "cmd": "ln2fill maxfillminutes"},
|
||||||
|
{"path": "minholdhours", "type": "float", "readonly": false, "cmd": "ln2fill minholdhours"},
|
||||||
|
{"path": "maxholdhours", "type": "float", "readonly": false, "cmd": "ln2fill maxholdhours"},
|
||||||
|
{"path": "tolerance", "type": "float", "readonly": false, "cmd": "ln2fill tolerance"},
|
||||||
|
{"path": "badreadingminutes", "type": "float", "readonly": false, "cmd": "ln2fill badreadingminutes"},
|
||||||
|
{"path": "tubecoolingminutes", "type": "float", "readonly": false, "cmd": "ln2fill tubecoolingminutes"}]},
|
||||||
|
|
||||||
|
"hefill": {"base": "/hefill", "params": [
|
||||||
|
{"path": "", "type": "enum", "enum": {"watching": 0, "filling": 1, "inactive": 2, "manualfill": 3}, "readonly": false, "cmd": "hefill", "kids": 16},
|
||||||
|
{"path": "send", "type": "text", "readonly": false, "cmd": "hefill send", "visibility": 3},
|
||||||
|
{"path": "status", "type": "text", "visibility": 3},
|
||||||
|
{"path": "state", "type": "text"},
|
||||||
|
{"path": "readlevel", "type": "text", "readonly": false, "cmd": "hefill readlevel", "visibility": 3},
|
||||||
|
{"path": "lowlevel", "type": "float", "readonly": false, "cmd": "hefill lowlevel"},
|
||||||
|
{"path": "highlevel", "type": "float", "readonly": false, "cmd": "hefill highlevel"},
|
||||||
|
{"path": "smooth", "type": "float"},
|
||||||
|
{"path": "minfillminutes", "type": "float", "readonly": false, "cmd": "hefill minfillminutes"},
|
||||||
|
{"path": "maxfillminutes", "type": "float", "readonly": false, "cmd": "hefill maxfillminutes"},
|
||||||
|
{"path": "minholdhours", "type": "float", "readonly": false, "cmd": "hefill minholdhours"},
|
||||||
|
{"path": "maxholdhours", "type": "float", "readonly": false, "cmd": "hefill maxholdhours"},
|
||||||
|
{"path": "tolerance", "type": "float", "readonly": false, "cmd": "hefill tolerance"},
|
||||||
|
{"path": "badreadingminutes", "type": "float", "readonly": false, "cmd": "hefill badreadingminutes"},
|
||||||
|
{"path": "tubecoolingminutes", "type": "float", "readonly": false, "cmd": "hefill tubecoolingminutes"},
|
||||||
|
{"path": "vessellimit", "type": "float", "readonly": false, "cmd": "hefill vessellimit"},
|
||||||
|
{"path": "vext", "type": "float"}]},
|
||||||
|
|
||||||
|
"table": {"base": "/table", "params": [
|
||||||
|
{"path": "", "type": "none", "kids": 17},
|
||||||
|
{"path": "send", "type": "text", "readonly": false, "cmd": "table send", "visibility": 3},
|
||||||
|
{"path": "status", "type": "text", "visibility": 3},
|
||||||
|
{"path": "fix_tt_set_prop", "type": "bool", "readonly": false, "cmd": "table fix_tt_set_prop"},
|
||||||
|
{"path": "val_tt_set_prop", "type": "float"},
|
||||||
|
{"path": "tbl_tt_set_prop", "type": "text", "readonly": false, "cmd": "table tbl_tt_set_prop", "description": "enter value pair separated with colon T1:par1 T2:par2 ..."},
|
||||||
|
{"path": "fix_tt_set_integ", "type": "bool", "readonly": false, "cmd": "table fix_tt_set_integ"},
|
||||||
|
{"path": "val_tt_set_integ", "type": "float"},
|
||||||
|
{"path": "tbl_tt_set_integ", "type": "text", "readonly": false, "cmd": "table tbl_tt_set_integ", "description": "enter value pair separated with colon T1:par1 T2:par2 ..."},
|
||||||
|
{"path": "fix_tt_dblctrl_int2", "type": "bool", "readonly": false, "cmd": "table fix_tt_dblctrl_int2"},
|
||||||
|
{"path": "val_tt_dblctrl_int2", "type": "float"},
|
||||||
|
{"path": "tbl_tt_dblctrl_int2", "type": "text", "readonly": false, "cmd": "table tbl_tt_dblctrl_int2", "description": "enter value pair separated with colon T1:par1 T2:par2 ..."},
|
||||||
|
{"path": "fix_tt_dblctrl_prop_up", "type": "bool", "readonly": false, "cmd": "table fix_tt_dblctrl_prop_up"},
|
||||||
|
{"path": "val_tt_dblctrl_prop_up", "type": "float"},
|
||||||
|
{"path": "tbl_tt_dblctrl_prop_up", "type": "text", "readonly": false, "cmd": "table tbl_tt_dblctrl_prop_up", "description": "enter value pair separated with colon T1:par1 T2:par2 ..."},
|
||||||
|
{"path": "fix_tt_dblctrl_prop_lo", "type": "bool", "readonly": false, "cmd": "table fix_tt_dblctrl_prop_lo"},
|
||||||
|
{"path": "val_tt_dblctrl_prop_lo", "type": "float"},
|
||||||
|
{"path": "tbl_tt_dblctrl_prop_lo", "type": "text", "readonly": false, "cmd": "table tbl_tt_dblctrl_prop_lo", "description": "enter value pair separated with colon T1:par1 T2:par2 ..."}]}}
|
426
cfg/sea/ma7_piezo.config.json
Normal file
426
cfg/sea/ma7_piezo.config.json
Normal file
@ -0,0 +1,426 @@
|
|||||||
|
{"tt": {"base": "/tt", "params": [
|
||||||
|
{"path": "", "type": "float", "readonly": false, "cmd": "run tt", "description": "tt", "kids": 18},
|
||||||
|
{"path": "send", "type": "text", "readonly": false, "cmd": "tt send", "visibility": 3},
|
||||||
|
{"path": "status", "type": "text", "visibility": 3},
|
||||||
|
{"path": "is_running", "type": "int", "readonly": false, "cmd": "tt is_running", "visibility": 3},
|
||||||
|
{"path": "mainloop", "type": "text", "readonly": false, "cmd": "tt mainloop", "visibility": 3},
|
||||||
|
{"path": "target", "type": "float"},
|
||||||
|
{"path": "running", "type": "int"},
|
||||||
|
{"path": "tolerance", "type": "float", "readonly": false, "cmd": "tt tolerance"},
|
||||||
|
{"path": "maxwait", "type": "float", "readonly": false, "cmd": "tt maxwait"},
|
||||||
|
{"path": "settle", "type": "float", "readonly": false, "cmd": "tt settle"},
|
||||||
|
{"path": "log", "type": "text", "readonly": false, "cmd": "tt log", "visibility": 3, "kids": 4},
|
||||||
|
{"path": "log/mean", "type": "float", "visibility": 3},
|
||||||
|
{"path": "log/m2", "type": "float", "visibility": 3},
|
||||||
|
{"path": "log/stddev", "type": "float", "visibility": 3},
|
||||||
|
{"path": "log/n", "type": "float", "visibility": 3},
|
||||||
|
{"path": "dblctrl", "type": "bool", "readonly": false, "cmd": "tt dblctrl", "kids": 9},
|
||||||
|
{"path": "dblctrl/tshift", "type": "float", "readonly": false, "cmd": "tt dblctrl/tshift"},
|
||||||
|
{"path": "dblctrl/mode", "type": "enum", "enum": {"disabled": -1, "inactive": 0, "stable": 1, "up": 2, "down": 3}, "readonly": false, "cmd": "tt dblctrl/mode"},
|
||||||
|
{"path": "dblctrl/shift_up", "type": "float"},
|
||||||
|
{"path": "dblctrl/shift_lo", "type": "float"},
|
||||||
|
{"path": "dblctrl/t_min", "type": "float"},
|
||||||
|
{"path": "dblctrl/t_max", "type": "float"},
|
||||||
|
{"path": "dblctrl/int2", "type": "float", "readonly": false, "cmd": "tt dblctrl/int2"},
|
||||||
|
{"path": "dblctrl/prop_up", "type": "float", "readonly": false, "cmd": "tt dblctrl/prop_up"},
|
||||||
|
{"path": "dblctrl/prop_lo", "type": "float", "readonly": false, "cmd": "tt dblctrl/prop_lo"},
|
||||||
|
{"path": "tm", "type": "float", "kids": 4},
|
||||||
|
{"path": "tm/curve", "type": "text", "readonly": false, "cmd": "tt tm/curve", "kids": 1},
|
||||||
|
{"path": "tm/curve/points", "type": "floatvarar", "readonly": false, "cmd": "tt tm/curve/points", "visibility": 3},
|
||||||
|
{"path": "tm/alarm", "type": "float", "readonly": false, "cmd": "tt tm/alarm"},
|
||||||
|
{"path": "tm/stddev", "type": "float"},
|
||||||
|
{"path": "tm/raw", "type": "float"},
|
||||||
|
{"path": "ts", "type": "float", "kids": 4},
|
||||||
|
{"path": "ts/curve", "type": "text", "readonly": false, "cmd": "tt ts/curve", "kids": 1},
|
||||||
|
{"path": "ts/curve/points", "type": "floatvarar", "readonly": false, "cmd": "tt ts/curve/points", "visibility": 3},
|
||||||
|
{"path": "ts/alarm", "type": "float", "readonly": false, "cmd": "tt ts/alarm"},
|
||||||
|
{"path": "ts/stddev", "type": "float"},
|
||||||
|
{"path": "ts/raw", "type": "float"},
|
||||||
|
{"path": "ts_2", "type": "float", "visibility": 3, "kids": 4},
|
||||||
|
{"path": "ts_2/curve", "type": "text", "readonly": false, "cmd": "tt ts_2/curve", "visibility": 3, "kids": 1},
|
||||||
|
{"path": "ts_2/curve/points", "type": "floatvarar", "readonly": false, "cmd": "tt ts_2/curve/points", "visibility": 3},
|
||||||
|
{"path": "ts_2/alarm", "type": "float", "readonly": false, "cmd": "tt ts_2/alarm", "visibility": 3},
|
||||||
|
{"path": "ts_2/stddev", "type": "float", "visibility": 3},
|
||||||
|
{"path": "ts_2/raw", "type": "float", "visibility": 3},
|
||||||
|
{"path": "set", "type": "float", "readonly": false, "cmd": "tt set", "kids": 18},
|
||||||
|
{"path": "set/mode", "type": "enum", "enum": {"disabled": -1, "off": 0, "controlling": 1, "manual": 2}, "readonly": false, "cmd": "tt set/mode"},
|
||||||
|
{"path": "set/reg", "type": "float"},
|
||||||
|
{"path": "set/ramp", "type": "float", "readonly": false, "cmd": "tt set/ramp", "description": "maximum ramp in K/min (0: ramp off)"},
|
||||||
|
{"path": "set/wramp", "type": "float", "readonly": false, "cmd": "tt set/wramp"},
|
||||||
|
{"path": "set/smooth", "type": "float", "readonly": false, "cmd": "tt set/smooth", "description": "smooth time (minutes)"},
|
||||||
|
{"path": "set/channel", "type": "text", "readonly": false, "cmd": "tt set/channel"},
|
||||||
|
{"path": "set/limit", "type": "float", "readonly": false, "cmd": "tt set/limit"},
|
||||||
|
{"path": "set/resist", "type": "float", "readonly": false, "cmd": "tt set/resist"},
|
||||||
|
{"path": "set/maxheater", "type": "text", "readonly": false, "cmd": "tt set/maxheater", "description": "maximum heater limit, units should be given without space: W, mW, A, mA"},
|
||||||
|
{"path": "set/linearpower", "type": "float", "readonly": false, "cmd": "tt set/linearpower", "description": "when not 0, it is the maximum effective power, and the power is linear to the heater output"},
|
||||||
|
{"path": "set/maxpowerlim", "type": "float", "description": "the maximum power limit (before any booster or converter)"},
|
||||||
|
{"path": "set/maxpower", "type": "float", "readonly": false, "cmd": "tt set/maxpower", "description": "maximum power [W]"},
|
||||||
|
{"path": "set/maxcurrent", "type": "float", "description": "the maximum current before any booster or converter"},
|
||||||
|
{"path": "set/power", "type": "float"},
|
||||||
|
{"path": "set/prop", "type": "float", "readonly": false, "cmd": "tt set/prop", "description": "bigger means more gain"},
|
||||||
|
{"path": "set/integ", "type": "float", "readonly": false, "cmd": "tt set/integ", "description": "bigger means faster"},
|
||||||
|
{"path": "set/deriv", "type": "float", "readonly": false, "cmd": "tt set/deriv"},
|
||||||
|
{"path": "setsamp", "type": "float", "readonly": false, "cmd": "tt setsamp", "kids": 18},
|
||||||
|
{"path": "setsamp/mode", "type": "enum", "enum": {"disabled": -1, "off": 0, "controlling": 1, "manual": 2}, "readonly": false, "cmd": "tt setsamp/mode"},
|
||||||
|
{"path": "setsamp/reg", "type": "float"},
|
||||||
|
{"path": "setsamp/ramp", "type": "float", "readonly": false, "cmd": "tt setsamp/ramp", "description": "maximum ramp in K/min (0: ramp off)"},
|
||||||
|
{"path": "setsamp/wramp", "type": "float", "readonly": false, "cmd": "tt setsamp/wramp"},
|
||||||
|
{"path": "setsamp/smooth", "type": "float", "readonly": false, "cmd": "tt setsamp/smooth", "description": "smooth time (minutes)"},
|
||||||
|
{"path": "setsamp/channel", "type": "text", "readonly": false, "cmd": "tt setsamp/channel"},
|
||||||
|
{"path": "setsamp/limit", "type": "float", "readonly": false, "cmd": "tt setsamp/limit"},
|
||||||
|
{"path": "setsamp/resist", "type": "float", "readonly": false, "cmd": "tt setsamp/resist"},
|
||||||
|
{"path": "setsamp/maxheater", "type": "text", "readonly": false, "cmd": "tt setsamp/maxheater", "description": "maximum heater limit, units should be given without space: W, mW, A, mA"},
|
||||||
|
{"path": "setsamp/linearpower", "type": "float", "readonly": false, "cmd": "tt setsamp/linearpower", "description": "when not 0, it is the maximum effective power, and the power is linear to the heater output"},
|
||||||
|
{"path": "setsamp/maxpowerlim", "type": "float", "description": "the maximum power limit (before any booster or converter)"},
|
||||||
|
{"path": "setsamp/maxpower", "type": "float", "readonly": false, "cmd": "tt setsamp/maxpower", "description": "maximum power [W]"},
|
||||||
|
{"path": "setsamp/maxcurrent", "type": "float", "description": "the maximum current before any booster or converter"},
|
||||||
|
{"path": "setsamp/power", "type": "float"},
|
||||||
|
{"path": "setsamp/prop", "type": "float", "readonly": false, "cmd": "tt setsamp/prop", "description": "bigger means more gain"},
|
||||||
|
{"path": "setsamp/integ", "type": "float", "readonly": false, "cmd": "tt setsamp/integ", "description": "bigger means faster"},
|
||||||
|
{"path": "setsamp/deriv", "type": "float", "readonly": false, "cmd": "tt setsamp/deriv"},
|
||||||
|
{"path": "voltage/manualpower", "type": "float", "readonly": false, "cmd": "tt voltage/manualpower"},
|
||||||
|
{"path": "display", "type": "text", "readonly": false, "cmd": "tt display"},
|
||||||
|
{"path": "remote", "type": "bool"}]},
|
||||||
|
|
||||||
|
"cc": {"base": "/cc", "params": [
|
||||||
|
{"path": "", "type": "bool", "kids": 96},
|
||||||
|
{"path": "send", "type": "text", "readonly": false, "cmd": "cc send", "visibility": 3},
|
||||||
|
{"path": "status", "type": "text", "visibility": 3},
|
||||||
|
{"path": "autodevice", "type": "bool", "readonly": false, "cmd": "cc autodevice"},
|
||||||
|
{"path": "fav", "type": "bool", "readonly": false, "cmd": "cc fav"},
|
||||||
|
{"path": "f", "type": "float"},
|
||||||
|
{"path": "fs", "type": "enum", "enum": {"ok": 0, "no_sens": 1}, "readonly": false, "cmd": "cc fs"},
|
||||||
|
{"path": "mav", "type": "bool", "readonly": false, "cmd": "cc mav"},
|
||||||
|
{"path": "fm", "type": "enum", "enum": {"idle": 0, "opening": 1, "closing": 2, "opened": 3, "closed": 4, "no_motor": 5}},
|
||||||
|
{"path": "fa", "type": "enum", "enum": {"fixed": 0, "controlled": 1, "automatic": 2, "offline": 3}, "readonly": false, "cmd": "cc fa"},
|
||||||
|
{"path": "mp", "type": "float", "readonly": false, "cmd": "cc mp"},
|
||||||
|
{"path": "msp", "type": "float"},
|
||||||
|
{"path": "mmp", "type": "float"},
|
||||||
|
{"path": "mc", "type": "float", "readonly": false, "cmd": "cc mc"},
|
||||||
|
{"path": "mfc", "type": "float", "readonly": false, "cmd": "cc mfc"},
|
||||||
|
{"path": "moc", "type": "float", "readonly": false, "cmd": "cc moc"},
|
||||||
|
{"path": "mtc", "type": "float", "readonly": false, "cmd": "cc mtc"},
|
||||||
|
{"path": "mtl", "type": "float"},
|
||||||
|
{"path": "mft", "type": "float", "readonly": false, "cmd": "cc mft"},
|
||||||
|
{"path": "mt", "type": "float"},
|
||||||
|
{"path": "mo", "type": "float"},
|
||||||
|
{"path": "mcr", "type": "float"},
|
||||||
|
{"path": "mot", "type": "float"},
|
||||||
|
{"path": "mw", "type": "float", "readonly": false, "cmd": "cc mw", "description": "correction pulse after automatic open"},
|
||||||
|
{"path": "hav", "type": "bool", "readonly": false, "cmd": "cc hav"},
|
||||||
|
{"path": "h", "type": "float"},
|
||||||
|
{"path": "hr", "type": "float"},
|
||||||
|
{"path": "hc", "type": "float"},
|
||||||
|
{"path": "hu", "type": "float"},
|
||||||
|
{"path": "hh", "type": "float", "readonly": false, "cmd": "cc hh"},
|
||||||
|
{"path": "hl", "type": "float", "readonly": false, "cmd": "cc hl"},
|
||||||
|
{"path": "htf", "type": "float", "readonly": false, "cmd": "cc htf", "description": "meas. period in fast mode"},
|
||||||
|
{"path": "hts", "type": "float", "readonly": false, "cmd": "cc hts", "description": "meas. period in slow mode"},
|
||||||
|
{"path": "hd", "type": "float", "readonly": false, "cmd": "cc hd"},
|
||||||
|
{"path": "hwr", "type": "float", "readonly": false, "cmd": "cc hwr"},
|
||||||
|
{"path": "hem", "type": "float", "readonly": false, "cmd": "cc hem", "description": "sensor length in mm from top to empty pos."},
|
||||||
|
{"path": "hfu", "type": "float", "readonly": false, "cmd": "cc hfu", "description": "sensor length in mm from top to full pos."},
|
||||||
|
{"path": "hcd", "type": "enum", "enum": {"stop": 0, "fill": 1, "off": 2, "auto": 3, "manual": 7}, "readonly": false, "cmd": "cc hcd"},
|
||||||
|
{"path": "hv", "type": "enum", "enum": {"fill_valve_off": 0, "filling": 1, "no_fill_valve": 2, "timeout": 3, "timeout1": 4}},
|
||||||
|
{"path": "hsf", "type": "enum", "enum": {"sens_ok": 0, "sens_warm": 1, "no_sens": 2, "timeout": 3, "not_yet_read": 4, "disabled": 5}},
|
||||||
|
{"path": "ha", "type": "bool", "readonly": false, "cmd": "cc ha"},
|
||||||
|
{"path": "hm", "type": "bool"},
|
||||||
|
{"path": "hf", "type": "enum", "enum": {"slow": 0, "fast": 1}, "readonly": false, "cmd": "cc hf"},
|
||||||
|
{"path": "hbe", "type": "bool", "readonly": false, "cmd": "cc hbe"},
|
||||||
|
{"path": "hmf", "type": "float"},
|
||||||
|
{"path": "hms", "type": "float"},
|
||||||
|
{"path": "hit", "type": "float", "readonly": false, "cmd": "cc hit"},
|
||||||
|
{"path": "hft", "type": "int", "readonly": false, "cmd": "cc hft"},
|
||||||
|
{"path": "hea", "type": "enum", "enum": {"0": 0, "1": 1, "6": 6}, "readonly": false, "cmd": "cc hea"},
|
||||||
|
{"path": "hch", "type": "int", "readonly": false, "cmd": "cc hch"},
|
||||||
|
{"path": "hwr0", "type": "float", "readonly": false, "cmd": "cc hwr0"},
|
||||||
|
{"path": "hem0", "type": "float", "readonly": false, "cmd": "cc hem0", "description": "sensor length in mm from top to empty pos."},
|
||||||
|
{"path": "hfu0", "type": "float", "readonly": false, "cmd": "cc hfu0", "description": "sensor length in mm from top to full pos."},
|
||||||
|
{"path": "hd0", "type": "float", "readonly": false, "cmd": "cc hd0", "description": "external sensor drive current (mA)"},
|
||||||
|
{"path": "h0", "type": "float"},
|
||||||
|
{"path": "hs0", "type": "enum", "enum": {"sens_ok": 0, "sens_warm": 1, "no_sens": 2, "timeout": 3, "not_yet_read": 4, "disabled": 5}},
|
||||||
|
{"path": "h1", "type": "float"},
|
||||||
|
{"path": "hs1", "type": "enum", "enum": {"sens_ok": 0, "sens_warm": 1, "no_sens": 2, "timeout": 3, "not_yet_read": 4, "disabled": 5}},
|
||||||
|
{"path": "h2", "type": "float"},
|
||||||
|
{"path": "hs2", "type": "enum", "enum": {"sens_ok": 0, "sens_warm": 1, "no_sens": 2, "timeout": 3, "not_yet_read": 4, "disabled": 5}},
|
||||||
|
{"path": "h3", "type": "float"},
|
||||||
|
{"path": "hs3", "type": "enum", "enum": {"sens_ok": 0, "sens_warm": 1, "no_sens": 2, "timeout": 3, "not_yet_read": 4, "disabled": 5}},
|
||||||
|
{"path": "h4", "type": "float"},
|
||||||
|
{"path": "hs4", "type": "enum", "enum": {"sens_ok": 0, "sens_warm": 1, "no_sens": 2, "timeout": 3, "not_yet_read": 4, "disabled": 5}},
|
||||||
|
{"path": "h5", "type": "float"},
|
||||||
|
{"path": "hs5", "type": "enum", "enum": {"sens_ok": 0, "sens_warm": 1, "no_sens": 2, "timeout": 3, "not_yet_read": 4, "disabled": 5}},
|
||||||
|
{"path": "hfb", "type": "float"},
|
||||||
|
{"path": "nav", "type": "bool", "readonly": false, "cmd": "cc nav"},
|
||||||
|
{"path": "nu", "type": "float"},
|
||||||
|
{"path": "nl", "type": "float"},
|
||||||
|
{"path": "nth", "type": "float", "readonly": false, "cmd": "cc nth"},
|
||||||
|
{"path": "ntc", "type": "float", "readonly": false, "cmd": "cc ntc"},
|
||||||
|
{"path": "ntm", "type": "float", "readonly": false, "cmd": "cc ntm"},
|
||||||
|
{"path": "ns", "type": "enum", "enum": {"sens_ok": 0, "no_sens": 1, "short_circuit": 2, "upside_down": 3, "sens_warm": 4, "empty": 5}},
|
||||||
|
{"path": "na", "type": "bool", "readonly": false, "cmd": "cc na"},
|
||||||
|
{"path": "nv", "type": "enum", "enum": {"fill_valve_off": 0, "filling": 1, "no_fill_valve": 2, "timeout": 3, "timeout1": 4, "boost": 5}},
|
||||||
|
{"path": "nc", "type": "enum", "enum": {"stop": 0, "fill": 1, "off": 2, "auto": 3}, "readonly": false, "cmd": "cc nc"},
|
||||||
|
{"path": "nfb", "type": "float"},
|
||||||
|
{"path": "cda", "type": "float"},
|
||||||
|
{"path": "cdb", "type": "float"},
|
||||||
|
{"path": "cba", "type": "float"},
|
||||||
|
{"path": "cbb", "type": "float"},
|
||||||
|
{"path": "cvs", "type": "int"},
|
||||||
|
{"path": "csp", "type": "int"},
|
||||||
|
{"path": "cdv", "type": "text", "readonly": false, "cmd": "cc cdv"},
|
||||||
|
{"path": "cic", "type": "text", "readonly": false, "cmd": "cc cic"},
|
||||||
|
{"path": "cin", "type": "text"},
|
||||||
|
{"path": "cds", "type": "enum", "enum": {"local": 0, "remote": 1, "loading": 2, "by_code": 3, "by_touch": 4}, "readonly": false, "cmd": "cc cds"},
|
||||||
|
{"path": "timing", "type": "bool", "readonly": false, "cmd": "cc timing"},
|
||||||
|
{"path": "tc", "type": "float", "visibility": 3},
|
||||||
|
{"path": "tn", "type": "float", "visibility": 3},
|
||||||
|
{"path": "th", "type": "float", "visibility": 3},
|
||||||
|
{"path": "tf", "type": "float", "visibility": 3},
|
||||||
|
{"path": "tm", "type": "float", "visibility": 3},
|
||||||
|
{"path": "tv", "type": "float", "visibility": 3},
|
||||||
|
{"path": "tq", "type": "float", "visibility": 3},
|
||||||
|
{"path": "bdl", "type": "float", "readonly": false, "cmd": "cc bdl"}]},
|
||||||
|
|
||||||
|
"nv": {"base": "/nv", "params": [
|
||||||
|
{"path": "", "type": "enum", "enum": {"fixed": 0, "controlled": 1, "automatic": 2, "close": 3, "open": 4}, "readonly": false, "cmd": "nv", "kids": 11},
|
||||||
|
{"path": "send", "type": "text", "readonly": false, "cmd": "nv send", "visibility": 3},
|
||||||
|
{"path": "status", "type": "text", "visibility": 3},
|
||||||
|
{"path": "motstat", "type": "enum", "enum": {"idle": 0, "opening": 1, "closing": 2, "opened": 3, "closed": 4, "no_motor": 5}},
|
||||||
|
{"path": "flow", "type": "float"},
|
||||||
|
{"path": "set", "type": "float", "readonly": false, "cmd": "nv set"},
|
||||||
|
{"path": "flowmax", "type": "float", "readonly": false, "cmd": "nv flowmax"},
|
||||||
|
{"path": "flowp", "type": "float"},
|
||||||
|
{"path": "span", "type": "float"},
|
||||||
|
{"path": "ctrl", "type": "none", "kids": 13},
|
||||||
|
{"path": "ctrl/regtext", "type": "text"},
|
||||||
|
{"path": "ctrl/prop_o", "type": "float", "readonly": false, "cmd": "nv ctrl/prop_o", "description": "prop [sec/mbar] when opening. above 4 mbar a 10 times lower value is used"},
|
||||||
|
{"path": "ctrl/prop_c", "type": "float", "readonly": false, "cmd": "nv ctrl/prop_c", "description": "prop [sec/mbar] when closing. above 4 mbar a 10 times lower value is used"},
|
||||||
|
{"path": "ctrl/deriv_o", "type": "float", "readonly": false, "cmd": "nv ctrl/deriv_o", "description": "convergence target time [sec] when opening"},
|
||||||
|
{"path": "ctrl/deriv_c", "type": "float", "readonly": false, "cmd": "nv ctrl/deriv_c", "description": "convergence target time [sec] when closing"},
|
||||||
|
{"path": "ctrl/minpulse_o", "type": "float", "readonly": false, "cmd": "nv ctrl/minpulse_o", "description": "minimum close pulse [sec]"},
|
||||||
|
{"path": "ctrl/minpulse_c", "type": "float", "readonly": false, "cmd": "nv ctrl/minpulse_c", "description": "standard close pulse [sec]"},
|
||||||
|
{"path": "ctrl/hystpulse_o", "type": "float", "readonly": false, "cmd": "nv ctrl/hystpulse_o", "description": "motor pulse to overcome hysteresis when opening"},
|
||||||
|
{"path": "ctrl/hystpulse_c", "type": "float", "readonly": false, "cmd": "nv ctrl/hystpulse_c", "description": "motor pulse to overcome hysteresis when closing"},
|
||||||
|
{"path": "ctrl/tol", "type": "float", "readonly": false, "cmd": "nv ctrl/tol", "description": "valid below 3 mbar"},
|
||||||
|
{"path": "ctrl/tolhigh", "type": "float", "readonly": false, "cmd": "nv ctrl/tolhigh", "description": "valid above 4 mbar"},
|
||||||
|
{"path": "ctrl/openpulse", "type": "float", "readonly": false, "cmd": "nv ctrl/openpulse", "description": "time to open from completely closed to a significant opening"},
|
||||||
|
{"path": "ctrl/adjust_minpulse", "type": "bool", "readonly": false, "cmd": "nv ctrl/adjust_minpulse", "description": "adjust minpulse automatically"},
|
||||||
|
{"path": "autoflow", "type": "none", "kids": 24},
|
||||||
|
{"path": "autoflow/suspended", "type": "bool", "readonly": false, "cmd": "nv autoflow/suspended"},
|
||||||
|
{"path": "autoflow/prop", "type": "float", "readonly": false, "cmd": "nv autoflow/prop"},
|
||||||
|
{"path": "autoflow/flowstd", "type": "float", "readonly": false, "cmd": "nv autoflow/flowstd"},
|
||||||
|
{"path": "autoflow/flowlim", "type": "float", "readonly": false, "cmd": "nv autoflow/flowlim"},
|
||||||
|
{"path": "autoflow/smooth", "type": "float", "readonly": false, "cmd": "nv autoflow/smooth"},
|
||||||
|
{"path": "autoflow/difSize", "type": "float", "readonly": false, "cmd": "nv autoflow/difSize"},
|
||||||
|
{"path": "autoflow/difRange", "type": "float", "readonly": false, "cmd": "nv autoflow/difRange"},
|
||||||
|
{"path": "autoflow/flowSize", "type": "float", "readonly": false, "cmd": "nv autoflow/flowSize"},
|
||||||
|
{"path": "autoflow/convTime", "type": "float", "readonly": false, "cmd": "nv autoflow/convTime"},
|
||||||
|
{"path": "autoflow/Tmin", "type": "float", "readonly": false, "cmd": "nv autoflow/Tmin"},
|
||||||
|
{"path": "autoflow/script", "type": "text", "readonly": false, "cmd": "nv autoflow/script"},
|
||||||
|
{"path": "autoflow/getTemp", "type": "text", "readonly": false, "cmd": "nv autoflow/getTemp"},
|
||||||
|
{"path": "autoflow/getTset", "type": "text", "readonly": false, "cmd": "nv autoflow/getTset"},
|
||||||
|
{"path": "autoflow/getFlow", "type": "text", "readonly": false, "cmd": "nv autoflow/getFlow"},
|
||||||
|
{"path": "autoflow/difBuf", "type": "text"},
|
||||||
|
{"path": "autoflow/flowBuf", "type": "text"},
|
||||||
|
{"path": "autoflow/flowset", "type": "float"},
|
||||||
|
{"path": "autoflow/flowmin", "type": "float"},
|
||||||
|
{"path": "autoflow/flowmax", "type": "float"},
|
||||||
|
{"path": "autoflow/difmin", "type": "float"},
|
||||||
|
{"path": "autoflow/difmax", "type": "float"},
|
||||||
|
{"path": "autoflow/setmin", "type": "float"},
|
||||||
|
{"path": "autoflow/setmax", "type": "float"},
|
||||||
|
{"path": "autoflow/flowtarget", "type": "float"},
|
||||||
|
{"path": "calib", "type": "none", "kids": 2},
|
||||||
|
{"path": "calib/ln_per_min_per_mbar", "type": "float", "readonly": false, "cmd": "nv calib/ln_per_min_per_mbar"},
|
||||||
|
{"path": "calib/mbar_offset", "type": "float", "readonly": false, "cmd": "nv calib/mbar_offset"}]},
|
||||||
|
|
||||||
|
"hefill": {"base": "/hefill", "params": [
|
||||||
|
{"path": "", "type": "enum", "enum": {"watching": 0, "filling": 1, "inactive": 2, "manualfill": 3}, "readonly": false, "cmd": "hefill", "kids": 16},
|
||||||
|
{"path": "send", "type": "text", "readonly": false, "cmd": "hefill send", "visibility": 3},
|
||||||
|
{"path": "status", "type": "text", "visibility": 3},
|
||||||
|
{"path": "state", "type": "text"},
|
||||||
|
{"path": "readlevel", "type": "text", "readonly": false, "cmd": "hefill readlevel", "visibility": 3},
|
||||||
|
{"path": "lowlevel", "type": "float", "readonly": false, "cmd": "hefill lowlevel"},
|
||||||
|
{"path": "highlevel", "type": "float", "readonly": false, "cmd": "hefill highlevel"},
|
||||||
|
{"path": "smooth", "type": "float"},
|
||||||
|
{"path": "minfillminutes", "type": "float", "readonly": false, "cmd": "hefill minfillminutes"},
|
||||||
|
{"path": "maxfillminutes", "type": "float", "readonly": false, "cmd": "hefill maxfillminutes"},
|
||||||
|
{"path": "minholdhours", "type": "float", "readonly": false, "cmd": "hefill minholdhours"},
|
||||||
|
{"path": "maxholdhours", "type": "float", "readonly": false, "cmd": "hefill maxholdhours"},
|
||||||
|
{"path": "tolerance", "type": "float", "readonly": false, "cmd": "hefill tolerance"},
|
||||||
|
{"path": "badreadingminutes", "type": "float", "readonly": false, "cmd": "hefill badreadingminutes"},
|
||||||
|
{"path": "tubecoolingminutes", "type": "float", "readonly": false, "cmd": "hefill tubecoolingminutes"},
|
||||||
|
{"path": "vessellimit", "type": "float", "readonly": false, "cmd": "hefill vessellimit"},
|
||||||
|
{"path": "vext", "type": "float"}]},
|
||||||
|
|
||||||
|
"hepump": {"base": "/hepump", "params": [
|
||||||
|
{"path": "", "type": "enum", "enum": {"neodry": 8, "xds35_auto": 0, "xds35_manual": 1, "sv65": 2, "other": 3, "no": -1}, "readonly": false, "cmd": "hepump", "description": "xds35: scroll pump, sv65: leybold", "kids": 10},
|
||||||
|
{"path": "send", "type": "text", "readonly": false, "cmd": "hepump send", "visibility": 3},
|
||||||
|
{"path": "status", "type": "text", "visibility": 3},
|
||||||
|
{"path": "running", "type": "bool", "readonly": false, "cmd": "hepump running"},
|
||||||
|
{"path": "eco", "type": "bool", "readonly": false, "cmd": "hepump eco"},
|
||||||
|
{"path": "auto", "type": "bool", "readonly": false, "cmd": "hepump auto"},
|
||||||
|
{"path": "valve", "type": "enum", "enum": {"closed": 0, "closing": 1, "opening": 2, "opened": 3, "undefined": 4}, "readonly": false, "cmd": "hepump valve"},
|
||||||
|
{"path": "eco_t_lim", "type": "float", "readonly": false, "cmd": "hepump eco_t_lim", "description": "switch off eco mode when T_set < eco_t_lim and T < eco_t_lim * 2"},
|
||||||
|
{"path": "calib", "type": "float", "readonly": false, "cmd": "hepump calib", "visibility": 3},
|
||||||
|
{"path": "health", "type": "float"}]},
|
||||||
|
|
||||||
|
"hemot": {"base": "/hepump/hemot", "params": [
|
||||||
|
{"path": "", "type": "float", "readonly": false, "cmd": "run hemot", "kids": 30},
|
||||||
|
{"path": "send", "type": "text", "readonly": false, "cmd": "hemot send", "visibility": 3},
|
||||||
|
{"path": "status", "type": "text", "visibility": 3},
|
||||||
|
{"path": "is_running", "type": "int", "readonly": false, "cmd": "hemot is_running", "visibility": 3},
|
||||||
|
{"path": "pos", "type": "float"},
|
||||||
|
{"path": "encoder", "type": "float"},
|
||||||
|
{"path": "zero", "type": "float", "readonly": false, "cmd": "hemot zero"},
|
||||||
|
{"path": "lowerlimit", "type": "float", "readonly": false, "cmd": "hemot lowerlimit"},
|
||||||
|
{"path": "upperlimit", "type": "float", "readonly": false, "cmd": "hemot upperlimit"},
|
||||||
|
{"path": "disablelimits", "type": "bool", "readonly": false, "cmd": "hemot disablelimits"},
|
||||||
|
{"path": "verbose", "type": "bool", "readonly": false, "cmd": "hemot verbose"},
|
||||||
|
{"path": "target", "type": "float"},
|
||||||
|
{"path": "runstate", "type": "enum", "enum": {"idle": 0, "running": 1, "finished": 2, "error": 3}},
|
||||||
|
{"path": "precision", "type": "float", "readonly": false, "cmd": "hemot precision"},
|
||||||
|
{"path": "maxencdif", "type": "float", "readonly": false, "cmd": "hemot maxencdif"},
|
||||||
|
{"path": "id", "type": "float", "readonly": false, "cmd": "hemot id"},
|
||||||
|
{"path": "pump_number", "type": "float", "readonly": false, "cmd": "hemot pump_number"},
|
||||||
|
{"path": "init", "type": "float", "readonly": false, "cmd": "hemot init"},
|
||||||
|
{"path": "maxspeed", "type": "float", "readonly": false, "cmd": "hemot maxspeed"},
|
||||||
|
{"path": "acceleration", "type": "float", "readonly": false, "cmd": "hemot acceleration"},
|
||||||
|
{"path": "maxcurrent", "type": "float", "readonly": false, "cmd": "hemot maxcurrent"},
|
||||||
|
{"path": "standbycurrent", "type": "float", "readonly": false, "cmd": "hemot standbycurrent"},
|
||||||
|
{"path": "freewheeling", "type": "bool", "readonly": false, "cmd": "hemot freewheeling"},
|
||||||
|
{"path": "output0", "type": "bool", "readonly": false, "cmd": "hemot output0"},
|
||||||
|
{"path": "output1", "type": "bool", "readonly": false, "cmd": "hemot output1"},
|
||||||
|
{"path": "input3", "type": "bool"},
|
||||||
|
{"path": "pullup", "type": "float", "readonly": false, "cmd": "hemot pullup"},
|
||||||
|
{"path": "nopumpfeedback", "type": "bool", "readonly": false, "cmd": "hemot nopumpfeedback"},
|
||||||
|
{"path": "eeprom", "type": "enum", "enum": {"ok": 0, "dirty": 1, "save": 2, "load": 3}, "readonly": false, "cmd": "hemot eeprom"},
|
||||||
|
{"path": "customadr", "type": "text", "readonly": false, "cmd": "hemot customadr"},
|
||||||
|
{"path": "custompar", "type": "float", "readonly": false, "cmd": "hemot custompar"}]},
|
||||||
|
|
||||||
|
"nvflow": {"base": "/nvflow", "params": [
|
||||||
|
{"path": "", "type": "float", "kids": 7},
|
||||||
|
{"path": "send", "type": "text", "readonly": false, "cmd": "nvflow send", "visibility": 3},
|
||||||
|
{"path": "status", "type": "text", "visibility": 3},
|
||||||
|
{"path": "stddev", "type": "float"},
|
||||||
|
{"path": "nsamples", "type": "int", "readonly": false, "cmd": "nvflow nsamples"},
|
||||||
|
{"path": "offset", "type": "float", "readonly": false, "cmd": "nvflow offset"},
|
||||||
|
{"path": "scale", "type": "float", "readonly": false, "cmd": "nvflow scale"},
|
||||||
|
{"path": "save", "type": "bool", "readonly": false, "cmd": "nvflow save", "description": "unchecked: current calib is not saved. set checked: save calib"}]},
|
||||||
|
|
||||||
|
"ln2fill": {"base": "/ln2fill", "params": [
|
||||||
|
{"path": "", "type": "enum", "enum": {"watching": 0, "filling": 1, "inactive": 2, "manualfill": 3}, "readonly": false, "cmd": "ln2fill", "kids": 14},
|
||||||
|
{"path": "send", "type": "text", "readonly": false, "cmd": "ln2fill send", "visibility": 3},
|
||||||
|
{"path": "status", "type": "text", "visibility": 3},
|
||||||
|
{"path": "state", "type": "text"},
|
||||||
|
{"path": "readlevel", "type": "text", "readonly": false, "cmd": "ln2fill readlevel", "visibility": 3},
|
||||||
|
{"path": "lowlevel", "type": "float", "readonly": false, "cmd": "ln2fill lowlevel"},
|
||||||
|
{"path": "highlevel", "type": "float", "readonly": false, "cmd": "ln2fill highlevel"},
|
||||||
|
{"path": "smooth", "type": "float"},
|
||||||
|
{"path": "minfillminutes", "type": "float", "readonly": false, "cmd": "ln2fill minfillminutes"},
|
||||||
|
{"path": "maxfillminutes", "type": "float", "readonly": false, "cmd": "ln2fill maxfillminutes"},
|
||||||
|
{"path": "minholdhours", "type": "float", "readonly": false, "cmd": "ln2fill minholdhours"},
|
||||||
|
{"path": "maxholdhours", "type": "float", "readonly": false, "cmd": "ln2fill maxholdhours"},
|
||||||
|
{"path": "tolerance", "type": "float", "readonly": false, "cmd": "ln2fill tolerance"},
|
||||||
|
{"path": "badreadingminutes", "type": "float", "readonly": false, "cmd": "ln2fill badreadingminutes"},
|
||||||
|
{"path": "tubecoolingminutes", "type": "float", "readonly": false, "cmd": "ln2fill tubecoolingminutes"}]},
|
||||||
|
|
||||||
|
"mf": {"base": "/mf", "params": [
|
||||||
|
{"path": "", "type": "float", "readonly": false, "cmd": "run mf", "kids": 26},
|
||||||
|
{"path": "persmode", "type": "int", "readonly": false, "cmd": "mf persmode"},
|
||||||
|
{"path": "perswitch", "type": "int"},
|
||||||
|
{"path": "nowait", "type": "int", "readonly": false, "cmd": "mf nowait"},
|
||||||
|
{"path": "maxlimit", "type": "float", "visibility": 3},
|
||||||
|
{"path": "limit", "type": "float", "readonly": false, "cmd": "mf limit"},
|
||||||
|
{"path": "ramp", "type": "float", "readonly": false, "cmd": "mf ramp"},
|
||||||
|
{"path": "perscurrent", "type": "float", "readonly": false, "cmd": "mf perscurrent"},
|
||||||
|
{"path": "perslimit", "type": "float", "readonly": false, "cmd": "mf perslimit"},
|
||||||
|
{"path": "perswait", "type": "int", "readonly": false, "cmd": "mf perswait"},
|
||||||
|
{"path": "persdelay", "type": "int", "readonly": false, "cmd": "mf persdelay"},
|
||||||
|
{"path": "current", "type": "float"},
|
||||||
|
{"path": "measured", "type": "float"},
|
||||||
|
{"path": "voltage", "type": "float"},
|
||||||
|
{"path": "lastfield", "type": "float", "visibility": 3},
|
||||||
|
{"path": "ampRamp", "type": "float", "visibility": 3},
|
||||||
|
{"path": "inductance", "type": "float", "visibility": 3},
|
||||||
|
{"path": "trainedTo", "type": "float", "readonly": false, "cmd": "mf trainedTo"},
|
||||||
|
{"path": "trainMode", "type": "int"},
|
||||||
|
{"path": "external", "type": "int", "readonly": false, "cmd": "mf external"},
|
||||||
|
{"path": "startScript", "type": "text", "readonly": false, "cmd": "mf startScript", "visibility": 3},
|
||||||
|
{"path": "is_running", "type": "int", "readonly": false, "cmd": "mf is_running", "visibility": 3},
|
||||||
|
{"path": "verbose", "type": "int", "readonly": false, "cmd": "mf verbose", "visibility": 3},
|
||||||
|
{"path": "driver", "type": "text", "visibility": 3},
|
||||||
|
{"path": "creationCmd", "type": "text", "visibility": 3},
|
||||||
|
{"path": "targetValue", "type": "float"},
|
||||||
|
{"path": "status", "type": "text", "readonly": false, "cmd": "mf status", "visibility": 3}]},
|
||||||
|
|
||||||
|
"lev": {"base": "/lev", "params": [
|
||||||
|
{"path": "", "type": "float", "kids": 4},
|
||||||
|
{"path": "send", "type": "text", "readonly": false, "cmd": "lev send", "visibility": 3},
|
||||||
|
{"path": "status", "type": "text", "visibility": 3},
|
||||||
|
{"path": "mode", "type": "enum", "enum": {"slow": 0, "fast (switches to slow automatically after filling)": 1}, "readonly": false, "cmd": "lev mode"},
|
||||||
|
{"path": "n2", "type": "float"}]},
|
||||||
|
|
||||||
|
"tcoil": {"base": "/tcoil", "params": [
|
||||||
|
{"path": "", "type": "float", "kids": 11},
|
||||||
|
{"path": "send", "type": "text", "readonly": false, "cmd": "tcoil send", "visibility": 3},
|
||||||
|
{"path": "status", "type": "text", "visibility": 3},
|
||||||
|
{"path": "excitation", "type": "float", "readonly": false, "cmd": "tcoil excitation", "visibility": 3},
|
||||||
|
{"path": "ta", "type": "float", "kids": 3},
|
||||||
|
{"path": "ta/enable", "type": "bool", "readonly": false, "cmd": "tcoil ta/enable"},
|
||||||
|
{"path": "ta/r", "type": "float"},
|
||||||
|
{"path": "ta/curve", "type": "text", "readonly": false, "cmd": "tcoil ta/curve", "kids": 3},
|
||||||
|
{"path": "ta/curve/adjust", "type": "text", "readonly": false, "cmd": "tcoil ta/curve/adjust"},
|
||||||
|
{"path": "ta/curve/points", "type": "floatvarar", "readonly": false, "cmd": "tcoil ta/curve/points"},
|
||||||
|
{"path": "ta/curve/cpoints", "type": "floatvarar", "readonly": false, "cmd": "tcoil ta/curve/cpoints"},
|
||||||
|
{"path": "tb", "type": "float", "kids": 3},
|
||||||
|
{"path": "tb/enable", "type": "bool", "readonly": false, "cmd": "tcoil tb/enable"},
|
||||||
|
{"path": "tb/r", "type": "float"},
|
||||||
|
{"path": "tb/curve", "type": "text", "readonly": false, "cmd": "tcoil tb/curve", "kids": 3},
|
||||||
|
{"path": "tb/curve/adjust", "type": "text", "readonly": false, "cmd": "tcoil tb/curve/adjust"},
|
||||||
|
{"path": "tb/curve/points", "type": "floatvarar", "readonly": false, "cmd": "tcoil tb/curve/points"},
|
||||||
|
{"path": "tb/curve/cpoints", "type": "floatvarar", "readonly": false, "cmd": "tcoil tb/curve/cpoints"},
|
||||||
|
{"path": "td", "type": "float", "visibility": 3, "kids": 3},
|
||||||
|
{"path": "td/enable", "type": "bool", "readonly": false, "cmd": "tcoil td/enable"},
|
||||||
|
{"path": "td/r", "type": "float"},
|
||||||
|
{"path": "td/curve", "type": "text", "readonly": false, "cmd": "tcoil td/curve", "kids": 3},
|
||||||
|
{"path": "td/curve/adjust", "type": "text", "readonly": false, "cmd": "tcoil td/curve/adjust"},
|
||||||
|
{"path": "td/curve/points", "type": "floatvarar", "readonly": false, "cmd": "tcoil td/curve/points"},
|
||||||
|
{"path": "td/curve/cpoints", "type": "floatvarar", "readonly": false, "cmd": "tcoil td/curve/cpoints"},
|
||||||
|
{"path": "ref", "type": "float", "visibility": 3, "kids": 3},
|
||||||
|
{"path": "ref/enable", "type": "bool", "readonly": false, "cmd": "tcoil ref/enable"},
|
||||||
|
{"path": "ref/r", "type": "float"},
|
||||||
|
{"path": "ref/curve", "type": "text", "readonly": false, "cmd": "tcoil ref/curve", "kids": 3},
|
||||||
|
{"path": "ref/curve/adjust", "type": "text", "readonly": false, "cmd": "tcoil ref/curve/adjust"},
|
||||||
|
{"path": "ref/curve/points", "type": "floatvarar", "readonly": false, "cmd": "tcoil ref/curve/points"},
|
||||||
|
{"path": "ref/curve/cpoints", "type": "floatvarar", "readonly": false, "cmd": "tcoil ref/curve/cpoints"},
|
||||||
|
{"path": "tc", "type": "float", "visibility": 3, "kids": 3},
|
||||||
|
{"path": "tc/enable", "type": "bool", "readonly": false, "cmd": "tcoil tc/enable"},
|
||||||
|
{"path": "tc/r", "type": "float"},
|
||||||
|
{"path": "tc/curve", "type": "text", "readonly": false, "cmd": "tcoil tc/curve", "kids": 3},
|
||||||
|
{"path": "tc/curve/adjust", "type": "text", "readonly": false, "cmd": "tcoil tc/curve/adjust"},
|
||||||
|
{"path": "tc/curve/points", "type": "floatvarar", "readonly": false, "cmd": "tcoil tc/curve/points"},
|
||||||
|
{"path": "tc/curve/cpoints", "type": "floatvarar", "readonly": false, "cmd": "tcoil tc/curve/cpoints"},
|
||||||
|
{"path": "ext", "type": "float", "visibility": 3},
|
||||||
|
{"path": "com", "type": "float", "visibility": 3},
|
||||||
|
{"path": "gnd", "type": "float", "visibility": 3}]},
|
||||||
|
|
||||||
|
"table": {"base": "/table", "params": [
|
||||||
|
{"path": "", "type": "none", "kids": 17},
|
||||||
|
{"path": "send", "type": "text", "readonly": false, "cmd": "table send", "visibility": 3},
|
||||||
|
{"path": "status", "type": "text", "visibility": 3},
|
||||||
|
{"path": "fix_tt_set_prop", "type": "bool", "readonly": false, "cmd": "table fix_tt_set_prop"},
|
||||||
|
{"path": "val_tt_set_prop", "type": "float"},
|
||||||
|
{"path": "tbl_tt_set_prop", "type": "text", "readonly": false, "cmd": "table tbl_tt_set_prop", "description": "enter value pair separated with colon T1:par1 T2:par2 ..."},
|
||||||
|
{"path": "fix_tt_set_integ", "type": "bool", "readonly": false, "cmd": "table fix_tt_set_integ"},
|
||||||
|
{"path": "val_tt_set_integ", "type": "float"},
|
||||||
|
{"path": "tbl_tt_set_integ", "type": "text", "readonly": false, "cmd": "table tbl_tt_set_integ", "description": "enter value pair separated with colon T1:par1 T2:par2 ..."},
|
||||||
|
{"path": "fix_tt_dblctrl_int2", "type": "bool", "readonly": false, "cmd": "table fix_tt_dblctrl_int2"},
|
||||||
|
{"path": "val_tt_dblctrl_int2", "type": "float"},
|
||||||
|
{"path": "tbl_tt_dblctrl_int2", "type": "text", "readonly": false, "cmd": "table tbl_tt_dblctrl_int2", "description": "enter value pair separated with colon T1:par1 T2:par2 ..."},
|
||||||
|
{"path": "fix_tt_dblctrl_prop_up", "type": "bool", "readonly": false, "cmd": "table fix_tt_dblctrl_prop_up"},
|
||||||
|
{"path": "val_tt_dblctrl_prop_up", "type": "float"},
|
||||||
|
{"path": "tbl_tt_dblctrl_prop_up", "type": "text", "readonly": false, "cmd": "table tbl_tt_dblctrl_prop_up", "description": "enter value pair separated with colon T1:par1 T2:par2 ..."},
|
||||||
|
{"path": "fix_tt_dblctrl_prop_lo", "type": "bool", "readonly": false, "cmd": "table fix_tt_dblctrl_prop_lo"},
|
||||||
|
{"path": "val_tt_dblctrl_prop_lo", "type": "float"},
|
||||||
|
{"path": "tbl_tt_dblctrl_prop_lo", "type": "text", "readonly": false, "cmd": "table tbl_tt_dblctrl_prop_lo", "description": "enter value pair separated with colon T1:par1 T2:par2 ..."}]}}
|
421
cfg/sea/ma7_thermalc.config.json
Normal file
421
cfg/sea/ma7_thermalc.config.json
Normal file
@ -0,0 +1,421 @@
|
|||||||
|
{"tt": {"base": "/tt", "params": [
|
||||||
|
{"path": "", "type": "float", "readonly": false, "cmd": "run tt", "description": "tt", "kids": 17},
|
||||||
|
{"path": "send", "type": "text", "readonly": false, "cmd": "tt send", "visibility": 3},
|
||||||
|
{"path": "status", "type": "text", "visibility": 3},
|
||||||
|
{"path": "is_running", "type": "int", "readonly": false, "cmd": "tt is_running", "visibility": 3},
|
||||||
|
{"path": "mainloop", "type": "text", "readonly": false, "cmd": "tt mainloop", "visibility": 3},
|
||||||
|
{"path": "target", "type": "float"},
|
||||||
|
{"path": "running", "type": "int"},
|
||||||
|
{"path": "tolerance", "type": "float", "readonly": false, "cmd": "tt tolerance"},
|
||||||
|
{"path": "maxwait", "type": "float", "readonly": false, "cmd": "tt maxwait"},
|
||||||
|
{"path": "settle", "type": "float", "readonly": false, "cmd": "tt settle"},
|
||||||
|
{"path": "log", "type": "text", "readonly": false, "cmd": "tt log", "visibility": 3, "kids": 4},
|
||||||
|
{"path": "log/mean", "type": "float", "visibility": 3},
|
||||||
|
{"path": "log/m2", "type": "float", "visibility": 3},
|
||||||
|
{"path": "log/stddev", "type": "float", "visibility": 3},
|
||||||
|
{"path": "log/n", "type": "float", "visibility": 3},
|
||||||
|
{"path": "dblctrl", "type": "bool", "readonly": false, "cmd": "tt dblctrl", "kids": 9},
|
||||||
|
{"path": "dblctrl/tshift", "type": "float", "readonly": false, "cmd": "tt dblctrl/tshift"},
|
||||||
|
{"path": "dblctrl/mode", "type": "enum", "enum": {"disabled": -1, "inactive": 0, "stable": 1, "up": 2, "down": 3}, "readonly": false, "cmd": "tt dblctrl/mode"},
|
||||||
|
{"path": "dblctrl/shift_up", "type": "float"},
|
||||||
|
{"path": "dblctrl/shift_lo", "type": "float"},
|
||||||
|
{"path": "dblctrl/t_min", "type": "float"},
|
||||||
|
{"path": "dblctrl/t_max", "type": "float"},
|
||||||
|
{"path": "dblctrl/int2", "type": "float", "readonly": false, "cmd": "tt dblctrl/int2"},
|
||||||
|
{"path": "dblctrl/prop_up", "type": "float", "readonly": false, "cmd": "tt dblctrl/prop_up"},
|
||||||
|
{"path": "dblctrl/prop_lo", "type": "float", "readonly": false, "cmd": "tt dblctrl/prop_lo"},
|
||||||
|
{"path": "tm", "type": "float", "kids": 4},
|
||||||
|
{"path": "tm/curve", "type": "text", "readonly": false, "cmd": "tt tm/curve", "kids": 1},
|
||||||
|
{"path": "tm/curve/points", "type": "floatvarar", "readonly": false, "cmd": "tt tm/curve/points", "visibility": 3},
|
||||||
|
{"path": "tm/alarm", "type": "float", "readonly": false, "cmd": "tt tm/alarm"},
|
||||||
|
{"path": "tm/stddev", "type": "float"},
|
||||||
|
{"path": "tm/raw", "type": "float"},
|
||||||
|
{"path": "ts", "type": "float", "kids": 4},
|
||||||
|
{"path": "ts/curve", "type": "text", "readonly": false, "cmd": "tt ts/curve", "kids": 1},
|
||||||
|
{"path": "ts/curve/points", "type": "floatvarar", "readonly": false, "cmd": "tt ts/curve/points", "visibility": 3},
|
||||||
|
{"path": "ts/alarm", "type": "float", "readonly": false, "cmd": "tt ts/alarm"},
|
||||||
|
{"path": "ts/stddev", "type": "float"},
|
||||||
|
{"path": "ts/raw", "type": "float"},
|
||||||
|
{"path": "set", "type": "float", "readonly": false, "cmd": "tt set", "kids": 18},
|
||||||
|
{"path": "set/mode", "type": "enum", "enum": {"disabled": -1, "off": 0, "controlling": 1, "manual": 2}, "readonly": false, "cmd": "tt set/mode"},
|
||||||
|
{"path": "set/reg", "type": "float"},
|
||||||
|
{"path": "set/ramp", "type": "float", "readonly": false, "cmd": "tt set/ramp", "description": "maximum ramp in K/min (0: ramp off)"},
|
||||||
|
{"path": "set/wramp", "type": "float", "readonly": false, "cmd": "tt set/wramp"},
|
||||||
|
{"path": "set/smooth", "type": "float", "readonly": false, "cmd": "tt set/smooth", "description": "smooth time (minutes)"},
|
||||||
|
{"path": "set/channel", "type": "text", "readonly": false, "cmd": "tt set/channel"},
|
||||||
|
{"path": "set/limit", "type": "float", "readonly": false, "cmd": "tt set/limit"},
|
||||||
|
{"path": "set/resist", "type": "float", "readonly": false, "cmd": "tt set/resist"},
|
||||||
|
{"path": "set/maxheater", "type": "text", "readonly": false, "cmd": "tt set/maxheater", "description": "maximum heater limit, units should be given without space: W, mW, A, mA"},
|
||||||
|
{"path": "set/linearpower", "type": "float", "readonly": false, "cmd": "tt set/linearpower", "description": "when not 0, it is the maximum effective power, and the power is linear to the heater output"},
|
||||||
|
{"path": "set/maxpowerlim", "type": "float", "description": "the maximum power limit (before any booster or converter)"},
|
||||||
|
{"path": "set/maxpower", "type": "float", "readonly": false, "cmd": "tt set/maxpower", "description": "maximum power [W]"},
|
||||||
|
{"path": "set/maxcurrent", "type": "float", "description": "the maximum current before any booster or converter"},
|
||||||
|
{"path": "set/manualpower", "type": "float", "readonly": false, "cmd": "tt set/manualpower"},
|
||||||
|
{"path": "set/power", "type": "float"},
|
||||||
|
{"path": "set/prop", "type": "float", "readonly": false, "cmd": "tt set/prop", "description": "bigger means more gain"},
|
||||||
|
{"path": "set/integ", "type": "float", "readonly": false, "cmd": "tt set/integ", "description": "bigger means faster"},
|
||||||
|
{"path": "set/deriv", "type": "float", "readonly": false, "cmd": "tt set/deriv"},
|
||||||
|
{"path": "setsamp", "type": "float", "readonly": false, "cmd": "tt setsamp", "kids": 18},
|
||||||
|
{"path": "setsamp/mode", "type": "enum", "enum": {"disabled": -1, "off": 0, "controlling": 1, "manual": 2}, "readonly": false, "cmd": "tt setsamp/mode"},
|
||||||
|
{"path": "setsamp/reg", "type": "float"},
|
||||||
|
{"path": "setsamp/ramp", "type": "float", "readonly": false, "cmd": "tt setsamp/ramp", "description": "maximum ramp in K/min (0: ramp off)"},
|
||||||
|
{"path": "setsamp/wramp", "type": "float", "readonly": false, "cmd": "tt setsamp/wramp"},
|
||||||
|
{"path": "setsamp/smooth", "type": "float", "readonly": false, "cmd": "tt setsamp/smooth", "description": "smooth time (minutes)"},
|
||||||
|
{"path": "setsamp/channel", "type": "text", "readonly": false, "cmd": "tt setsamp/channel"},
|
||||||
|
{"path": "setsamp/limit", "type": "float", "readonly": false, "cmd": "tt setsamp/limit"},
|
||||||
|
{"path": "setsamp/resist", "type": "float", "readonly": false, "cmd": "tt setsamp/resist"},
|
||||||
|
{"path": "setsamp/maxheater", "type": "text", "readonly": false, "cmd": "tt setsamp/maxheater", "description": "maximum heater limit, units should be given without space: W, mW, A, mA"},
|
||||||
|
{"path": "setsamp/linearpower", "type": "float", "readonly": false, "cmd": "tt setsamp/linearpower", "description": "when not 0, it is the maximum effective power, and the power is linear to the heater output"},
|
||||||
|
{"path": "setsamp/maxpowerlim", "type": "float", "description": "the maximum power limit (before any booster or converter)"},
|
||||||
|
{"path": "setsamp/maxpower", "type": "float", "readonly": false, "cmd": "tt setsamp/maxpower", "description": "maximum power [W]"},
|
||||||
|
{"path": "setsamp/maxcurrent", "type": "float", "description": "the maximum current before any booster or converter"},
|
||||||
|
{"path": "setsamp/manualpower", "type": "float", "readonly": false, "cmd": "tt setsamp/manualpower"},
|
||||||
|
{"path": "setsamp/power", "type": "float"},
|
||||||
|
{"path": "setsamp/prop", "type": "float", "readonly": false, "cmd": "tt setsamp/prop", "description": "bigger means more gain"},
|
||||||
|
{"path": "setsamp/integ", "type": "float", "readonly": false, "cmd": "tt setsamp/integ", "description": "bigger means faster"},
|
||||||
|
{"path": "setsamp/deriv", "type": "float", "readonly": false, "cmd": "tt setsamp/deriv"},
|
||||||
|
{"path": "display", "type": "text", "readonly": false, "cmd": "tt display"},
|
||||||
|
{"path": "remote", "type": "bool"}]},
|
||||||
|
|
||||||
|
"cc": {"base": "/cc", "params": [
|
||||||
|
{"path": "", "type": "bool", "kids": 96},
|
||||||
|
{"path": "send", "type": "text", "readonly": false, "cmd": "cc send", "visibility": 3},
|
||||||
|
{"path": "status", "type": "text", "visibility": 3},
|
||||||
|
{"path": "autodevice", "type": "bool", "readonly": false, "cmd": "cc autodevice"},
|
||||||
|
{"path": "fav", "type": "bool", "readonly": false, "cmd": "cc fav"},
|
||||||
|
{"path": "f", "type": "float"},
|
||||||
|
{"path": "fs", "type": "enum", "enum": {"ok": 0, "no_sens": 1}, "readonly": false, "cmd": "cc fs"},
|
||||||
|
{"path": "mav", "type": "bool", "readonly": false, "cmd": "cc mav"},
|
||||||
|
{"path": "fm", "type": "enum", "enum": {"idle": 0, "opening": 1, "closing": 2, "opened": 3, "closed": 4, "no_motor": 5}},
|
||||||
|
{"path": "fa", "type": "enum", "enum": {"fixed": 0, "controlled": 1, "automatic": 2, "offline": 3}, "readonly": false, "cmd": "cc fa"},
|
||||||
|
{"path": "mp", "type": "float", "readonly": false, "cmd": "cc mp"},
|
||||||
|
{"path": "msp", "type": "float"},
|
||||||
|
{"path": "mmp", "type": "float"},
|
||||||
|
{"path": "mc", "type": "float", "readonly": false, "cmd": "cc mc"},
|
||||||
|
{"path": "mfc", "type": "float", "readonly": false, "cmd": "cc mfc"},
|
||||||
|
{"path": "moc", "type": "float", "readonly": false, "cmd": "cc moc"},
|
||||||
|
{"path": "mtc", "type": "float", "readonly": false, "cmd": "cc mtc"},
|
||||||
|
{"path": "mtl", "type": "float"},
|
||||||
|
{"path": "mft", "type": "float", "readonly": false, "cmd": "cc mft"},
|
||||||
|
{"path": "mt", "type": "float"},
|
||||||
|
{"path": "mo", "type": "float"},
|
||||||
|
{"path": "mcr", "type": "float"},
|
||||||
|
{"path": "mot", "type": "float"},
|
||||||
|
{"path": "mw", "type": "float", "readonly": false, "cmd": "cc mw", "description": "correction pulse after automatic open"},
|
||||||
|
{"path": "hav", "type": "bool", "readonly": false, "cmd": "cc hav"},
|
||||||
|
{"path": "h", "type": "float"},
|
||||||
|
{"path": "hr", "type": "float"},
|
||||||
|
{"path": "hc", "type": "float"},
|
||||||
|
{"path": "hu", "type": "float"},
|
||||||
|
{"path": "hh", "type": "float", "readonly": false, "cmd": "cc hh"},
|
||||||
|
{"path": "hl", "type": "float", "readonly": false, "cmd": "cc hl"},
|
||||||
|
{"path": "htf", "type": "float", "readonly": false, "cmd": "cc htf", "description": "meas. period in fast mode"},
|
||||||
|
{"path": "hts", "type": "float", "readonly": false, "cmd": "cc hts", "description": "meas. period in slow mode"},
|
||||||
|
{"path": "hd", "type": "float", "readonly": false, "cmd": "cc hd"},
|
||||||
|
{"path": "hwr", "type": "float", "readonly": false, "cmd": "cc hwr"},
|
||||||
|
{"path": "hem", "type": "float", "readonly": false, "cmd": "cc hem", "description": "sensor length in mm from top to empty pos."},
|
||||||
|
{"path": "hfu", "type": "float", "readonly": false, "cmd": "cc hfu", "description": "sensor length in mm from top to full pos."},
|
||||||
|
{"path": "hcd", "type": "enum", "enum": {"stop": 0, "fill": 1, "off": 2, "auto": 3, "manual": 7}, "readonly": false, "cmd": "cc hcd"},
|
||||||
|
{"path": "hv", "type": "enum", "enum": {"fill_valve_off": 0, "filling": 1, "no_fill_valve": 2, "timeout": 3, "timeout1": 4}},
|
||||||
|
{"path": "hsf", "type": "enum", "enum": {"sens_ok": 0, "sens_warm": 1, "no_sens": 2, "timeout": 3, "not_yet_read": 4, "disabled": 5}},
|
||||||
|
{"path": "ha", "type": "bool", "readonly": false, "cmd": "cc ha"},
|
||||||
|
{"path": "hm", "type": "bool"},
|
||||||
|
{"path": "hf", "type": "enum", "enum": {"slow": 0, "fast": 1}, "readonly": false, "cmd": "cc hf"},
|
||||||
|
{"path": "hbe", "type": "bool", "readonly": false, "cmd": "cc hbe"},
|
||||||
|
{"path": "hmf", "type": "float"},
|
||||||
|
{"path": "hms", "type": "float"},
|
||||||
|
{"path": "hit", "type": "float", "readonly": false, "cmd": "cc hit"},
|
||||||
|
{"path": "hft", "type": "int", "readonly": false, "cmd": "cc hft"},
|
||||||
|
{"path": "hea", "type": "enum", "enum": {"0": 0, "1": 1, "6": 6}, "readonly": false, "cmd": "cc hea"},
|
||||||
|
{"path": "hch", "type": "int", "readonly": false, "cmd": "cc hch"},
|
||||||
|
{"path": "hwr0", "type": "float", "readonly": false, "cmd": "cc hwr0"},
|
||||||
|
{"path": "hem0", "type": "float", "readonly": false, "cmd": "cc hem0", "description": "sensor length in mm from top to empty pos."},
|
||||||
|
{"path": "hfu0", "type": "float", "readonly": false, "cmd": "cc hfu0", "description": "sensor length in mm from top to full pos."},
|
||||||
|
{"path": "hd0", "type": "float", "readonly": false, "cmd": "cc hd0", "description": "external sensor drive current (mA)"},
|
||||||
|
{"path": "h0", "type": "float"},
|
||||||
|
{"path": "hs0", "type": "enum", "enum": {"sens_ok": 0, "sens_warm": 1, "no_sens": 2, "timeout": 3, "not_yet_read": 4, "disabled": 5}},
|
||||||
|
{"path": "h1", "type": "float"},
|
||||||
|
{"path": "hs1", "type": "enum", "enum": {"sens_ok": 0, "sens_warm": 1, "no_sens": 2, "timeout": 3, "not_yet_read": 4, "disabled": 5}},
|
||||||
|
{"path": "h2", "type": "float"},
|
||||||
|
{"path": "hs2", "type": "enum", "enum": {"sens_ok": 0, "sens_warm": 1, "no_sens": 2, "timeout": 3, "not_yet_read": 4, "disabled": 5}},
|
||||||
|
{"path": "h3", "type": "float"},
|
||||||
|
{"path": "hs3", "type": "enum", "enum": {"sens_ok": 0, "sens_warm": 1, "no_sens": 2, "timeout": 3, "not_yet_read": 4, "disabled": 5}},
|
||||||
|
{"path": "h4", "type": "float"},
|
||||||
|
{"path": "hs4", "type": "enum", "enum": {"sens_ok": 0, "sens_warm": 1, "no_sens": 2, "timeout": 3, "not_yet_read": 4, "disabled": 5}},
|
||||||
|
{"path": "h5", "type": "float"},
|
||||||
|
{"path": "hs5", "type": "enum", "enum": {"sens_ok": 0, "sens_warm": 1, "no_sens": 2, "timeout": 3, "not_yet_read": 4, "disabled": 5}},
|
||||||
|
{"path": "hfb", "type": "float"},
|
||||||
|
{"path": "nav", "type": "bool", "readonly": false, "cmd": "cc nav"},
|
||||||
|
{"path": "nu", "type": "float"},
|
||||||
|
{"path": "nl", "type": "float"},
|
||||||
|
{"path": "nth", "type": "float", "readonly": false, "cmd": "cc nth"},
|
||||||
|
{"path": "ntc", "type": "float", "readonly": false, "cmd": "cc ntc"},
|
||||||
|
{"path": "ntm", "type": "float", "readonly": false, "cmd": "cc ntm"},
|
||||||
|
{"path": "ns", "type": "enum", "enum": {"sens_ok": 0, "no_sens": 1, "short_circuit": 2, "upside_down": 3, "sens_warm": 4, "empty": 5}},
|
||||||
|
{"path": "na", "type": "bool", "readonly": false, "cmd": "cc na"},
|
||||||
|
{"path": "nv", "type": "enum", "enum": {"fill_valve_off": 0, "filling": 1, "no_fill_valve": 2, "timeout": 3, "timeout1": 4, "boost": 5}},
|
||||||
|
{"path": "nc", "type": "enum", "enum": {"stop": 0, "fill": 1, "off": 2, "auto": 3}, "readonly": false, "cmd": "cc nc"},
|
||||||
|
{"path": "nfb", "type": "float"},
|
||||||
|
{"path": "cda", "type": "float"},
|
||||||
|
{"path": "cdb", "type": "float"},
|
||||||
|
{"path": "cba", "type": "float"},
|
||||||
|
{"path": "cbb", "type": "float"},
|
||||||
|
{"path": "cvs", "type": "int"},
|
||||||
|
{"path": "csp", "type": "int"},
|
||||||
|
{"path": "cdv", "type": "text", "readonly": false, "cmd": "cc cdv"},
|
||||||
|
{"path": "cic", "type": "text", "readonly": false, "cmd": "cc cic"},
|
||||||
|
{"path": "cin", "type": "text"},
|
||||||
|
{"path": "cds", "type": "enum", "enum": {"local": 0, "remote": 1, "loading": 2, "by_code": 3, "by_touch": 4}, "readonly": false, "cmd": "cc cds"},
|
||||||
|
{"path": "timing", "type": "bool", "readonly": false, "cmd": "cc timing"},
|
||||||
|
{"path": "tc", "type": "float", "visibility": 3},
|
||||||
|
{"path": "tn", "type": "float", "visibility": 3},
|
||||||
|
{"path": "th", "type": "float", "visibility": 3},
|
||||||
|
{"path": "tf", "type": "float", "visibility": 3},
|
||||||
|
{"path": "tm", "type": "float", "visibility": 3},
|
||||||
|
{"path": "tv", "type": "float", "visibility": 3},
|
||||||
|
{"path": "tq", "type": "float", "visibility": 3},
|
||||||
|
{"path": "bdl", "type": "float", "readonly": false, "cmd": "cc bdl"}]},
|
||||||
|
|
||||||
|
"nv": {"base": "/nv", "params": [
|
||||||
|
{"path": "", "type": "enum", "enum": {"fixed": 0, "controlled": 1, "automatic": 2, "close": 3, "open": 4}, "readonly": false, "cmd": "nv", "kids": 11},
|
||||||
|
{"path": "send", "type": "text", "readonly": false, "cmd": "nv send", "visibility": 3},
|
||||||
|
{"path": "status", "type": "text", "visibility": 3},
|
||||||
|
{"path": "motstat", "type": "enum", "enum": {"idle": 0, "opening": 1, "closing": 2, "opened": 3, "closed": 4, "no_motor": 5}},
|
||||||
|
{"path": "flow", "type": "float"},
|
||||||
|
{"path": "set", "type": "float", "readonly": false, "cmd": "nv set"},
|
||||||
|
{"path": "flowmax", "type": "float", "readonly": false, "cmd": "nv flowmax"},
|
||||||
|
{"path": "flowp", "type": "float"},
|
||||||
|
{"path": "span", "type": "float"},
|
||||||
|
{"path": "ctrl", "type": "none", "kids": 13},
|
||||||
|
{"path": "ctrl/regtext", "type": "text"},
|
||||||
|
{"path": "ctrl/prop_o", "type": "float", "readonly": false, "cmd": "nv ctrl/prop_o", "description": "prop [sec/mbar] when opening. above 4 mbar a 10 times lower value is used"},
|
||||||
|
{"path": "ctrl/prop_c", "type": "float", "readonly": false, "cmd": "nv ctrl/prop_c", "description": "prop [sec/mbar] when closing. above 4 mbar a 10 times lower value is used"},
|
||||||
|
{"path": "ctrl/deriv_o", "type": "float", "readonly": false, "cmd": "nv ctrl/deriv_o", "description": "convergence target time [sec] when opening"},
|
||||||
|
{"path": "ctrl/deriv_c", "type": "float", "readonly": false, "cmd": "nv ctrl/deriv_c", "description": "convergence target time [sec] when closing"},
|
||||||
|
{"path": "ctrl/minpulse_o", "type": "float", "readonly": false, "cmd": "nv ctrl/minpulse_o", "description": "minimum close pulse [sec]"},
|
||||||
|
{"path": "ctrl/minpulse_c", "type": "float", "readonly": false, "cmd": "nv ctrl/minpulse_c", "description": "standard close pulse [sec]"},
|
||||||
|
{"path": "ctrl/hystpulse_o", "type": "float", "readonly": false, "cmd": "nv ctrl/hystpulse_o", "description": "motor pulse to overcome hysteresis when opening"},
|
||||||
|
{"path": "ctrl/hystpulse_c", "type": "float", "readonly": false, "cmd": "nv ctrl/hystpulse_c", "description": "motor pulse to overcome hysteresis when closing"},
|
||||||
|
{"path": "ctrl/tol", "type": "float", "readonly": false, "cmd": "nv ctrl/tol", "description": "valid below 3 mbar"},
|
||||||
|
{"path": "ctrl/tolhigh", "type": "float", "readonly": false, "cmd": "nv ctrl/tolhigh", "description": "valid above 4 mbar"},
|
||||||
|
{"path": "ctrl/openpulse", "type": "float", "readonly": false, "cmd": "nv ctrl/openpulse", "description": "time to open from completely closed to a significant opening"},
|
||||||
|
{"path": "ctrl/adjust_minpulse", "type": "bool", "readonly": false, "cmd": "nv ctrl/adjust_minpulse", "description": "adjust minpulse automatically"},
|
||||||
|
{"path": "autoflow", "type": "none", "kids": 24},
|
||||||
|
{"path": "autoflow/suspended", "type": "bool", "readonly": false, "cmd": "nv autoflow/suspended"},
|
||||||
|
{"path": "autoflow/prop", "type": "float", "readonly": false, "cmd": "nv autoflow/prop"},
|
||||||
|
{"path": "autoflow/flowstd", "type": "float", "readonly": false, "cmd": "nv autoflow/flowstd"},
|
||||||
|
{"path": "autoflow/flowlim", "type": "float", "readonly": false, "cmd": "nv autoflow/flowlim"},
|
||||||
|
{"path": "autoflow/smooth", "type": "float", "readonly": false, "cmd": "nv autoflow/smooth"},
|
||||||
|
{"path": "autoflow/difSize", "type": "float", "readonly": false, "cmd": "nv autoflow/difSize"},
|
||||||
|
{"path": "autoflow/difRange", "type": "float", "readonly": false, "cmd": "nv autoflow/difRange"},
|
||||||
|
{"path": "autoflow/flowSize", "type": "float", "readonly": false, "cmd": "nv autoflow/flowSize"},
|
||||||
|
{"path": "autoflow/convTime", "type": "float", "readonly": false, "cmd": "nv autoflow/convTime"},
|
||||||
|
{"path": "autoflow/Tmin", "type": "float", "readonly": false, "cmd": "nv autoflow/Tmin"},
|
||||||
|
{"path": "autoflow/script", "type": "text", "readonly": false, "cmd": "nv autoflow/script"},
|
||||||
|
{"path": "autoflow/getTemp", "type": "text", "readonly": false, "cmd": "nv autoflow/getTemp"},
|
||||||
|
{"path": "autoflow/getTset", "type": "text", "readonly": false, "cmd": "nv autoflow/getTset"},
|
||||||
|
{"path": "autoflow/getFlow", "type": "text", "readonly": false, "cmd": "nv autoflow/getFlow"},
|
||||||
|
{"path": "autoflow/difBuf", "type": "text"},
|
||||||
|
{"path": "autoflow/flowBuf", "type": "text"},
|
||||||
|
{"path": "autoflow/flowset", "type": "float"},
|
||||||
|
{"path": "autoflow/flowmin", "type": "float"},
|
||||||
|
{"path": "autoflow/flowmax", "type": "float"},
|
||||||
|
{"path": "autoflow/difmin", "type": "float"},
|
||||||
|
{"path": "autoflow/difmax", "type": "float"},
|
||||||
|
{"path": "autoflow/setmin", "type": "float"},
|
||||||
|
{"path": "autoflow/setmax", "type": "float"},
|
||||||
|
{"path": "autoflow/flowtarget", "type": "float"},
|
||||||
|
{"path": "calib", "type": "none", "kids": 2},
|
||||||
|
{"path": "calib/ln_per_min_per_mbar", "type": "float", "readonly": false, "cmd": "nv calib/ln_per_min_per_mbar"},
|
||||||
|
{"path": "calib/mbar_offset", "type": "float", "readonly": false, "cmd": "nv calib/mbar_offset"}]},
|
||||||
|
|
||||||
|
"hefill": {"base": "/hefill", "params": [
|
||||||
|
{"path": "", "type": "enum", "enum": {"watching": 0, "filling": 1, "inactive": 2, "manualfill": 3}, "readonly": false, "cmd": "hefill", "kids": 16},
|
||||||
|
{"path": "send", "type": "text", "readonly": false, "cmd": "hefill send", "visibility": 3},
|
||||||
|
{"path": "status", "type": "text", "visibility": 3},
|
||||||
|
{"path": "state", "type": "text"},
|
||||||
|
{"path": "readlevel", "type": "text", "readonly": false, "cmd": "hefill readlevel", "visibility": 3},
|
||||||
|
{"path": "lowlevel", "type": "float", "readonly": false, "cmd": "hefill lowlevel"},
|
||||||
|
{"path": "highlevel", "type": "float", "readonly": false, "cmd": "hefill highlevel"},
|
||||||
|
{"path": "smooth", "type": "float"},
|
||||||
|
{"path": "minfillminutes", "type": "float", "readonly": false, "cmd": "hefill minfillminutes"},
|
||||||
|
{"path": "maxfillminutes", "type": "float", "readonly": false, "cmd": "hefill maxfillminutes"},
|
||||||
|
{"path": "minholdhours", "type": "float", "readonly": false, "cmd": "hefill minholdhours"},
|
||||||
|
{"path": "maxholdhours", "type": "float", "readonly": false, "cmd": "hefill maxholdhours"},
|
||||||
|
{"path": "tolerance", "type": "float", "readonly": false, "cmd": "hefill tolerance"},
|
||||||
|
{"path": "badreadingminutes", "type": "float", "readonly": false, "cmd": "hefill badreadingminutes"},
|
||||||
|
{"path": "tubecoolingminutes", "type": "float", "readonly": false, "cmd": "hefill tubecoolingminutes"},
|
||||||
|
{"path": "vessellimit", "type": "float", "readonly": false, "cmd": "hefill vessellimit"},
|
||||||
|
{"path": "vext", "type": "float"}]},
|
||||||
|
|
||||||
|
"hepump": {"base": "/hepump", "params": [
|
||||||
|
{"path": "", "type": "enum", "enum": {"neodry": 8, "xds35_auto": 0, "xds35_manual": 1, "sv65": 2, "other": 3, "no": -1}, "readonly": false, "cmd": "hepump", "description": "xds35: scroll pump, sv65: leybold", "kids": 10},
|
||||||
|
{"path": "send", "type": "text", "readonly": false, "cmd": "hepump send", "visibility": 3},
|
||||||
|
{"path": "status", "type": "text", "visibility": 3},
|
||||||
|
{"path": "running", "type": "bool", "readonly": false, "cmd": "hepump running"},
|
||||||
|
{"path": "eco", "type": "bool", "readonly": false, "cmd": "hepump eco"},
|
||||||
|
{"path": "auto", "type": "bool", "readonly": false, "cmd": "hepump auto"},
|
||||||
|
{"path": "valve", "type": "enum", "enum": {"closed": 0, "closing": 1, "opening": 2, "opened": 3, "undefined": 4}, "readonly": false, "cmd": "hepump valve"},
|
||||||
|
{"path": "eco_t_lim", "type": "float", "readonly": false, "cmd": "hepump eco_t_lim", "description": "switch off eco mode when T_set < eco_t_lim and T < eco_t_lim * 2"},
|
||||||
|
{"path": "calib", "type": "float", "readonly": false, "cmd": "hepump calib", "visibility": 3},
|
||||||
|
{"path": "health", "type": "float"}]},
|
||||||
|
|
||||||
|
"hemot": {"base": "/hepump/hemot", "params": [
|
||||||
|
{"path": "", "type": "float", "readonly": false, "cmd": "run hemot", "kids": 30},
|
||||||
|
{"path": "send", "type": "text", "readonly": false, "cmd": "hemot send", "visibility": 3},
|
||||||
|
{"path": "status", "type": "text", "visibility": 3},
|
||||||
|
{"path": "is_running", "type": "int", "readonly": false, "cmd": "hemot is_running", "visibility": 3},
|
||||||
|
{"path": "pos", "type": "float"},
|
||||||
|
{"path": "encoder", "type": "float"},
|
||||||
|
{"path": "zero", "type": "float", "readonly": false, "cmd": "hemot zero"},
|
||||||
|
{"path": "lowerlimit", "type": "float", "readonly": false, "cmd": "hemot lowerlimit"},
|
||||||
|
{"path": "upperlimit", "type": "float", "readonly": false, "cmd": "hemot upperlimit"},
|
||||||
|
{"path": "disablelimits", "type": "bool", "readonly": false, "cmd": "hemot disablelimits"},
|
||||||
|
{"path": "verbose", "type": "bool", "readonly": false, "cmd": "hemot verbose"},
|
||||||
|
{"path": "target", "type": "float"},
|
||||||
|
{"path": "runstate", "type": "enum", "enum": {"idle": 0, "running": 1, "finished": 2, "error": 3}},
|
||||||
|
{"path": "precision", "type": "float", "readonly": false, "cmd": "hemot precision"},
|
||||||
|
{"path": "maxencdif", "type": "float", "readonly": false, "cmd": "hemot maxencdif"},
|
||||||
|
{"path": "id", "type": "float", "readonly": false, "cmd": "hemot id"},
|
||||||
|
{"path": "pump_number", "type": "float", "readonly": false, "cmd": "hemot pump_number"},
|
||||||
|
{"path": "init", "type": "float", "readonly": false, "cmd": "hemot init"},
|
||||||
|
{"path": "maxspeed", "type": "float", "readonly": false, "cmd": "hemot maxspeed"},
|
||||||
|
{"path": "acceleration", "type": "float", "readonly": false, "cmd": "hemot acceleration"},
|
||||||
|
{"path": "maxcurrent", "type": "float", "readonly": false, "cmd": "hemot maxcurrent"},
|
||||||
|
{"path": "standbycurrent", "type": "float", "readonly": false, "cmd": "hemot standbycurrent"},
|
||||||
|
{"path": "freewheeling", "type": "bool", "readonly": false, "cmd": "hemot freewheeling"},
|
||||||
|
{"path": "output0", "type": "bool", "readonly": false, "cmd": "hemot output0"},
|
||||||
|
{"path": "output1", "type": "bool", "readonly": false, "cmd": "hemot output1"},
|
||||||
|
{"path": "input3", "type": "bool"},
|
||||||
|
{"path": "pullup", "type": "float", "readonly": false, "cmd": "hemot pullup"},
|
||||||
|
{"path": "nopumpfeedback", "type": "bool", "readonly": false, "cmd": "hemot nopumpfeedback"},
|
||||||
|
{"path": "eeprom", "type": "enum", "enum": {"ok": 0, "dirty": 1, "save": 2, "load": 3}, "readonly": false, "cmd": "hemot eeprom"},
|
||||||
|
{"path": "customadr", "type": "text", "readonly": false, "cmd": "hemot customadr"},
|
||||||
|
{"path": "custompar", "type": "float", "readonly": false, "cmd": "hemot custompar"}]},
|
||||||
|
|
||||||
|
"nvflow": {"base": "/nvflow", "params": [
|
||||||
|
{"path": "", "type": "float", "kids": 7},
|
||||||
|
{"path": "send", "type": "text", "readonly": false, "cmd": "nvflow send", "visibility": 3},
|
||||||
|
{"path": "status", "type": "text", "visibility": 3},
|
||||||
|
{"path": "stddev", "type": "float"},
|
||||||
|
{"path": "nsamples", "type": "int", "readonly": false, "cmd": "nvflow nsamples"},
|
||||||
|
{"path": "offset", "type": "float", "readonly": false, "cmd": "nvflow offset"},
|
||||||
|
{"path": "scale", "type": "float", "readonly": false, "cmd": "nvflow scale"},
|
||||||
|
{"path": "save", "type": "bool", "readonly": false, "cmd": "nvflow save", "description": "unchecked: current calib is not saved. set checked: save calib"}]},
|
||||||
|
|
||||||
|
"ln2fill": {"base": "/ln2fill", "params": [
|
||||||
|
{"path": "", "type": "enum", "enum": {"watching": 0, "filling": 1, "inactive": 2, "manualfill": 3}, "readonly": false, "cmd": "ln2fill", "kids": 14},
|
||||||
|
{"path": "send", "type": "text", "readonly": false, "cmd": "ln2fill send", "visibility": 3},
|
||||||
|
{"path": "status", "type": "text", "visibility": 3},
|
||||||
|
{"path": "state", "type": "text"},
|
||||||
|
{"path": "readlevel", "type": "text", "readonly": false, "cmd": "ln2fill readlevel", "visibility": 3},
|
||||||
|
{"path": "lowlevel", "type": "float", "readonly": false, "cmd": "ln2fill lowlevel"},
|
||||||
|
{"path": "highlevel", "type": "float", "readonly": false, "cmd": "ln2fill highlevel"},
|
||||||
|
{"path": "smooth", "type": "float"},
|
||||||
|
{"path": "minfillminutes", "type": "float", "readonly": false, "cmd": "ln2fill minfillminutes"},
|
||||||
|
{"path": "maxfillminutes", "type": "float", "readonly": false, "cmd": "ln2fill maxfillminutes"},
|
||||||
|
{"path": "minholdhours", "type": "float", "readonly": false, "cmd": "ln2fill minholdhours"},
|
||||||
|
{"path": "maxholdhours", "type": "float", "readonly": false, "cmd": "ln2fill maxholdhours"},
|
||||||
|
{"path": "tolerance", "type": "float", "readonly": false, "cmd": "ln2fill tolerance"},
|
||||||
|
{"path": "badreadingminutes", "type": "float", "readonly": false, "cmd": "ln2fill badreadingminutes"},
|
||||||
|
{"path": "tubecoolingminutes", "type": "float", "readonly": false, "cmd": "ln2fill tubecoolingminutes"}]},
|
||||||
|
|
||||||
|
"mf": {"base": "/mf", "params": [
|
||||||
|
{"path": "", "type": "float", "readonly": false, "cmd": "run mf", "kids": 26},
|
||||||
|
{"path": "persmode", "type": "int", "readonly": false, "cmd": "mf persmode"},
|
||||||
|
{"path": "perswitch", "type": "int"},
|
||||||
|
{"path": "nowait", "type": "int", "readonly": false, "cmd": "mf nowait"},
|
||||||
|
{"path": "maxlimit", "type": "float", "visibility": 3},
|
||||||
|
{"path": "limit", "type": "float", "readonly": false, "cmd": "mf limit"},
|
||||||
|
{"path": "ramp", "type": "float", "readonly": false, "cmd": "mf ramp"},
|
||||||
|
{"path": "perscurrent", "type": "float", "readonly": false, "cmd": "mf perscurrent"},
|
||||||
|
{"path": "perslimit", "type": "float", "readonly": false, "cmd": "mf perslimit"},
|
||||||
|
{"path": "perswait", "type": "int", "readonly": false, "cmd": "mf perswait"},
|
||||||
|
{"path": "persdelay", "type": "int", "readonly": false, "cmd": "mf persdelay"},
|
||||||
|
{"path": "current", "type": "float"},
|
||||||
|
{"path": "measured", "type": "float"},
|
||||||
|
{"path": "voltage", "type": "float"},
|
||||||
|
{"path": "lastfield", "type": "float", "visibility": 3},
|
||||||
|
{"path": "ampRamp", "type": "float", "visibility": 3},
|
||||||
|
{"path": "inductance", "type": "float", "visibility": 3},
|
||||||
|
{"path": "trainedTo", "type": "float", "readonly": false, "cmd": "mf trainedTo"},
|
||||||
|
{"path": "trainMode", "type": "int"},
|
||||||
|
{"path": "external", "type": "int", "readonly": false, "cmd": "mf external"},
|
||||||
|
{"path": "startScript", "type": "text", "readonly": false, "cmd": "mf startScript", "visibility": 3},
|
||||||
|
{"path": "is_running", "type": "int", "readonly": false, "cmd": "mf is_running", "visibility": 3},
|
||||||
|
{"path": "verbose", "type": "int", "readonly": false, "cmd": "mf verbose", "visibility": 3},
|
||||||
|
{"path": "driver", "type": "text", "visibility": 3},
|
||||||
|
{"path": "creationCmd", "type": "text", "visibility": 3},
|
||||||
|
{"path": "targetValue", "type": "float"},
|
||||||
|
{"path": "status", "type": "text", "readonly": false, "cmd": "mf status", "visibility": 3}]},
|
||||||
|
|
||||||
|
"lev": {"base": "/lev", "params": [
|
||||||
|
{"path": "", "type": "float", "kids": 4},
|
||||||
|
{"path": "send", "type": "text", "readonly": false, "cmd": "lev send", "visibility": 3},
|
||||||
|
{"path": "status", "type": "text", "visibility": 3},
|
||||||
|
{"path": "mode", "type": "enum", "enum": {"slow": 0, "fast (switches to slow automatically after filling)": 1}, "readonly": false, "cmd": "lev mode"},
|
||||||
|
{"path": "n2", "type": "float"}]},
|
||||||
|
|
||||||
|
"tcoil": {"base": "/tcoil", "params": [
|
||||||
|
{"path": "", "type": "float", "kids": 11},
|
||||||
|
{"path": "send", "type": "text", "readonly": false, "cmd": "tcoil send", "visibility": 3},
|
||||||
|
{"path": "status", "type": "text", "visibility": 3},
|
||||||
|
{"path": "excitation", "type": "float", "readonly": false, "cmd": "tcoil excitation", "visibility": 3},
|
||||||
|
{"path": "ta", "type": "float", "visibility": 3, "kids": 3},
|
||||||
|
{"path": "ta/enable", "type": "bool", "readonly": false, "cmd": "tcoil ta/enable"},
|
||||||
|
{"path": "ta/r", "type": "float"},
|
||||||
|
{"path": "ta/curve", "type": "text", "readonly": false, "cmd": "tcoil ta/curve", "kids": 3},
|
||||||
|
{"path": "ta/curve/adjust", "type": "text", "readonly": false, "cmd": "tcoil ta/curve/adjust"},
|
||||||
|
{"path": "ta/curve/points", "type": "floatvarar", "readonly": false, "cmd": "tcoil ta/curve/points"},
|
||||||
|
{"path": "ta/curve/cpoints", "type": "floatvarar", "readonly": false, "cmd": "tcoil ta/curve/cpoints"},
|
||||||
|
{"path": "tb", "type": "float", "visibility": 3, "kids": 3},
|
||||||
|
{"path": "tb/enable", "type": "bool", "readonly": false, "cmd": "tcoil tb/enable"},
|
||||||
|
{"path": "tb/r", "type": "float"},
|
||||||
|
{"path": "tb/curve", "type": "text", "readonly": false, "cmd": "tcoil tb/curve", "kids": 3},
|
||||||
|
{"path": "tb/curve/adjust", "type": "text", "readonly": false, "cmd": "tcoil tb/curve/adjust"},
|
||||||
|
{"path": "tb/curve/points", "type": "floatvarar", "readonly": false, "cmd": "tcoil tb/curve/points"},
|
||||||
|
{"path": "tb/curve/cpoints", "type": "floatvarar", "readonly": false, "cmd": "tcoil tb/curve/cpoints"},
|
||||||
|
{"path": "td", "type": "float", "visibility": 3, "kids": 3},
|
||||||
|
{"path": "td/enable", "type": "bool", "readonly": false, "cmd": "tcoil td/enable"},
|
||||||
|
{"path": "td/r", "type": "float"},
|
||||||
|
{"path": "td/curve", "type": "text", "readonly": false, "cmd": "tcoil td/curve", "kids": 3},
|
||||||
|
{"path": "td/curve/adjust", "type": "text", "readonly": false, "cmd": "tcoil td/curve/adjust"},
|
||||||
|
{"path": "td/curve/points", "type": "floatvarar", "readonly": false, "cmd": "tcoil td/curve/points"},
|
||||||
|
{"path": "td/curve/cpoints", "type": "floatvarar", "readonly": false, "cmd": "tcoil td/curve/cpoints"},
|
||||||
|
{"path": "ref", "type": "float", "visibility": 3, "kids": 3},
|
||||||
|
{"path": "ref/enable", "type": "bool", "readonly": false, "cmd": "tcoil ref/enable"},
|
||||||
|
{"path": "ref/r", "type": "float"},
|
||||||
|
{"path": "ref/curve", "type": "text", "readonly": false, "cmd": "tcoil ref/curve", "kids": 3},
|
||||||
|
{"path": "ref/curve/adjust", "type": "text", "readonly": false, "cmd": "tcoil ref/curve/adjust"},
|
||||||
|
{"path": "ref/curve/points", "type": "floatvarar", "readonly": false, "cmd": "tcoil ref/curve/points"},
|
||||||
|
{"path": "ref/curve/cpoints", "type": "floatvarar", "readonly": false, "cmd": "tcoil ref/curve/cpoints"},
|
||||||
|
{"path": "tc", "type": "float", "visibility": 3, "kids": 3},
|
||||||
|
{"path": "tc/enable", "type": "bool", "readonly": false, "cmd": "tcoil tc/enable"},
|
||||||
|
{"path": "tc/r", "type": "float"},
|
||||||
|
{"path": "tc/curve", "type": "text", "readonly": false, "cmd": "tcoil tc/curve", "kids": 3},
|
||||||
|
{"path": "tc/curve/adjust", "type": "text", "readonly": false, "cmd": "tcoil tc/curve/adjust"},
|
||||||
|
{"path": "tc/curve/points", "type": "floatvarar", "readonly": false, "cmd": "tcoil tc/curve/points"},
|
||||||
|
{"path": "tc/curve/cpoints", "type": "floatvarar", "readonly": false, "cmd": "tcoil tc/curve/cpoints"},
|
||||||
|
{"path": "ext", "type": "float", "visibility": 3},
|
||||||
|
{"path": "com", "type": "float", "visibility": 3},
|
||||||
|
{"path": "gnd", "type": "float", "visibility": 3}]},
|
||||||
|
|
||||||
|
"table": {"base": "/table", "params": [
|
||||||
|
{"path": "", "type": "none", "kids": 17},
|
||||||
|
{"path": "send", "type": "text", "readonly": false, "cmd": "table send", "visibility": 3},
|
||||||
|
{"path": "status", "type": "text", "visibility": 3},
|
||||||
|
{"path": "fix_tt_set_prop", "type": "bool", "readonly": false, "cmd": "table fix_tt_set_prop"},
|
||||||
|
{"path": "val_tt_set_prop", "type": "float"},
|
||||||
|
{"path": "tbl_tt_set_prop", "type": "text", "readonly": false, "cmd": "table tbl_tt_set_prop", "description": "enter value pair separated with colon T1:par1 T2:par2 ..."},
|
||||||
|
{"path": "fix_tt_set_integ", "type": "bool", "readonly": false, "cmd": "table fix_tt_set_integ"},
|
||||||
|
{"path": "val_tt_set_integ", "type": "float"},
|
||||||
|
{"path": "tbl_tt_set_integ", "type": "text", "readonly": false, "cmd": "table tbl_tt_set_integ", "description": "enter value pair separated with colon T1:par1 T2:par2 ..."},
|
||||||
|
{"path": "fix_tt_dblctrl_int2", "type": "bool", "readonly": false, "cmd": "table fix_tt_dblctrl_int2"},
|
||||||
|
{"path": "val_tt_dblctrl_int2", "type": "float"},
|
||||||
|
{"path": "tbl_tt_dblctrl_int2", "type": "text", "readonly": false, "cmd": "table tbl_tt_dblctrl_int2", "description": "enter value pair separated with colon T1:par1 T2:par2 ..."},
|
||||||
|
{"path": "fix_tt_dblctrl_prop_up", "type": "bool", "readonly": false, "cmd": "table fix_tt_dblctrl_prop_up"},
|
||||||
|
{"path": "val_tt_dblctrl_prop_up", "type": "float"},
|
||||||
|
{"path": "tbl_tt_dblctrl_prop_up", "type": "text", "readonly": false, "cmd": "table tbl_tt_dblctrl_prop_up", "description": "enter value pair separated with colon T1:par1 T2:par2 ..."},
|
||||||
|
{"path": "fix_tt_dblctrl_prop_lo", "type": "bool", "readonly": false, "cmd": "table fix_tt_dblctrl_prop_lo"},
|
||||||
|
{"path": "val_tt_dblctrl_prop_lo", "type": "float"},
|
||||||
|
{"path": "tbl_tt_dblctrl_prop_lo", "type": "text", "readonly": false, "cmd": "table tbl_tt_dblctrl_prop_lo", "description": "enter value pair separated with colon T1:par1 T2:par2 ..."}]}}
|
76
cfg/sea/thermalcond.stick.json
Normal file
76
cfg/sea/thermalcond.stick.json
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
{"res": {"base": "/res", "params": [
|
||||||
|
{"path": "", "type": "int", "kids": 10},
|
||||||
|
{"path": "send", "type": "text", "readonly": false, "cmd": "res send", "visibility": 3},
|
||||||
|
{"path": "status", "type": "text", "visibility": 3},
|
||||||
|
{"path": "autoscan", "type": "bool", "readonly": false, "cmd": "res autoscan", "kids": 4},
|
||||||
|
{"path": "autoscan/synchronized", "type": "bool", "readonly": false, "cmd": "res autoscan/synchronized"},
|
||||||
|
{"path": "autoscan/interval", "type": "text", "readonly": false, "cmd": "res autoscan/interval"},
|
||||||
|
{"path": "autoscan/pause", "type": "text", "readonly": false, "cmd": "res autoscan/pause"},
|
||||||
|
{"path": "autoscan/dwell", "type": "text", "readonly": false, "cmd": "res autoscan/dwell"},
|
||||||
|
{"path": "s1", "type": "float", "kids": 14},
|
||||||
|
{"path": "s1/active", "type": "enum", "enum": {"inactive": 0, "active": 1}, "readonly": false, "cmd": "res s1/active"},
|
||||||
|
{"path": "s1/autorange", "type": "bool", "readonly": false, "cmd": "res s1/autorange", "description": "autorange (common for all channels)"},
|
||||||
|
{"path": "s1/range", "type": "text", "readonly": false, "cmd": "res s1/range", "description": "resistance range in Ohm"},
|
||||||
|
{"path": "s1/range_num", "type": "int"},
|
||||||
|
{"path": "s1/excitation", "type": "text", "readonly": false, "cmd": "res s1/excitation", "description": "excitation with unit, i.e. 2uV or 3pA"},
|
||||||
|
{"path": "s1/excitation_num", "type": "int"},
|
||||||
|
{"path": "s1/excitation_mode", "type": "enum", "enum": {"voltage": 0, "current": 1, "off": 2}},
|
||||||
|
{"path": "s1/pause", "type": "int", "readonly": false, "cmd": "res s1/pause", "description": "pause time [sec] after channel change"},
|
||||||
|
{"path": "s1/filter", "type": "int", "readonly": false, "cmd": "res s1/filter", "description": "filter average time [sec]"},
|
||||||
|
{"path": "s1/dwell", "type": "int", "readonly": false, "cmd": "res s1/dwell", "description": "dwell time [sec]. Total time per channel: pause + filter + dwell"},
|
||||||
|
{"path": "s1/status", "type": "text"},
|
||||||
|
{"path": "s1/curve", "type": "text", "readonly": false, "cmd": "res s1/curve", "kids": 1},
|
||||||
|
{"path": "s1/curve/points", "type": "floatvarar", "readonly": false, "cmd": "res s1/curve/points", "visibility": 3},
|
||||||
|
{"path": "s1/alarm", "type": "float", "readonly": false, "cmd": "res s1/alarm"},
|
||||||
|
{"path": "s1/raw", "type": "float"},
|
||||||
|
{"path": "s2", "type": "float", "kids": 14},
|
||||||
|
{"path": "s2/active", "type": "enum", "enum": {"inactive": 0, "active": 1}, "readonly": false, "cmd": "res s2/active"},
|
||||||
|
{"path": "s2/autorange", "type": "bool", "readonly": false, "cmd": "res s2/autorange", "description": "autorange (common for all channels)"},
|
||||||
|
{"path": "s2/range", "type": "text", "readonly": false, "cmd": "res s2/range", "description": "resistance range in Ohm"},
|
||||||
|
{"path": "s2/range_num", "type": "int"},
|
||||||
|
{"path": "s2/excitation", "type": "text", "readonly": false, "cmd": "res s2/excitation", "description": "excitation with unit, i.e. 2uV or 3pA"},
|
||||||
|
{"path": "s2/excitation_num", "type": "int"},
|
||||||
|
{"path": "s2/excitation_mode", "type": "enum", "enum": {"voltage": 0, "current": 1, "off": 2}},
|
||||||
|
{"path": "s2/pause", "type": "int", "readonly": false, "cmd": "res s2/pause", "description": "pause time [sec] after channel change"},
|
||||||
|
{"path": "s2/filter", "type": "int", "readonly": false, "cmd": "res s2/filter", "description": "filter average time [sec]"},
|
||||||
|
{"path": "s2/dwell", "type": "int", "readonly": false, "cmd": "res s2/dwell", "description": "dwell time [sec]. Total time per channel: pause + filter + dwell"},
|
||||||
|
{"path": "s2/status", "type": "text"},
|
||||||
|
{"path": "s2/curve", "type": "text", "readonly": false, "cmd": "res s2/curve", "kids": 1},
|
||||||
|
{"path": "s2/curve/points", "type": "floatvarar", "readonly": false, "cmd": "res s2/curve/points", "visibility": 3},
|
||||||
|
{"path": "s2/alarm", "type": "float", "readonly": false, "cmd": "res s2/alarm"},
|
||||||
|
{"path": "s2/raw", "type": "float"},
|
||||||
|
{"path": "s3", "type": "float", "kids": 14},
|
||||||
|
{"path": "s3/active", "type": "enum", "enum": {"inactive": 0, "active": 1}, "readonly": false, "cmd": "res s3/active"},
|
||||||
|
{"path": "s3/autorange", "type": "bool", "readonly": false, "cmd": "res s3/autorange", "description": "autorange (common for all channels)"},
|
||||||
|
{"path": "s3/range", "type": "text", "readonly": false, "cmd": "res s3/range", "description": "resistance range in Ohm"},
|
||||||
|
{"path": "s3/range_num", "type": "int"},
|
||||||
|
{"path": "s3/excitation", "type": "text", "readonly": false, "cmd": "res s3/excitation", "description": "excitation with unit, i.e. 2uV or 3pA"},
|
||||||
|
{"path": "s3/excitation_num", "type": "int"},
|
||||||
|
{"path": "s3/excitation_mode", "type": "enum", "enum": {"voltage": 0, "current": 1, "off": 2}},
|
||||||
|
{"path": "s3/pause", "type": "int", "readonly": false, "cmd": "res s3/pause", "description": "pause time [sec] after channel change"},
|
||||||
|
{"path": "s3/filter", "type": "int", "readonly": false, "cmd": "res s3/filter", "description": "filter average time [sec]"},
|
||||||
|
{"path": "s3/dwell", "type": "int", "readonly": false, "cmd": "res s3/dwell", "description": "dwell time [sec]. Total time per channel: pause + filter + dwell"},
|
||||||
|
{"path": "s3/status", "type": "text"},
|
||||||
|
{"path": "s3/curve", "type": "text", "readonly": false, "cmd": "res s3/curve", "kids": 1},
|
||||||
|
{"path": "s3/curve/points", "type": "floatvarar", "readonly": false, "cmd": "res s3/curve/points", "visibility": 3},
|
||||||
|
{"path": "s3/alarm", "type": "float", "readonly": false, "cmd": "res s3/alarm"},
|
||||||
|
{"path": "s3/raw", "type": "float"},
|
||||||
|
{"path": "s4", "type": "float", "kids": 14},
|
||||||
|
{"path": "s4/active", "type": "enum", "enum": {"inactive": 0, "active": 1}, "readonly": false, "cmd": "res s4/active"},
|
||||||
|
{"path": "s4/autorange", "type": "bool", "readonly": false, "cmd": "res s4/autorange", "description": "autorange (common for all channels)"},
|
||||||
|
{"path": "s4/range", "type": "text", "readonly": false, "cmd": "res s4/range", "description": "resistance range in Ohm"},
|
||||||
|
{"path": "s4/range_num", "type": "int"},
|
||||||
|
{"path": "s4/excitation", "type": "text", "readonly": false, "cmd": "res s4/excitation", "description": "excitation with unit, i.e. 2uV or 3pA"},
|
||||||
|
{"path": "s4/excitation_num", "type": "int"},
|
||||||
|
{"path": "s4/excitation_mode", "type": "enum", "enum": {"voltage": 0, "current": 1, "off": 2}},
|
||||||
|
{"path": "s4/pause", "type": "int", "readonly": false, "cmd": "res s4/pause", "description": "pause time [sec] after channel change"},
|
||||||
|
{"path": "s4/filter", "type": "int", "readonly": false, "cmd": "res s4/filter", "description": "filter average time [sec]"},
|
||||||
|
{"path": "s4/dwell", "type": "int", "readonly": false, "cmd": "res s4/dwell", "description": "dwell time [sec]. Total time per channel: pause + filter + dwell"},
|
||||||
|
{"path": "s4/status", "type": "text"},
|
||||||
|
{"path": "s4/curve", "type": "text", "readonly": false, "cmd": "res s4/curve", "kids": 1},
|
||||||
|
{"path": "s4/curve/points", "type": "floatvarar", "readonly": false, "cmd": "res s4/curve/points", "visibility": 3},
|
||||||
|
{"path": "s4/alarm", "type": "float", "readonly": false, "cmd": "res s4/alarm"},
|
||||||
|
{"path": "s4/raw", "type": "float"},
|
||||||
|
{"path": "analog2", "type": "float", "readonly": false, "cmd": "res analog2"},
|
||||||
|
{"path": "remote", "type": "bool"},
|
||||||
|
{"path": "display", "type": "text", "readonly": false, "cmd": "res display"}]}}
|
49
cfg/sim_mlz_entangle_simulation_cfg.py
Normal file
49
cfg/sim_mlz_entangle_simulation_cfg.py
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
Node('simulation',
|
||||||
|
'Auto-generated configuration by frappy.',
|
||||||
|
'tcp://10767',
|
||||||
|
)
|
||||||
|
Mod('analoginput',
|
||||||
|
'frappy_mlz.entangle.AnalogInput',
|
||||||
|
'from test/sim/analoginput',
|
||||||
|
tangodevice = 'tango://localhost:10000/test/sim/analoginput',
|
||||||
|
)
|
||||||
|
Mod('sensor',
|
||||||
|
'frappy_mlz.entangle.Sensor',
|
||||||
|
'from test/sim/sensor',
|
||||||
|
tangodevice = 'tango://localhost:10000/test/sim/sensor',
|
||||||
|
)
|
||||||
|
Mod('analogoutput',
|
||||||
|
'frappy_mlz.entangle.AnalogOutput',
|
||||||
|
'from test/sim/analogoutput',
|
||||||
|
tangodevice = 'tango://localhost:10000/test/sim/analogoutput',
|
||||||
|
)
|
||||||
|
Mod('actuator',
|
||||||
|
'frappy_mlz.entangle.Actuator',
|
||||||
|
'from test/sim/actuator',
|
||||||
|
tangodevice = 'tango://localhost:10000/test/sim/actuator',
|
||||||
|
)
|
||||||
|
Mod('motor',
|
||||||
|
'frappy_mlz.entangle.Motor',
|
||||||
|
'from test/sim/motor',
|
||||||
|
tangodevice = 'tango://localhost:10000/test/sim/motor',
|
||||||
|
)
|
||||||
|
Mod('powersupply',
|
||||||
|
'frappy_mlz.entangle.PowerSupply',
|
||||||
|
'from test/sim/powersupply',
|
||||||
|
tangodevice = 'tango://localhost:10000/test/sim/powersupply',
|
||||||
|
)
|
||||||
|
Mod('digitalinput',
|
||||||
|
'frappy_mlz.entangle.DigitalInput',
|
||||||
|
'from test/sim/digitalinput',
|
||||||
|
tangodevice = 'tango://localhost:10000/test/sim/digitalinput',
|
||||||
|
)
|
||||||
|
Mod('digitaloutput',
|
||||||
|
'frappy_mlz.entangle.DigitalOutput',
|
||||||
|
'from test/sim/digitaloutput',
|
||||||
|
tangodevice = 'tango://localhost:10000/test/sim/digitaloutput',
|
||||||
|
)
|
||||||
|
Mod('stringio',
|
||||||
|
'frappy_mlz.entangle.StringIO',
|
||||||
|
'from test/sim/stringio',
|
||||||
|
tangodevice = 'tango://localhost:10000/test/sim/stringio',
|
||||||
|
)
|
@ -138,13 +138,6 @@ Mod('T_one_K',
|
|||||||
io='itc',
|
io='itc',
|
||||||
)
|
)
|
||||||
|
|
||||||
Mod('htr_one_K',
|
|
||||||
'frappy_psi.mercury.HeaterOutput',
|
|
||||||
'1 K plate warmup heater',
|
|
||||||
slot='DB3.H1',
|
|
||||||
io='itc',
|
|
||||||
)
|
|
||||||
|
|
||||||
Mod('T_mix_wup',
|
Mod('T_mix_wup',
|
||||||
'frappy_psi.mercury.TemperatureLoop',
|
'frappy_psi.mercury.TemperatureLoop',
|
||||||
'mix. chamber warmup temperature',
|
'mix. chamber warmup temperature',
|
||||||
|
@ -10,6 +10,14 @@ Mod('sea_stick',
|
|||||||
)
|
)
|
||||||
|
|
||||||
Mod('ts',
|
Mod('ts',
|
||||||
|
'frappy_psi.sea.SeaReadable', '',
|
||||||
|
io='sea_stick',
|
||||||
|
sea_object='tt',
|
||||||
|
json_file='ma6.config.json',
|
||||||
|
rel_paths=['ts_2'],
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('ts_reg',
|
||||||
'frappy_psi.sea.SeaReadable', '',
|
'frappy_psi.sea.SeaReadable', '',
|
||||||
io='sea_stick',
|
io='sea_stick',
|
||||||
sea_object='tt',
|
sea_object='tt',
|
||||||
@ -22,3 +30,11 @@ Mod('hcp',
|
|||||||
io='sea_stick',
|
io='sea_stick',
|
||||||
sea_object='hcp',
|
sea_object='hcp',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Mod('v',
|
||||||
|
'frappy_psi.parmod.Driv',
|
||||||
|
'drivable voltage',
|
||||||
|
read='hcp.value',
|
||||||
|
write='hcp.set',
|
||||||
|
unit='V',
|
||||||
|
)
|
||||||
|
@ -22,8 +22,8 @@ Mod('ts',
|
|||||||
'frappy_psi.parmod.Converging',
|
'frappy_psi.parmod.Converging',
|
||||||
'virtual stick T',
|
'virtual stick T',
|
||||||
unit='K',
|
unit='K',
|
||||||
read='tsam.value',
|
value_param='tsam.value',
|
||||||
write='tsam.setsamp',
|
target_param='tsam.setsamp',
|
||||||
meaning=['temperature', 20],
|
meaning=['temperature', 20],
|
||||||
settling_time=20,
|
settling_time=20,
|
||||||
tolerance=1,
|
tolerance=1,
|
||||||
|
11
cfg/stick/ma6_sampleheat_cfg.py
Normal file
11
cfg/stick/ma6_sampleheat_cfg.py
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
Node('ma6_sampleheat.psi.ch', '', interface='tcp://5000')
|
||||||
|
|
||||||
|
Mod('sea_stick',
|
||||||
|
'frappy_psi.sea.SeaClient',
|
||||||
|
'stick sea connection for ma6_sampleheat.stick',
|
||||||
|
config='ma6_sampleheat.stick',
|
||||||
|
service='stick',
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# ts is configured on ma7_sampleheat_cfg.py
|
18
cfg/stick/ma7_piezostick_cfg.py
Normal file
18
cfg/stick/ma7_piezostick_cfg.py
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
Node('ma7.stick.sea.psi.ch',
|
||||||
|
'MA7 standard sample stick',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('sea_stick',
|
||||||
|
'frappy_psi.sea.SeaClient',
|
||||||
|
'SEA stick connection',
|
||||||
|
config='ma7_piezo.stick',
|
||||||
|
service='stick',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('ts',
|
||||||
|
'frappy_psi.sea.SeaReadable', '',
|
||||||
|
io='sea_stick',
|
||||||
|
sea_object='tt',
|
||||||
|
json_file='ma7_piezo.config.json',
|
||||||
|
rel_paths=['ts'],
|
||||||
|
)
|
72
cfg/stick/ma7combi_cfg.py
Normal file
72
cfg/stick/ma7combi_cfg.py
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
Node('ma7.stick.sea.psi.ch',
|
||||||
|
'MA7 standard sample stick',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('sea_stick',
|
||||||
|
'frappy_psi.sea.SeaClient',
|
||||||
|
'SEA stick connection',
|
||||||
|
config='ma7.stick',
|
||||||
|
service='stick',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('ts_sea',
|
||||||
|
'frappy_psi.sea.SeaReadable',
|
||||||
|
'sample stick temperature',
|
||||||
|
io='sea_stick',
|
||||||
|
json_file='ma7.config.json',
|
||||||
|
sea_object='tt',
|
||||||
|
rel_paths=['ts', 'setsamp'],
|
||||||
|
# export=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('tm_sea',
|
||||||
|
'frappy_psi.sea.SeaReadable',
|
||||||
|
'sample stick temperature',
|
||||||
|
io='sea_stick',
|
||||||
|
json_file='ma7.config.json',
|
||||||
|
sea_object='tt',
|
||||||
|
rel_paths=['tm', 'set'],
|
||||||
|
# export=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('ts_writ',
|
||||||
|
'frappy_psi.parmod.ParWrit',
|
||||||
|
'writable version of ts',
|
||||||
|
unit='K',
|
||||||
|
value_param='ts_sea.value',
|
||||||
|
target_param='ts_sea.setsamp',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('tm_writ',
|
||||||
|
'frappy_psi.parmod.ParWrit',
|
||||||
|
'writable version of tm',
|
||||||
|
unit='K',
|
||||||
|
value_param='tm_sea.value',
|
||||||
|
target_param='tm_sea.set',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('sam_htr',
|
||||||
|
'frappy_psi.parmod.Par',
|
||||||
|
'htr module version',
|
||||||
|
unit='W',
|
||||||
|
value_param='ts_sea.power',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('vti_htr',
|
||||||
|
'frappy_psi.parmod.Par',
|
||||||
|
'htr module version',
|
||||||
|
unit='W',
|
||||||
|
value_param='tm_sea.power',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('ts',
|
||||||
|
'frappy_psi.parmod.CombinedSampleVti',
|
||||||
|
'drivable stick T using setsamp',
|
||||||
|
sample='ts_writ',
|
||||||
|
sample_htr='sam_htr',
|
||||||
|
vti='tm_writ',
|
||||||
|
vti_htr='vti_htr',
|
||||||
|
meaning=['temperature', 20],
|
||||||
|
settling_time=20,
|
||||||
|
tolerance=1,
|
||||||
|
)
|
@ -9,7 +9,7 @@ Mod('sea_stick',
|
|||||||
service='stick',
|
service='stick',
|
||||||
)
|
)
|
||||||
|
|
||||||
Mod('tsam',
|
Mod('ts_sea',
|
||||||
'frappy_psi.sea.SeaReadable',
|
'frappy_psi.sea.SeaReadable',
|
||||||
'sample stick temperature',
|
'sample stick temperature',
|
||||||
io='sea_stick',
|
io='sea_stick',
|
||||||
@ -22,8 +22,8 @@ Mod('ts',
|
|||||||
'frappy_psi.parmod.Converging',
|
'frappy_psi.parmod.Converging',
|
||||||
'drivable stick T using setsamp',
|
'drivable stick T using setsamp',
|
||||||
unit='K',
|
unit='K',
|
||||||
read='tsam.value',
|
value_param='ts_sea.value',
|
||||||
write='tsam.setsamp',
|
target_param='ts_sea.setsamp',
|
||||||
meaning=['temperature', 20],
|
meaning=['temperature', 20],
|
||||||
settling_time=20,
|
settling_time=20,
|
||||||
tolerance=1,
|
tolerance=1,
|
||||||
|
@ -9,10 +9,23 @@ Mod('sea_stick',
|
|||||||
service='stick',
|
service='stick',
|
||||||
)
|
)
|
||||||
|
|
||||||
Mod('ts',
|
Mod('tsam',
|
||||||
'frappy_psi.sea.SeaReadable', '',
|
'frappy_psi.sea.SeaReadable',
|
||||||
|
'sample stick temperature',
|
||||||
io='sea_stick',
|
io='sea_stick',
|
||||||
sea_object='tt',
|
|
||||||
json_file='ma7.config.json',
|
json_file='ma7.config.json',
|
||||||
rel_paths=['ts'],
|
sea_object='tt',
|
||||||
|
rel_paths=['ts', 'setsamp']
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Mod('ts',
|
||||||
|
'frappy_psi.parmod.Converging',
|
||||||
|
'drivable stick T using setsamp',
|
||||||
|
unit='K',
|
||||||
|
value_param='tsam.value',
|
||||||
|
target_param='tsam.setsamp',
|
||||||
|
meaning=['temperature', 20],
|
||||||
|
settling_time=20,
|
||||||
|
tolerance=1,
|
||||||
|
)
|
||||||
|
|
||||||
|
@ -1,23 +0,0 @@
|
|||||||
[NODE]
|
|
||||||
description = PGAS5 gas pressure cell stick
|
|
||||||
id = pgas5.stick.sea.psi.ch
|
|
||||||
|
|
||||||
[sea_stick]
|
|
||||||
class = secop_psi.sea.SeaClient
|
|
||||||
description = stick SEA connection to ill5.stick
|
|
||||||
config = ill5.stick
|
|
||||||
service = stick
|
|
||||||
|
|
||||||
[ts]
|
|
||||||
class = secop_psi.sea.SeaReadable
|
|
||||||
io = sea_stick
|
|
||||||
sea_object = tt
|
|
||||||
json_file = ill5.config.json
|
|
||||||
rel_paths = ts
|
|
||||||
|
|
||||||
[T_bottom]
|
|
||||||
class = secop_psi.sea.SeaReadable
|
|
||||||
io = sea_stick
|
|
||||||
sea_object = tt
|
|
||||||
json_file = ill5.config.json
|
|
||||||
rel_paths = tb
|
|
28
cfg/stick/pgas5_cfg.py
Normal file
28
cfg/stick/pgas5_cfg.py
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
Node('pgas5.stick.sea.psi.ch',
|
||||||
|
'PGAS5 gas pressure cell stick',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('sea_stick',
|
||||||
|
'frappy_psi.sea.SeaClient',
|
||||||
|
'stick SEA connection to ill5.stick',
|
||||||
|
config = 'pgas5.stick',
|
||||||
|
service = 'stick',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('ts',
|
||||||
|
'frappy_psi.sea.SeaReadable',
|
||||||
|
'sample temperature',
|
||||||
|
io = 'sea_stick',
|
||||||
|
sea_object = 'tt',
|
||||||
|
json_file = 'ill5pgas5.config.json',
|
||||||
|
rel_paths = ['ts'],
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('T_bottom',
|
||||||
|
'frappy_psi.sea.SeaReadable',
|
||||||
|
'bottom T',
|
||||||
|
io = 'sea_stick',
|
||||||
|
sea_object = 'tt',
|
||||||
|
json_file = 'ill5pgas5.config.json',
|
||||||
|
rel_paths = ['ts_2'],
|
||||||
|
)
|
67
cfg/stick/thermalcond_cfg.py
Normal file
67
cfg/stick/thermalcond_cfg.py
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
Node('thermalcond.stick.sea.psi.ch',
|
||||||
|
'''50 mm thermal conductivity stick, version with standard lsc370 driver''',
|
||||||
|
)
|
||||||
|
Mod('sea_stick',
|
||||||
|
'frappy_psi.sea.SeaClient',
|
||||||
|
'stick sea connection for thermalcond.stick',
|
||||||
|
config = 'thermalcond.stick',
|
||||||
|
service = 'stick',
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#Mod('tsam',
|
||||||
|
# 'frappy_psi.sea.SeaReadable',
|
||||||
|
# 'sample stick temperature',
|
||||||
|
# io='sea_stick',
|
||||||
|
# json_file='ma7.config.json',
|
||||||
|
# sea_object='tt',
|
||||||
|
# rel_paths=['ts', 'setsamp']
|
||||||
|
#)
|
||||||
|
|
||||||
|
#Mod('ts',
|
||||||
|
# 'frappy_psi.parmod.Converging',
|
||||||
|
# 'drivable stick T using setsamp',
|
||||||
|
# unit='K',
|
||||||
|
# value_param='tsam.value',
|
||||||
|
# target_param='tsam.setsamp',
|
||||||
|
# meaning=['temperature', 20],
|
||||||
|
# settling_time=20,
|
||||||
|
# tolerance=1,
|
||||||
|
#)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#Mod('res',
|
||||||
|
# 'frappy_psi.sea.SeaReadable', '',
|
||||||
|
# io = 'sea_stick',
|
||||||
|
# sea_object = 'res',
|
||||||
|
#)
|
||||||
|
|
||||||
|
Mod('R1',
|
||||||
|
'frappy_psi.sea.SeaReadable', '',
|
||||||
|
io='sea_stick',
|
||||||
|
sea_object='res',
|
||||||
|
rel_paths=['s1'],
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('R2',
|
||||||
|
'frappy_psi.sea.SeaReadable', '',
|
||||||
|
io='sea_stick',
|
||||||
|
sea_object='res',
|
||||||
|
rel_paths=['s2'],
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('R3',
|
||||||
|
'frappy_psi.sea.SeaReadable', '',
|
||||||
|
io='sea_stick',
|
||||||
|
sea_object='res',
|
||||||
|
rel_paths=['s3'],
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('R4',
|
||||||
|
'frappy_psi.sea.SeaReadable', '',
|
||||||
|
io='sea_stick',
|
||||||
|
sea_object='res',
|
||||||
|
rel_paths=['s4'],
|
||||||
|
)
|
103
cfg/vf_cfg.py
Normal file
103
cfg/vf_cfg.py
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
Node('vf.psi.ch',
|
||||||
|
'small vacuum furnace',
|
||||||
|
'tcp://5000',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('htr_io',
|
||||||
|
'frappy_psi.bkpower.IO',
|
||||||
|
'powersupply communicator',
|
||||||
|
uri = 'serial:///dev/ttyUSBupper',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('htr',
|
||||||
|
'frappy_psi.bkpower.Power',
|
||||||
|
'heater power',
|
||||||
|
io= 'htr_io',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('out',
|
||||||
|
'frappy_psi.bkpower.Output',
|
||||||
|
'heater output',
|
||||||
|
io = 'htr_io',
|
||||||
|
maxvolt = 50,
|
||||||
|
maxcurrent = 2,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
Mod('relais',
|
||||||
|
'frappy_psi.ionopimax.DigitalOutput',
|
||||||
|
'relais for power output',
|
||||||
|
addr = 'o2',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('T_main',
|
||||||
|
'frappy_psi.ionopimax.CurrentInput',
|
||||||
|
'sample temperature',
|
||||||
|
addr = 'ai4',
|
||||||
|
valuerange = (0, 1372),
|
||||||
|
value = Param(unit='degC'),
|
||||||
|
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
Mod('T_extra',
|
||||||
|
'frappy_psi.ionopimax.CurrentInput',
|
||||||
|
'extra temperature',
|
||||||
|
addr = 'ai3',
|
||||||
|
valuerange = (0, 1372),
|
||||||
|
value = Param(unit='degC'),
|
||||||
|
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('T_htr',
|
||||||
|
'frappy_psi.ionopimax.CurrentInput',
|
||||||
|
'heater temperature',
|
||||||
|
addr = 'ai2',
|
||||||
|
valuerange = (0, 1372),
|
||||||
|
value = Param(unit='degC'),
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('T_wall',
|
||||||
|
'frappy_psi.ionopimax.VoltageInput',
|
||||||
|
'furnace wall temperature',
|
||||||
|
addr = 'av2',
|
||||||
|
rawrange = (0, 1.5),
|
||||||
|
valuerange = (0, 150),
|
||||||
|
value = Param(unit='degC'),
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('T',
|
||||||
|
'frappy_psi.picontrol.PI',
|
||||||
|
'controlled Temperature',
|
||||||
|
input = 'T_htr',
|
||||||
|
output = 'out',
|
||||||
|
relais = 'relais',
|
||||||
|
p = 2,
|
||||||
|
i = 0.01,
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('interlocks',
|
||||||
|
'frappy_psi.furnace.Interlocks',
|
||||||
|
'interlock parameters',
|
||||||
|
input = 'T_htr',
|
||||||
|
wall_T = 'T_wall',
|
||||||
|
vacuum = 'p',
|
||||||
|
relais = 'relais',
|
||||||
|
control = 'T',
|
||||||
|
wall_limit = 50,
|
||||||
|
vacuum_limit = 0.1,
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('p_io',
|
||||||
|
'frappy_psi.pfeiffer.IO',
|
||||||
|
'pressure io',
|
||||||
|
uri='serial:///dev/ttyUSBlower',
|
||||||
|
)
|
||||||
|
|
||||||
|
Mod('p',
|
||||||
|
'frappy_psi.pfeiffer.Pressure',
|
||||||
|
'pressure reading',
|
||||||
|
io = 'p_io',
|
||||||
|
)
|
||||||
|
|
||||||
|
|
11
ci/Jenkinsfile
vendored
11
ci/Jenkinsfile
vendored
@ -141,12 +141,23 @@ def run_docs() {
|
|||||||
'''
|
'''
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* does not work with too many quote levels
|
||||||
|
* alternatively use pdf (based on rst2pdf)
|
||||||
|
* or singlehtml converted to pdf manually from a browser (may produce nicer output)
|
||||||
stage('build latexpdf') {
|
stage('build latexpdf') {
|
||||||
sh '''
|
sh '''
|
||||||
. /home/jenkins/secopvenv/bin/activate
|
. /home/jenkins/secopvenv/bin/activate
|
||||||
make -C doc latexpdf
|
make -C doc latexpdf
|
||||||
'''
|
'''
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
stage('build pdf') {
|
||||||
|
sh '''
|
||||||
|
. /home/jenkins/secopvenv/bin/activate
|
||||||
|
make -C doc pdf
|
||||||
|
'''
|
||||||
|
}
|
||||||
|
|
||||||
stage('build man') {
|
stage('build man') {
|
||||||
sh '''
|
sh '''
|
||||||
|
174
debian/changelog
vendored
174
debian/changelog
vendored
@ -1,3 +1,177 @@
|
|||||||
|
frappy-core (0.19.0) jammy; urgency=medium
|
||||||
|
|
||||||
|
[ Markus Zolliker ]
|
||||||
|
* simulation: extra_params might be a list
|
||||||
|
* add FloatEnumParam
|
||||||
|
* move StructParam to frappy/extparams.py
|
||||||
|
* bugfix in automatic creation if attached io
|
||||||
|
* fixes for proxy modules
|
||||||
|
* simplify callbacks
|
||||||
|
* fix docstring in frappy.error.OutOfRangeError
|
||||||
|
|
||||||
|
[ Alexander Zaft ]
|
||||||
|
* core: introduce common handler class
|
||||||
|
* core: cover errors in handler setup()
|
||||||
|
|
||||||
|
[ Markus Zolliker ]
|
||||||
|
* fix command doc string handling and change default stop doc string
|
||||||
|
* follow up fix for change 33168
|
||||||
|
* follow up fix: handler export=True correctly
|
||||||
|
|
||||||
|
[ Alexander Zaft ]
|
||||||
|
* core: add websocket interface
|
||||||
|
|
||||||
|
[ Georg Brandl ]
|
||||||
|
* dispatcher: consistent handling of missing timestamps
|
||||||
|
|
||||||
|
[ Alexander Zaft ]
|
||||||
|
* gui: catch invalid inputs
|
||||||
|
* gui: sort qt imports
|
||||||
|
|
||||||
|
[ Markus Zolliker ]
|
||||||
|
* frappy.client: cleanup properly after a reply timeout
|
||||||
|
|
||||||
|
[ Alexander Zaft ]
|
||||||
|
* gui: more specialized input widgets
|
||||||
|
* test: add uri attach test
|
||||||
|
|
||||||
|
[ Markus Zolliker ]
|
||||||
|
* frappy.client: catch errors on callbacks
|
||||||
|
* frappy.client: improve error handling more
|
||||||
|
* frappy.client.interactive: improve logging and error handling
|
||||||
|
* frappy.client.SecopClient: add the option to use no logging at all
|
||||||
|
* SecopClient.__del__ must not call callbacks
|
||||||
|
* frappy.client: avoid shutdown callback sent twice
|
||||||
|
|
||||||
|
[ Georg Brandl ]
|
||||||
|
* add config for the Entangle simulation server
|
||||||
|
|
||||||
|
[ Jens Krüger ]
|
||||||
|
* Fix abslimits reading from entangle device
|
||||||
|
|
||||||
|
[ Georg Brandl ]
|
||||||
|
* fix LimitsType to be actually used and validated
|
||||||
|
|
||||||
|
-- Markus Zolliker <jenkins@frm2.tum.de> Thu, 16 May 2024 11:31:25 +0200
|
||||||
|
|
||||||
|
frappy-core (0.18.1) focal; urgency=medium
|
||||||
|
|
||||||
|
* mlz: Zapf fix unit handling and small errors
|
||||||
|
* mlz: entangle fix limit check
|
||||||
|
|
||||||
|
-- Alexander Zaft <jenkins@frm2.tum.de> Wed, 24 Jan 2024 14:59:21 +0100
|
||||||
|
|
||||||
|
frappy-core (0.18.0) focal; urgency=medium
|
||||||
|
|
||||||
|
[ Alexander Zaft ]
|
||||||
|
* Add shutdownModule function
|
||||||
|
|
||||||
|
[ Markus Zolliker ]
|
||||||
|
* frappy_psi.convergence: bug fixes and improvements
|
||||||
|
|
||||||
|
[ Alexander Zaft ]
|
||||||
|
* server: Add signal handling
|
||||||
|
* add test cases for server and config
|
||||||
|
|
||||||
|
[ Markus Zolliker ]
|
||||||
|
* fix frappy.lib.merge_status
|
||||||
|
* frappy_psi.sea: try to reconnect on failure
|
||||||
|
* pylint: disable use-dict-literal
|
||||||
|
|
||||||
|
[ Alexander Zaft ]
|
||||||
|
* server: add option to dynamically create devices
|
||||||
|
|
||||||
|
[ Markus Zolliker ]
|
||||||
|
* add StructParam
|
||||||
|
* add frappy_psi.thermofisher
|
||||||
|
* add frappy_psi.thermofisher to the doc
|
||||||
|
* frappy.io: make error reporting consistent
|
||||||
|
* frappy_psi.sea: avoid multiple connections
|
||||||
|
* frappy_psi.sea: further bug fixes
|
||||||
|
* frappy.client.interactive: bug fixes
|
||||||
|
|
||||||
|
[ Alexander Zaft ]
|
||||||
|
* mlz: Add Zebra Barcode Reader
|
||||||
|
* frappy_mlz: Zebra fixes after basic test
|
||||||
|
* dispatcher: change logging calls to debug
|
||||||
|
* core: do not call register_module on error
|
||||||
|
* add zapf to requirements-dev.txt
|
||||||
|
* frappy_mlz: Add Zapf PLC
|
||||||
|
* Revert "add zapf to requirements-dev.txt"
|
||||||
|
* add zapf to requirements-dev
|
||||||
|
* frappy_mlz: fix one-off error in barcode reader
|
||||||
|
|
||||||
|
[ Markus Zolliker ]
|
||||||
|
* improve error message on client when host/port is bad
|
||||||
|
* frappy/protocol/interface/tcp.py: use SECoP_DEFAULT_PORT
|
||||||
|
* frappy_psi.phytron: stop motor before restart
|
||||||
|
* interactive client: improve keyboard interrupt
|
||||||
|
* fix frappy/playground.py after change 31470
|
||||||
|
|
||||||
|
[ Alexander Zaft ]
|
||||||
|
* frappy_mlz seop: add count to ampl and phase cmds
|
||||||
|
|
||||||
|
[ Markus Zolliker ]
|
||||||
|
* frappy_psi.phytron: further improvements
|
||||||
|
* further fixes after change 31470
|
||||||
|
* fix missing .poll attribute in simulation
|
||||||
|
* psi: improve sea interface
|
||||||
|
* fix frappy_demo.lakeshore
|
||||||
|
* change FloatRange arguments minval/maxval to min/max
|
||||||
|
* improve client shutdown time
|
||||||
|
* introduce FrozenParam
|
||||||
|
* phytron.py: improve status
|
||||||
|
* frappy_psi.sea: small fixes
|
||||||
|
* bug in Attached (fix after change 31470)
|
||||||
|
|
||||||
|
[ Alexander Zaft ]
|
||||||
|
* core: split module code
|
||||||
|
* core: factor out accessibles from init
|
||||||
|
|
||||||
|
[ Markus Zolliker ]
|
||||||
|
* proxy: fix command wrapper
|
||||||
|
|
||||||
|
[ Alexander Zaft ]
|
||||||
|
* server: handle signals during startup
|
||||||
|
* all: remove coding cookies
|
||||||
|
* psi: fix Done import in sea
|
||||||
|
|
||||||
|
[ Markus Zolliker ]
|
||||||
|
* frappy.io: change default to retry_first_idn=True
|
||||||
|
|
||||||
|
[ Alexander Zaft ]
|
||||||
|
* core: move module handling out of dispatcher
|
||||||
|
* mlz/demo: move old examples to Attached
|
||||||
|
|
||||||
|
[ Markus Zolliker ]
|
||||||
|
* frappy.client: fix the case then timestamp is missing
|
||||||
|
* doc: drop latex support, add pdf support
|
||||||
|
* add StringIO.writeline, improve StringIO.multicomm
|
||||||
|
* implement pfeiffer TPG vacuum reading
|
||||||
|
|
||||||
|
[ Alexander Zaft ]
|
||||||
|
* core: allow multiple interfaces
|
||||||
|
* core: formatting and update server docstring
|
||||||
|
* mlz: handle unconfigured abslimits
|
||||||
|
* datatypes: fix optional struct export
|
||||||
|
* core: better command handling
|
||||||
|
|
||||||
|
[ Markus Zolliker ]
|
||||||
|
* frappy_psi.sea: workaround for bug in sea
|
||||||
|
|
||||||
|
[ Alexander Zaft ]
|
||||||
|
* core: better error on export of internal type
|
||||||
|
|
||||||
|
[ Markus Zolliker ]
|
||||||
|
* fix missing import in change message
|
||||||
|
* modify arguments of Dispatcher.announce_update
|
||||||
|
* frappy.secnode: fix strange error message
|
||||||
|
* fix playground after change 32249
|
||||||
|
* remove py35 compatibility code
|
||||||
|
* bug fix in frappy.io.BytesIO.checkHWIdent
|
||||||
|
|
||||||
|
-- Alexander Zaft <jenkins@frm2.tum.de> Wed, 17 Jan 2024 12:35:00 +0100
|
||||||
|
|
||||||
frappy-core (0.17.13) focal; urgency=medium
|
frappy-core (0.17.13) focal; urgency=medium
|
||||||
|
|
||||||
[ Alexander Zaft ]
|
[ Alexander Zaft ]
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
#
|
#
|
||||||
# Frappy documentation build configuration file, created by
|
# Frappy documentation build configuration file, created by
|
||||||
# sphinx-quickstart on Mon Sep 11 10:58:28 2017.
|
# sphinx-quickstart on Mon Sep 11 10:58:28 2017.
|
||||||
@ -43,7 +42,9 @@ extensions = ['sphinx.ext.autodoc',
|
|||||||
'sphinx.ext.intersphinx',
|
'sphinx.ext.intersphinx',
|
||||||
'sphinx.ext.todo',
|
'sphinx.ext.todo',
|
||||||
'sphinx.ext.mathjax',
|
'sphinx.ext.mathjax',
|
||||||
'sphinx.ext.viewcode']
|
'sphinx.ext.viewcode',
|
||||||
|
'rst2pdf.pdfbuilder',
|
||||||
|
]
|
||||||
|
|
||||||
# Add any paths that contain templates here, relative to this directory.
|
# Add any paths that contain templates here, relative to this directory.
|
||||||
templates_path = ['_templates']
|
templates_path = ['_templates']
|
||||||
@ -220,3 +221,80 @@ from frappy.lib.classdoc import class_doc_handler
|
|||||||
|
|
||||||
def setup(app):
|
def setup(app):
|
||||||
app.connect('autodoc-process-docstring', class_doc_handler)
|
app.connect('autodoc-process-docstring', class_doc_handler)
|
||||||
|
|
||||||
|
|
||||||
|
# -- Options for PDF output --------------------------------------------------
|
||||||
|
# Grouping the document tree into PDF files. List of tuples
|
||||||
|
# (source start file, target name, title, author, options).
|
||||||
|
#
|
||||||
|
# If there is more than one author, separate them with \\.
|
||||||
|
# For example: r'Guido van Rossum\\Fred L. Drake, Jr., editor'
|
||||||
|
#
|
||||||
|
# The options element is a dictionary that lets you override
|
||||||
|
# this config per-document. For example:
|
||||||
|
#
|
||||||
|
# ('index', 'MyProject', 'My Project', 'Author Name', {'pdf_compressed': True})
|
||||||
|
#
|
||||||
|
# would mean that specific document would be compressed
|
||||||
|
# regardless of the global 'pdf_compressed' setting.
|
||||||
|
pdf_documents = [
|
||||||
|
('index', project, project, author),
|
||||||
|
]
|
||||||
|
# A comma-separated list of custom stylesheets. Example:
|
||||||
|
pdf_stylesheets = ['sphinx', 'a4']
|
||||||
|
# A list of folders to search for stylesheets. Example:
|
||||||
|
pdf_style_path = ['.', '_styles']
|
||||||
|
# Create a compressed PDF
|
||||||
|
# Use True/False or 1/0
|
||||||
|
# Example: compressed=True
|
||||||
|
# pdf_compressed = False
|
||||||
|
# A colon-separated list of folders to search for fonts. Example:
|
||||||
|
# pdf_font_path = ['/usr/share/fonts', '/usr/share/texmf-dist/fonts/']
|
||||||
|
# Language to be used for hyphenation support
|
||||||
|
# pdf_language = "en_US"
|
||||||
|
# Mode for literal blocks wider than the frame. Can be
|
||||||
|
# overflow, shrink or truncate
|
||||||
|
# pdf_fit_mode = "shrink"
|
||||||
|
# Section level that forces a break page.
|
||||||
|
# For example: 1 means top-level sections start in a new page
|
||||||
|
# 0 means disabled
|
||||||
|
# pdf_break_level = 0
|
||||||
|
# When a section starts in a new page, force it to be 'even', 'odd',
|
||||||
|
# or just use 'any'
|
||||||
|
# pdf_breakside = 'any'
|
||||||
|
# Insert footnotes where they are defined instead of
|
||||||
|
# at the end.
|
||||||
|
# pdf_inline_footnotes = True
|
||||||
|
# verbosity level. 0 1 or 2
|
||||||
|
# pdf_verbosity = 0
|
||||||
|
# If false, no index is generated.
|
||||||
|
# pdf_use_index = True
|
||||||
|
# If false, no modindex is generated.
|
||||||
|
# pdf_use_modindex = True
|
||||||
|
# If false, no coverpage is generated.
|
||||||
|
# pdf_use_coverpage = True
|
||||||
|
# Name of the cover page template to use
|
||||||
|
# pdf_cover_template = 'sphinxcover.tmpl'
|
||||||
|
# Documents to append as an appendix to all manuals.
|
||||||
|
# pdf_appendices = []
|
||||||
|
# Enable experimental feature to split table cells. Use it
|
||||||
|
# if you get "DelayedTable too big" errors
|
||||||
|
# pdf_splittables = False
|
||||||
|
# Set the default DPI for images
|
||||||
|
# pdf_default_dpi = 72
|
||||||
|
# Enable rst2pdf extension modules
|
||||||
|
# pdf_extensions = []
|
||||||
|
# Page template name for "regular" pages
|
||||||
|
# pdf_page_template = 'cutePage'
|
||||||
|
# Show Table Of Contents at the beginning?
|
||||||
|
# pdf_use_toc = True
|
||||||
|
# How many levels deep should the table of contents be?
|
||||||
|
pdf_toc_depth = 9999
|
||||||
|
# Add section number to section references
|
||||||
|
pdf_use_numbered_links = False
|
||||||
|
# Background images fitting mode
|
||||||
|
pdf_fit_background_mode = 'scale'
|
||||||
|
# Repeat table header on tables that cross a page boundary?
|
||||||
|
pdf_repeat_table_rows = True
|
||||||
|
# Enable smart quotes (1, 2 or 3) or disable by setting to 0
|
||||||
|
pdf_smartquotes = 0
|
||||||
|
@ -405,7 +405,7 @@ Appendix 2: Extract from the LakeShore Manual
|
|||||||
Reply <range> *term*
|
Reply <range> *term*
|
||||||
**Operation Complete Query**
|
**Operation Complete Query**
|
||||||
----------------------------------------------
|
----------------------------------------------
|
||||||
Command *OPC?
|
Command \*OPC?
|
||||||
Reply 1
|
Reply 1
|
||||||
Description in Frappy, we append this command to request in order
|
Description in Frappy, we append this command to request in order
|
||||||
to generate a reply
|
to generate a reply
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
# *****************************************************************************
|
# *****************************************************************************
|
||||||
# Copyright (c) 2015-2019 by the authors, see LICENSE
|
# Copyright (c) 2015-2019 by the authors, see LICENSE
|
||||||
#
|
#
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# *****************************************************************************
|
# *****************************************************************************
|
||||||
# Copyright (c) 2015-2016 by the authors, see LICENSE
|
# Copyright (c) 2015-2016 by the authors, see LICENSE
|
||||||
#
|
#
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# *****************************************************************************
|
# *****************************************************************************
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify it under
|
# This program is free software; you can redistribute it and/or modify it under
|
||||||
@ -30,10 +29,10 @@ import time
|
|||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from threading import Event, RLock, current_thread
|
from threading import Event, RLock, current_thread
|
||||||
|
|
||||||
import frappy.errors
|
|
||||||
import frappy.params
|
import frappy.params
|
||||||
|
from frappy.errors import make_secop_error, SECoPError, WrongTypeError
|
||||||
from frappy.datatypes import get_datatype
|
from frappy.datatypes import get_datatype
|
||||||
from frappy.lib import mkthread, formatExtendedStack
|
from frappy.lib import mkthread
|
||||||
from frappy.lib.asynconn import AsynConn, ConnectionClosed
|
from frappy.lib.asynconn import AsynConn, ConnectionClosed
|
||||||
from frappy.protocol.interface import decode_msg, encode_msg_frame
|
from frappy.protocol.interface import decode_msg, encode_msg_frame
|
||||||
from frappy.protocol.messages import COMMANDREQUEST, \
|
from frappy.protocol.messages import COMMANDREQUEST, \
|
||||||
@ -69,6 +68,10 @@ class Logger:
|
|||||||
error = exception = warning = critical = info
|
error = exception = warning = critical = info
|
||||||
|
|
||||||
|
|
||||||
|
class NullLogger(Logger):
|
||||||
|
error = exception = warning = critical = info = Logger.noop
|
||||||
|
|
||||||
|
|
||||||
class CallbackObject:
|
class CallbackObject:
|
||||||
"""abstract definition for a target object for callbacks
|
"""abstract definition for a target object for callbacks
|
||||||
|
|
||||||
@ -84,6 +87,12 @@ class CallbackObject:
|
|||||||
def unhandledMessage(self, action, ident, data):
|
def unhandledMessage(self, action, ident, data):
|
||||||
"""called on an unhandled message"""
|
"""called on an unhandled message"""
|
||||||
|
|
||||||
|
def handleError(self, exc):
|
||||||
|
"""called on errors handling messages
|
||||||
|
|
||||||
|
:param exc: the exception raised (= sys.exception())
|
||||||
|
"""
|
||||||
|
|
||||||
def nodeStateChange(self, online, state):
|
def nodeStateChange(self, online, state):
|
||||||
"""called when the state of the connection changes
|
"""called when the state of the connection changes
|
||||||
|
|
||||||
@ -106,19 +115,13 @@ class CacheItem(tuple):
|
|||||||
inheriting from tuple: compatible with old previous version of cache
|
inheriting from tuple: compatible with old previous version of cache
|
||||||
"""
|
"""
|
||||||
def __new__(cls, value, timestamp=None, readerror=None, datatype=None):
|
def __new__(cls, value, timestamp=None, readerror=None, datatype=None):
|
||||||
if readerror:
|
|
||||||
assert isinstance(readerror, Exception)
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
value = datatype.import_value(value)
|
|
||||||
except (KeyError, ValueError, AttributeError):
|
|
||||||
readerror = ValueError(f'can not import {value!r} as {datatype!r}')
|
|
||||||
value = None
|
|
||||||
obj = tuple.__new__(cls, (value, timestamp, readerror))
|
obj = tuple.__new__(cls, (value, timestamp, readerror))
|
||||||
|
if datatype:
|
||||||
try:
|
try:
|
||||||
|
# override default method
|
||||||
obj.format_value = datatype.format_value
|
obj.format_value = datatype.format_value
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
obj.format_value = lambda value, unit=None: str(value)
|
pass
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -145,6 +148,11 @@ class CacheItem(tuple):
|
|||||||
return repr(self[2])
|
return repr(self[2])
|
||||||
return self.format_value(self[0])
|
return self.format_value(self[0])
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def format_value(value, unit=None):
|
||||||
|
"""typically overridden with datatype.format_value"""
|
||||||
|
return str(value)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
args = (self.value,)
|
args = (self.value,)
|
||||||
if self.timestamp:
|
if self.timestamp:
|
||||||
@ -154,11 +162,22 @@ class CacheItem(tuple):
|
|||||||
return f'CacheItem{repr(args)}'
|
return f'CacheItem{repr(args)}'
|
||||||
|
|
||||||
|
|
||||||
|
class Cache(dict):
|
||||||
|
class Undefined(Exception):
|
||||||
|
def __repr__(self):
|
||||||
|
return '<undefined>'
|
||||||
|
|
||||||
|
undefined = CacheItem(None, None, Undefined())
|
||||||
|
|
||||||
|
def __missing__(self, key):
|
||||||
|
return self.undefined
|
||||||
|
|
||||||
|
|
||||||
class ProxyClient:
|
class ProxyClient:
|
||||||
"""common functionality for proxy clients"""
|
"""common functionality for proxy clients"""
|
||||||
|
|
||||||
CALLBACK_NAMES = {'updateEvent', 'updateItem', 'descriptiveDataChange',
|
CALLBACK_NAMES = {'updateEvent', 'updateItem', 'descriptiveDataChange',
|
||||||
'nodeStateChange', 'unhandledMessage'}
|
'nodeStateChange', 'unhandledMessage', 'handleError'}
|
||||||
online = False # connected or reconnecting since a short time
|
online = False # connected or reconnecting since a short time
|
||||||
state = 'disconnected' # further possible values: 'connecting', 'reconnecting', 'connected'
|
state = 'disconnected' # further possible values: 'connecting', 'reconnecting', 'connected'
|
||||||
log = None
|
log = None
|
||||||
@ -166,7 +185,7 @@ class ProxyClient:
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.callbacks = {cbname: defaultdict(list) for cbname in self.CALLBACK_NAMES}
|
self.callbacks = {cbname: defaultdict(list) for cbname in self.CALLBACK_NAMES}
|
||||||
# caches (module, parameter) = value, timestamp, readerror (internal names!)
|
# caches (module, parameter) = value, timestamp, readerror (internal names!)
|
||||||
self.cache = {}
|
self.cache = Cache() # dict returning Cache.undefined for missing keys
|
||||||
|
|
||||||
def register_callback(self, key, *args, **kwds):
|
def register_callback(self, key, *args, **kwds):
|
||||||
"""register callback functions
|
"""register callback functions
|
||||||
@ -245,10 +264,12 @@ class ProxyClient:
|
|||||||
except UnregisterCallback:
|
except UnregisterCallback:
|
||||||
cblist.remove(cbfunc)
|
cblist.remove(cbfunc)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
# the programmer should catch all errors in callbacks
|
if cbname != 'handleError':
|
||||||
# if not, the log will be flooded with errors
|
try:
|
||||||
if self.log:
|
e.args = [f'error in callback {cbname}{args}: {e}']
|
||||||
self.log.exception('error %r calling %s%r', e, cbfunc.__name__, args)
|
self.callback(None, 'handleError', e)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
return bool(cblist)
|
return bool(cblist)
|
||||||
|
|
||||||
def updateValue(self, module, param, value, timestamp, readerror):
|
def updateValue(self, module, param, value, timestamp, readerror):
|
||||||
@ -269,8 +290,17 @@ class SecopClient(ProxyClient):
|
|||||||
descriptive_data = {}
|
descriptive_data = {}
|
||||||
modules = {}
|
modules = {}
|
||||||
_last_error = None
|
_last_error = None
|
||||||
|
_update_error_count = 0
|
||||||
|
_max_error_count = 10
|
||||||
|
|
||||||
def __init__(self, uri, log=Logger):
|
def __init__(self, uri, log=Logger):
|
||||||
|
"""initialize SecopClient
|
||||||
|
|
||||||
|
:param uri: the uri to connect to
|
||||||
|
:param log: a logger.
|
||||||
|
when not given, the print command is used for messages with at least info level.
|
||||||
|
when None, nothing is logged at all
|
||||||
|
"""
|
||||||
super().__init__()
|
super().__init__()
|
||||||
# maps expected replies to [request, Event, is_error, result] until a response came
|
# maps expected replies to [request, Event, is_error, result] until a response came
|
||||||
# there can only be one entry per thread calling 'request'
|
# there can only be one entry per thread calling 'request'
|
||||||
@ -278,15 +308,21 @@ class SecopClient(ProxyClient):
|
|||||||
self.io = None
|
self.io = None
|
||||||
self.txq = queue.Queue(30) # queue for tx requests
|
self.txq = queue.Queue(30) # queue for tx requests
|
||||||
self.pending = queue.Queue(30) # requests with colliding action + ident
|
self.pending = queue.Queue(30) # requests with colliding action + ident
|
||||||
self.log = log
|
self.log = log or NullLogger
|
||||||
self.uri = uri
|
self.uri = uri
|
||||||
self.nodename = uri
|
self.nodename = uri
|
||||||
self._lock = RLock()
|
self._lock = RLock()
|
||||||
self._shutdown = Event()
|
self._shutdown = Event()
|
||||||
|
self.cleanup = []
|
||||||
|
self.register_callback(None, self.handleError)
|
||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
|
# make sure threads are stopping. this is needed in case
|
||||||
|
# a frappy client object is lost without calling .disconnect()
|
||||||
try:
|
try:
|
||||||
self.disconnect()
|
# avoid callbacks when deleting. may cause deadlocks in NICOS
|
||||||
|
self.callbacks.clear()
|
||||||
|
self.disconnect(True)
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -298,6 +334,11 @@ class SecopClient(ProxyClient):
|
|||||||
with self._lock:
|
with self._lock:
|
||||||
if self.io:
|
if self.io:
|
||||||
return
|
return
|
||||||
|
self._shutdown.clear()
|
||||||
|
self.txq = queue.Queue(30)
|
||||||
|
self.pending = queue.Queue(30)
|
||||||
|
self.active_requests.clear()
|
||||||
|
self.cleanup.clear()
|
||||||
if self.online:
|
if self.online:
|
||||||
self._set_state(True, 'reconnecting')
|
self._set_state(True, 'reconnecting')
|
||||||
else:
|
else:
|
||||||
@ -329,9 +370,9 @@ class SecopClient(ProxyClient):
|
|||||||
# pylint: disable=unsubscriptable-object
|
# pylint: disable=unsubscriptable-object
|
||||||
self._init_descriptive_data(self.request(DESCRIPTIONREQUEST)[2])
|
self._init_descriptive_data(self.request(DESCRIPTIONREQUEST)[2])
|
||||||
self.nodename = self.properties.get('equipment_id', self.uri)
|
self.nodename = self.properties.get('equipment_id', self.uri)
|
||||||
|
self._set_state(True, 'connected')
|
||||||
if self.activate:
|
if self.activate:
|
||||||
self.request(ENABLEEVENTSREQUEST)
|
self.request(ENABLEEVENTSREQUEST)
|
||||||
self._set_state(True, 'connected')
|
|
||||||
break
|
break
|
||||||
except Exception:
|
except Exception:
|
||||||
# print(formatExtendedTraceback())
|
# print(formatExtendedTraceback())
|
||||||
@ -367,8 +408,15 @@ class SecopClient(ProxyClient):
|
|||||||
|
|
||||||
def __rxthread(self):
|
def __rxthread(self):
|
||||||
noactivity = 0
|
noactivity = 0
|
||||||
|
shutdown = False
|
||||||
try:
|
try:
|
||||||
while self._running:
|
while self._running:
|
||||||
|
while self.cleanup:
|
||||||
|
entry = self.cleanup.pop()
|
||||||
|
for key, prev in self.active_requests.items():
|
||||||
|
if prev is entry:
|
||||||
|
self.active_requests.pop(key)
|
||||||
|
break
|
||||||
# may raise ConnectionClosed
|
# may raise ConnectionClosed
|
||||||
reply = self.io.readline()
|
reply = self.io.readline()
|
||||||
if reply is None:
|
if reply is None:
|
||||||
@ -379,6 +427,7 @@ class SecopClient(ProxyClient):
|
|||||||
continue
|
continue
|
||||||
self.log.debug('RX: %r', reply)
|
self.log.debug('RX: %r', reply)
|
||||||
noactivity = 0
|
noactivity = 0
|
||||||
|
try:
|
||||||
action, ident, data = decode_msg(reply)
|
action, ident, data = decode_msg(reply)
|
||||||
if ident == '.':
|
if ident == '.':
|
||||||
ident = None
|
ident = None
|
||||||
@ -394,7 +443,7 @@ class SecopClient(ProxyClient):
|
|||||||
now = time.time()
|
now = time.time()
|
||||||
if action.startswith(ERRORPREFIX):
|
if action.startswith(ERRORPREFIX):
|
||||||
timestamp = data[2].get('t', now)
|
timestamp = data[2].get('t', now)
|
||||||
readerror = frappy.errors.make_secop_error(*data[0:2])
|
readerror = make_secop_error(*data[0:2])
|
||||||
value = None
|
value = None
|
||||||
else:
|
else:
|
||||||
timestamp = data[1].get('t', now)
|
timestamp = data[1].get('t', now)
|
||||||
@ -402,12 +451,13 @@ class SecopClient(ProxyClient):
|
|||||||
readerror = None
|
readerror = None
|
||||||
module, param = module_param
|
module, param = module_param
|
||||||
timestamp = min(now, timestamp) # no timestamps in the future!
|
timestamp = min(now, timestamp) # no timestamps in the future!
|
||||||
try:
|
|
||||||
self.updateValue(module, param, value, timestamp, readerror)
|
self.updateValue(module, param, value, timestamp, readerror)
|
||||||
except KeyError:
|
|
||||||
pass # ignore updates of unknown parameters
|
|
||||||
if action in (EVENTREPLY, ERRORPREFIX + EVENTREPLY):
|
if action in (EVENTREPLY, ERRORPREFIX + EVENTREPLY):
|
||||||
continue
|
continue
|
||||||
|
except Exception as e:
|
||||||
|
e.args = (f'error handling SECoP message {reply!r}: {e}',)
|
||||||
|
self.callback(None, 'handleError', e)
|
||||||
|
continue
|
||||||
try:
|
try:
|
||||||
key = action, ident
|
key = action, ident
|
||||||
entry = self.active_requests.pop(key)
|
entry = self.active_requests.pop(key)
|
||||||
@ -434,9 +484,11 @@ class SecopClient(ProxyClient):
|
|||||||
except ConnectionClosed:
|
except ConnectionClosed:
|
||||||
pass
|
pass
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.log.error('rxthread ended with %r', e)
|
shutdown = True
|
||||||
|
self.callback(None, 'handleError', e)
|
||||||
|
finally:
|
||||||
self._rxthread = None
|
self._rxthread = None
|
||||||
self.disconnect(False)
|
self.disconnect(shutdown)
|
||||||
if self._shutdown.is_set():
|
if self._shutdown.is_set():
|
||||||
return
|
return
|
||||||
if self.activate:
|
if self.activate:
|
||||||
@ -572,6 +624,13 @@ class SecopClient(ProxyClient):
|
|||||||
if not self.callback(None, 'unhandledMessage', action, ident, data):
|
if not self.callback(None, 'unhandledMessage', action, ident, data):
|
||||||
self.log.warning('unhandled message: %s %s %r', action, ident, data)
|
self.log.warning('unhandled message: %s %s %r', action, ident, data)
|
||||||
|
|
||||||
|
def handleError(self, exc):
|
||||||
|
if self._update_error_count < self._max_error_count:
|
||||||
|
self.log.exception('%s', exc)
|
||||||
|
self._update_error_count += 1
|
||||||
|
if self._update_error_count == self._max_error_count:
|
||||||
|
self.log.error('disabled reporting of further update errors')
|
||||||
|
|
||||||
def _set_state(self, online, state=None):
|
def _set_state(self, online, state=None):
|
||||||
# remark: reconnecting is treated as online
|
# remark: reconnecting is treated as online
|
||||||
self.online = online
|
self.online = online
|
||||||
@ -592,12 +651,16 @@ class SecopClient(ProxyClient):
|
|||||||
def get_reply(self, entry):
|
def get_reply(self, entry):
|
||||||
"""wait for reply and return it"""
|
"""wait for reply and return it"""
|
||||||
if not entry[1].wait(10): # event
|
if not entry[1].wait(10): # event
|
||||||
|
self.cleanup.append(entry)
|
||||||
raise TimeoutError('no response within 10s')
|
raise TimeoutError('no response within 10s')
|
||||||
if not entry[2]: # reply
|
if not entry[2]: # reply
|
||||||
|
if self._shutdown.is_set():
|
||||||
|
raise ConnectionError('connection shut down')
|
||||||
|
# no cleanup needed as self.active_requests will be cleared on connect
|
||||||
raise ConnectionError('connection closed before reply')
|
raise ConnectionError('connection closed before reply')
|
||||||
action, _, data = entry[2] # pylint: disable=unpacking-non-sequence
|
action, _, data = entry[2] # pylint: disable=unpacking-non-sequence
|
||||||
if action.startswith(ERRORPREFIX):
|
if action.startswith(ERRORPREFIX):
|
||||||
raise frappy.errors.make_secop_error(*data[0:2])
|
raise make_secop_error(*data[0:2])
|
||||||
return entry[2] # reply
|
return entry[2] # reply
|
||||||
|
|
||||||
def request(self, action, ident=None, data=None):
|
def request(self, action, ident=None, data=None):
|
||||||
@ -612,9 +675,14 @@ class SecopClient(ProxyClient):
|
|||||||
"""forced read over connection"""
|
"""forced read over connection"""
|
||||||
try:
|
try:
|
||||||
self.request(READREQUEST, self.identifier[module, parameter])
|
self.request(READREQUEST, self.identifier[module, parameter])
|
||||||
except frappy.errors.SECoPError:
|
except SECoPError as e:
|
||||||
# error reply message is already stored as readerror in cache
|
result = self.cache[module, parameter]
|
||||||
pass
|
if e == result.readerror:
|
||||||
|
# the update was already done in the rx thread
|
||||||
|
return result
|
||||||
|
# e was not originating from a secop error message e.g. a connection problem
|
||||||
|
# -> we have to do the error update
|
||||||
|
self.updateValue(module, parameter, None, time.time(), e)
|
||||||
return self.cache.get((module, parameter), None)
|
return self.cache.get((module, parameter), None)
|
||||||
|
|
||||||
def getParameter(self, module, parameter, trycache=False):
|
def getParameter(self, module, parameter, trycache=False):
|
||||||
@ -640,7 +708,7 @@ class SecopClient(ProxyClient):
|
|||||||
argument = datatype.export_value(argument)
|
argument = datatype.export_value(argument)
|
||||||
else:
|
else:
|
||||||
if argument is not None:
|
if argument is not None:
|
||||||
raise frappy.errors.WrongTypeError('command has no argument')
|
raise WrongTypeError('command has no argument')
|
||||||
# pylint: disable=unsubscriptable-object
|
# pylint: disable=unsubscriptable-object
|
||||||
data, qualifiers = self.request(COMMANDREQUEST, self.identifier[module, command], argument)[2]
|
data, qualifiers = self.request(COMMANDREQUEST, self.identifier[module, command], argument)[2]
|
||||||
datatype = self.modules[module]['commands'][command]['datatype'].result
|
datatype = self.modules[module]['commands'][command]['datatype'].result
|
||||||
@ -649,8 +717,12 @@ class SecopClient(ProxyClient):
|
|||||||
return data, qualifiers
|
return data, qualifiers
|
||||||
|
|
||||||
def updateValue(self, module, param, value, timestamp, readerror):
|
def updateValue(self, module, param, value, timestamp, readerror):
|
||||||
entry = CacheItem(value, timestamp, readerror,
|
datatype = self.modules[module]['parameters'][param]['datatype']
|
||||||
self.modules[module]['parameters'][param]['datatype'])
|
if readerror:
|
||||||
|
assert isinstance(readerror, Exception)
|
||||||
|
else:
|
||||||
|
value = datatype.import_value(value)
|
||||||
|
entry = CacheItem(value, timestamp, readerror, datatype)
|
||||||
self.cache[(module, param)] = entry
|
self.cache[(module, param)] = entry
|
||||||
self.callback(None, 'updateItem', module, param, entry)
|
self.callback(None, 'updateItem', module, param, entry)
|
||||||
self.callback(module, 'updateItem', module, param, entry)
|
self.callback(module, 'updateItem', module, param, entry)
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# *****************************************************************************
|
# *****************************************************************************
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify it under
|
# This program is free software; you can redistribute it and/or modify it under
|
||||||
@ -29,8 +28,9 @@ import signal
|
|||||||
import os
|
import os
|
||||||
import traceback
|
import traceback
|
||||||
import threading
|
import threading
|
||||||
|
import logging
|
||||||
from os.path import expanduser
|
from os.path import expanduser
|
||||||
from frappy.client import SecopClient
|
from frappy.client import SecopClient, UnregisterCallback
|
||||||
from frappy.errors import SECoPError
|
from frappy.errors import SECoPError
|
||||||
from frappy.datatypes import get_datatype, StatusType
|
from frappy.datatypes import get_datatype, StatusType
|
||||||
try:
|
try:
|
||||||
@ -56,40 +56,45 @@ watch(io, T=True) # watch io and all parameters of T
|
|||||||
{tail}"""
|
{tail}"""
|
||||||
|
|
||||||
|
|
||||||
LOG_LEVELS = {'debug', 'comlog', 'info', 'warning', 'error', 'off'}
|
LOG_LEVELS = {
|
||||||
|
'debug': logging.DEBUG,
|
||||||
|
'comlog': logging.DEBUG+1,
|
||||||
|
'info': logging.INFO,
|
||||||
|
'warning': logging.WARN,
|
||||||
|
'error': logging.ERROR,
|
||||||
|
'off': logging.ERROR+1}
|
||||||
CLR = '\r\x1b[K' # code to move to the left and clear current line
|
CLR = '\r\x1b[K' # code to move to the left and clear current line
|
||||||
|
|
||||||
|
|
||||||
class Logger:
|
class Handler(logging.StreamHandler):
|
||||||
show_time = False
|
def emit(self, record):
|
||||||
sigwinch = False
|
super().emit(record)
|
||||||
|
if clientenv.sigwinch:
|
||||||
def __init__(self, loglevel='info'):
|
|
||||||
func = self.noop
|
|
||||||
for lev in 'debug', 'info', 'warning', 'error', 'exception':
|
|
||||||
if lev == loglevel:
|
|
||||||
func = self.emit
|
|
||||||
setattr(self, lev, func)
|
|
||||||
self._minute = 0
|
|
||||||
|
|
||||||
def emit(self, fmt, *args, **kwds):
|
|
||||||
if self.show_time:
|
|
||||||
now = time.time()
|
|
||||||
tm = time.localtime(now)
|
|
||||||
if tm.tm_min != self._minute:
|
|
||||||
self._minute = tm.tm_min
|
|
||||||
print(CLR + time.strftime('--- %H:%M:%S ---', tm))
|
|
||||||
sec = f'{now % 60.0:6.3f}'.replace(' ', '0')
|
|
||||||
print(CLR + sec, str(fmt) % args)
|
|
||||||
else:
|
|
||||||
print(CLR + (str(fmt) % args))
|
|
||||||
if self.sigwinch:
|
|
||||||
# SIGWINCH: 'window size has changed' -> triggers a refresh of the input line
|
# SIGWINCH: 'window size has changed' -> triggers a refresh of the input line
|
||||||
os.kill(os.getpid(), signal.SIGWINCH)
|
os.kill(os.getpid(), signal.SIGWINCH)
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def noop(fmt, *args, **kwds):
|
class Logger(logging.Logger):
|
||||||
pass
|
show_time = False
|
||||||
|
_minute = None
|
||||||
|
|
||||||
|
def __init__(self, name, loglevel='info'):
|
||||||
|
super().__init__(name, LOG_LEVELS.get(loglevel, logging.INFO))
|
||||||
|
handler = Handler()
|
||||||
|
handler.formatter = logging.Formatter('%(asctime)s%(message)s')
|
||||||
|
handler.formatter.formatTime = self.format_time
|
||||||
|
self.addHandler(handler)
|
||||||
|
|
||||||
|
def format_time(self, record, datefmt=None):
|
||||||
|
if self.show_time:
|
||||||
|
now = record.created
|
||||||
|
tm = time.localtime(now)
|
||||||
|
sec = f'{now % 60.0:6.3f}'.replace(' ', '0')
|
||||||
|
if tm.tm_min == self._minute:
|
||||||
|
return f'{CLR}{sec} '
|
||||||
|
self._minute = tm.tm_min
|
||||||
|
return f"{CLR}{time.strftime('--- %H:%M:%S ---', tm)}\n{sec} "
|
||||||
|
return ''
|
||||||
|
|
||||||
|
|
||||||
class PrettyFloat(float):
|
class PrettyFloat(float):
|
||||||
@ -239,6 +244,9 @@ class Module:
|
|||||||
return self.value
|
return self.value
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
|
return f'<module {self._name}>'
|
||||||
|
|
||||||
|
def showAll(self):
|
||||||
wid = max((len(k) for k in self._parameters), default=0)
|
wid = max((len(k) for k in self._parameters), default=0)
|
||||||
return '%s\n%s%s' % (
|
return '%s\n%s%s' % (
|
||||||
self._title,
|
self._title,
|
||||||
@ -272,10 +280,7 @@ class Param:
|
|||||||
return value
|
return value
|
||||||
|
|
||||||
def formatted(self, obj):
|
def formatted(self, obj):
|
||||||
value, _, error = obj._secnode.cache[obj._name, self.name]
|
return obj._secnode.cache[obj._name, self.name].formatted()
|
||||||
if error:
|
|
||||||
return repr(error)
|
|
||||||
return self.format(value)
|
|
||||||
|
|
||||||
def __set__(self, obj, value):
|
def __set__(self, obj, value):
|
||||||
try:
|
try:
|
||||||
@ -287,9 +292,6 @@ class Param:
|
|||||||
clientenv.raise_with_short_traceback(e)
|
clientenv.raise_with_short_traceback(e)
|
||||||
obj._secnode.log.error(repr(e))
|
obj._secnode.log.error(repr(e))
|
||||||
|
|
||||||
def format(self, value):
|
|
||||||
return self.datatype.format_value(value)
|
|
||||||
|
|
||||||
|
|
||||||
class Command:
|
class Command:
|
||||||
def __init__(self, name, modname, secnode):
|
def __init__(self, name, modname, secnode):
|
||||||
@ -338,9 +340,28 @@ def watch(*args, **kwds):
|
|||||||
mobj._set_watching(arg)
|
mobj._set_watching(arg)
|
||||||
print('---')
|
print('---')
|
||||||
try:
|
try:
|
||||||
|
nodes = set()
|
||||||
for mobj in modules:
|
for mobj in modules:
|
||||||
|
nodes.add(mobj._secnode)
|
||||||
mobj._start_watching()
|
mobj._start_watching()
|
||||||
time.sleep(3600)
|
|
||||||
|
close_event = threading.Event()
|
||||||
|
|
||||||
|
def close_node(online, state):
|
||||||
|
if online and state != 'shutdown':
|
||||||
|
return
|
||||||
|
close_event.set()
|
||||||
|
return UnregisterCallback
|
||||||
|
|
||||||
|
def handle_error(*_):
|
||||||
|
close_event.set()
|
||||||
|
return UnregisterCallback
|
||||||
|
|
||||||
|
for node in nodes:
|
||||||
|
node.register_callback(None, nodeStateChange=close_node, handleError=handle_error)
|
||||||
|
|
||||||
|
close_event.wait()
|
||||||
|
|
||||||
except KeyboardInterrupt as e:
|
except KeyboardInterrupt as e:
|
||||||
clientenv.raise_with_short_traceback(e)
|
clientenv.raise_with_short_traceback(e)
|
||||||
finally:
|
finally:
|
||||||
@ -360,7 +381,7 @@ class Client(SecopClient):
|
|||||||
clientenv.init(sys.modules['__main__'].__dict__)
|
clientenv.init(sys.modules['__main__'].__dict__)
|
||||||
# remove previous client:
|
# remove previous client:
|
||||||
prev = self.secnodes.pop(uri, None)
|
prev = self.secnodes.pop(uri, None)
|
||||||
log = Logger(loglevel)
|
log = Logger(name, loglevel)
|
||||||
removed_modules = []
|
removed_modules = []
|
||||||
if prev:
|
if prev:
|
||||||
log.info('remove previous client to %s', uri)
|
log.info('remove previous client to %s', uri)
|
||||||
@ -434,8 +455,10 @@ def run(filepath):
|
|||||||
class ClientEnvironment:
|
class ClientEnvironment:
|
||||||
namespace = None
|
namespace = None
|
||||||
last_frames = 0
|
last_frames = 0
|
||||||
|
sigwinch = False
|
||||||
|
|
||||||
def init(self, namespace=None):
|
def init(self, namespace=None):
|
||||||
|
self.nodes = []
|
||||||
self.namespace = namespace or {}
|
self.namespace = namespace or {}
|
||||||
self.namespace.update(run=run, watch=watch, Client=Client)
|
self.namespace.update(run=run, watch=watch, Client=Client)
|
||||||
|
|
||||||
@ -445,7 +468,7 @@ class ClientEnvironment:
|
|||||||
raise exc
|
raise exc
|
||||||
|
|
||||||
def short_traceback(self):
|
def short_traceback(self):
|
||||||
"""cleanup tracback from irrelevant lines"""
|
"""cleanup traceback from irrelevant lines"""
|
||||||
lines = traceback.format_exception(*sys.exc_info())
|
lines = traceback.format_exception(*sys.exc_info())
|
||||||
# line 0: Traceback header
|
# line 0: Traceback header
|
||||||
# skip line 1+2 (contains unspecific console line and exec code)
|
# skip line 1+2 (contains unspecific console line and exec code)
|
||||||
@ -483,11 +506,15 @@ class Console(code.InteractiveConsole):
|
|||||||
readline.write_history_file(history)
|
readline.write_history_file(history)
|
||||||
|
|
||||||
def raw_input(self, prompt=""):
|
def raw_input(self, prompt=""):
|
||||||
Logger.sigwinch = bool(readline) # activate refresh signal
|
clientenv.sigwinch = bool(readline) # activate refresh signal
|
||||||
line = input(prompt)
|
line = input(prompt)
|
||||||
Logger.sigwinch = False
|
clientenv.sigwinch = False
|
||||||
if line.startswith('/'):
|
if line.startswith('/'):
|
||||||
line = f"run('{line[1:].strip()}')"
|
line = f"run('{line[1:].strip()}')"
|
||||||
|
module = clientenv.namespace.get(line.strip())
|
||||||
|
if isinstance(module, Module):
|
||||||
|
print(module.showAll())
|
||||||
|
line = ''
|
||||||
return line
|
return line
|
||||||
|
|
||||||
def showtraceback(self):
|
def showtraceback(self):
|
||||||
@ -500,7 +527,8 @@ def init(*nodes):
|
|||||||
for idx, node in enumerate(nodes):
|
for idx, node in enumerate(nodes):
|
||||||
client_name = '_c%d' % idx
|
client_name = '_c%d' % idx
|
||||||
try:
|
try:
|
||||||
clientenv.namespace[client_name] = Client(node, name=client_name)
|
node = clientenv.namespace[client_name] = Client(node, name=client_name)
|
||||||
|
clientenv.nodes.append(node)
|
||||||
success = True
|
success = True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(repr(e))
|
print(repr(e))
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# *****************************************************************************
|
# *****************************************************************************
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify it under
|
# This program is free software; you can redistribute it and/or modify it under
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# *****************************************************************************
|
# *****************************************************************************
|
||||||
# Copyright (c) 2015-2016 by the authors, see LICENSE
|
# Copyright (c) 2015-2016 by the authors, see LICENSE
|
||||||
#
|
#
|
||||||
@ -29,8 +28,9 @@
|
|||||||
from frappy.datatypes import ArrayOf, BLOBType, BoolType, EnumType, \
|
from frappy.datatypes import ArrayOf, BLOBType, BoolType, EnumType, \
|
||||||
FloatRange, IntRange, ScaledInteger, StringType, StructOf, TupleOf, StatusType
|
FloatRange, IntRange, ScaledInteger, StringType, StructOf, TupleOf, StatusType
|
||||||
from frappy.lib.enum import Enum
|
from frappy.lib.enum import Enum
|
||||||
|
from frappy.modulebase import Done, Module, Feature
|
||||||
from frappy.modules import Attached, Communicator, \
|
from frappy.modules import Attached, Communicator, \
|
||||||
Done, Drivable, Feature, Module, Readable, Writable, HasAccessibles
|
Drivable, Readable, Writable
|
||||||
from frappy.params import Command, Parameter, Limit
|
from frappy.params import Command, Parameter, Limit
|
||||||
from frappy.properties import Property
|
from frappy.properties import Property
|
||||||
from frappy.proxy import Proxy, SecNode, proxy_class
|
from frappy.proxy import Proxy, SecNode, proxy_class
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# *****************************************************************************
|
# *****************************************************************************
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify it under
|
# This program is free software; you can redistribute it and/or modify it under
|
||||||
@ -90,7 +89,11 @@ class DataType(HasProperties):
|
|||||||
|
|
||||||
def export_datatype(self):
|
def export_datatype(self):
|
||||||
"""return a python object which after jsonifying identifies this datatype"""
|
"""return a python object which after jsonifying identifies this datatype"""
|
||||||
raise NotImplementedError
|
raise ProgrammingError(
|
||||||
|
f"{type(self).__name__} is not able to be exported to SECoP. "
|
||||||
|
f"It is intended for internal use only."
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def export_value(self, value):
|
def export_value(self, value):
|
||||||
"""if needed, reformat value for transport"""
|
"""if needed, reformat value for transport"""
|
||||||
@ -102,7 +105,7 @@ class DataType(HasProperties):
|
|||||||
note: for importing from gui/configfile/commandline use :meth:`from_string`
|
note: for importing from gui/configfile/commandline use :meth:`from_string`
|
||||||
instead.
|
instead.
|
||||||
"""
|
"""
|
||||||
return value
|
return self(value)
|
||||||
|
|
||||||
def format_value(self, value, unit=None):
|
def format_value(self, value, unit=None):
|
||||||
"""format a value of this type into a str string
|
"""format a value of this type into a str string
|
||||||
@ -256,10 +259,6 @@ class FloatRange(HasUnit, DataType):
|
|||||||
"""returns a python object fit for serialisation"""
|
"""returns a python object fit for serialisation"""
|
||||||
return float(value)
|
return float(value)
|
||||||
|
|
||||||
def import_value(self, value):
|
|
||||||
"""returns a python object from serialisation"""
|
|
||||||
return float(value)
|
|
||||||
|
|
||||||
def from_string(self, text):
|
def from_string(self, text):
|
||||||
value = float(text)
|
value = float(text)
|
||||||
return self(value)
|
return self(value)
|
||||||
@ -315,7 +314,7 @@ class IntRange(DataType):
|
|||||||
except Exception:
|
except Exception:
|
||||||
raise WrongTypeError(f'can not convert {shortrepr(value)} to an int') from None
|
raise WrongTypeError(f'can not convert {shortrepr(value)} to an int') from None
|
||||||
if round(fvalue) != fvalue:
|
if round(fvalue) != fvalue:
|
||||||
raise WrongTypeError('%r should be an int')
|
raise WrongTypeError(f'{value} should be an int')
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def validate(self, value, previous=None):
|
def validate(self, value, previous=None):
|
||||||
@ -338,10 +337,6 @@ class IntRange(DataType):
|
|||||||
"""returns a python object fit for serialisation"""
|
"""returns a python object fit for serialisation"""
|
||||||
return int(value)
|
return int(value)
|
||||||
|
|
||||||
def import_value(self, value):
|
|
||||||
"""returns a python object from serialisation"""
|
|
||||||
return int(value)
|
|
||||||
|
|
||||||
def from_string(self, text):
|
def from_string(self, text):
|
||||||
value = int(text)
|
value = int(text)
|
||||||
return self(value)
|
return self(value)
|
||||||
@ -458,7 +453,10 @@ class ScaledInteger(HasUnit, DataType):
|
|||||||
|
|
||||||
def import_value(self, value):
|
def import_value(self, value):
|
||||||
"""returns a python object from serialisation"""
|
"""returns a python object from serialisation"""
|
||||||
|
try:
|
||||||
return self.scale * int(value)
|
return self.scale * int(value)
|
||||||
|
except Exception:
|
||||||
|
raise WrongTypeError(f'can not import {shortrepr(value)} to scaled') from None
|
||||||
|
|
||||||
def from_string(self, text):
|
def from_string(self, text):
|
||||||
value = float(text)
|
value = float(text)
|
||||||
@ -510,10 +508,6 @@ class EnumType(DataType):
|
|||||||
"""returns a python object fit for serialisation"""
|
"""returns a python object fit for serialisation"""
|
||||||
return int(self(value))
|
return int(self(value))
|
||||||
|
|
||||||
def import_value(self, value):
|
|
||||||
"""returns a python object from serialisation"""
|
|
||||||
return self(value)
|
|
||||||
|
|
||||||
def __call__(self, value):
|
def __call__(self, value):
|
||||||
"""accepts integers and strings, converts to EnumMember (may be used like an int)"""
|
"""accepts integers and strings, converts to EnumMember (may be used like an int)"""
|
||||||
try:
|
try:
|
||||||
@ -585,7 +579,10 @@ class BLOBType(DataType):
|
|||||||
|
|
||||||
def import_value(self, value):
|
def import_value(self, value):
|
||||||
"""returns a python object from serialisation"""
|
"""returns a python object from serialisation"""
|
||||||
|
try:
|
||||||
return b64decode(value)
|
return b64decode(value)
|
||||||
|
except Exception:
|
||||||
|
raise WrongTypeError(f'can not b64decode {shortrepr(value)}') from None
|
||||||
|
|
||||||
def from_string(self, text):
|
def from_string(self, text):
|
||||||
value = text
|
value = text
|
||||||
@ -656,10 +653,6 @@ class StringType(DataType):
|
|||||||
"""returns a python object fit for serialisation"""
|
"""returns a python object fit for serialisation"""
|
||||||
return f'{value}'
|
return f'{value}'
|
||||||
|
|
||||||
def import_value(self, value):
|
|
||||||
"""returns a python object from serialisation"""
|
|
||||||
return str(value)
|
|
||||||
|
|
||||||
def from_string(self, text):
|
def from_string(self, text):
|
||||||
value = str(text)
|
value = str(text)
|
||||||
return self(value)
|
return self(value)
|
||||||
@ -720,10 +713,6 @@ class BoolType(DataType):
|
|||||||
"""returns a python object fit for serialisation"""
|
"""returns a python object fit for serialisation"""
|
||||||
return self(value)
|
return self(value)
|
||||||
|
|
||||||
def import_value(self, value):
|
|
||||||
"""returns a python object from serialisation"""
|
|
||||||
return self(value)
|
|
||||||
|
|
||||||
def from_string(self, text):
|
def from_string(self, text):
|
||||||
value = text
|
value = text
|
||||||
return self(value)
|
return self(value)
|
||||||
@ -993,7 +982,7 @@ class StructOf(DataType):
|
|||||||
return res
|
return res
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
opt = f', optional={self.optional!r}' if set(self.optional) == set(self.members) else ''
|
opt = f', optional={self.optional!r}' if set(self.optional) != set(self.members) else ''
|
||||||
return 'StructOf(%s%s)' % (', '.join(
|
return 'StructOf(%s%s)' % (', '.join(
|
||||||
['%s=%s' % (n, repr(st)) for n, st in list(self.members.items())]), opt)
|
['%s=%s' % (n, repr(st)) for n, st in list(self.members.items())]), opt)
|
||||||
|
|
||||||
@ -1232,6 +1221,7 @@ class OrType(DataType):
|
|||||||
self.types = types
|
self.types = types
|
||||||
self.default = self.types[0].default
|
self.default = self.types[0].default
|
||||||
|
|
||||||
|
|
||||||
def __call__(self, value):
|
def __call__(self, value):
|
||||||
"""accepts any of the given types, takes the first valid"""
|
"""accepts any of the given types, takes the first valid"""
|
||||||
for t in self.types:
|
for t in self.types:
|
||||||
@ -1254,16 +1244,20 @@ UInt64 = IntRange(0, (1 << 64) - 1)
|
|||||||
|
|
||||||
# Goodie: Convenience Datatypes for Programming
|
# Goodie: Convenience Datatypes for Programming
|
||||||
class LimitsType(TupleOf):
|
class LimitsType(TupleOf):
|
||||||
def __init__(self, members):
|
def __init__(self, member):
|
||||||
super().__init__(members, members)
|
super().__init__(member, member)
|
||||||
|
|
||||||
def __call__(self, value):
|
def validate(self, value, previous=None):
|
||||||
"""accepts an ordered tuple of numeric member types"""
|
"""accepts an ordered tuple of numeric member types"""
|
||||||
limits = TupleOf.validate(self, value)
|
limits = TupleOf.validate(self, value, previous)
|
||||||
if limits[1] < limits[0]:
|
if limits[1] < limits[0]:
|
||||||
raise RangeError(f'Maximum Value {limits[1]} must be greater than minimum value {limits[0]}!')
|
raise RangeError(f'maximum value {limits[1]} must be greater than '
|
||||||
|
f'minimum value {limits[0]}')
|
||||||
return limits
|
return limits
|
||||||
|
|
||||||
|
def copy(self):
|
||||||
|
return LimitsType(TupleOf.copy(self).members[0])
|
||||||
|
|
||||||
|
|
||||||
class StatusType(TupleOf):
|
class StatusType(TupleOf):
|
||||||
"""convenience type for status
|
"""convenience type for status
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# *****************************************************************************
|
# *****************************************************************************
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify it under
|
# This program is free software; you can redistribute it and/or modify it under
|
||||||
@ -219,7 +218,7 @@ class IsErrorError(SECoPError):
|
|||||||
|
|
||||||
class DisabledError(SECoPError):
|
class DisabledError(SECoPError):
|
||||||
"""The requested action can not be performed while the module is disabled"""
|
"""The requested action can not be performed while the module is disabled"""
|
||||||
name = 'disabled'
|
name = 'Disabled'
|
||||||
|
|
||||||
|
|
||||||
class ImpossibleError(SECoPError):
|
class ImpossibleError(SECoPError):
|
||||||
@ -233,7 +232,7 @@ class ReadFailedError(SECoPError):
|
|||||||
|
|
||||||
|
|
||||||
class OutOfRangeError(SECoPError):
|
class OutOfRangeError(SECoPError):
|
||||||
"""The requested parameter can not be read just now"""
|
"""The value read from the hardware is out of sensor or calibration range"""
|
||||||
name = 'OutOfRange'
|
name = 'OutOfRange'
|
||||||
|
|
||||||
|
|
||||||
|
304
frappy/extparams.py
Normal file
304
frappy/extparams.py
Normal file
@ -0,0 +1,304 @@
|
|||||||
|
# *****************************************************************************
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify it under
|
||||||
|
# the terms of the GNU General Public License as published by the Free Software
|
||||||
|
# Foundation; either version 2 of the License, or (at your option) any later
|
||||||
|
# version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||||
|
# details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License along with
|
||||||
|
# this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
#
|
||||||
|
# Module authors:
|
||||||
|
# Markus Zolliker <markus.zolliker@psi.ch>
|
||||||
|
#
|
||||||
|
# *****************************************************************************
|
||||||
|
"""extended parameters
|
||||||
|
|
||||||
|
special parameter classes with some automatic functionality
|
||||||
|
"""
|
||||||
|
|
||||||
|
import re
|
||||||
|
from frappy.core import Parameter, Property
|
||||||
|
from frappy.datatypes import BoolType, DataType, DataTypeType, EnumType, \
|
||||||
|
FloatRange, StringType, StructOf, ValueType
|
||||||
|
from frappy.errors import ProgrammingError
|
||||||
|
|
||||||
|
|
||||||
|
class StructParam(Parameter):
|
||||||
|
"""convenience class to create a struct Parameter together with individual params
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
|
||||||
|
class Controller(Drivable):
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
ctrlpars = StructParam('ctrlpars struct', [
|
||||||
|
('pid_p', 'p', Parameter('control parameter p', FloatRange())),
|
||||||
|
('pid_i', 'i', Parameter('control parameter i', FloatRange())),
|
||||||
|
('pid_d', 'd', Parameter('control parameter d', FloatRange())),
|
||||||
|
], readonly=False)
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
then implement either read_ctrlpars and write_ctrlpars or
|
||||||
|
read_pid_p, read_pid_i, read_pid_d, write_pid_p, write_pid_i and write_pid_d
|
||||||
|
|
||||||
|
the methods not implemented will be created automatically
|
||||||
|
"""
|
||||||
|
|
||||||
|
# use properties, as simple attributes are not considered on copy()
|
||||||
|
paramdict = Property('dict <parametername> of Parameter(...)', ValueType())
|
||||||
|
hasStructRW = Property('has a read_<struct param> or write_<struct param> method',
|
||||||
|
BoolType(), default=False)
|
||||||
|
|
||||||
|
insideRW = 0 # counter for avoiding multiple superfluous updates
|
||||||
|
|
||||||
|
def __init__(self, description=None, paramdict=None, prefix_or_map='', *, datatype=None, readonly=False, **kwds):
|
||||||
|
"""create a struct parameter together with individual parameters
|
||||||
|
|
||||||
|
in addition to normal Parameter arguments:
|
||||||
|
|
||||||
|
:param paramdict: dict <member name> of Parameter(...)
|
||||||
|
:param prefix_or_map: either a prefix for the parameter name to add to the member name
|
||||||
|
or a dict <member name> or <parameter name>
|
||||||
|
"""
|
||||||
|
if isinstance(paramdict, DataType):
|
||||||
|
raise ProgrammingError('second argument must be a dict of Param')
|
||||||
|
if datatype is None and paramdict is not None: # omit the following on Parameter.copy()
|
||||||
|
if isinstance(prefix_or_map, str):
|
||||||
|
prefix_or_map = {m: prefix_or_map + m for m in paramdict}
|
||||||
|
for membername, param in paramdict.items():
|
||||||
|
param.name = prefix_or_map[membername]
|
||||||
|
datatype = StructOf(**{m: p.datatype for m, p in paramdict.items()})
|
||||||
|
kwds['influences'] = [p.name for p in paramdict.values()]
|
||||||
|
self.updateEnable = {}
|
||||||
|
if paramdict:
|
||||||
|
kwds['paramdict'] = paramdict
|
||||||
|
super().__init__(description, datatype, readonly=readonly, **kwds)
|
||||||
|
|
||||||
|
def __set_name__(self, owner, name):
|
||||||
|
# names of access methods of structed param (e.g. ctrlpars)
|
||||||
|
struct_read_name = f'read_{name}' # e.g. 'read_ctrlpars'
|
||||||
|
struct_write_name = f'write_{name}' # e.h. 'write_ctrlpars'
|
||||||
|
self.hasStructRW = hasattr(owner, struct_read_name) or hasattr(owner, struct_write_name)
|
||||||
|
|
||||||
|
for membername, param in self.paramdict.items():
|
||||||
|
pname = param.name
|
||||||
|
changes = {
|
||||||
|
'readonly': self.readonly,
|
||||||
|
'influences': set(param.influences) | {name},
|
||||||
|
}
|
||||||
|
param.ownProperties.update(changes)
|
||||||
|
param.init(changes)
|
||||||
|
setattr(owner, pname, param)
|
||||||
|
param.__set_name__(owner, param.name)
|
||||||
|
|
||||||
|
if self.hasStructRW:
|
||||||
|
rname = f'read_{pname}'
|
||||||
|
|
||||||
|
if not hasattr(owner, rname):
|
||||||
|
def rfunc(self, membername=membername, struct_read_name=struct_read_name):
|
||||||
|
return getattr(self, struct_read_name)()[membername]
|
||||||
|
|
||||||
|
rfunc.poll = False # read_<struct param> is polled only
|
||||||
|
setattr(owner, rname, rfunc)
|
||||||
|
|
||||||
|
if not self.readonly:
|
||||||
|
wname = f'write_{pname}'
|
||||||
|
if not hasattr(owner, wname):
|
||||||
|
def wfunc(self, value, membername=membername,
|
||||||
|
name=name, rname=rname, struct_write_name=struct_write_name):
|
||||||
|
valuedict = dict(getattr(self, name))
|
||||||
|
valuedict[membername] = value
|
||||||
|
getattr(self, struct_write_name)(valuedict)
|
||||||
|
return getattr(self, rname)()
|
||||||
|
|
||||||
|
setattr(owner, wname, wfunc)
|
||||||
|
|
||||||
|
if not self.hasStructRW:
|
||||||
|
if not hasattr(owner, struct_read_name):
|
||||||
|
def struct_read_func(self, name=name, flist=tuple(
|
||||||
|
(m, f'read_{p.name}') for m, p in self.paramdict.items())):
|
||||||
|
pobj = self.parameters[name]
|
||||||
|
# disable updates generated from the callbacks of individual params
|
||||||
|
pobj.insideRW += 1 # guarded by self.accessLock
|
||||||
|
try:
|
||||||
|
return {m: getattr(self, f)() for m, f in flist}
|
||||||
|
finally:
|
||||||
|
pobj.insideRW -= 1
|
||||||
|
|
||||||
|
setattr(owner, struct_read_name, struct_read_func)
|
||||||
|
|
||||||
|
if not (self.readonly or hasattr(owner, struct_write_name)):
|
||||||
|
|
||||||
|
def struct_write_func(self, value, name=name, funclist=tuple(
|
||||||
|
(m, f'write_{p.name}') for m, p in self.paramdict.items())):
|
||||||
|
pobj = self.parameters[name]
|
||||||
|
pobj.insideRW += 1 # guarded by self.accessLock
|
||||||
|
try:
|
||||||
|
return {m: getattr(self, f)(value[m]) for m, f in funclist}
|
||||||
|
finally:
|
||||||
|
pobj.insideRW -= 1
|
||||||
|
|
||||||
|
setattr(owner, struct_write_name, struct_write_func)
|
||||||
|
|
||||||
|
super().__set_name__(owner, name)
|
||||||
|
|
||||||
|
def finish(self, modobj=None):
|
||||||
|
"""register callbacks for consistency"""
|
||||||
|
super().finish(modobj)
|
||||||
|
if modobj:
|
||||||
|
|
||||||
|
if self.hasStructRW:
|
||||||
|
def cb(value, modobj=modobj, structparam=self):
|
||||||
|
for membername, param in structparam.paramdict.items():
|
||||||
|
setattr(modobj, param.name, value[membername])
|
||||||
|
|
||||||
|
modobj.addCallback(self.name, cb)
|
||||||
|
else:
|
||||||
|
for membername, param in self.paramdict.items():
|
||||||
|
def cb(value, modobj=modobj, structparam=self, membername=membername):
|
||||||
|
if not structparam.insideRW:
|
||||||
|
prev = dict(getattr(modobj, structparam.name))
|
||||||
|
prev[membername] = value
|
||||||
|
setattr(modobj, structparam.name, prev)
|
||||||
|
|
||||||
|
modobj.addCallback(param.name, cb)
|
||||||
|
|
||||||
|
|
||||||
|
class FloatEnumParam(Parameter):
|
||||||
|
"""combine enum and float parameter
|
||||||
|
|
||||||
|
Example Usage:
|
||||||
|
|
||||||
|
vrange = FloatEnumParam('sensor range', ['500uV', '20mV', '1V'], 'V')
|
||||||
|
|
||||||
|
The following will be created automatically:
|
||||||
|
|
||||||
|
- the parameter vrange will get a datatype FloatRange(5e-4, 1, unit='V')
|
||||||
|
- an additional parameter `vrange_idx` will be created with an enum type
|
||||||
|
{'500uV': 0, '20mV': 1, '1V': 2}
|
||||||
|
- the method `write_vrange` will be created automatically
|
||||||
|
|
||||||
|
However, the methods `write_vrange_idx` and `read_vrange_idx`, if needed,
|
||||||
|
have to implemented by the programmer.
|
||||||
|
|
||||||
|
Writing to the float parameter involves 'rounding' to the closest allowed value.
|
||||||
|
|
||||||
|
Customization:
|
||||||
|
|
||||||
|
The individual labels might be customized by defining them as a tuple
|
||||||
|
(<index>, <label>, <float value>) where either the index or the float value
|
||||||
|
may be omitted.
|
||||||
|
|
||||||
|
When the index is omitted, the element will be the previous index + 1 or
|
||||||
|
0 when it is the first element.
|
||||||
|
|
||||||
|
Omitted values will be determined from the label, assuming that they use
|
||||||
|
one of the predefined unit prefixes together with the given unit.
|
||||||
|
|
||||||
|
The name of the index parameter is by default '<name>_idx' but might be
|
||||||
|
changed with the idx_name argument.
|
||||||
|
"""
|
||||||
|
# use properties, as simple attributes are not considered on copy()
|
||||||
|
idx_name = Property('name of attached index parameter', StringType(), default='')
|
||||||
|
valuedict = Property('dict <index> of <value>', ValueType(dict))
|
||||||
|
enumtype = Property('dict <label> of <index', DataTypeType())
|
||||||
|
|
||||||
|
# TODO: factor out unit handling, at the latest when needed elsewhere
|
||||||
|
PREFIXES = {'q': -30, 'r': -27, 'y': -24, 'z': -21, 'a': -18, 'f': -15,
|
||||||
|
'p': -12, 'n': -9, 'u': -6, 'µ': -6, 'm': -3,
|
||||||
|
'': 0, 'k': 3, 'M': 6, 'G': 9, 'T': 12,
|
||||||
|
'P': 15, 'E': 18, 'Z': 21, 'Y': 24, 'R': 25, 'Q': 30}
|
||||||
|
|
||||||
|
def __init__(self, description=None, labels=None, unit='',
|
||||||
|
*, datatype=None, readonly=False, **kwds):
|
||||||
|
if labels is None:
|
||||||
|
# called on Parameter.copy()
|
||||||
|
super().__init__(description, datatype, readonly=readonly, **kwds)
|
||||||
|
return
|
||||||
|
if isinstance(labels, DataType):
|
||||||
|
raise ProgrammingError('second argument must be a list of labels, not a datatype')
|
||||||
|
nextidx = 0
|
||||||
|
try:
|
||||||
|
edict = {}
|
||||||
|
vdict = {}
|
||||||
|
for elem in labels:
|
||||||
|
if isinstance(elem, str):
|
||||||
|
idx, label = [nextidx, elem]
|
||||||
|
else:
|
||||||
|
if isinstance(elem[0], str):
|
||||||
|
elem = [nextidx] + list(elem)
|
||||||
|
idx, label, *tail = elem
|
||||||
|
if tail:
|
||||||
|
vdict[idx], = tail
|
||||||
|
edict[label] = idx
|
||||||
|
nextidx = idx + 1
|
||||||
|
except (ValueError, TypeError) as e:
|
||||||
|
raise ProgrammingError('labels must be a list of labels or tuples '
|
||||||
|
'([index], label, [value])') from e
|
||||||
|
pat = re.compile(rf'([+-]?\d*\.?\d*) *({"|".join(self.PREFIXES)}){unit}$')
|
||||||
|
try:
|
||||||
|
# determine missing values from labels
|
||||||
|
for label, idx in edict.items():
|
||||||
|
if idx not in vdict:
|
||||||
|
value, prefix = pat.match(label).groups()
|
||||||
|
vdict[idx] = float(f'{value}e{self.PREFIXES[prefix]}')
|
||||||
|
except (AttributeError, ValueError) as e:
|
||||||
|
raise ProgrammingError(f"{label!r} has not the form '<float><prefix>{unit}'") from e
|
||||||
|
try:
|
||||||
|
enumtype = EnumType(**edict)
|
||||||
|
except TypeError as e:
|
||||||
|
raise ProgrammingError(str(e)) from e
|
||||||
|
datatype = FloatRange(min(vdict.values()), max(vdict.values()), unit=unit)
|
||||||
|
super().__init__(description, datatype, enumtype=enumtype, valuedict=vdict,
|
||||||
|
readonly=readonly, **kwds)
|
||||||
|
|
||||||
|
def __set_name__(self, owner, name):
|
||||||
|
super().__set_name__(owner, name)
|
||||||
|
if not self.idx_name:
|
||||||
|
self.idx_name = name + '_idx'
|
||||||
|
iname = self.idx_name
|
||||||
|
idx_param = Parameter(f'index of {name}', self.enumtype,
|
||||||
|
readonly=self.readonly, influences={name})
|
||||||
|
idx_param.init({})
|
||||||
|
setattr(owner, iname, idx_param)
|
||||||
|
idx_param.__set_name__(owner, iname)
|
||||||
|
|
||||||
|
self.setProperty('influences', {iname})
|
||||||
|
|
||||||
|
if not hasattr(owner, f'write_{name}'):
|
||||||
|
|
||||||
|
# customization (like rounding up or down) might be
|
||||||
|
# achieved by adding write_<name>. if not, the default
|
||||||
|
# is rounding to the closest value
|
||||||
|
|
||||||
|
def wfunc(mobj, value, vdict=self.valuedict, fname=name, wfunc_iname=f'write_{iname}'):
|
||||||
|
getattr(mobj, wfunc_iname)(
|
||||||
|
min(vdict, key=lambda i: abs(vdict[i] - value)))
|
||||||
|
return getattr(mobj, fname)
|
||||||
|
|
||||||
|
setattr(owner, f'write_{name}', wfunc)
|
||||||
|
|
||||||
|
def __get__(self, instance, owner):
|
||||||
|
"""getter for value"""
|
||||||
|
if instance is None:
|
||||||
|
return self
|
||||||
|
return self.valuedict[instance.parameters[self.idx_name].value]
|
||||||
|
|
||||||
|
def trigger_setter(self, modobj, _):
|
||||||
|
# trigger update of float parameter on change of enum parameter
|
||||||
|
modobj.announceUpdate(self.name, getattr(modobj, self.name))
|
||||||
|
|
||||||
|
def finish(self, modobj=None):
|
||||||
|
"""register callbacks for consistency"""
|
||||||
|
super().finish(modobj)
|
||||||
|
if modobj:
|
||||||
|
modobj.addCallback(self.idx_name, self.trigger_setter, modobj)
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# *****************************************************************************
|
# *****************************************************************************
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify it under
|
# This program is free software; you can redistribute it and/or modify it under
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# *****************************************************************************
|
# *****************************************************************************
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify it under
|
# This program is free software; you can redistribute it and/or modify it under
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# *****************************************************************************
|
# *****************************************************************************
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify it under
|
# This program is free software; you can redistribute it and/or modify it under
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# *****************************************************************************
|
# *****************************************************************************
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify it under
|
# This program is free software; you can redistribute it and/or modify it under
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# *****************************************************************************
|
# *****************************************************************************
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify it under
|
# This program is free software; you can redistribute it and/or modify it under
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# *****************************************************************************
|
# *****************************************************************************
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify it under
|
# This program is free software; you can redistribute it and/or modify it under
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# *****************************************************************************
|
# *****************************************************************************
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify it under
|
# This program is free software; you can redistribute it and/or modify it under
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# *****************************************************************************
|
# *****************************************************************************
|
||||||
# Copyright (c) 2015-2023 by the authors, see LICENSE
|
# Copyright (c) 2015-2023 by the authors, see LICENSE
|
||||||
#
|
#
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# *****************************************************************************
|
# *****************************************************************************
|
||||||
# Copyright (c) 2015-2016 by the authors, see LICENSE
|
# Copyright (c) 2015-2016 by the authors, see LICENSE
|
||||||
#
|
#
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# *****************************************************************************
|
# *****************************************************************************
|
||||||
# Copyright (c) 2015-2023 by the authors, see LICENSE
|
# Copyright (c) 2015-2023 by the authors, see LICENSE
|
||||||
#
|
#
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
from frappy.gui.qt import QCheckBox, QComboBox, QLineEdit, pyqtSignal
|
import sys
|
||||||
|
|
||||||
from frappy.datatypes import BoolType, EnumType
|
from frappy.gui.qt import QCheckBox, QComboBox, QDoubleSpinBox, QLineEdit, \
|
||||||
|
QSpinBox, pyqtSignal
|
||||||
|
|
||||||
|
from frappy.datatypes import BoolType, EnumType, FloatRange, IntRange, \
|
||||||
|
StringType, TextType
|
||||||
|
|
||||||
# ArrayOf, BLOBType, FloatRange, IntRange, StringType, StructOf, TextType, TupleOf
|
# ArrayOf, BLOBType, FloatRange, IntRange, StringType, StructOf, TextType, TupleOf
|
||||||
|
|
||||||
@ -9,11 +13,24 @@ def get_input_widget(datatype, parent=None):
|
|||||||
return {
|
return {
|
||||||
EnumType: EnumInput,
|
EnumType: EnumInput,
|
||||||
BoolType: BoolInput,
|
BoolType: BoolInput,
|
||||||
|
IntRange: IntInput,
|
||||||
|
StringType: StringInput,
|
||||||
|
TextType: StringInput,
|
||||||
}.get(datatype.__class__, GenericInput)(datatype, parent)
|
}.get(datatype.__class__, GenericInput)(datatype, parent)
|
||||||
|
|
||||||
|
|
||||||
class GenericInput(QLineEdit):
|
class InputBase:
|
||||||
submitted = pyqtSignal()
|
submitted = pyqtSignal()
|
||||||
|
input_feedback = pyqtSignal(str)
|
||||||
|
|
||||||
|
def get_input(self):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def submit(self):
|
||||||
|
self.submitted.emit()
|
||||||
|
|
||||||
|
|
||||||
|
class GenericInput(InputBase, QLineEdit):
|
||||||
def __init__(self, datatype, parent=None):
|
def __init__(self, datatype, parent=None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self.datatype = datatype
|
self.datatype = datatype
|
||||||
@ -23,12 +40,28 @@ class GenericInput(QLineEdit):
|
|||||||
def get_input(self):
|
def get_input(self):
|
||||||
return self.datatype.from_string(self.text())
|
return self.datatype.from_string(self.text())
|
||||||
|
|
||||||
def submit(self):
|
|
||||||
self.submitted.emit()
|
class StringInput(GenericInput):
|
||||||
|
def __init__(self, datatype, parent=None):
|
||||||
|
super().__init__(datatype, parent)
|
||||||
|
|
||||||
|
|
||||||
class EnumInput(QComboBox):
|
class IntInput(InputBase, QSpinBox):
|
||||||
submitted = pyqtSignal()
|
def __init__(self, datatype, parent=None):
|
||||||
|
super().__init__(parent)
|
||||||
|
self.datatype = datatype
|
||||||
|
# we dont use setMaximum and setMinimum because it is quite restrictive
|
||||||
|
# when typing, so set it as high as possible
|
||||||
|
self.setMaximum(2147483647)
|
||||||
|
self.setMinimum(-2147483648)
|
||||||
|
|
||||||
|
self.lineEdit().returnPressed.connect(self.submit)
|
||||||
|
|
||||||
|
def get_input(self):
|
||||||
|
return self.datatype(self.value())
|
||||||
|
|
||||||
|
|
||||||
|
class EnumInput(InputBase, QComboBox):
|
||||||
def __init__(self, datatype, parent=None):
|
def __init__(self, datatype, parent=None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self.setPlaceholderText('choose value')
|
self.setPlaceholderText('choose value')
|
||||||
@ -45,18 +78,11 @@ class EnumInput(QComboBox):
|
|||||||
def get_input(self):
|
def get_input(self):
|
||||||
return self._map[self.currentIndex()].value
|
return self._map[self.currentIndex()].value
|
||||||
|
|
||||||
def submit(self):
|
|
||||||
self.submitted.emit()
|
|
||||||
|
|
||||||
|
class BoolInput(InputBase, QCheckBox):
|
||||||
class BoolInput(QCheckBox):
|
|
||||||
submitted = pyqtSignal()
|
|
||||||
def __init__(self, datatype, parent=None):
|
def __init__(self, datatype, parent=None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self.datatype = datatype
|
self.datatype = datatype
|
||||||
|
|
||||||
def get_input(self):
|
def get_input(self):
|
||||||
return self.isChecked()
|
return self.isChecked()
|
||||||
|
|
||||||
def submit(self):
|
|
||||||
self.submitted.emit()
|
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# *****************************************************************************
|
# *****************************************************************************
|
||||||
# Copyright (c) 2015-2023 by the authors, see LICENSE
|
# Copyright (c) 2015-2023 by the authors, see LICENSE
|
||||||
#
|
#
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# *****************************************************************************
|
# *****************************************************************************
|
||||||
# Copyright (c) 2015-2023 by the authors, see LICENSE
|
# Copyright (c) 2015-2023 by the authors, see LICENSE
|
||||||
#
|
#
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# *****************************************************************************
|
# *****************************************************************************
|
||||||
# Copyright (c) 2015-2023 by the authors, see LICENSE
|
# Copyright (c) 2015-2023 by the authors, see LICENSE
|
||||||
#
|
#
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# *****************************************************************************
|
# *****************************************************************************
|
||||||
# Copyright (c) 2015-2023 by the authors, see LICENSE
|
# Copyright (c) 2015-2023 by the authors, see LICENSE
|
||||||
#
|
#
|
||||||
@ -25,9 +24,9 @@ from frappy.gui.qt import QColor, QDialog, QHBoxLayout, QIcon, QLabel, \
|
|||||||
QLineEdit, QMessageBox, QPropertyAnimation, QPushButton, Qt, QToolButton, \
|
QLineEdit, QMessageBox, QPropertyAnimation, QPushButton, Qt, QToolButton, \
|
||||||
QWidget, pyqtProperty, pyqtSignal
|
QWidget, pyqtProperty, pyqtSignal
|
||||||
|
|
||||||
|
from frappy.gui.inputwidgets import get_input_widget
|
||||||
from frappy.gui.util import Colors, loadUi
|
from frappy.gui.util import Colors, loadUi
|
||||||
from frappy.gui.valuewidgets import get_widget
|
from frappy.gui.valuewidgets import get_widget
|
||||||
from frappy.gui.inputwidgets import get_input_widget
|
|
||||||
|
|
||||||
|
|
||||||
class CommandDialog(QDialog):
|
class CommandDialog(QDialog):
|
||||||
@ -55,7 +54,11 @@ class CommandDialog(QDialog):
|
|||||||
self.resize(self.sizeHint())
|
self.resize(self.sizeHint())
|
||||||
|
|
||||||
def get_value(self):
|
def get_value(self):
|
||||||
return True, self.widgets[0].get_value()
|
try:
|
||||||
|
return self.widgets[0].get_value()
|
||||||
|
except Exception as e:
|
||||||
|
QMessageBox.warning(self.parent(), 'Operation failed', str(e))
|
||||||
|
return None
|
||||||
|
|
||||||
def exec(self):
|
def exec(self):
|
||||||
if super().exec():
|
if super().exec():
|
||||||
@ -96,8 +99,9 @@ class CommandButton(QPushButton):
|
|||||||
if self._argintype:
|
if self._argintype:
|
||||||
dlg = CommandDialog(self._cmdname, self._argintype)
|
dlg = CommandDialog(self._cmdname, self._argintype)
|
||||||
args = dlg.exec()
|
args = dlg.exec()
|
||||||
if args: # not 'Cancel' clicked
|
if args is not None:
|
||||||
self._cb(self._cmdname, args[1])
|
# no errors when converting value and 'Cancel' wasn't clicked
|
||||||
|
self._cb(self._cmdname, args)
|
||||||
else:
|
else:
|
||||||
# no need for arguments
|
# no need for arguments
|
||||||
self._cb(self._cmdname, None)
|
self._cb(self._cmdname, None)
|
||||||
@ -443,8 +447,8 @@ class ModuleWidget(QWidget):
|
|||||||
self.paramDetails.emit(self._name, param)
|
self.paramDetails.emit(self._name, param)
|
||||||
|
|
||||||
def _button_pressed(self, param):
|
def _button_pressed(self, param):
|
||||||
target = self._paramInputs[param].get_input()
|
|
||||||
try:
|
try:
|
||||||
|
target = self._paramInputs[param].get_input()
|
||||||
self._node.setParameter(self._name, param, target)
|
self._node.setParameter(self._name, param, target)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
QMessageBox.warning(self.parent(), 'Operation failed', str(e))
|
QMessageBox.warning(self.parent(), 'Operation failed', str(e))
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# *****************************************************************************
|
# *****************************************************************************
|
||||||
# Copyright (c) 2015-2023 by the authors, see LICENSE
|
# Copyright (c) 2015-2023 by the authors, see LICENSE
|
||||||
#
|
#
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# *****************************************************************************
|
# *****************************************************************************
|
||||||
# Copyright (c) 2015-2016 by the authors, see LICENSE
|
# Copyright (c) 2015-2016 by the authors, see LICENSE
|
||||||
#
|
#
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# *****************************************************************************
|
# *****************************************************************************
|
||||||
# Copyright (c) 2015-2017 by the authors, see LICENSE
|
# Copyright (c) 2015-2017 by the authors, see LICENSE
|
||||||
#
|
#
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# *****************************************************************************
|
# *****************************************************************************
|
||||||
# Copyright (c) 2015-2023 by the authors, see LICENSE
|
# Copyright (c) 2015-2023 by the authors, see LICENSE
|
||||||
#
|
#
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# *****************************************************************************
|
# *****************************************************************************
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify it under
|
# This program is free software; you can redistribute it and/or modify it under
|
||||||
@ -43,10 +42,10 @@ try:
|
|||||||
QDialogButtonBox, QDoubleSpinBox, QFileDialog, QFrame, QGridLayout, \
|
QDialogButtonBox, QDoubleSpinBox, QFileDialog, QFrame, QGridLayout, \
|
||||||
QGroupBox, QHBoxLayout, QInputDialog, QLabel, QLineEdit, QMainWindow, \
|
QGroupBox, QHBoxLayout, QInputDialog, QLabel, QLineEdit, QMainWindow, \
|
||||||
QMenu, QMessageBox, QPlainTextEdit, QPushButton, QRadioButton, \
|
QMenu, QMessageBox, QPlainTextEdit, QPushButton, QRadioButton, \
|
||||||
QScrollArea, QSizePolicy, QSpacerItem, QSpinBox, QStyle, \
|
QScrollArea, QSizePolicy, QSlider, QSpacerItem, QSpinBox, QStyle, \
|
||||||
QStyleOptionTab, QStylePainter, QTabBar, QTabWidget, QTextEdit, \
|
QStyleOptionTab, QStylePainter, QTabBar, QTabWidget, QTextEdit, \
|
||||||
QToolButton, QTreeView, QTreeWidget, QTreeWidgetItem, QVBoxLayout, \
|
QToolButton, QTreeView, QTreeWidget, QTreeWidgetItem, QVBoxLayout, \
|
||||||
QWidget,QSlider
|
QWidget
|
||||||
|
|
||||||
import frappy.gui.resources_qt6
|
import frappy.gui.resources_qt6
|
||||||
|
|
||||||
@ -63,9 +62,9 @@ except ImportError as e:
|
|||||||
QDialog, QDialogButtonBox, QDoubleSpinBox, QFileDialog, QFrame, \
|
QDialog, QDialogButtonBox, QDoubleSpinBox, QFileDialog, QFrame, \
|
||||||
QGridLayout, QGroupBox, QHBoxLayout, QInputDialog, QLabel, QLineEdit, \
|
QGridLayout, QGroupBox, QHBoxLayout, QInputDialog, QLabel, QLineEdit, \
|
||||||
QMainWindow, QMenu, QMessageBox, QPlainTextEdit, QPushButton, \
|
QMainWindow, QMenu, QMessageBox, QPlainTextEdit, QPushButton, \
|
||||||
QRadioButton, QScrollArea, QShortcut, QSizePolicy, QSpacerItem, \
|
QRadioButton, QScrollArea, QShortcut, QSizePolicy, QSlider, \
|
||||||
QSpinBox, QStyle, QStyleOptionTab, QStylePainter, QTabBar, \
|
QSpacerItem, QSpinBox, QStyle, QStyleOptionTab, QStylePainter, \
|
||||||
QTabWidget, QTextEdit, QToolButton, QTreeView, QTreeWidget, \
|
QTabBar, QTabWidget, QTextEdit, QToolButton, QTreeView, QTreeWidget, \
|
||||||
QTreeWidgetItem, QVBoxLayout, QWidget, QSlider
|
QTreeWidgetItem, QVBoxLayout, QWidget
|
||||||
|
|
||||||
import frappy.gui.resources_qt5
|
import frappy.gui.resources_qt5
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
# Resource object code
|
# Resource object code
|
||||||
#
|
#
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# *****************************************************************************
|
# *****************************************************************************
|
||||||
# NICOS, the Networked Instrument Control System of the MLZ
|
# NICOS, the Networked Instrument Control System of the MLZ
|
||||||
# Copyright (c) 2009-2023 by the NICOS contributors (see AUTHORS)
|
# Copyright (c) 2009-2023 by the NICOS contributors (see AUTHORS)
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# *****************************************************************************
|
# *****************************************************************************
|
||||||
# Copyright (c) 2015-2016 by the authors, see LICENSE
|
# Copyright (c) 2015-2016 by the authors, see LICENSE
|
||||||
#
|
#
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# *****************************************************************************
|
# *****************************************************************************
|
||||||
# Copyright (c) 2015-2016 by the authors, see LICENSE
|
# Copyright (c) 2015-2016 by the authors, see LICENSE
|
||||||
#
|
#
|
||||||
|
112
frappy/io.py
112
frappy/io.py
@ -1,5 +1,4 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
# *****************************************************************************
|
# *****************************************************************************
|
||||||
# This program is free software; you can redistribute it and/or modify it under
|
# This program is free software; you can redistribute it and/or modify it under
|
||||||
# the terms of the GNU General Public License as published by the Free Software
|
# the terms of the GNU General Public License as published by the Free Software
|
||||||
@ -25,17 +24,17 @@ other future extensions of AsynConn
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import re
|
import re
|
||||||
import time
|
|
||||||
import threading
|
import threading
|
||||||
|
import time
|
||||||
|
|
||||||
from frappy.lib.asynconn import AsynConn, ConnectionClosed
|
from frappy.datatypes import ArrayOf, BLOBType, BoolType, FloatRange, \
|
||||||
from frappy.datatypes import ArrayOf, BLOBType, BoolType, FloatRange, IntRange, \
|
IntRange, StringType, StructOf, TupleOf, ValueType
|
||||||
StringType, TupleOf, ValueType
|
from frappy.errors import CommunicationFailedError, ConfigError, \
|
||||||
from frappy.errors import CommunicationFailedError, ConfigError, ProgrammingError, \
|
ProgrammingError, SilentCommunicationFailedError as SilentError
|
||||||
SilentCommunicationFailedError as SilentError
|
|
||||||
from frappy.modules import Attached, Command, \
|
|
||||||
Communicator, Module, Parameter, Property
|
|
||||||
from frappy.lib import generalConfig
|
from frappy.lib import generalConfig
|
||||||
|
from frappy.lib.asynconn import AsynConn, ConnectionClosed
|
||||||
|
from frappy.modules import Attached, Command, Communicator, Module, \
|
||||||
|
Parameter, Property
|
||||||
|
|
||||||
generalConfig.set_default('legacy_hasiodev', False)
|
generalConfig.set_default('legacy_hasiodev', False)
|
||||||
|
|
||||||
@ -62,8 +61,7 @@ class HasIO(Module):
|
|||||||
ioname = opts.get('io') or f'{name}_io'
|
ioname = opts.get('io') or f'{name}_io'
|
||||||
io = self.ioClass(ioname, srv.log.getChild(ioname), opts, srv) # pylint: disable=not-callable
|
io = self.ioClass(ioname, srv.log.getChild(ioname), opts, srv) # pylint: disable=not-callable
|
||||||
io.callingModule = []
|
io.callingModule = []
|
||||||
srv.modules[ioname] = io
|
srv.secnode.add_module(io, ioname)
|
||||||
srv.dispatcher.register_module(io, ioname)
|
|
||||||
self.ioDict[self.uri] = ioname
|
self.ioDict[self.uri] = ioname
|
||||||
self.io = ioname
|
self.io = ioname
|
||||||
|
|
||||||
@ -76,8 +74,11 @@ class HasIO(Module):
|
|||||||
def communicate(self, *args):
|
def communicate(self, *args):
|
||||||
return self.io.communicate(*args)
|
return self.io.communicate(*args)
|
||||||
|
|
||||||
def multicomm(self, *args):
|
def writeline(self, *args):
|
||||||
return self.io.multicomm(*args)
|
return self.io.writeline(*args)
|
||||||
|
|
||||||
|
def multicomm(self, *args, **kwds):
|
||||||
|
return self.io.multicomm(*args, **kwds)
|
||||||
|
|
||||||
|
|
||||||
class HasIodev(HasIO):
|
class HasIodev(HasIO):
|
||||||
@ -287,7 +288,7 @@ class StringIO(IOBase):
|
|||||||
f' does not match {regexp!r}')
|
f' does not match {regexp!r}')
|
||||||
|
|
||||||
@Command(StringType(), result=StringType())
|
@Command(StringType(), result=StringType())
|
||||||
def communicate(self, command):
|
def communicate(self, command, noreply=False):
|
||||||
"""send a command and receive a reply
|
"""send a command and receive a reply
|
||||||
|
|
||||||
using end_of_line, encoding and self._lock
|
using end_of_line, encoding and self._lock
|
||||||
@ -314,6 +315,8 @@ class StringIO(IOBase):
|
|||||||
self.comLog('garbage: %r', garbage)
|
self.comLog('garbage: %r', garbage)
|
||||||
self._conn.send(cmd + self._eol_write)
|
self._conn.send(cmd + self._eol_write)
|
||||||
self.comLog('> %s', cmd.decode(self.encoding))
|
self.comLog('> %s', cmd.decode(self.encoding))
|
||||||
|
if noreply:
|
||||||
|
return None
|
||||||
reply = self._conn.readline(self.timeout)
|
reply = self._conn.readline(self.timeout)
|
||||||
except ConnectionClosed:
|
except ConnectionClosed:
|
||||||
self.closeConnection()
|
self.closeConnection()
|
||||||
@ -329,13 +332,69 @@ class StringIO(IOBase):
|
|||||||
self.log.error(self._last_error)
|
self.log.error(self._last_error)
|
||||||
raise SilentError(repr(e)) from e
|
raise SilentError(repr(e)) from e
|
||||||
|
|
||||||
@Command(ArrayOf(StringType()), result=ArrayOf(StringType()))
|
@Command(StringType())
|
||||||
def multicomm(self, commands):
|
def writeline(self, command):
|
||||||
"""communicate multiple request/replies in one row"""
|
"""send a command without needing a reply
|
||||||
|
|
||||||
|
For keeping a request-reply scheme it is recommended to overwrite
|
||||||
|
this method to append a query on the same line, for example:
|
||||||
|
|
||||||
|
.. code::
|
||||||
|
|
||||||
|
def writeline(self, command):
|
||||||
|
self.communicate(command + ';*OPC?')
|
||||||
|
|
||||||
|
or to add an additional query which is returning always a reply, e.g.:
|
||||||
|
|
||||||
|
.. code::
|
||||||
|
|
||||||
|
def writeline(self, command):
|
||||||
|
with self._lock: # important!
|
||||||
|
self.communicate(command, noreply=True)
|
||||||
|
self.communicate('*OPC?')
|
||||||
|
|
||||||
|
The first version is preferred when the hardware allows to join several
|
||||||
|
commands by a separator.
|
||||||
|
"""
|
||||||
|
self.communicate(command, noreply=True)
|
||||||
|
|
||||||
|
@Command(ArrayOf(TupleOf(StringType(), BoolType(), FloatRange(0, unit='s'))),
|
||||||
|
result=ArrayOf(StringType()))
|
||||||
|
def multicomm(self, requests):
|
||||||
|
"""communicate multiple request/replies in one go
|
||||||
|
|
||||||
|
:param requests: a sequence of tuple of (command, request_expected, delay)
|
||||||
|
if called internally, a sequence of strings (command) is also accepted
|
||||||
|
:return: list of replies
|
||||||
|
|
||||||
|
This method may be rarely used, it is intended when the hardware needs
|
||||||
|
that several commands are not intercepted by an other client or by the poller,
|
||||||
|
for example selecting a channel before reading it. Or when wait times different
|
||||||
|
from 'wait_before' have to be specified.
|
||||||
|
|
||||||
|
These cases may also handled by adding an additional method to the IO class.
|
||||||
|
This could also be a custom SECoP command.
|
||||||
|
Or, in the case where all useful commands in this IO class need it,
|
||||||
|
:meth:`communicate` may be overridden.
|
||||||
|
|
||||||
|
This method should be used in the following cases:
|
||||||
|
|
||||||
|
1) you want to use a generic communicator covering above use cases over SECoP.
|
||||||
|
2) you do not want to subclass the IO class.
|
||||||
|
"""
|
||||||
replies = []
|
replies = []
|
||||||
with self._lock:
|
with self._lock:
|
||||||
for cmd in commands:
|
for request in requests:
|
||||||
|
if isinstance(request, str):
|
||||||
|
cmd, expect_reply, delay = request, True, 0
|
||||||
|
else:
|
||||||
|
cmd, expect_reply, delay = request
|
||||||
|
if expect_reply:
|
||||||
replies.append(self.communicate(cmd))
|
replies.append(self.communicate(cmd))
|
||||||
|
else:
|
||||||
|
self.writeline(cmd)
|
||||||
|
if delay:
|
||||||
|
time.sleep(delay)
|
||||||
return replies
|
return replies
|
||||||
|
|
||||||
|
|
||||||
@ -395,7 +454,7 @@ class BytesIO(IOBase):
|
|||||||
if not replypat.match(reply):
|
if not replypat.match(reply):
|
||||||
self.closeConnection()
|
self.closeConnection()
|
||||||
raise CommunicationFailedError(f'bad response: {reply!r}'
|
raise CommunicationFailedError(f'bad response: {reply!r}'
|
||||||
' does not match {expected!r}')
|
f' does not match {expected!r}')
|
||||||
|
|
||||||
@Command((BLOBType(), IntRange(0)), result=BLOBType())
|
@Command((BLOBType(), IntRange(0)), result=BLOBType())
|
||||||
def communicate(self, request, replylen): # pylint: disable=arguments-differ
|
def communicate(self, request, replylen): # pylint: disable=arguments-differ
|
||||||
@ -426,13 +485,20 @@ class BytesIO(IOBase):
|
|||||||
self.log.error(self._last_error)
|
self.log.error(self._last_error)
|
||||||
raise SilentError(repr(e)) from e
|
raise SilentError(repr(e)) from e
|
||||||
|
|
||||||
@Command((ArrayOf(TupleOf(BLOBType(), IntRange(0)))), result=ArrayOf(BLOBType()))
|
@Command(StructOf(requests=ArrayOf(TupleOf(BLOBType(), IntRange(0), FloatRange(0, unit='s')))),
|
||||||
|
result=ArrayOf(BLOBType()))
|
||||||
def multicomm(self, requests):
|
def multicomm(self, requests):
|
||||||
"""communicate multiple request/replies in one row"""
|
"""communicate multiple request/replies in one go
|
||||||
|
|
||||||
|
:param requests: sequence of tuple (<command>, <expected reply length>, <delay>)
|
||||||
|
:return: list of replies
|
||||||
|
"""
|
||||||
replies = []
|
replies = []
|
||||||
with self._lock:
|
with self._lock:
|
||||||
for request in requests:
|
for cmd, replylen, delay in requests:
|
||||||
replies.append(self.communicate(*request))
|
replies.append(self.communicate(cmd, replylen))
|
||||||
|
if delay:
|
||||||
|
time.sleep(delay)
|
||||||
return replies
|
return replies
|
||||||
|
|
||||||
def readBytes(self, nbytes):
|
def readBytes(self, nbytes):
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# *****************************************************************************
|
# *****************************************************************************
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify it under
|
# This program is free software; you can redistribute it and/or modify it under
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# *****************************************************************************
|
# *****************************************************************************
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify it under
|
# This program is free software; you can redistribute it and/or modify it under
|
||||||
@ -22,12 +21,14 @@
|
|||||||
|
|
||||||
from textwrap import indent
|
from textwrap import indent
|
||||||
|
|
||||||
from frappy.modules import Command, HasProperties, Module, Parameter, Property
|
from frappy.modules import Command, Parameter, Property
|
||||||
|
from frappy.modulebase import HasProperties, Module
|
||||||
|
|
||||||
|
|
||||||
def indent_description(p):
|
def indent_description(p):
|
||||||
"""indent lines except first one"""
|
"""indent lines except first one"""
|
||||||
return indent(p.description, ' ').replace(' ', '', 1)
|
space = ' ' * 6
|
||||||
|
return indent(p.description, space).replace(space, '', 1)
|
||||||
|
|
||||||
|
|
||||||
def fmt_param(name, param):
|
def fmt_param(name, param):
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# *****************************************************************************
|
# *****************************************************************************
|
||||||
# Copyright (c) 2015-2016 by the authors, see LICENSE
|
# Copyright (c) 2015-2016 by the authors, see LICENSE
|
||||||
#
|
#
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# *****************************************************************************
|
# *****************************************************************************
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify it under
|
# This program is free software; you can redistribute it and/or modify it under
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# *****************************************************************************
|
# *****************************************************************************
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify it under
|
# This program is free software; you can redistribute it and/or modify it under
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# *****************************************************************************
|
# *****************************************************************************
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify it under
|
# This program is free software; you can redistribute it and/or modify it under
|
||||||
@ -33,7 +32,7 @@ else:
|
|||||||
class PEP487Metaclass(type):
|
class PEP487Metaclass(type):
|
||||||
# support for __set_name__ and __init_subclass__ for older python versions
|
# support for __set_name__ and __init_subclass__ for older python versions
|
||||||
# slightly modified from PEP487 doc
|
# slightly modified from PEP487 doc
|
||||||
def __new__(cls, *args, **kwargs):
|
def __new__(cls, *args, **kwargs): # pylint: disable=bad-mcs-classmethod-argument
|
||||||
if len(args) != 3:
|
if len(args) != 3:
|
||||||
return super().__new__(cls, *args)
|
return super().__new__(cls, *args)
|
||||||
name, bases, ns = args
|
name, bases, ns = args
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# *****************************************************************************
|
# *****************************************************************************
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify it under
|
# This program is free software; you can redistribute it and/or modify it under
|
||||||
@ -142,6 +141,7 @@ class SequencerMixin:
|
|||||||
return self.Status.IDLE, ''
|
return self.Status.IDLE, ''
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
|
"""stop sequence"""
|
||||||
if self.seq_is_alive():
|
if self.seq_is_alive():
|
||||||
self._seq_stopflag = True
|
self._seq_stopflag = True
|
||||||
|
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# *****************************************************************************
|
# *****************************************************************************
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify it under
|
# This program is free software; you can redistribute it and/or modify it under
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
# *****************************************************************************
|
# *****************************************************************************
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify it under
|
# This program is free software; you can redistribute it and/or modify it under
|
||||||
@ -55,6 +54,8 @@ class RemoteLogHandler(mlzlog.Handler):
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.subscriptions = {} # dict[modname] of tuple(mobobj, dict [conn] of level)
|
self.subscriptions = {} # dict[modname] of tuple(mobobj, dict [conn] of level)
|
||||||
|
# None will be replaced by a callback when one is first installed
|
||||||
|
self.send_log = None
|
||||||
|
|
||||||
def emit(self, record):
|
def emit(self, record):
|
||||||
"""unused"""
|
"""unused"""
|
||||||
@ -62,18 +63,18 @@ class RemoteLogHandler(mlzlog.Handler):
|
|||||||
def handle(self, record):
|
def handle(self, record):
|
||||||
modname = record.name.split('.')[-1]
|
modname = record.name.split('.')[-1]
|
||||||
try:
|
try:
|
||||||
modobj, subscriptions = self.subscriptions[modname]
|
subscriptions = self.subscriptions[modname]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
return
|
return
|
||||||
for conn, lev in subscriptions.items():
|
for conn, lev in subscriptions.items():
|
||||||
if record.levelno >= lev:
|
if record.levelno >= lev:
|
||||||
modobj.DISPATCHER.send_log_msg(
|
self.send_log( # pylint: disable=not-callable
|
||||||
conn, modobj.name, LEVEL_NAMES[record.levelno],
|
conn, modname, LEVEL_NAMES[record.levelno],
|
||||||
record.getMessage())
|
record.getMessage())
|
||||||
|
|
||||||
def set_conn_level(self, modobj, conn, level):
|
def set_conn_level(self, modname, conn, level):
|
||||||
level = check_level(level)
|
level = check_level(level)
|
||||||
modobj, subscriptions = self.subscriptions.setdefault(modobj.name, (modobj, {}))
|
subscriptions = self.subscriptions.setdefault(modname, {})
|
||||||
if level == OFF:
|
if level == OFF:
|
||||||
subscriptions.pop(conn, None)
|
subscriptions.pop(conn, None)
|
||||||
else:
|
else:
|
||||||
@ -127,7 +128,7 @@ class HasComlog:
|
|||||||
if self.comlog and generalConfig.initialized and generalConfig.comlog:
|
if self.comlog and generalConfig.initialized and generalConfig.comlog:
|
||||||
self._comLog = mlzlog.Logger(f'COMLOG.{self.name}')
|
self._comLog = mlzlog.Logger(f'COMLOG.{self.name}')
|
||||||
self._comLog.handlers[:] = []
|
self._comLog.handlers[:] = []
|
||||||
directory = join(logger.logdir, logger.rootname, 'comlog', self.DISPATCHER.name)
|
directory = join(logger.logdir, logger.rootname, 'comlog', self.secNode.name)
|
||||||
self._comLog.addHandler(ComLogfileHandler(
|
self._comLog.addHandler(ComLogfileHandler(
|
||||||
directory, self.name, max_days=generalConfig.getint('comlog_days', 7)))
|
directory, self.name, max_days=generalConfig.getint('comlog_days', 7)))
|
||||||
return
|
return
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# *****************************************************************************
|
# *****************************************************************************
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify it under
|
# This program is free software; you can redistribute it and/or modify it under
|
||||||
@ -71,11 +70,8 @@ class HasOutputModule:
|
|||||||
|
|
||||||
def initModule(self):
|
def initModule(self):
|
||||||
super().initModule()
|
super().initModule()
|
||||||
try:
|
|
||||||
if self.output_module:
|
if self.output_module:
|
||||||
self.output_module.register_input(self.name, self.deactivate_control)
|
self.output_module.register_input(self.name, self.deactivate_control)
|
||||||
except Exception:
|
|
||||||
self.log.info(f'{self.name} has no output module')
|
|
||||||
|
|
||||||
def set_control_active(self, active):
|
def set_control_active(self, active):
|
||||||
"""to be overridden for switching hw control"""
|
"""to be overridden for switching hw control"""
|
||||||
|
835
frappy/modulebase.py
Normal file
835
frappy/modulebase.py
Normal file
@ -0,0 +1,835 @@
|
|||||||
|
# *****************************************************************************
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify it under
|
||||||
|
# the terms of the GNU General Public License as published by the Free Software
|
||||||
|
# Foundation; either version 2 of the License, or (at your option) any later
|
||||||
|
# version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||||
|
# details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License along with
|
||||||
|
# this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
#
|
||||||
|
# Module authors:
|
||||||
|
# Enrico Faulhaber <enrico.faulhaber@frm2.tum.de>
|
||||||
|
# Markus Zolliker <markus.zolliker@psi.ch>
|
||||||
|
# Alexander Zaft <a.zaft@fz-juelich.de>
|
||||||
|
#
|
||||||
|
# *****************************************************************************
|
||||||
|
"""Defines the base Module class"""
|
||||||
|
|
||||||
|
|
||||||
|
import time
|
||||||
|
import threading
|
||||||
|
from collections import OrderedDict
|
||||||
|
|
||||||
|
from frappy.datatypes import ArrayOf, BoolType, EnumType, FloatRange, \
|
||||||
|
IntRange, StringType, TextType, TupleOf, \
|
||||||
|
NoneOr
|
||||||
|
from frappy.errors import BadValueError, CommunicationFailedError, ConfigError, \
|
||||||
|
ProgrammingError, SECoPError, secop_error, RangeError
|
||||||
|
from frappy.lib import formatException, mkthread, UniqueObject
|
||||||
|
from frappy.params import Accessible, Command, Parameter, Limit
|
||||||
|
from frappy.properties import HasProperties, Property
|
||||||
|
from frappy.logging import RemoteLogHandler
|
||||||
|
|
||||||
|
# TODO: resolve cirular import
|
||||||
|
# from .interfaces import SECoP_BASE_CLASSES
|
||||||
|
# WORKAROUND:
|
||||||
|
SECoP_BASE_CLASSES = ['Readable', 'Writable', 'Drivable', 'Communicator']
|
||||||
|
|
||||||
|
Done = UniqueObject('Done')
|
||||||
|
"""a special return value for a read_<param>/write_<param> method
|
||||||
|
|
||||||
|
indicating that the setter is triggered already"""
|
||||||
|
|
||||||
|
wrapperClasses = {}
|
||||||
|
|
||||||
|
|
||||||
|
class HasAccessibles(HasProperties):
|
||||||
|
"""base class of Module
|
||||||
|
|
||||||
|
joining the class's properties, parameters and commands dicts with
|
||||||
|
those of base classes.
|
||||||
|
wrap read_*/write_* methods
|
||||||
|
(so the dispatcher will get notified of changed values)
|
||||||
|
"""
|
||||||
|
isWrapped = False
|
||||||
|
checkedMethods = set()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def __init_subclass__(cls): # pylint: disable=too-many-branches
|
||||||
|
super().__init_subclass__()
|
||||||
|
if cls.isWrapped:
|
||||||
|
return
|
||||||
|
# merge accessibles from all sub-classes, treat overrides
|
||||||
|
# for now, allow to use also the old syntax (parameters/commands dict)
|
||||||
|
accessibles = OrderedDict() # dict of accessibles
|
||||||
|
merged_properties = {} # dict of dict of merged properties
|
||||||
|
new_names = [] # list of names of new accessibles
|
||||||
|
override_values = {} # bare values overriding a parameter and methods overriding a command
|
||||||
|
|
||||||
|
for base in reversed(cls.__mro__):
|
||||||
|
for key, value in base.__dict__.items():
|
||||||
|
if isinstance(value, Accessible):
|
||||||
|
value.updateProperties(merged_properties.setdefault(key, {}))
|
||||||
|
if base == cls and key not in accessibles:
|
||||||
|
new_names.append(key)
|
||||||
|
accessibles[key] = value
|
||||||
|
override_values.pop(key, None)
|
||||||
|
elif key in accessibles:
|
||||||
|
override_values[key] = value
|
||||||
|
# remark: merged_properties contain already the properties of accessibles of cls
|
||||||
|
for aname, aobj in list(accessibles.items()):
|
||||||
|
if aname in override_values:
|
||||||
|
value = override_values[aname]
|
||||||
|
if value is None:
|
||||||
|
accessibles.pop(aname)
|
||||||
|
continue
|
||||||
|
aobj = aobj.create_from_value(merged_properties[aname], value)
|
||||||
|
# replace the bare value by the created accessible
|
||||||
|
setattr(cls, aname, aobj)
|
||||||
|
else:
|
||||||
|
aobj.merge(merged_properties[aname])
|
||||||
|
accessibles[aname] = aobj
|
||||||
|
|
||||||
|
# rebuild order: (1) inherited items, (2) items from paramOrder, (3) new accessibles
|
||||||
|
# move (2) to the end
|
||||||
|
paramOrder = cls.__dict__.get('paramOrder', ())
|
||||||
|
for aname in paramOrder:
|
||||||
|
if aname in accessibles:
|
||||||
|
accessibles.move_to_end(aname)
|
||||||
|
# ignore unknown names
|
||||||
|
# move (3) to the end
|
||||||
|
for aname in new_names:
|
||||||
|
if aname not in paramOrder:
|
||||||
|
accessibles.move_to_end(aname)
|
||||||
|
cls.accessibles = accessibles
|
||||||
|
|
||||||
|
cls.wrappedAttributes = {'isWrapped': True}
|
||||||
|
# create wrappers for access methods
|
||||||
|
wrapped_name = '_' + cls.__name__
|
||||||
|
for pname, pobj in accessibles.items():
|
||||||
|
# wrap of reading/writing funcs
|
||||||
|
if not isinstance(pobj, Parameter):
|
||||||
|
# nothing to do for Commands
|
||||||
|
continue
|
||||||
|
|
||||||
|
rname = 'read_' + pname
|
||||||
|
rfunc = getattr(cls, rname, None)
|
||||||
|
# create wrapper
|
||||||
|
if rfunc:
|
||||||
|
|
||||||
|
def new_rfunc(self, pname=pname, rfunc=rfunc):
|
||||||
|
with self.accessLock:
|
||||||
|
try:
|
||||||
|
value = rfunc(self)
|
||||||
|
self.log.debug("read_%s returned %r", pname, value)
|
||||||
|
if value is Done: # TODO: to be removed when all code using Done is updated
|
||||||
|
return getattr(self, pname)
|
||||||
|
pobj = self.accessibles[pname]
|
||||||
|
value = pobj.datatype(value)
|
||||||
|
except Exception as e:
|
||||||
|
self.log.debug("read_%s failed with %r", pname, e)
|
||||||
|
if isinstance(e, SECoPError):
|
||||||
|
e.raising_methods.append(f'{self.name}.read_{pname}')
|
||||||
|
self.announceUpdate(pname, err=e)
|
||||||
|
raise
|
||||||
|
self.announceUpdate(pname, value, validate=False)
|
||||||
|
return value
|
||||||
|
|
||||||
|
new_rfunc.poll = getattr(rfunc, 'poll', True)
|
||||||
|
else:
|
||||||
|
|
||||||
|
def new_rfunc(self, pname=pname):
|
||||||
|
return getattr(self, pname)
|
||||||
|
|
||||||
|
new_rfunc.poll = False
|
||||||
|
|
||||||
|
new_rfunc.__name__ = rname
|
||||||
|
new_rfunc.__qualname__ = wrapped_name + '.' + rname
|
||||||
|
new_rfunc.__module__ = cls.__module__
|
||||||
|
cls.wrappedAttributes[rname] = new_rfunc
|
||||||
|
|
||||||
|
cname = 'check_' + pname
|
||||||
|
for postfix in ('_limits', '_min', '_max'):
|
||||||
|
limname = pname + postfix
|
||||||
|
if limname in accessibles:
|
||||||
|
# find the base class, where the parameter <limname> is defined first.
|
||||||
|
# we have to check all bases, as they may not be treated yet when
|
||||||
|
# not inheriting from HasAccessibles
|
||||||
|
base = next(b for b in reversed(cls.__mro__) if limname in b.__dict__)
|
||||||
|
if cname not in base.__dict__:
|
||||||
|
# there is no check method yet at this class
|
||||||
|
# add check function to the class where the limit was defined
|
||||||
|
setattr(base, cname, lambda self, value, pname=pname: self.checkLimits(value, pname))
|
||||||
|
|
||||||
|
cfuncs = tuple(filter(None, (b.__dict__.get(cname) for b in cls.__mro__)))
|
||||||
|
wname = 'write_' + pname
|
||||||
|
wfunc = getattr(cls, wname, None)
|
||||||
|
if wfunc or not pobj.readonly:
|
||||||
|
# allow write method even when parameter is readonly, but internally writable
|
||||||
|
|
||||||
|
def new_wfunc(self, value, pname=pname, wfunc=wfunc, check_funcs=cfuncs):
|
||||||
|
with self.accessLock:
|
||||||
|
self.log.debug('validate %r to datatype of %r', value, pname)
|
||||||
|
validate = self.parameters[pname].datatype.validate
|
||||||
|
try:
|
||||||
|
new_value = validate(value)
|
||||||
|
for c in check_funcs:
|
||||||
|
if c(self, value):
|
||||||
|
break
|
||||||
|
if wfunc:
|
||||||
|
new_value = wfunc(self, new_value)
|
||||||
|
self.log.debug('write_%s(%r) returned %r', pname, value, new_value)
|
||||||
|
if new_value is Done: # TODO: to be removed when all code using Done is updated
|
||||||
|
return getattr(self, pname)
|
||||||
|
new_value = value if new_value is None else validate(new_value)
|
||||||
|
except Exception as e:
|
||||||
|
if isinstance(e, SECoPError):
|
||||||
|
e.raising_methods.append(f'{self.name}.write_{pname}')
|
||||||
|
self.announceUpdate(pname, err=e)
|
||||||
|
raise
|
||||||
|
self.announceUpdate(pname, new_value, validate=False)
|
||||||
|
return new_value
|
||||||
|
|
||||||
|
new_wfunc.__name__ = wname
|
||||||
|
new_wfunc.__qualname__ = wrapped_name + '.' + wname
|
||||||
|
new_wfunc.__module__ = cls.__module__
|
||||||
|
cls.wrappedAttributes[wname] = new_wfunc
|
||||||
|
|
||||||
|
cls.checkedMethods.update(cls.wrappedAttributes)
|
||||||
|
|
||||||
|
# check for programming errors
|
||||||
|
for attrname in dir(cls):
|
||||||
|
prefix, _, pname = attrname.partition('_')
|
||||||
|
if not pname:
|
||||||
|
continue
|
||||||
|
if prefix == 'do':
|
||||||
|
raise ProgrammingError(f'{cls.__name__!r}: old style command {attrname!r} not supported anymore')
|
||||||
|
if prefix in ('read', 'write') and attrname not in cls.checkedMethods:
|
||||||
|
raise ProgrammingError(f'{cls.__name__}.{attrname} defined, but {pname!r} is no parameter')
|
||||||
|
|
||||||
|
try:
|
||||||
|
# update Status type
|
||||||
|
cls.Status = cls.status.datatype.members[0]._enum
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
res = {}
|
||||||
|
# collect info about properties
|
||||||
|
for pn, pv in cls.propertyDict.items():
|
||||||
|
if pv.settable:
|
||||||
|
res[pn] = pv
|
||||||
|
# collect info about parameters and their properties
|
||||||
|
for param, pobj in cls.accessibles.items():
|
||||||
|
res[param] = {}
|
||||||
|
for pn, pv in pobj.getProperties().items():
|
||||||
|
if pv.settable:
|
||||||
|
res[param][pn] = pv
|
||||||
|
cls.configurables = res
|
||||||
|
|
||||||
|
def __new__(cls, *args, **kwds):
|
||||||
|
wrapper_class = wrapperClasses.get(cls)
|
||||||
|
if wrapper_class is None:
|
||||||
|
wrapper_class = type('_' + cls.__name__, (cls,), cls.wrappedAttributes)
|
||||||
|
wrapperClasses[cls] = wrapper_class
|
||||||
|
return super().__new__(wrapper_class)
|
||||||
|
|
||||||
|
|
||||||
|
class Feature(HasAccessibles):
|
||||||
|
"""all things belonging to a small, predefined functionality influencing the working of a module
|
||||||
|
|
||||||
|
a mixin with Feature as a direct base class is recognized as a SECoP feature
|
||||||
|
and reported in the module property 'features'
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class PollInfo:
|
||||||
|
def __init__(self, pollinterval, trigger_event):
|
||||||
|
self.interval = pollinterval
|
||||||
|
self.last_main = 0
|
||||||
|
self.last_slow = 0
|
||||||
|
self.pending_errors = set()
|
||||||
|
self.polled_parameters = []
|
||||||
|
self.fast_flag = False
|
||||||
|
self.trigger_event = trigger_event
|
||||||
|
|
||||||
|
def trigger(self, immediate=False):
|
||||||
|
"""trigger a recalculation of poll due times
|
||||||
|
|
||||||
|
:param immediate: when True, doPoll should be called as soon as possible
|
||||||
|
"""
|
||||||
|
if immediate:
|
||||||
|
self.last_main = 0
|
||||||
|
self.trigger_event.set()
|
||||||
|
|
||||||
|
def update_interval(self, pollinterval):
|
||||||
|
if not self.fast_flag:
|
||||||
|
self.interval = pollinterval
|
||||||
|
self.trigger()
|
||||||
|
|
||||||
|
|
||||||
|
class Module(HasAccessibles):
|
||||||
|
"""basic module
|
||||||
|
|
||||||
|
all SECoP modules derive from this.
|
||||||
|
|
||||||
|
:param name: the modules name
|
||||||
|
:param logger: a logger instance
|
||||||
|
:param cfgdict: the dict from this modules section in the config file
|
||||||
|
:param srv: the server instance
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
|
||||||
|
- the programmer normally should not need to reimplement :meth:`__init__`
|
||||||
|
- within modules, parameters should only be addressed as ``self.<pname>``,
|
||||||
|
i.e. ``self.value``, ``self.target`` etc...
|
||||||
|
|
||||||
|
- these are accessing the cached version.
|
||||||
|
- they can also be written to, generating an async update
|
||||||
|
|
||||||
|
- if you want to 'update from the hardware', call ``self.read_<pname>()`` instead
|
||||||
|
|
||||||
|
- the return value of this method will be used as the new cached value and
|
||||||
|
be an async update sent automatically.
|
||||||
|
|
||||||
|
- if you want to 'update the hardware' call ``self.write_<pname>(<new value>)``.
|
||||||
|
|
||||||
|
- The return value of this method will also update the cache.
|
||||||
|
|
||||||
|
"""
|
||||||
|
# static properties, definitions in derived classes should overwrite earlier ones.
|
||||||
|
# note: properties don't change after startup and are usually filled
|
||||||
|
# with data from a cfg file...
|
||||||
|
# note: only the properties predefined here are allowed to be set in the cfg file
|
||||||
|
export = Property('flag if this module is to be exported', BoolType(), default=True, export=False)
|
||||||
|
group = Property('optional group the module belongs to', StringType(), default='', extname='group')
|
||||||
|
description = Property('description of the module', TextType(), extname='description', mandatory=True)
|
||||||
|
meaning = Property('optional meaning indicator', TupleOf(StringType(), IntRange(0, 50)),
|
||||||
|
default=('', 0), extname='meaning')
|
||||||
|
visibility = Property('optional visibility hint', EnumType('visibility', user=1, advanced=2, expert=3),
|
||||||
|
default='user', extname='visibility')
|
||||||
|
implementation = Property('internal name of the implementation class of the module', StringType(),
|
||||||
|
extname='implementation')
|
||||||
|
interface_classes = Property('offical highest interface-class of the module', ArrayOf(StringType()),
|
||||||
|
extname='interface_classes')
|
||||||
|
features = Property('list of features', ArrayOf(StringType()), extname='features')
|
||||||
|
pollinterval = Property('poll interval for parameters handled by doPoll', FloatRange(0.1, 120), default=5)
|
||||||
|
slowinterval = Property('poll interval for other parameters', FloatRange(0.1, 120), default=15)
|
||||||
|
omit_unchanged_within = Property('default for minimum time between updates of unchanged values',
|
||||||
|
NoneOr(FloatRange(0)), export=False, default=None)
|
||||||
|
enablePoll = True
|
||||||
|
|
||||||
|
pollInfo = None
|
||||||
|
triggerPoll = None # trigger event for polls. used on io modules and modules without io
|
||||||
|
|
||||||
|
def __init__(self, name, logger, cfgdict, srv):
|
||||||
|
# remember the secnode for interacting with other modules and the
|
||||||
|
# server
|
||||||
|
self.secNode = srv.secnode
|
||||||
|
self.log = logger
|
||||||
|
self.name = name
|
||||||
|
self.paramCallbacks = {}
|
||||||
|
self.earlyInitDone = False
|
||||||
|
self.initModuleDone = False
|
||||||
|
self.startModuleDone = False
|
||||||
|
self.remoteLogHandler = None
|
||||||
|
self.accessLock = threading.RLock() # for read_* / write_* methods
|
||||||
|
self.updateLock = threading.RLock() # for announceUpdate
|
||||||
|
self.polledModules = [] # modules polled by thread started in self.startModules
|
||||||
|
self.attachedModules = {}
|
||||||
|
self.errors = []
|
||||||
|
self._isinitialized = False
|
||||||
|
self.updateCallback = srv.dispatcher.announce_update
|
||||||
|
|
||||||
|
# handle module properties
|
||||||
|
# 1) make local copies of properties
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
# conversion from exported names to internal attribute names
|
||||||
|
self.accessiblename2attr = {}
|
||||||
|
self.writeDict = {} # values of parameters to be written
|
||||||
|
# properties, parameters and commands are auto-merged upon subclassing
|
||||||
|
self.parameters = {}
|
||||||
|
self.commands = {}
|
||||||
|
|
||||||
|
# 2) check and apply properties specified in cfgdict as
|
||||||
|
# '<propertyname> = <propertyvalue>'
|
||||||
|
# pylint: disable=consider-using-dict-items
|
||||||
|
for key in self.propertyDict:
|
||||||
|
value = cfgdict.pop(key, None)
|
||||||
|
if value is not None:
|
||||||
|
try:
|
||||||
|
if isinstance(value, dict):
|
||||||
|
self.setProperty(key, value['value'])
|
||||||
|
else:
|
||||||
|
self.setProperty(key, value)
|
||||||
|
except BadValueError:
|
||||||
|
self.errors.append(f'{key}: value {value!r} does not match {self.propertyDict[key].datatype!r}!')
|
||||||
|
|
||||||
|
# 3) set automatic properties
|
||||||
|
mycls, = self.__class__.__bases__ # skip the wrapper class
|
||||||
|
myclassname = f'{mycls.__module__}.{mycls.__name__}'
|
||||||
|
self.implementation = myclassname
|
||||||
|
|
||||||
|
# list of only the 'highest' secop module class
|
||||||
|
self.interface_classes = [
|
||||||
|
b.__name__ for b in mycls.__mro__ if b.__name__ in SECoP_BASE_CLASSES][:1]
|
||||||
|
|
||||||
|
# handle Features
|
||||||
|
self.features = [b.__name__ for b in mycls.__mro__ if Feature in b.__bases__]
|
||||||
|
|
||||||
|
# handle accessibles
|
||||||
|
# 1) make local copies of parameter objects
|
||||||
|
# they need to be individual per instance since we use them also
|
||||||
|
# to cache the current value + qualifiers...
|
||||||
|
# do not re-use self.accessibles as this is the same for all instances
|
||||||
|
accessibles = self.accessibles
|
||||||
|
self.accessibles = {}
|
||||||
|
for aname, aobj in accessibles.items():
|
||||||
|
# make a copy of the Parameter/Command object
|
||||||
|
aobj = aobj.copy()
|
||||||
|
acfg = cfgdict.pop(aname, None)
|
||||||
|
self._add_accessible(aname, aobj, cfg=acfg)
|
||||||
|
|
||||||
|
# 3) complain about names not found as accessible or property names
|
||||||
|
if cfgdict:
|
||||||
|
self.errors.append(
|
||||||
|
f"{', '.join(cfgdict.keys())} does not exist (use one of"
|
||||||
|
f" {', '.join(list(self.accessibles) + list(self.propertyDict))})")
|
||||||
|
|
||||||
|
# 5) ensure consistency of all accessibles added here
|
||||||
|
for aobj in self.accessibles.values():
|
||||||
|
aobj.finish(self)
|
||||||
|
|
||||||
|
# Modify units AFTER applying the cfgdict
|
||||||
|
mainvalue = self.parameters.get('value')
|
||||||
|
if mainvalue:
|
||||||
|
mainunit = mainvalue.datatype.unit
|
||||||
|
if mainunit:
|
||||||
|
self.applyMainUnit(mainunit)
|
||||||
|
|
||||||
|
# 6) check complete configuration of * properties
|
||||||
|
if not self.errors:
|
||||||
|
try:
|
||||||
|
self.checkProperties()
|
||||||
|
except ConfigError as e:
|
||||||
|
self.errors.append(str(e))
|
||||||
|
for aname, aobj in self.accessibles.items():
|
||||||
|
try:
|
||||||
|
aobj.checkProperties()
|
||||||
|
except (ConfigError, ProgrammingError) as e:
|
||||||
|
self.errors.append(f'{aname}: {e}')
|
||||||
|
if self.errors:
|
||||||
|
raise ConfigError(self.errors)
|
||||||
|
|
||||||
|
# helper cfg-editor
|
||||||
|
def __iter__(self):
|
||||||
|
return self.accessibles.__iter__()
|
||||||
|
|
||||||
|
def __getitem__(self, item):
|
||||||
|
return self.accessibles.__getitem__(item)
|
||||||
|
|
||||||
|
def applyMainUnit(self, mainunit):
|
||||||
|
"""replace $ in units of parameters by mainunit"""
|
||||||
|
for pobj in self.parameters.values():
|
||||||
|
pobj.datatype.set_main_unit(mainunit)
|
||||||
|
|
||||||
|
def _add_accessible(self, name, accessible, cfg=None):
|
||||||
|
if self.startModuleDone:
|
||||||
|
raise ProgrammingError('Accessibles can only be added before startModule()!')
|
||||||
|
if not self.export: # do not export parameters of a module not exported
|
||||||
|
accessible.export = False
|
||||||
|
self.accessibles[name] = accessible
|
||||||
|
if accessible.export:
|
||||||
|
self.accessiblename2attr[accessible.export] = name
|
||||||
|
if isinstance(accessible, Parameter):
|
||||||
|
self.parameters[name] = accessible
|
||||||
|
if isinstance(accessible, Command):
|
||||||
|
self.commands[name] = accessible
|
||||||
|
if cfg:
|
||||||
|
try:
|
||||||
|
for propname, propvalue in cfg.items():
|
||||||
|
accessible.setProperty(propname, propvalue)
|
||||||
|
except KeyError:
|
||||||
|
self.errors.append(f"'{name}' has no property '{propname}'")
|
||||||
|
except BadValueError as e:
|
||||||
|
self.errors.append(f'{name}.{propname}: {str(e)}')
|
||||||
|
if isinstance(accessible, Parameter):
|
||||||
|
self._handle_writes(name, accessible)
|
||||||
|
|
||||||
|
def _handle_writes(self, pname, pobj):
|
||||||
|
""" register value for writing, if given
|
||||||
|
apply default when no value is given (in cfg or as Parameter argument)
|
||||||
|
or complain, when cfg is needed
|
||||||
|
"""
|
||||||
|
self.paramCallbacks[pname] = []
|
||||||
|
if isinstance(pobj, Limit):
|
||||||
|
basepname = pname.rpartition('_')[0]
|
||||||
|
baseparam = self.parameters.get(basepname)
|
||||||
|
if not baseparam:
|
||||||
|
self.errors.append(f'limit {pname!r} is given, but not {basepname!r}')
|
||||||
|
return
|
||||||
|
if baseparam.datatype is None:
|
||||||
|
return # an error will be reported on baseparam
|
||||||
|
pobj.set_datatype(baseparam.datatype)
|
||||||
|
if not pobj.hasDatatype():
|
||||||
|
self.errors.append(f'{pname} needs a datatype')
|
||||||
|
return
|
||||||
|
if pobj.value is None:
|
||||||
|
if pobj.needscfg:
|
||||||
|
self.errors.append(f'{pname!r} has no default value and was not given in config!')
|
||||||
|
if pobj.default is None:
|
||||||
|
# we do not want to call the setter for this parameter for now,
|
||||||
|
# this should happen on the first read
|
||||||
|
pobj.readerror = ConfigError(f'parameter {pname!r} not initialized')
|
||||||
|
# above error will be triggered on activate after startup,
|
||||||
|
# when not all hardware parameters are read because of startup timeout
|
||||||
|
pobj.default = pobj.datatype.default
|
||||||
|
pobj.value = pobj.default
|
||||||
|
else:
|
||||||
|
# value given explicitly, either by cfg or as Parameter argument
|
||||||
|
pobj.given = True # for PersistentMixin
|
||||||
|
if hasattr(self, 'write_' + pname):
|
||||||
|
self.writeDict[pname] = pobj.value
|
||||||
|
if pobj.default is None:
|
||||||
|
pobj.default = pobj.value
|
||||||
|
# this checks again for datatype and sets the timestamp
|
||||||
|
setattr(self, pname, pobj.value)
|
||||||
|
|
||||||
|
def announceUpdate(self, pname, value=None, err=None, timestamp=None, validate=True):
|
||||||
|
"""announce a changed value or readerror
|
||||||
|
|
||||||
|
:param pname: parameter name
|
||||||
|
:param value: new value or None in case of error
|
||||||
|
:param err: None or an exception
|
||||||
|
:param timestamp: a timestamp or None for taking current time
|
||||||
|
:param validate: True: convert to datatype, in case of error store in readerror
|
||||||
|
:return:
|
||||||
|
|
||||||
|
when err=None and validate=False, the value must already be converted to the datatype
|
||||||
|
"""
|
||||||
|
|
||||||
|
with self.updateLock:
|
||||||
|
pobj = self.parameters[pname]
|
||||||
|
timestamp = timestamp or time.time()
|
||||||
|
if not err:
|
||||||
|
try:
|
||||||
|
if validate:
|
||||||
|
value = pobj.datatype(value)
|
||||||
|
except Exception as e:
|
||||||
|
err = e
|
||||||
|
else:
|
||||||
|
changed = pobj.value != value
|
||||||
|
# store the value even in case of error
|
||||||
|
pobj.value = value
|
||||||
|
if err:
|
||||||
|
if secop_error(err) == pobj.readerror:
|
||||||
|
err.report_error = False
|
||||||
|
return # no updates for repeated errors
|
||||||
|
err = secop_error(err)
|
||||||
|
value_err = value, err
|
||||||
|
else:
|
||||||
|
if not changed and timestamp < (pobj.timestamp or 0) + pobj.omit_unchanged_within:
|
||||||
|
# no change within short time -> omit
|
||||||
|
return
|
||||||
|
value_err = (value,)
|
||||||
|
pobj.timestamp = timestamp or time.time()
|
||||||
|
pobj.readerror = err
|
||||||
|
for cbfunc, cbargs in self.paramCallbacks[pname]:
|
||||||
|
try:
|
||||||
|
cbfunc(*cbargs, *value_err)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
if pobj.export:
|
||||||
|
self.updateCallback(self, pobj)
|
||||||
|
|
||||||
|
def addCallback(self, pname, callback_function, *args):
|
||||||
|
self.paramCallbacks[pname].append((callback_function, args))
|
||||||
|
|
||||||
|
def registerCallbacks(self, modobj, autoupdate=()):
|
||||||
|
"""register callbacks to another module <modobj>
|
||||||
|
|
||||||
|
whenever a self.<param> changes or changes its error state:
|
||||||
|
<modobj>.update_param(<value> [, <exc>]) is called,
|
||||||
|
where <value> is the new value and <exc> is given only in case of error.
|
||||||
|
if the method does not exist, and <param> is in autoupdate
|
||||||
|
<modobj>.announceUpdate(<pname>, <value>, <exc>) is called
|
||||||
|
with <exc> being None in case of no error.
|
||||||
|
|
||||||
|
Remark: when <modobj>.update_<param> does not accept the <exc> argument,
|
||||||
|
nothing happens (the callback is catched by try / except).
|
||||||
|
Any exceptions raised by the callback function are silently ignored.
|
||||||
|
"""
|
||||||
|
autoupdate = set(autoupdate)
|
||||||
|
for pname in self.parameters:
|
||||||
|
cbfunc = getattr(modobj, 'update_' + pname, None)
|
||||||
|
if cbfunc:
|
||||||
|
self.addCallback(pname, cbfunc)
|
||||||
|
elif pname in autoupdate:
|
||||||
|
self.addCallback(pname, modobj.announceUpdate, pname)
|
||||||
|
|
||||||
|
def isBusy(self, status=None):
|
||||||
|
"""helper function for treating substates of BUSY correctly"""
|
||||||
|
# defined even for non drivable (used for dynamic polling)
|
||||||
|
return False
|
||||||
|
|
||||||
|
def earlyInit(self):
|
||||||
|
"""initialise module with stuff to be done before all modules are created"""
|
||||||
|
self.earlyInitDone = True
|
||||||
|
|
||||||
|
def initModule(self):
|
||||||
|
"""initialise module with stuff to be done after all modules are created"""
|
||||||
|
self.initModuleDone = True
|
||||||
|
if self.enablePoll or self.writeDict:
|
||||||
|
# enablePoll == False: we still need the poll thread for writing values from writeDict
|
||||||
|
if hasattr(self, 'io'):
|
||||||
|
self.io.polledModules.append(self)
|
||||||
|
if not self.io.triggerPoll:
|
||||||
|
# when self.io.enablePoll is False, triggerPoll is not
|
||||||
|
# created for self.io in the else clause below
|
||||||
|
self.io.triggerPoll = threading.Event()
|
||||||
|
else:
|
||||||
|
self.triggerPoll = threading.Event()
|
||||||
|
self.polledModules.append(self)
|
||||||
|
|
||||||
|
def startModule(self, start_events):
|
||||||
|
"""runs after init of all modules
|
||||||
|
|
||||||
|
when a thread is started, a trigger function may signal that it
|
||||||
|
has finished its initial work
|
||||||
|
start_events.get_trigger(<timeout>) creates such a trigger and
|
||||||
|
registers it in the server for waiting
|
||||||
|
<timeout> defaults to 30 seconds
|
||||||
|
"""
|
||||||
|
# we do not need self.errors any longer. should we delete it?
|
||||||
|
# del self.errors
|
||||||
|
if self.polledModules:
|
||||||
|
mkthread(self.__pollThread, self.polledModules, start_events.get_trigger())
|
||||||
|
self.startModuleDone = True
|
||||||
|
|
||||||
|
def initialReads(self):
|
||||||
|
"""initial reads to be done
|
||||||
|
|
||||||
|
override to read initial values from HW, when it is not desired
|
||||||
|
to poll them afterwards
|
||||||
|
|
||||||
|
called from the poll thread, after writeInitParams but before
|
||||||
|
all parameters are polled once
|
||||||
|
"""
|
||||||
|
|
||||||
|
def shutdownModule(self):
|
||||||
|
"""called when the sever shuts down
|
||||||
|
|
||||||
|
any cleanup-work should be performed here, like closing threads and
|
||||||
|
saving data.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def doPoll(self):
|
||||||
|
"""polls important parameters like value and status
|
||||||
|
|
||||||
|
all other parameters are polled automatically
|
||||||
|
"""
|
||||||
|
|
||||||
|
def setFastPoll(self, flag, fast_interval=0.25):
|
||||||
|
"""change poll interval
|
||||||
|
|
||||||
|
:param flag: enable/disable fast poll mode
|
||||||
|
:param fast_interval: fast poll interval
|
||||||
|
"""
|
||||||
|
if self.pollInfo:
|
||||||
|
self.pollInfo.fast_flag = flag
|
||||||
|
self.pollInfo.interval = fast_interval if flag else self.pollinterval
|
||||||
|
self.pollInfo.trigger()
|
||||||
|
|
||||||
|
def callPollFunc(self, rfunc, raise_com_failed=False):
|
||||||
|
"""call read method with proper error handling"""
|
||||||
|
try:
|
||||||
|
rfunc()
|
||||||
|
if rfunc.__name__ in self.pollInfo.pending_errors:
|
||||||
|
self.log.info('%s: o.k.', rfunc.__name__)
|
||||||
|
self.pollInfo.pending_errors.discard(rfunc.__name__)
|
||||||
|
except Exception as e:
|
||||||
|
if getattr(e, 'report_error', True):
|
||||||
|
name = rfunc.__name__
|
||||||
|
self.pollInfo.pending_errors.add(name) # trigger o.k. message after error is resolved
|
||||||
|
if isinstance(e, SECoPError):
|
||||||
|
e.raising_methods.append(name)
|
||||||
|
if e.silent:
|
||||||
|
self.log.debug('%s', e.format(False))
|
||||||
|
else:
|
||||||
|
self.log.error('%s', e.format(False))
|
||||||
|
if raise_com_failed and isinstance(e, CommunicationFailedError):
|
||||||
|
raise
|
||||||
|
else:
|
||||||
|
# not a SECoPError: this is proabably a programming error
|
||||||
|
# we want to log the traceback
|
||||||
|
self.log.error('%s', formatException())
|
||||||
|
|
||||||
|
def __pollThread(self, modules, started_callback):
|
||||||
|
"""poll thread body
|
||||||
|
|
||||||
|
:param modules: list of modules to be handled by this thread
|
||||||
|
:param started_callback: to be called after all polls are done once
|
||||||
|
|
||||||
|
before polling, parameters which need hardware initialisation are written
|
||||||
|
"""
|
||||||
|
polled_modules = [m for m in modules if m.enablePoll]
|
||||||
|
if hasattr(self, 'registerReconnectCallback'):
|
||||||
|
# self is a communicator supporting reconnections
|
||||||
|
def trigger_all(trg=self.triggerPoll, polled_modules=polled_modules):
|
||||||
|
for m in polled_modules:
|
||||||
|
m.pollInfo.last_main = 0
|
||||||
|
m.pollInfo.last_slow = 0
|
||||||
|
trg.set()
|
||||||
|
self.registerReconnectCallback('trigger_polls', trigger_all)
|
||||||
|
|
||||||
|
# collect all read functions
|
||||||
|
for mobj in polled_modules:
|
||||||
|
pinfo = mobj.pollInfo = PollInfo(mobj.pollinterval, self.triggerPoll)
|
||||||
|
# trigger a poll interval change when self.pollinterval changes.
|
||||||
|
if 'pollinterval' in mobj.paramCallbacks:
|
||||||
|
mobj.addCallback('pollinterval', pinfo.update_interval)
|
||||||
|
|
||||||
|
for pname, pobj in mobj.parameters.items():
|
||||||
|
rfunc = getattr(mobj, 'read_' + pname)
|
||||||
|
if rfunc.poll:
|
||||||
|
pinfo.polled_parameters.append((mobj, rfunc, pobj))
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
for mobj in modules:
|
||||||
|
# TODO when needed: here we might add a call to a method :meth:`beforeWriteInit`
|
||||||
|
mobj.writeInitParams()
|
||||||
|
mobj.initialReads()
|
||||||
|
# call all read functions a first time
|
||||||
|
for m in polled_modules:
|
||||||
|
for mobj, rfunc, _ in m.pollInfo.polled_parameters:
|
||||||
|
mobj.callPollFunc(rfunc, raise_com_failed=True)
|
||||||
|
# TODO when needed: here we might add calls to a method :meth:`afterInitPolls`
|
||||||
|
break
|
||||||
|
except CommunicationFailedError as e:
|
||||||
|
# when communication failed, probably all parameters and may be more modules are affected.
|
||||||
|
# as this would take a lot of time (summed up timeouts), we do not continue
|
||||||
|
# trying and let the server accept connections, further polls might success later
|
||||||
|
if started_callback:
|
||||||
|
self.log.error('communication failure on startup: %s', e)
|
||||||
|
started_callback()
|
||||||
|
started_callback = None
|
||||||
|
self.triggerPoll.wait(0.1) # wait for reconnection or max 10 sec.
|
||||||
|
break
|
||||||
|
if started_callback:
|
||||||
|
started_callback()
|
||||||
|
if not polled_modules: # no polls needed - exit thread
|
||||||
|
return
|
||||||
|
to_poll = ()
|
||||||
|
while True:
|
||||||
|
now = time.time()
|
||||||
|
wait_time = 999
|
||||||
|
for mobj in modules:
|
||||||
|
pinfo = mobj.pollInfo
|
||||||
|
wait_time = min(pinfo.last_main + pinfo.interval - now, wait_time,
|
||||||
|
pinfo.last_slow + mobj.slowinterval - now)
|
||||||
|
if wait_time > 0 and not to_poll:
|
||||||
|
# nothing to do
|
||||||
|
self.triggerPoll.wait(wait_time)
|
||||||
|
self.triggerPoll.clear()
|
||||||
|
continue
|
||||||
|
# call doPoll of all modules where due
|
||||||
|
for mobj in modules:
|
||||||
|
pinfo = mobj.pollInfo
|
||||||
|
if now > pinfo.last_main + pinfo.interval:
|
||||||
|
try:
|
||||||
|
pinfo.last_main = (now // pinfo.interval) * pinfo.interval
|
||||||
|
except ZeroDivisionError:
|
||||||
|
pinfo.last_main = now
|
||||||
|
mobj.callPollFunc(mobj.doPoll)
|
||||||
|
now = time.time()
|
||||||
|
# find ONE due slow poll and call it
|
||||||
|
loop = True
|
||||||
|
while loop: # loops max. 2 times, when to_poll is at end
|
||||||
|
for mobj, rfunc, pobj in to_poll:
|
||||||
|
if now > pobj.timestamp + mobj.slowinterval * 0.5:
|
||||||
|
mobj.callPollFunc(rfunc)
|
||||||
|
loop = False # one poll done
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
to_poll = []
|
||||||
|
# collect due slow polls
|
||||||
|
for mobj in modules:
|
||||||
|
pinfo = mobj.pollInfo
|
||||||
|
if now > pinfo.last_slow + mobj.slowinterval:
|
||||||
|
to_poll.extend(pinfo.polled_parameters)
|
||||||
|
pinfo.last_slow = (now // mobj.slowinterval) * mobj.slowinterval
|
||||||
|
if to_poll:
|
||||||
|
to_poll = iter(to_poll)
|
||||||
|
else:
|
||||||
|
loop = False # no slow polls ready
|
||||||
|
|
||||||
|
def writeInitParams(self):
|
||||||
|
"""write values for parameters with configured values
|
||||||
|
|
||||||
|
- does proper error handling
|
||||||
|
|
||||||
|
called at the beginning of the poller thread and for writing persistent values
|
||||||
|
"""
|
||||||
|
for pname in list(self.writeDict):
|
||||||
|
value = self.writeDict.pop(pname, Done)
|
||||||
|
# in the mean time, a poller or handler might already have done it
|
||||||
|
if value is not Done:
|
||||||
|
wfunc = getattr(self, 'write_' + pname, None)
|
||||||
|
if wfunc is None:
|
||||||
|
setattr(self, pname, value)
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
self.log.debug('initialize parameter %s', pname)
|
||||||
|
wfunc(value)
|
||||||
|
except SECoPError as e:
|
||||||
|
if e.silent:
|
||||||
|
self.log.debug('%s: %s', pname, str(e))
|
||||||
|
else:
|
||||||
|
self.log.error('%s: %s', pname, str(e))
|
||||||
|
except Exception:
|
||||||
|
self.log.error(formatException())
|
||||||
|
|
||||||
|
def setRemoteLogging(self, conn, level, send_log):
|
||||||
|
if self.remoteLogHandler is None:
|
||||||
|
for handler in self.log.handlers:
|
||||||
|
if isinstance(handler, RemoteLogHandler):
|
||||||
|
handler.send_log = send_log
|
||||||
|
self.remoteLogHandler = handler
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
raise ValueError('remote handler not found')
|
||||||
|
self.remoteLogHandler.set_conn_level(self.name, conn, level)
|
||||||
|
|
||||||
|
def checkLimits(self, value, pname='target'):
|
||||||
|
"""check for limits
|
||||||
|
|
||||||
|
:param value: the value to be checked for <pname>_min <= value <= <pname>_max
|
||||||
|
:param pname: parameter name, default is 'target'
|
||||||
|
|
||||||
|
raises RangeError in case the value is not valid
|
||||||
|
|
||||||
|
This method is called automatically and needs therefore rarely to be
|
||||||
|
called by the programmer. It might be used in a check_<param> method,
|
||||||
|
when no automatic super call is desired.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
min_, max_ = getattr(self, pname + '_limits')
|
||||||
|
if not min_ <= value <= max_:
|
||||||
|
raise RangeError(f'{pname} outside {pname}_limits')
|
||||||
|
return
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
min_ = getattr(self, pname + '_min', float('-inf'))
|
||||||
|
max_ = getattr(self, pname + '_max', float('inf'))
|
||||||
|
if min_ > max_:
|
||||||
|
raise RangeError(f'invalid limits: {pname}_min > {pname}_max')
|
||||||
|
if value < min_:
|
||||||
|
raise RangeError(f'{pname} below {pname}_min')
|
||||||
|
if value > max_:
|
||||||
|
raise RangeError(f'{pname} above {pname}_max')
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# *****************************************************************************
|
# *****************************************************************************
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify it under
|
# This program is free software; you can redistribute it and/or modify it under
|
||||||
@ -18,842 +17,26 @@
|
|||||||
# Module authors:
|
# Module authors:
|
||||||
# Enrico Faulhaber <enrico.faulhaber@frm2.tum.de>
|
# Enrico Faulhaber <enrico.faulhaber@frm2.tum.de>
|
||||||
# Markus Zolliker <markus.zolliker@psi.ch>
|
# Markus Zolliker <markus.zolliker@psi.ch>
|
||||||
|
# Alexander Zaft <a.zaft@fz-juelich.de>
|
||||||
#
|
#
|
||||||
# *****************************************************************************
|
# *****************************************************************************
|
||||||
"""Define base classes for real Modules implemented in the server"""
|
"""Define base classes for real Modules implemented in the server"""
|
||||||
|
|
||||||
|
|
||||||
import time
|
from frappy.datatypes import FloatRange, \
|
||||||
import threading
|
StatusType, StringType
|
||||||
from collections import OrderedDict
|
from frappy.errors import ConfigError, ProgrammingError
|
||||||
|
|
||||||
from frappy.datatypes import ArrayOf, BoolType, EnumType, FloatRange, \
|
|
||||||
IntRange, StatusType, StringType, TextType, TupleOf, \
|
|
||||||
NoneOr
|
|
||||||
from frappy.errors import BadValueError, CommunicationFailedError, ConfigError, \
|
|
||||||
ProgrammingError, SECoPError, secop_error, RangeError
|
|
||||||
from frappy.lib import formatException, mkthread, UniqueObject
|
|
||||||
from frappy.lib.enum import Enum
|
from frappy.lib.enum import Enum
|
||||||
from frappy.params import Accessible, Command, Parameter, Limit
|
from frappy.params import Command, Parameter
|
||||||
from frappy.properties import HasProperties, Property
|
from frappy.properties import Property
|
||||||
from frappy.logging import RemoteLogHandler, HasComlog
|
from frappy.logging import HasComlog
|
||||||
|
|
||||||
Done = UniqueObject('Done')
|
from .modulebase import Module
|
||||||
"""a special return value for a read_<param>/write_<param> method
|
|
||||||
|
|
||||||
indicating that the setter is triggered already"""
|
|
||||||
|
|
||||||
wrapperClasses = {}
|
|
||||||
|
|
||||||
|
|
||||||
class HasAccessibles(HasProperties):
|
|
||||||
"""base class of Module
|
|
||||||
|
|
||||||
joining the class's properties, parameters and commands dicts with
|
|
||||||
those of base classes.
|
|
||||||
wrap read_*/write_* methods
|
|
||||||
(so the dispatcher will get notified of changed values)
|
|
||||||
"""
|
|
||||||
isWrapped = False
|
|
||||||
checkedMethods = set()
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def __init_subclass__(cls): # pylint: disable=too-many-branches
|
|
||||||
super().__init_subclass__()
|
|
||||||
if cls.isWrapped:
|
|
||||||
return
|
|
||||||
# merge accessibles from all sub-classes, treat overrides
|
|
||||||
# for now, allow to use also the old syntax (parameters/commands dict)
|
|
||||||
accessibles = OrderedDict() # dict of accessibles
|
|
||||||
merged_properties = {} # dict of dict of merged properties
|
|
||||||
new_names = [] # list of names of new accessibles
|
|
||||||
override_values = {} # bare values overriding a parameter and methods overriding a command
|
|
||||||
|
|
||||||
for base in reversed(cls.__mro__):
|
|
||||||
for key, value in base.__dict__.items():
|
|
||||||
if isinstance(value, Accessible):
|
|
||||||
value.updateProperties(merged_properties.setdefault(key, {}))
|
|
||||||
if base == cls and key not in accessibles:
|
|
||||||
new_names.append(key)
|
|
||||||
accessibles[key] = value
|
|
||||||
override_values.pop(key, None)
|
|
||||||
elif key in accessibles:
|
|
||||||
override_values[key] = value
|
|
||||||
for aname, aobj in list(accessibles.items()):
|
|
||||||
if aname in override_values:
|
|
||||||
aobj = aobj.copy()
|
|
||||||
value = override_values[aname]
|
|
||||||
if value is None:
|
|
||||||
accessibles.pop(aname)
|
|
||||||
continue
|
|
||||||
aobj.merge(merged_properties[aname])
|
|
||||||
aobj.override(value)
|
|
||||||
# replace the bare value by the created accessible
|
|
||||||
setattr(cls, aname, aobj)
|
|
||||||
else:
|
|
||||||
aobj.merge(merged_properties[aname])
|
|
||||||
accessibles[aname] = aobj
|
|
||||||
|
|
||||||
# rebuild order: (1) inherited items, (2) items from paramOrder, (3) new accessibles
|
|
||||||
# move (2) to the end
|
|
||||||
paramOrder = cls.__dict__.get('paramOrder', ())
|
|
||||||
for aname in paramOrder:
|
|
||||||
if aname in accessibles:
|
|
||||||
accessibles.move_to_end(aname)
|
|
||||||
# ignore unknown names
|
|
||||||
# move (3) to the end
|
|
||||||
for aname in new_names:
|
|
||||||
if aname not in paramOrder:
|
|
||||||
accessibles.move_to_end(aname)
|
|
||||||
# note: for python < 3.6 the order of inherited items is not ensured between
|
|
||||||
# declarations within the same class
|
|
||||||
cls.accessibles = accessibles
|
|
||||||
|
|
||||||
cls.wrappedAttributes = {'isWrapped': True}
|
|
||||||
# create wrappers for access methods
|
|
||||||
wrapped_name = '_' + cls.__name__
|
|
||||||
for pname, pobj in accessibles.items():
|
|
||||||
# wrap of reading/writing funcs
|
|
||||||
if not isinstance(pobj, Parameter):
|
|
||||||
# nothing to do for Commands
|
|
||||||
continue
|
|
||||||
|
|
||||||
rname = 'read_' + pname
|
|
||||||
rfunc = getattr(cls, rname, None)
|
|
||||||
# create wrapper
|
|
||||||
if rfunc:
|
|
||||||
|
|
||||||
def new_rfunc(self, pname=pname, rfunc=rfunc):
|
|
||||||
with self.accessLock:
|
|
||||||
try:
|
|
||||||
value = rfunc(self)
|
|
||||||
self.log.debug("read_%s returned %r", pname, value)
|
|
||||||
if value is Done: # TODO: to be removed when all code using Done is updated
|
|
||||||
return getattr(self, pname)
|
|
||||||
pobj = self.accessibles[pname]
|
|
||||||
value = pobj.datatype(value)
|
|
||||||
except Exception as e:
|
|
||||||
self.log.debug("read_%s failed with %r", pname, e)
|
|
||||||
if isinstance(e, SECoPError):
|
|
||||||
e.raising_methods.append(f'{self.name}.read_{pname}')
|
|
||||||
self.announceUpdate(pname, err=e)
|
|
||||||
raise
|
|
||||||
self.announceUpdate(pname, value, validate=False)
|
|
||||||
return value
|
|
||||||
|
|
||||||
new_rfunc.poll = getattr(rfunc, 'poll', True)
|
|
||||||
else:
|
|
||||||
|
|
||||||
def new_rfunc(self, pname=pname):
|
|
||||||
return getattr(self, pname)
|
|
||||||
|
|
||||||
new_rfunc.poll = False
|
|
||||||
|
|
||||||
new_rfunc.__name__ = rname
|
|
||||||
new_rfunc.__qualname__ = wrapped_name + '.' + rname
|
|
||||||
new_rfunc.__module__ = cls.__module__
|
|
||||||
cls.wrappedAttributes[rname] = new_rfunc
|
|
||||||
|
|
||||||
cname = 'check_' + pname
|
|
||||||
for postfix in ('_limits', '_min', '_max'):
|
|
||||||
limname = pname + postfix
|
|
||||||
if limname in accessibles:
|
|
||||||
# find the base class, where the parameter <limname> is defined first.
|
|
||||||
# we have to check all bases, as they may not be treated yet when
|
|
||||||
# not inheriting from HasAccessibles
|
|
||||||
base = next(b for b in reversed(cls.__mro__) if limname in b.__dict__)
|
|
||||||
if cname not in base.__dict__:
|
|
||||||
# there is no check method yet at this class
|
|
||||||
# add check function to the class where the limit was defined
|
|
||||||
setattr(base, cname, lambda self, value, pname=pname: self.checkLimits(value, pname))
|
|
||||||
|
|
||||||
cfuncs = tuple(filter(None, (b.__dict__.get(cname) for b in cls.__mro__)))
|
|
||||||
wname = 'write_' + pname
|
|
||||||
wfunc = getattr(cls, wname, None)
|
|
||||||
if wfunc or not pobj.readonly:
|
|
||||||
# allow write method even when parameter is readonly, but internally writable
|
|
||||||
|
|
||||||
def new_wfunc(self, value, pname=pname, wfunc=wfunc, check_funcs=cfuncs):
|
|
||||||
with self.accessLock:
|
|
||||||
self.log.debug('validate %r to datatype of %r', value, pname)
|
|
||||||
validate = self.parameters[pname].datatype.validate
|
|
||||||
try:
|
|
||||||
new_value = validate(value)
|
|
||||||
for c in check_funcs:
|
|
||||||
if c(self, value):
|
|
||||||
break
|
|
||||||
if wfunc:
|
|
||||||
new_value = wfunc(self, new_value)
|
|
||||||
self.log.debug('write_%s(%r) returned %r', pname, value, new_value)
|
|
||||||
if new_value is Done: # TODO: to be removed when all code using Done is updated
|
|
||||||
return getattr(self, pname)
|
|
||||||
new_value = value if new_value is None else validate(new_value)
|
|
||||||
except Exception as e:
|
|
||||||
if isinstance(e, SECoPError):
|
|
||||||
e.raising_methods.append(f'{self.name}.write_{pname}')
|
|
||||||
self.announceUpdate(pname, err=e)
|
|
||||||
raise
|
|
||||||
self.announceUpdate(pname, new_value, validate=False)
|
|
||||||
return new_value
|
|
||||||
|
|
||||||
new_wfunc.__name__ = wname
|
|
||||||
new_wfunc.__qualname__ = wrapped_name + '.' + wname
|
|
||||||
new_wfunc.__module__ = cls.__module__
|
|
||||||
cls.wrappedAttributes[wname] = new_wfunc
|
|
||||||
|
|
||||||
cls.checkedMethods.update(cls.wrappedAttributes)
|
|
||||||
|
|
||||||
# check for programming errors
|
|
||||||
for attrname in dir(cls):
|
|
||||||
prefix, _, pname = attrname.partition('_')
|
|
||||||
if not pname:
|
|
||||||
continue
|
|
||||||
if prefix == 'do':
|
|
||||||
raise ProgrammingError(f'{cls.__name__!r}: old style command {attrname!r} not supported anymore')
|
|
||||||
if prefix in ('read', 'write') and attrname not in cls.checkedMethods:
|
|
||||||
raise ProgrammingError(f'{cls.__name__}.{attrname} defined, but {pname!r} is no parameter')
|
|
||||||
|
|
||||||
try:
|
|
||||||
# update Status type
|
|
||||||
cls.Status = cls.status.datatype.members[0]._enum
|
|
||||||
except AttributeError:
|
|
||||||
pass
|
|
||||||
res = {}
|
|
||||||
# collect info about properties
|
|
||||||
for pn, pv in cls.propertyDict.items():
|
|
||||||
if pv.settable:
|
|
||||||
res[pn] = pv
|
|
||||||
# collect info about parameters and their properties
|
|
||||||
for param, pobj in cls.accessibles.items():
|
|
||||||
res[param] = {}
|
|
||||||
for pn, pv in pobj.getProperties().items():
|
|
||||||
if pv.settable:
|
|
||||||
res[param][pn] = pv
|
|
||||||
cls.configurables = res
|
|
||||||
|
|
||||||
def __new__(cls, *args, **kwds):
|
|
||||||
wrapper_class = wrapperClasses.get(cls)
|
|
||||||
if wrapper_class is None:
|
|
||||||
wrapper_class = type('_' + cls.__name__, (cls,), cls.wrappedAttributes)
|
|
||||||
wrapperClasses[cls] = wrapper_class
|
|
||||||
return super().__new__(wrapper_class)
|
|
||||||
|
|
||||||
|
|
||||||
class Feature(HasAccessibles):
|
|
||||||
"""all things belonging to a small, predefined functionality influencing the working of a module
|
|
||||||
|
|
||||||
a mixin with Feature as a direct base class is recognized as a SECoP feature
|
|
||||||
and reported in the module property 'features'
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
class PollInfo:
|
|
||||||
def __init__(self, pollinterval, trigger_event):
|
|
||||||
self.interval = pollinterval
|
|
||||||
self.last_main = 0
|
|
||||||
self.last_slow = 0
|
|
||||||
self.pending_errors = set()
|
|
||||||
self.polled_parameters = []
|
|
||||||
self.fast_flag = False
|
|
||||||
self.trigger_event = trigger_event
|
|
||||||
|
|
||||||
def trigger(self, immediate=False):
|
|
||||||
"""trigger a recalculation of poll due times
|
|
||||||
|
|
||||||
:param immediate: when True, doPoll should be called as soon as possible
|
|
||||||
"""
|
|
||||||
if immediate:
|
|
||||||
self.last_main = 0
|
|
||||||
self.trigger_event.set()
|
|
||||||
|
|
||||||
def update_interval(self, pollinterval):
|
|
||||||
if not self.fast_flag:
|
|
||||||
self.interval = pollinterval
|
|
||||||
self.trigger()
|
|
||||||
|
|
||||||
|
|
||||||
class Module(HasAccessibles):
|
|
||||||
"""basic module
|
|
||||||
|
|
||||||
all SECoP modules derive from this.
|
|
||||||
|
|
||||||
:param name: the modules name
|
|
||||||
:param logger: a logger instance
|
|
||||||
:param cfgdict: the dict from this modules section in the config file
|
|
||||||
:param srv: the server instance
|
|
||||||
|
|
||||||
Notes:
|
|
||||||
|
|
||||||
- the programmer normally should not need to reimplement :meth:`__init__`
|
|
||||||
- within modules, parameters should only be addressed as ``self.<pname>``,
|
|
||||||
i.e. ``self.value``, ``self.target`` etc...
|
|
||||||
|
|
||||||
- these are accessing the cached version.
|
|
||||||
- they can also be written to, generating an async update
|
|
||||||
|
|
||||||
- if you want to 'update from the hardware', call ``self.read_<pname>()`` instead
|
|
||||||
|
|
||||||
- the return value of this method will be used as the new cached value and
|
|
||||||
be an async update sent automatically.
|
|
||||||
|
|
||||||
- if you want to 'update the hardware' call ``self.write_<pname>(<new value>)``.
|
|
||||||
|
|
||||||
- The return value of this method will also update the cache.
|
|
||||||
|
|
||||||
"""
|
|
||||||
# static properties, definitions in derived classes should overwrite earlier ones.
|
|
||||||
# note: properties don't change after startup and are usually filled
|
|
||||||
# with data from a cfg file...
|
|
||||||
# note: only the properties predefined here are allowed to be set in the cfg file
|
|
||||||
export = Property('flag if this module is to be exported', BoolType(), default=True, export=False)
|
|
||||||
group = Property('optional group the module belongs to', StringType(), default='', extname='group')
|
|
||||||
description = Property('description of the module', TextType(), extname='description', mandatory=True)
|
|
||||||
meaning = Property('optional meaning indicator', TupleOf(StringType(), IntRange(0, 50)),
|
|
||||||
default=('', 0), extname='meaning')
|
|
||||||
visibility = Property('optional visibility hint', EnumType('visibility', user=1, advanced=2, expert=3),
|
|
||||||
default='user', extname='visibility')
|
|
||||||
implementation = Property('internal name of the implementation class of the module', StringType(),
|
|
||||||
extname='implementation')
|
|
||||||
interface_classes = Property('offical highest interface-class of the module', ArrayOf(StringType()),
|
|
||||||
extname='interface_classes')
|
|
||||||
features = Property('list of features', ArrayOf(StringType()), extname='features')
|
|
||||||
pollinterval = Property('poll interval for parameters handled by doPoll', FloatRange(0.1, 120), default=5)
|
|
||||||
slowinterval = Property('poll interval for other parameters', FloatRange(0.1, 120), default=15)
|
|
||||||
omit_unchanged_within = Property('default for minimum time between updates of unchanged values',
|
|
||||||
NoneOr(FloatRange(0)), export=False, default=None)
|
|
||||||
enablePoll = True
|
|
||||||
|
|
||||||
# properties, parameters and commands are auto-merged upon subclassing
|
|
||||||
parameters = {}
|
|
||||||
commands = {}
|
|
||||||
|
|
||||||
# reference to the dispatcher (used for sending async updates)
|
|
||||||
DISPATCHER = None
|
|
||||||
pollInfo = None
|
|
||||||
triggerPoll = None # trigger event for polls. used on io modules and modules without io
|
|
||||||
|
|
||||||
def __init__(self, name, logger, cfgdict, srv):
|
|
||||||
# remember the dispatcher object (for the async callbacks)
|
|
||||||
self.DISPATCHER = srv.dispatcher
|
|
||||||
self.log = logger
|
|
||||||
self.name = name
|
|
||||||
self.valueCallbacks = {}
|
|
||||||
self.errorCallbacks = {}
|
|
||||||
self.earlyInitDone = False
|
|
||||||
self.initModuleDone = False
|
|
||||||
self.startModuleDone = False
|
|
||||||
self.remoteLogHandler = None
|
|
||||||
self.accessLock = threading.RLock() # for read_* / write_* methods
|
|
||||||
self.updateLock = threading.RLock() # for announceUpdate
|
|
||||||
self.polledModules = [] # modules polled by thread started in self.startModules
|
|
||||||
self.attachedModules = {}
|
|
||||||
errors = []
|
|
||||||
self._isinitialized = False
|
|
||||||
|
|
||||||
# handle module properties
|
|
||||||
# 1) make local copies of properties
|
|
||||||
super().__init__()
|
|
||||||
|
|
||||||
# 2) check and apply properties specified in cfgdict as
|
|
||||||
# '<propertyname> = <propertyvalue>'
|
|
||||||
# pylint: disable=consider-using-dict-items
|
|
||||||
for key in self.propertyDict:
|
|
||||||
value = cfgdict.pop(key, None)
|
|
||||||
if value is not None:
|
|
||||||
try:
|
|
||||||
if isinstance(value, dict):
|
|
||||||
self.setProperty(key, value['value'])
|
|
||||||
else:
|
|
||||||
self.setProperty(key, value)
|
|
||||||
except BadValueError:
|
|
||||||
errors.append(f'{key}: value {value!r} does not match {self.propertyDict[key].datatype!r}!')
|
|
||||||
|
|
||||||
# 3) set automatic properties
|
|
||||||
mycls, = self.__class__.__bases__ # skip the wrapper class
|
|
||||||
myclassname = f'{mycls.__module__}.{mycls.__name__}'
|
|
||||||
self.implementation = myclassname
|
|
||||||
# list of all 'secop' modules
|
|
||||||
# self.interface_classes = [
|
|
||||||
# b.__name__ for b in mycls.__mro__ if b.__module__.startswith('frappy.modules')]
|
|
||||||
# list of only the 'highest' secop module class
|
|
||||||
self.interface_classes = [
|
|
||||||
b.__name__ for b in mycls.__mro__ if b in SECoP_BASE_CLASSES][:1]
|
|
||||||
|
|
||||||
# handle Features
|
|
||||||
self.features = [b.__name__ for b in mycls.__mro__ if Feature in b.__bases__]
|
|
||||||
|
|
||||||
# handle accessibles
|
|
||||||
# 1) make local copies of parameter objects
|
|
||||||
# they need to be individual per instance since we use them also
|
|
||||||
# to cache the current value + qualifiers...
|
|
||||||
accessibles = {}
|
|
||||||
# conversion from exported names to internal attribute names
|
|
||||||
accessiblename2attr = {}
|
|
||||||
for aname, aobj in self.accessibles.items():
|
|
||||||
# make a copy of the Parameter/Command object
|
|
||||||
aobj = aobj.copy()
|
|
||||||
if not self.export: # do not export parameters of a module not exported
|
|
||||||
aobj.export = False
|
|
||||||
if aobj.export:
|
|
||||||
accessiblename2attr[aobj.export] = aname
|
|
||||||
accessibles[aname] = aobj
|
|
||||||
# do not re-use self.accessibles as this is the same for all instances
|
|
||||||
self.accessibles = accessibles
|
|
||||||
self.accessiblename2attr = accessiblename2attr
|
|
||||||
# provide properties to 'filter' out the parameters/commands
|
|
||||||
self.parameters = {k: v for k, v in accessibles.items() if isinstance(v, Parameter)}
|
|
||||||
self.commands = {k: v for k, v in accessibles.items() if isinstance(v, Command)}
|
|
||||||
|
|
||||||
# 2) check and apply parameter_properties
|
|
||||||
bad = []
|
|
||||||
for aname, cfg in cfgdict.items():
|
|
||||||
aobj = self.accessibles.get(aname, None)
|
|
||||||
if aobj:
|
|
||||||
try:
|
|
||||||
for propname, propvalue in cfg.items():
|
|
||||||
aobj.setProperty(propname, propvalue)
|
|
||||||
except KeyError:
|
|
||||||
errors.append(f"'{aname}' has no property '{propname}'")
|
|
||||||
except BadValueError as e:
|
|
||||||
errors.append(f'{aname}.{propname}: {str(e)}')
|
|
||||||
else:
|
|
||||||
bad.append(aname)
|
|
||||||
|
|
||||||
# 3) complain about names not found as accessible or property names
|
|
||||||
if bad:
|
|
||||||
errors.append(
|
|
||||||
f"{', '.join(bad)} does not exist (use one of {', '.join(list(self.accessibles) + list(self.propertyDict))})")
|
|
||||||
# 4) register value for writing, if given
|
|
||||||
# apply default when no value is given (in cfg or as Parameter argument)
|
|
||||||
# or complain, when cfg is needed
|
|
||||||
self.writeDict = {} # values of parameters to be written
|
|
||||||
for pname, pobj in self.parameters.items():
|
|
||||||
self.valueCallbacks[pname] = []
|
|
||||||
self.errorCallbacks[pname] = []
|
|
||||||
|
|
||||||
if isinstance(pobj, Limit):
|
|
||||||
basepname = pname.rpartition('_')[0]
|
|
||||||
baseparam = self.parameters.get(basepname)
|
|
||||||
if not baseparam:
|
|
||||||
errors.append(f'limit {pname!r} is given, but not {basepname!r}')
|
|
||||||
continue
|
|
||||||
if baseparam.datatype is None:
|
|
||||||
continue # an error will be reported on baseparam
|
|
||||||
pobj.set_datatype(baseparam.datatype)
|
|
||||||
|
|
||||||
if not pobj.hasDatatype():
|
|
||||||
errors.append(f'{pname} needs a datatype')
|
|
||||||
continue
|
|
||||||
|
|
||||||
if pobj.value is None:
|
|
||||||
if pobj.needscfg:
|
|
||||||
errors.append(f'{pname!r} has no default value and was not given in config!')
|
|
||||||
if pobj.default is None:
|
|
||||||
# we do not want to call the setter for this parameter for now,
|
|
||||||
# this should happen on the first read
|
|
||||||
pobj.readerror = ConfigError(f'parameter {pname!r} not initialized')
|
|
||||||
# above error will be triggered on activate after startup,
|
|
||||||
# when not all hardware parameters are read because of startup timeout
|
|
||||||
pobj.default = pobj.datatype.default
|
|
||||||
pobj.value = pobj.default
|
|
||||||
else:
|
|
||||||
# value given explicitly, either by cfg or as Parameter argument
|
|
||||||
pobj.given = True # for PersistentMixin
|
|
||||||
if hasattr(self, 'write_' + pname):
|
|
||||||
self.writeDict[pname] = pobj.value
|
|
||||||
if pobj.default is None:
|
|
||||||
pobj.default = pobj.value
|
|
||||||
# this checks again for datatype and sets the timestamp
|
|
||||||
setattr(self, pname, pobj.value)
|
|
||||||
|
|
||||||
# 5) ensure consistency
|
|
||||||
for aobj in self.accessibles.values():
|
|
||||||
aobj.finish(self)
|
|
||||||
|
|
||||||
# Modify units AFTER applying the cfgdict
|
|
||||||
mainvalue = self.parameters.get('value')
|
|
||||||
if mainvalue:
|
|
||||||
mainunit = mainvalue.datatype.unit
|
|
||||||
if mainunit:
|
|
||||||
self.applyMainUnit(mainunit)
|
|
||||||
|
|
||||||
# 6) check complete configuration of * properties
|
|
||||||
if not errors:
|
|
||||||
try:
|
|
||||||
self.checkProperties()
|
|
||||||
except ConfigError as e:
|
|
||||||
errors.append(str(e))
|
|
||||||
for aname, aobj in self.accessibles.items():
|
|
||||||
try:
|
|
||||||
aobj.checkProperties()
|
|
||||||
except (ConfigError, ProgrammingError) as e:
|
|
||||||
errors.append(f'{aname}: {e}')
|
|
||||||
if errors:
|
|
||||||
raise ConfigError(errors)
|
|
||||||
|
|
||||||
# helper cfg-editor
|
|
||||||
def __iter__(self):
|
|
||||||
return self.accessibles.__iter__()
|
|
||||||
|
|
||||||
def __getitem__(self, item):
|
|
||||||
return self.accessibles.__getitem__(item)
|
|
||||||
|
|
||||||
def applyMainUnit(self, mainunit):
|
|
||||||
"""replace $ in units of parameters by mainunit"""
|
|
||||||
for pobj in self.parameters.values():
|
|
||||||
pobj.datatype.set_main_unit(mainunit)
|
|
||||||
|
|
||||||
def announceUpdate(self, pname, value=None, err=None, timestamp=None, validate=True):
|
|
||||||
"""announce a changed value or readerror
|
|
||||||
|
|
||||||
:param pname: parameter name
|
|
||||||
:param value: new value or None in case of error
|
|
||||||
:param err: None or an exception
|
|
||||||
:param timestamp: a timestamp or None for taking current time
|
|
||||||
:param validate: True: convert to datatype, in case of error store in readerror
|
|
||||||
:return:
|
|
||||||
|
|
||||||
when err=None and validate=False, the value must already be converted to the datatype
|
|
||||||
"""
|
|
||||||
|
|
||||||
with self.updateLock:
|
|
||||||
pobj = self.parameters[pname]
|
|
||||||
timestamp = timestamp or time.time()
|
|
||||||
if not err:
|
|
||||||
try:
|
|
||||||
if validate:
|
|
||||||
value = pobj.datatype(value)
|
|
||||||
except Exception as e:
|
|
||||||
err = e
|
|
||||||
else:
|
|
||||||
changed = pobj.value != value
|
|
||||||
# store the value even in case of error
|
|
||||||
pobj.value = value
|
|
||||||
if err:
|
|
||||||
if secop_error(err) == pobj.readerror:
|
|
||||||
err.report_error = False
|
|
||||||
return # no updates for repeated errors
|
|
||||||
err = secop_error(err)
|
|
||||||
elif not changed and timestamp < (pobj.timestamp or 0) + pobj.omit_unchanged_within:
|
|
||||||
# no change within short time -> omit
|
|
||||||
return
|
|
||||||
pobj.timestamp = timestamp or time.time()
|
|
||||||
if err:
|
|
||||||
callbacks = self.errorCallbacks
|
|
||||||
pobj.readerror = arg = err
|
|
||||||
else:
|
|
||||||
callbacks = self.valueCallbacks
|
|
||||||
arg = value
|
|
||||||
pobj.readerror = None
|
|
||||||
if pobj.export:
|
|
||||||
self.DISPATCHER.announce_update(self.name, pname, pobj)
|
|
||||||
cblist = callbacks[pname]
|
|
||||||
for cb in cblist:
|
|
||||||
try:
|
|
||||||
cb(arg)
|
|
||||||
except Exception:
|
|
||||||
# print(formatExtendedTraceback())
|
|
||||||
pass
|
|
||||||
|
|
||||||
def registerCallbacks(self, modobj, autoupdate=()):
|
|
||||||
"""register callbacks to another module <modobj>
|
|
||||||
|
|
||||||
- whenever a self.<param> changes:
|
|
||||||
<modobj>.update_<param> is called with the new value as argument.
|
|
||||||
If this method raises an exception, <modobj>.<param> gets into an error state.
|
|
||||||
If the method does not exist and <param> is in autoupdate,
|
|
||||||
<modobj>.<param> is updated to self.<param>
|
|
||||||
- whenever <self>.<param> gets into an error state:
|
|
||||||
<modobj>.error_update_<param> is called with the exception as argument.
|
|
||||||
If this method raises an error, <modobj>.<param> gets into an error state.
|
|
||||||
If this method does not exist, and <param> is in autoupdate,
|
|
||||||
<modobj>.<param> gets into the same error state as self.<param>
|
|
||||||
"""
|
|
||||||
for pname in self.parameters:
|
|
||||||
errfunc = getattr(modobj, 'error_update_' + pname, None)
|
|
||||||
if errfunc:
|
|
||||||
def errcb(err, p=pname, efunc=errfunc):
|
|
||||||
try:
|
|
||||||
efunc(err)
|
|
||||||
except Exception as e:
|
|
||||||
modobj.announceUpdate(p, err=e)
|
|
||||||
self.errorCallbacks[pname].append(errcb)
|
|
||||||
else:
|
|
||||||
def errcb(err, p=pname):
|
|
||||||
modobj.announceUpdate(p, err=err)
|
|
||||||
if pname in autoupdate:
|
|
||||||
self.errorCallbacks[pname].append(errcb)
|
|
||||||
|
|
||||||
updfunc = getattr(modobj, 'update_' + pname, None)
|
|
||||||
if updfunc:
|
|
||||||
def cb(value, ufunc=updfunc, efunc=errcb):
|
|
||||||
try:
|
|
||||||
ufunc(value)
|
|
||||||
except Exception as e:
|
|
||||||
efunc(e)
|
|
||||||
self.valueCallbacks[pname].append(cb)
|
|
||||||
elif pname in autoupdate:
|
|
||||||
def cb(value, p=pname):
|
|
||||||
modobj.announceUpdate(p, value)
|
|
||||||
self.valueCallbacks[pname].append(cb)
|
|
||||||
|
|
||||||
def isBusy(self, status=None):
|
|
||||||
"""helper function for treating substates of BUSY correctly"""
|
|
||||||
# defined even for non drivable (used for dynamic polling)
|
|
||||||
return False
|
|
||||||
|
|
||||||
def earlyInit(self):
|
|
||||||
"""initialise module with stuff to be done before all modules are created"""
|
|
||||||
self.earlyInitDone = True
|
|
||||||
|
|
||||||
def initModule(self):
|
|
||||||
"""initialise module with stuff to be done after all modules are created"""
|
|
||||||
self.initModuleDone = True
|
|
||||||
if self.enablePoll or self.writeDict:
|
|
||||||
# enablePoll == False: we still need the poll thread for writing values from writeDict
|
|
||||||
if hasattr(self, 'io'):
|
|
||||||
self.io.polledModules.append(self)
|
|
||||||
else:
|
|
||||||
self.triggerPoll = threading.Event()
|
|
||||||
self.polledModules.append(self)
|
|
||||||
|
|
||||||
def startModule(self, start_events):
|
|
||||||
"""runs after init of all modules
|
|
||||||
|
|
||||||
when a thread is started, a trigger function may signal that it
|
|
||||||
has finished its initial work
|
|
||||||
start_events.get_trigger(<timeout>) creates such a trigger and
|
|
||||||
registers it in the server for waiting
|
|
||||||
<timeout> defaults to 30 seconds
|
|
||||||
"""
|
|
||||||
if self.polledModules:
|
|
||||||
mkthread(self.__pollThread, self.polledModules, start_events.get_trigger())
|
|
||||||
self.startModuleDone = True
|
|
||||||
|
|
||||||
def initialReads(self):
|
|
||||||
"""initial reads to be done
|
|
||||||
|
|
||||||
override to read initial values from HW, when it is not desired
|
|
||||||
to poll them afterwards
|
|
||||||
|
|
||||||
called from the poll thread, after writeInitParams but before
|
|
||||||
all parameters are polled once
|
|
||||||
"""
|
|
||||||
|
|
||||||
def shutdownModule(self):
|
|
||||||
"""called when the sever shuts down
|
|
||||||
|
|
||||||
any cleanup-work should be performed here, like closing threads and
|
|
||||||
saving data.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def doPoll(self):
|
|
||||||
"""polls important parameters like value and status
|
|
||||||
|
|
||||||
all other parameters are polled automatically
|
|
||||||
"""
|
|
||||||
|
|
||||||
def setFastPoll(self, flag, fast_interval=0.25):
|
|
||||||
"""change poll interval
|
|
||||||
|
|
||||||
:param flag: enable/disable fast poll mode
|
|
||||||
:param fast_interval: fast poll interval
|
|
||||||
"""
|
|
||||||
if self.pollInfo:
|
|
||||||
self.pollInfo.fast_flag = flag
|
|
||||||
self.pollInfo.interval = fast_interval if flag else self.pollinterval
|
|
||||||
self.pollInfo.trigger()
|
|
||||||
|
|
||||||
def callPollFunc(self, rfunc, raise_com_failed=False):
|
|
||||||
"""call read method with proper error handling"""
|
|
||||||
try:
|
|
||||||
rfunc()
|
|
||||||
if rfunc.__name__ in self.pollInfo.pending_errors:
|
|
||||||
self.log.info('%s: o.k.', rfunc.__name__)
|
|
||||||
self.pollInfo.pending_errors.discard(rfunc.__name__)
|
|
||||||
except Exception as e:
|
|
||||||
if getattr(e, 'report_error', True):
|
|
||||||
name = rfunc.__name__
|
|
||||||
self.pollInfo.pending_errors.add(name) # trigger o.k. message after error is resolved
|
|
||||||
if isinstance(e, SECoPError):
|
|
||||||
e.raising_methods.append(name)
|
|
||||||
if e.silent:
|
|
||||||
self.log.debug('%s', e.format(False))
|
|
||||||
else:
|
|
||||||
self.log.error('%s', e.format(False))
|
|
||||||
if raise_com_failed and isinstance(e, CommunicationFailedError):
|
|
||||||
raise
|
|
||||||
else:
|
|
||||||
# not a SECoPError: this is proabably a programming error
|
|
||||||
# we want to log the traceback
|
|
||||||
self.log.error('%s', formatException())
|
|
||||||
|
|
||||||
def __pollThread(self, modules, started_callback):
|
|
||||||
"""poll thread body
|
|
||||||
|
|
||||||
:param modules: list of modules to be handled by this thread
|
|
||||||
:param started_callback: to be called after all polls are done once
|
|
||||||
|
|
||||||
before polling, parameters which need hardware initialisation are written
|
|
||||||
"""
|
|
||||||
polled_modules = [m for m in modules if m.enablePoll]
|
|
||||||
if hasattr(self, 'registerReconnectCallback'):
|
|
||||||
# self is a communicator supporting reconnections
|
|
||||||
def trigger_all(trg=self.triggerPoll, polled_modules=polled_modules):
|
|
||||||
for m in polled_modules:
|
|
||||||
m.pollInfo.last_main = 0
|
|
||||||
m.pollInfo.last_slow = 0
|
|
||||||
trg.set()
|
|
||||||
self.registerReconnectCallback('trigger_polls', trigger_all)
|
|
||||||
|
|
||||||
# collect all read functions
|
|
||||||
for mobj in polled_modules:
|
|
||||||
pinfo = mobj.pollInfo = PollInfo(mobj.pollinterval, self.triggerPoll)
|
|
||||||
# trigger a poll interval change when self.pollinterval changes.
|
|
||||||
if 'pollinterval' in mobj.valueCallbacks:
|
|
||||||
mobj.valueCallbacks['pollinterval'].append(pinfo.update_interval)
|
|
||||||
|
|
||||||
for pname, pobj in mobj.parameters.items():
|
|
||||||
rfunc = getattr(mobj, 'read_' + pname)
|
|
||||||
if rfunc.poll:
|
|
||||||
pinfo.polled_parameters.append((mobj, rfunc, pobj))
|
|
||||||
while True:
|
|
||||||
try:
|
|
||||||
for mobj in modules:
|
|
||||||
# TODO when needed: here we might add a call to a method :meth:`beforeWriteInit`
|
|
||||||
mobj.writeInitParams()
|
|
||||||
mobj.initialReads()
|
|
||||||
# call all read functions a first time
|
|
||||||
for m in polled_modules:
|
|
||||||
for mobj, rfunc, _ in m.pollInfo.polled_parameters:
|
|
||||||
mobj.callPollFunc(rfunc, raise_com_failed=True)
|
|
||||||
# TODO when needed: here we might add calls to a method :meth:`afterInitPolls`
|
|
||||||
break
|
|
||||||
except CommunicationFailedError as e:
|
|
||||||
# when communication failed, probably all parameters and may be more modules are affected.
|
|
||||||
# as this would take a lot of time (summed up timeouts), we do not continue
|
|
||||||
# trying and let the server accept connections, further polls might success later
|
|
||||||
if started_callback:
|
|
||||||
self.log.error('communication failure on startup: %s', e)
|
|
||||||
started_callback()
|
|
||||||
started_callback = None
|
|
||||||
self.triggerPoll.wait(0.1) # wait for reconnection or max 10 sec.
|
|
||||||
break
|
|
||||||
if started_callback:
|
|
||||||
started_callback()
|
|
||||||
if not polled_modules: # no polls needed - exit thread
|
|
||||||
return
|
|
||||||
to_poll = ()
|
|
||||||
while True:
|
|
||||||
now = time.time()
|
|
||||||
wait_time = 999
|
|
||||||
for mobj in modules:
|
|
||||||
pinfo = mobj.pollInfo
|
|
||||||
wait_time = min(pinfo.last_main + pinfo.interval - now, wait_time,
|
|
||||||
pinfo.last_slow + mobj.slowinterval - now)
|
|
||||||
if wait_time > 0 and not to_poll:
|
|
||||||
# nothing to do
|
|
||||||
self.triggerPoll.wait(wait_time)
|
|
||||||
self.triggerPoll.clear()
|
|
||||||
continue
|
|
||||||
# call doPoll of all modules where due
|
|
||||||
for mobj in modules:
|
|
||||||
pinfo = mobj.pollInfo
|
|
||||||
if now > pinfo.last_main + pinfo.interval:
|
|
||||||
try:
|
|
||||||
pinfo.last_main = (now // pinfo.interval) * pinfo.interval
|
|
||||||
except ZeroDivisionError:
|
|
||||||
pinfo.last_main = now
|
|
||||||
mobj.callPollFunc(mobj.doPoll)
|
|
||||||
now = time.time()
|
|
||||||
# find ONE due slow poll and call it
|
|
||||||
loop = True
|
|
||||||
while loop: # loops max. 2 times, when to_poll is at end
|
|
||||||
for mobj, rfunc, pobj in to_poll:
|
|
||||||
if now > pobj.timestamp + mobj.slowinterval * 0.5:
|
|
||||||
mobj.callPollFunc(rfunc)
|
|
||||||
loop = False # one poll done
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
to_poll = []
|
|
||||||
# collect due slow polls
|
|
||||||
for mobj in modules:
|
|
||||||
pinfo = mobj.pollInfo
|
|
||||||
if now > pinfo.last_slow + mobj.slowinterval:
|
|
||||||
to_poll.extend(pinfo.polled_parameters)
|
|
||||||
pinfo.last_slow = (now // mobj.slowinterval) * mobj.slowinterval
|
|
||||||
if to_poll:
|
|
||||||
to_poll = iter(to_poll)
|
|
||||||
else:
|
|
||||||
loop = False # no slow polls ready
|
|
||||||
|
|
||||||
def writeInitParams(self):
|
|
||||||
"""write values for parameters with configured values
|
|
||||||
|
|
||||||
- does proper error handling
|
|
||||||
|
|
||||||
called at the beginning of the poller thread and for writing persistent values
|
|
||||||
"""
|
|
||||||
for pname in list(self.writeDict):
|
|
||||||
value = self.writeDict.pop(pname, Done)
|
|
||||||
# in the mean time, a poller or handler might already have done it
|
|
||||||
if value is not Done:
|
|
||||||
wfunc = getattr(self, 'write_' + pname, None)
|
|
||||||
if wfunc is None:
|
|
||||||
setattr(self, pname, value)
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
self.log.debug('initialize parameter %s', pname)
|
|
||||||
wfunc(value)
|
|
||||||
except SECoPError as e:
|
|
||||||
if e.silent:
|
|
||||||
self.log.debug('%s: %s', pname, str(e))
|
|
||||||
else:
|
|
||||||
self.log.error('%s: %s', pname, str(e))
|
|
||||||
except Exception:
|
|
||||||
self.log.error(formatException())
|
|
||||||
|
|
||||||
def setRemoteLogging(self, conn, level):
|
|
||||||
if self.remoteLogHandler is None:
|
|
||||||
for handler in self.log.handlers:
|
|
||||||
if isinstance(handler, RemoteLogHandler):
|
|
||||||
self.remoteLogHandler = handler
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
raise ValueError('remote handler not found')
|
|
||||||
self.remoteLogHandler.set_conn_level(self, conn, level)
|
|
||||||
|
|
||||||
def checkLimits(self, value, pname='target'):
|
|
||||||
"""check for limits
|
|
||||||
|
|
||||||
:param value: the value to be checked for <pname>_min <= value <= <pname>_max
|
|
||||||
:param pname: parameter name, default is 'target'
|
|
||||||
|
|
||||||
raises RangeError in case the value is not valid
|
|
||||||
|
|
||||||
This method is called automatically and needs therefore rarely to be
|
|
||||||
called by the programmer. It might be used in a check_<param> method,
|
|
||||||
when no automatic super call is desired.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
min_, max_ = getattr(self, pname + '_limits')
|
|
||||||
if not min_ <= value <= max_:
|
|
||||||
raise RangeError(f'{pname} outside {pname}_limits')
|
|
||||||
return
|
|
||||||
except AttributeError:
|
|
||||||
pass
|
|
||||||
min_ = getattr(self, pname + '_min', float('-inf'))
|
|
||||||
max_ = getattr(self, pname + '_max', float('inf'))
|
|
||||||
if min_ > max_:
|
|
||||||
raise RangeError(f'invalid limits: {pname}_min > {pname}_max')
|
|
||||||
if value < min_:
|
|
||||||
raise RangeError(f'{pname} below {pname}_min')
|
|
||||||
if value > max_:
|
|
||||||
raise RangeError(f'{pname} above {pname}_max')
|
|
||||||
|
|
||||||
|
|
||||||
class Readable(Module):
|
class Readable(Module):
|
||||||
"""basic readable module"""
|
"""basic readable module"""
|
||||||
|
# pylint: disable=invalid-name
|
||||||
Status = Enum('Status',
|
Status = Enum('Status',
|
||||||
IDLE=StatusType.IDLE,
|
IDLE=StatusType.IDLE,
|
||||||
WARN=StatusType.WARN,
|
WARN=StatusType.WARN,
|
||||||
@ -910,7 +93,7 @@ class Drivable(Writable):
|
|||||||
|
|
||||||
@Command(None, result=None)
|
@Command(None, result=None)
|
||||||
def stop(self):
|
def stop(self):
|
||||||
"""cease driving, go to IDLE state"""
|
"""not implemented - this is a no-op"""
|
||||||
|
|
||||||
|
|
||||||
class Communicator(HasComlog, Module):
|
class Communicator(HasComlog, Module):
|
||||||
@ -925,13 +108,18 @@ class Communicator(HasComlog, Module):
|
|||||||
"""
|
"""
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
|
||||||
SECoP_BASE_CLASSES = {Readable, Writable, Drivable, Communicator}
|
SECoP_BASE_CLASSES = {Readable, Writable, Drivable, Communicator}
|
||||||
|
|
||||||
|
|
||||||
class Attached(Property):
|
class Attached(Property):
|
||||||
"""a special property, defining an attached module
|
"""a special property, defining an attached module
|
||||||
|
|
||||||
assign a module name to this property in the cfg file,
|
assign a module name to this property in the cfg file,
|
||||||
and the server will create an attribute with this module
|
and the server will create an attribute with this module
|
||||||
|
|
||||||
|
When mandatory is set to False, and there is no value or an empty string
|
||||||
|
given in the config file, the value of the attribute will be None.
|
||||||
"""
|
"""
|
||||||
def __init__(self, basecls=Module, description='attached module', mandatory=True):
|
def __init__(self, basecls=Module, description='attached module', mandatory=True):
|
||||||
self.basecls = basecls
|
self.basecls = basecls
|
||||||
@ -940,13 +128,20 @@ class Attached(Property):
|
|||||||
def __get__(self, obj, owner):
|
def __get__(self, obj, owner):
|
||||||
if obj is None:
|
if obj is None:
|
||||||
return self
|
return self
|
||||||
if self.name not in obj.attachedModules:
|
modobj = obj.attachedModules.get(self.name)
|
||||||
modobj = obj.DISPATCHER.get_module(super().__get__(obj, owner))
|
if not modobj:
|
||||||
|
modulename = super().__get__(obj, owner)
|
||||||
|
if not modulename:
|
||||||
|
return None # happens when mandatory=False and modulename is not given
|
||||||
|
modobj = obj.secNode.get_module(modulename)
|
||||||
|
if not modobj:
|
||||||
|
raise ConfigError(f'attached module {self.name}={modulename!r} '
|
||||||
|
f'does not exist')
|
||||||
if not isinstance(modobj, self.basecls):
|
if not isinstance(modobj, self.basecls):
|
||||||
raise ConfigError(f'attached module {self.name}={modobj.name!r} '\
|
raise ConfigError(f'attached module {self.name}={modobj.name!r} '
|
||||||
f'must inherit from {self.basecls.__qualname__!r}')
|
f'must inherit from {self.basecls.__qualname__!r}')
|
||||||
obj.attachedModules[self.name] = modobj
|
obj.attachedModules[self.name] = modobj
|
||||||
return obj.attachedModules.get(self.name) # return None if not given
|
return modobj
|
||||||
|
|
||||||
def copy(self):
|
def copy(self):
|
||||||
return Attached(self.basecls, self.description, self.mandatory)
|
return Attached(self.basecls, self.description, self.mandatory)
|
||||||
|
121
frappy/params.py
121
frappy/params.py
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# *****************************************************************************
|
# *****************************************************************************
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify it under
|
# This program is free software; you can redistribute it and/or modify it under
|
||||||
@ -25,12 +24,12 @@
|
|||||||
|
|
||||||
import inspect
|
import inspect
|
||||||
|
|
||||||
from frappy.datatypes import BoolType, CommandType, DataType, \
|
from frappy.datatypes import ArrayOf, BoolType, CommandType, DataType, \
|
||||||
DataTypeType, EnumType, NoneOr, OrType, FloatRange, \
|
DataTypeType, EnumType, FloatRange, NoneOr, OrType, StringType, StructOf, \
|
||||||
StringType, StructOf, TextType, TupleOf, ValueType, ArrayOf
|
TextType, TupleOf, ValueType
|
||||||
from frappy.errors import BadValueError, WrongTypeError, ProgrammingError
|
from frappy.errors import BadValueError, ProgrammingError, WrongTypeError
|
||||||
from frappy.properties import HasProperties, Property
|
|
||||||
from frappy.lib import generalConfig
|
from frappy.lib import generalConfig
|
||||||
|
from frappy.properties import HasProperties, Property
|
||||||
|
|
||||||
generalConfig.set_default('tolerate_poll_property', False)
|
generalConfig.set_default('tolerate_poll_property', False)
|
||||||
generalConfig.set_default('omit_unchanged_within', 0.1)
|
generalConfig.set_default('omit_unchanged_within', 0.1)
|
||||||
@ -58,13 +57,17 @@ class Accessible(HasProperties):
|
|||||||
def as_dict(self):
|
def as_dict(self):
|
||||||
return self.propertyValues
|
return self.propertyValues
|
||||||
|
|
||||||
def override(self, value):
|
def create_from_value(self, properties, value):
|
||||||
"""override with a bare value"""
|
"""return a clone with given value and inherited properties"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def clone(self, properties, **kwds):
|
||||||
|
"""return a clone of ourselfs with inherited properties"""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
def copy(self):
|
def copy(self):
|
||||||
"""return a (deep) copy of ourselfs"""
|
"""return a (deep) copy of ourselfs"""
|
||||||
raise NotImplementedError
|
return self.clone(self.propertyValues)
|
||||||
|
|
||||||
def updateProperties(self, merged_properties):
|
def updateProperties(self, merged_properties):
|
||||||
"""update merged_properties with our own properties"""
|
"""update merged_properties with our own properties"""
|
||||||
@ -95,6 +98,16 @@ class Accessible(HasProperties):
|
|||||||
props.append(f'{k}={v!r}')
|
props.append(f'{k}={v!r}')
|
||||||
return f"{self.__class__.__name__}({', '.join(props)})"
|
return f"{self.__class__.__name__}({', '.join(props)})"
|
||||||
|
|
||||||
|
def fixExport(self):
|
||||||
|
if self.export is True:
|
||||||
|
predefined_cls = PREDEFINED_ACCESSIBLES.get(self.name)
|
||||||
|
if predefined_cls is None:
|
||||||
|
self.export = '_' + self.name
|
||||||
|
elif isinstance(self, predefined_cls):
|
||||||
|
self.export = self.name
|
||||||
|
else:
|
||||||
|
raise ProgrammingError(f'can not use {self.name!r} as name of a {type(self).__name__}')
|
||||||
|
|
||||||
|
|
||||||
class Parameter(Accessible):
|
class Parameter(Accessible):
|
||||||
"""defines a parameter
|
"""defines a parameter
|
||||||
@ -222,26 +235,17 @@ class Parameter(Accessible):
|
|||||||
self.name = name
|
self.name = name
|
||||||
if isinstance(self.datatype, EnumType):
|
if isinstance(self.datatype, EnumType):
|
||||||
self.datatype.set_name(name)
|
self.datatype.set_name(name)
|
||||||
|
self.fixExport()
|
||||||
|
|
||||||
if self.export is True:
|
def clone(self, properties, **kwds):
|
||||||
predefined_cls = PREDEFINED_ACCESSIBLES.get(self.name, None)
|
"""return a clone of ourselfs with inherited properties"""
|
||||||
if predefined_cls is Parameter:
|
res = type(self)(**kwds)
|
||||||
self.export = self.name
|
|
||||||
elif predefined_cls is None:
|
|
||||||
self.export = '_' + self.name
|
|
||||||
else:
|
|
||||||
raise ProgrammingError(f'can not use {self.name!r} as name of a Parameter')
|
|
||||||
if 'export' in self.ownProperties:
|
|
||||||
# avoid export=True overrides export=<name>
|
|
||||||
self.ownProperties['export'] = self.export
|
|
||||||
|
|
||||||
def copy(self):
|
|
||||||
"""return a (deep) copy of ourselfs"""
|
|
||||||
res = type(self)()
|
|
||||||
res.name = self.name
|
res.name = self.name
|
||||||
res.init(self.propertyValues)
|
res.init(properties)
|
||||||
|
res.init(res.ownProperties)
|
||||||
if 'datatype' in self.propertyValues:
|
if 'datatype' in self.propertyValues:
|
||||||
res.datatype = res.datatype.copy()
|
res.datatype = res.datatype.copy()
|
||||||
|
res.finish()
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def updateProperties(self, merged_properties):
|
def updateProperties(self, merged_properties):
|
||||||
@ -254,9 +258,9 @@ class Parameter(Accessible):
|
|||||||
merged_properties.pop(key)
|
merged_properties.pop(key)
|
||||||
merged_properties.update(self.ownProperties)
|
merged_properties.update(self.ownProperties)
|
||||||
|
|
||||||
def override(self, value):
|
def create_from_value(self, properties, value):
|
||||||
"""override default"""
|
"""return a clone with given value and inherited properties"""
|
||||||
self.value = self.datatype(value)
|
return self.clone(properties, value=self.datatype(value))
|
||||||
|
|
||||||
def merge(self, merged_properties):
|
def merge(self, merged_properties):
|
||||||
"""merge with inherited properties
|
"""merge with inherited properties
|
||||||
@ -275,7 +279,7 @@ class Parameter(Accessible):
|
|||||||
|
|
||||||
:param modobj: final call, called from Module.__init__
|
:param modobj: final call, called from Module.__init__
|
||||||
"""
|
"""
|
||||||
|
self.fixExport()
|
||||||
if self.constant is not None:
|
if self.constant is not None:
|
||||||
constant = self.datatype(self.constant)
|
constant = self.datatype(self.constant)
|
||||||
# The value of the `constant` property should be the
|
# The value of the `constant` property should be the
|
||||||
@ -391,7 +395,7 @@ class Command(Accessible):
|
|||||||
else:
|
else:
|
||||||
# goodie: allow @Command instead of @Command()
|
# goodie: allow @Command instead of @Command()
|
||||||
self.func = argument # this is the wrapped method!
|
self.func = argument # this is the wrapped method!
|
||||||
if argument.__doc__:
|
if argument.__doc__ is not None:
|
||||||
self.description = inspect.cleandoc(argument.__doc__)
|
self.description = inspect.cleandoc(argument.__doc__)
|
||||||
self.name = self.func.__name__ # this is probably not needed
|
self.name = self.func.__name__ # this is probably not needed
|
||||||
self._inherit = inherit # save for __set_name__
|
self._inherit = inherit # save for __set_name__
|
||||||
@ -402,18 +406,8 @@ class Command(Accessible):
|
|||||||
if self.func is None:
|
if self.func is None:
|
||||||
raise ProgrammingError(f'Command {owner.__name__}.{name} must be used as a method decorator')
|
raise ProgrammingError(f'Command {owner.__name__}.{name} must be used as a method decorator')
|
||||||
|
|
||||||
|
self.fixExport()
|
||||||
self.datatype = CommandType(self.argument, self.result)
|
self.datatype = CommandType(self.argument, self.result)
|
||||||
if self.export is True:
|
|
||||||
predefined_cls = PREDEFINED_ACCESSIBLES.get(name, None)
|
|
||||||
if predefined_cls is Command:
|
|
||||||
self.export = name
|
|
||||||
elif predefined_cls is None:
|
|
||||||
self.export = '_' + name
|
|
||||||
else:
|
|
||||||
raise ProgrammingError(f'can not use {name!r} as name of a Command') from None
|
|
||||||
if 'export' in self.ownProperties:
|
|
||||||
# avoid export=True overrides export=<name>
|
|
||||||
self.ownProperties['export'] = self.export
|
|
||||||
if not self._inherit:
|
if not self._inherit:
|
||||||
for key, pobj in self.properties.items():
|
for key, pobj in self.properties.items():
|
||||||
if key not in self.propertyValues:
|
if key not in self.propertyValues:
|
||||||
@ -428,38 +422,50 @@ class Command(Accessible):
|
|||||||
|
|
||||||
def __call__(self, func):
|
def __call__(self, func):
|
||||||
"""called when used as decorator"""
|
"""called when used as decorator"""
|
||||||
if 'description' not in self.propertyValues and func.__doc__:
|
if isinstance(self.argument, StructOf):
|
||||||
|
# automatically set optional struct members
|
||||||
|
sig = inspect.signature(func)
|
||||||
|
params = set(sig.parameters.keys())
|
||||||
|
params.discard('self')
|
||||||
|
members = set(self.argument.members)
|
||||||
|
if params != members:
|
||||||
|
raise ProgrammingError(f'Command {func.__name__}: Function'
|
||||||
|
f' argument names do not match struct'
|
||||||
|
f' members!: {params} != {members}')
|
||||||
|
self.argument.optional = [p for p,v in sig.parameters.items()
|
||||||
|
if v.default is not inspect.Parameter.empty]
|
||||||
|
if 'description' not in self.ownProperties and func.__doc__ is not None:
|
||||||
self.description = inspect.cleandoc(func.__doc__)
|
self.description = inspect.cleandoc(func.__doc__)
|
||||||
self.ownProperties['description'] = self.description
|
self.ownProperties['description'] = self.description
|
||||||
self.func = func
|
self.func = func
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def copy(self):
|
def clone(self, properties, **kwds):
|
||||||
"""return a (deep) copy of ourselfs"""
|
"""return a clone of ourselfs with inherited properties"""
|
||||||
res = type(self)()
|
res = type(self)(**kwds)
|
||||||
res.name = self.name
|
res.name = self.name
|
||||||
|
self.fixExport()
|
||||||
res.func = self.func
|
res.func = self.func
|
||||||
res.init(self.propertyValues)
|
res.init(properties)
|
||||||
|
res.init(res.ownProperties)
|
||||||
if res.argument:
|
if res.argument:
|
||||||
res.argument = res.argument.copy()
|
res.argument = res.argument.copy()
|
||||||
if res.result:
|
if res.result:
|
||||||
res.result = res.result.copy()
|
res.result = res.result.copy()
|
||||||
self.finish()
|
res.finish()
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def updateProperties(self, merged_properties):
|
def updateProperties(self, merged_properties):
|
||||||
"""update merged_properties with our own properties"""
|
"""update merged_properties with our own properties"""
|
||||||
merged_properties.update(self.ownProperties)
|
merged_properties.update(self.ownProperties)
|
||||||
|
|
||||||
def override(self, value):
|
def create_from_value(self, properties, value):
|
||||||
"""override method
|
"""return a clone with given value and inherited properties
|
||||||
|
|
||||||
this is needed when the @Command is missing on a method overriding a command"""
|
this is needed when the @Command is missing on a method overriding a command"""
|
||||||
if not callable(value):
|
if not callable(value):
|
||||||
raise ProgrammingError(f'{self.name} = {value!r} is overriding a Command')
|
raise ProgrammingError(f'{self.name} = {value!r} is overriding a Command')
|
||||||
self.func = value
|
return self.clone(properties)(value)
|
||||||
if value.__doc__:
|
|
||||||
self.description = inspect.cleandoc(value.__doc__)
|
|
||||||
|
|
||||||
def merge(self, merged_properties):
|
def merge(self, merged_properties):
|
||||||
"""merge with inherited properties
|
"""merge with inherited properties
|
||||||
@ -488,7 +494,7 @@ class Command(Accessible):
|
|||||||
"""perform function call
|
"""perform function call
|
||||||
|
|
||||||
:param module_obj: the module on which the command is to be executed
|
:param module_obj: the module on which the command is to be executed
|
||||||
:param argument: the argument from the do command
|
:param argument: the argument from the do command (transported value!)
|
||||||
:returns: the return value converted to the result type
|
:returns: the return value converted to the result type
|
||||||
|
|
||||||
- when the argument type is TupleOf, the function is called with multiple arguments
|
- when the argument type is TupleOf, the function is called with multiple arguments
|
||||||
@ -498,6 +504,15 @@ class Command(Accessible):
|
|||||||
# pylint: disable=unnecessary-dunder-call
|
# pylint: disable=unnecessary-dunder-call
|
||||||
func = self.__get__(module_obj)
|
func = self.__get__(module_obj)
|
||||||
if self.argument:
|
if self.argument:
|
||||||
|
if argument is None:
|
||||||
|
raise WrongTypeError(
|
||||||
|
f'{module_obj.__class__.__name__}.{self.name} needs an'
|
||||||
|
f' argument of type {self.argument}!'
|
||||||
|
)
|
||||||
|
# convert transported value to internal value
|
||||||
|
argument = self.argument.import_value(argument)
|
||||||
|
# verify range
|
||||||
|
self.argument.validate(argument)
|
||||||
if isinstance(self.argument, TupleOf):
|
if isinstance(self.argument, TupleOf):
|
||||||
res = func(*argument)
|
res = func(*argument)
|
||||||
elif isinstance(self.argument, StructOf):
|
elif isinstance(self.argument, StructOf):
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# *****************************************************************************
|
# *****************************************************************************
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify it under
|
# This program is free software; you can redistribute it and/or modify it under
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# *****************************************************************************
|
# *****************************************************************************
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify it under
|
# This program is free software; you can redistribute it and/or modify it under
|
||||||
@ -78,17 +77,14 @@ class PersistentMixin(Module):
|
|||||||
super().__init__(name, logger, cfgdict, srv)
|
super().__init__(name, logger, cfgdict, srv)
|
||||||
persistentdir = os.path.join(generalConfig.logdir, 'persistent')
|
persistentdir = os.path.join(generalConfig.logdir, 'persistent')
|
||||||
os.makedirs(persistentdir, exist_ok=True)
|
os.makedirs(persistentdir, exist_ok=True)
|
||||||
self.persistentFile = os.path.join(persistentdir, f'{self.DISPATCHER.equipment_id}.{self.name}.json')
|
self.persistentFile = os.path.join(persistentdir, f'{self.secNode.equipment_id}.{self.name}.json')
|
||||||
self.initData = {} # "factory" settings
|
self.initData = {} # "factory" settings
|
||||||
loaded = self.loadPersistentData()
|
loaded = self.loadPersistentData()
|
||||||
for pname in self.parameters:
|
for pname, pobj in self.parameters.items():
|
||||||
pobj = self.parameters[pname]
|
|
||||||
flag = getattr(pobj, 'persistent', False)
|
flag = getattr(pobj, 'persistent', False)
|
||||||
if flag:
|
if flag:
|
||||||
if flag == 'auto':
|
if flag == 'auto':
|
||||||
def cb(value, m=self):
|
self.addCallback(pname, self.saveParameters)
|
||||||
m.saveParameters()
|
|
||||||
self.valueCallbacks[pname].append(cb)
|
|
||||||
self.initData[pname] = pobj.value
|
self.initData[pname] = pobj.value
|
||||||
if not pobj.given:
|
if not pobj.given:
|
||||||
if pname in loaded:
|
if pname in loaded:
|
||||||
@ -131,12 +127,14 @@ class PersistentMixin(Module):
|
|||||||
self.writeInitParams()
|
self.writeInitParams()
|
||||||
return loaded
|
return loaded
|
||||||
|
|
||||||
def saveParameters(self):
|
def saveParameters(self, _=None):
|
||||||
"""save persistent parameters
|
"""save persistent parameters
|
||||||
|
|
||||||
- to be called regularly explicitly by the module
|
- to be called regularly explicitly by the module
|
||||||
- the caller has to make sure that this is not called after
|
- the caller has to make sure that this is not called after
|
||||||
a power down of the connected hardware before loadParameters
|
a power down of the connected hardware before loadParameters
|
||||||
|
|
||||||
|
dummy argument to avoid closure for callback
|
||||||
"""
|
"""
|
||||||
if self.writeDict:
|
if self.writeDict:
|
||||||
# do not save before all values are written to the hw, as potentially
|
# do not save before all values are written to the hw, as potentially
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# *****************************************************************************
|
# *****************************************************************************
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify it under
|
# This program is free software; you can redistribute it and/or modify it under
|
||||||
@ -70,8 +69,8 @@ class MainLogger:
|
|||||||
self.log = None
|
self.log = None
|
||||||
self.console_handler = None
|
self.console_handler = None
|
||||||
mlzlog.setLoggerClass(mlzlog.MLZLogger)
|
mlzlog.setLoggerClass(mlzlog.MLZLogger)
|
||||||
assert self.log is None
|
mlzlog.log = mlzlog.MLZLogger('')
|
||||||
self.log = mlzlog.log = mlzlog.MLZLogger('')
|
self.log = mlzlog.log.getChild('')
|
||||||
self.log.setLevel(mlzlog.DEBUG)
|
self.log.setLevel(mlzlog.DEBUG)
|
||||||
self.log.addHandler(mlzlog.ColoredConsoleHandler())
|
self.log.addHandler(mlzlog.ColoredConsoleHandler())
|
||||||
self.log.handlers[0].setLevel(LOG_LEVELS['comlog'])
|
self.log.handlers[0].setLevel(LOG_LEVELS['comlog'])
|
||||||
@ -82,20 +81,12 @@ class Dispatcher(dispatcher.Dispatcher):
|
|||||||
super().__init__(name, log, options, srv)
|
super().__init__(name, log, options, srv)
|
||||||
self.log = srv.log # overwrite child logger
|
self.log = srv.log # overwrite child logger
|
||||||
|
|
||||||
def announce_update(self, modulename, pname, pobj):
|
def announce_update(self, moduleobj, pobj):
|
||||||
if pobj.readerror:
|
if pobj.readerror:
|
||||||
value = repr(pobj.readerror)
|
value = repr(pobj.readerror)
|
||||||
else:
|
else:
|
||||||
value = pobj.value
|
value = pobj.value
|
||||||
logobj = self._modules.get(modulename, self)
|
moduleobj.log.info('%s %r', pobj.name, value)
|
||||||
# self.log.info('%s:%s %r', modulename, pname, value)
|
|
||||||
logobj.log.info('%s %r', pname, value)
|
|
||||||
|
|
||||||
def register_module(self, moduleobj, modulename, export=True):
|
|
||||||
self.log.info('registering %s', modulename)
|
|
||||||
super().register_module(moduleobj, modulename, export)
|
|
||||||
setattr(main, modulename, moduleobj)
|
|
||||||
self.get_module(modulename)
|
|
||||||
|
|
||||||
|
|
||||||
logger = MainLogger()
|
logger = MainLogger()
|
||||||
@ -119,6 +110,10 @@ class Playground(Server):
|
|||||||
merged_cfg.pop('node', None)
|
merged_cfg.pop('node', None)
|
||||||
self.module_cfg = merged_cfg
|
self.module_cfg = merged_cfg
|
||||||
self._processCfg()
|
self._processCfg()
|
||||||
|
for modulename, moduleobj in self.secnode.modules.items():
|
||||||
|
cls = type(moduleobj).__bases__[0]
|
||||||
|
moduleobj.log.info('created as %s.%s', cls.__module__, cls.__name__)
|
||||||
|
setattr(main, modulename, moduleobj)
|
||||||
|
|
||||||
|
|
||||||
play = Playground()
|
play = Playground()
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user