minor fixes
Change-Id: I4be15d264e402be000811dffc1b28a2bc93ab297 Reviewed-on: https://forge.frm2.tum.de/review/18941 Tested-by: JenkinsCodeReview <bjoern_pedersen@frm2.tum.de> Reviewed-by: Enrico Faulhaber <enrico.faulhaber@frm2.tum.de>
This commit is contained in:
135
etc/sim_mlz_amagnet.cfg
Normal file
135
etc/sim_mlz_amagnet.cfg
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
[equipment SIM_MLZ_amagnet(Garfield)]
|
||||||
|
description=MLZ-Amagnet
|
||||||
|
.
|
||||||
|
Water cooled magnet from ANTARES@MLZ.
|
||||||
|
.
|
||||||
|
Use module to control the magnetic field.
|
||||||
|
Don't forget to select symmetry first (can be moved only at zero field!).
|
||||||
|
.
|
||||||
|
Monitor T1..T4 (Coil temps), if they get to hot, field will ramp down!
|
||||||
|
.
|
||||||
|
In case of Problems, contact the ANTARES people at MLZ.
|
||||||
|
|
||||||
|
visibility=expert
|
||||||
|
foo=bar
|
||||||
|
|
||||||
|
[interface tcp]
|
||||||
|
interface=tcp
|
||||||
|
bindto=0.0.0.0
|
||||||
|
bindport=10767
|
||||||
|
# protocol to use for this interface
|
||||||
|
framing=eol
|
||||||
|
encoding=secop
|
||||||
|
|
||||||
|
[module enable]
|
||||||
|
class=secop.simulation.SimWritable
|
||||||
|
value.datatype=["enum", {'On':1,'Off':0}]
|
||||||
|
target.datatype=["enum", {'On':1,'Off':0}]
|
||||||
|
.description='Enables to Output of the Powersupply'
|
||||||
|
.visibility='advanced'
|
||||||
|
|
||||||
|
[module polarity]
|
||||||
|
class=secop.simulation.SimWritable
|
||||||
|
value.datatype=["enum", {'+1':1,'0':0,'-1':-1}]
|
||||||
|
target.datatype=["enum", {'+1':1,'0':0,'-1':-1}]
|
||||||
|
.description=polarity (+/-) switch
|
||||||
|
.
|
||||||
|
there is an interlock in the plc:
|
||||||
|
if there is current, switching polarity is forbidden
|
||||||
|
if polarity is short, powersupply is disabled
|
||||||
|
.visibility=advanced
|
||||||
|
#comtries = 50
|
||||||
|
|
||||||
|
|
||||||
|
[module symmetry]
|
||||||
|
class=secop.simulation.SimWritable
|
||||||
|
value.datatype=["enum",{'symmetric':1,'short':0, 'asymmetric':-1}]
|
||||||
|
target.datatype=["enum",{'symmetric':1,'short':0, 'asymmetric':-1}]
|
||||||
|
.description=par/ser switch selecting (a)symmetric mode
|
||||||
|
.
|
||||||
|
note: on the front panel symmetric is ser, asymmetric is par
|
||||||
|
.visibility=advanced
|
||||||
|
value.default = 'symmetric'
|
||||||
|
value.value = 'symmetric'
|
||||||
|
|
||||||
|
[module T1]
|
||||||
|
class=secop.simulation.SimReadable
|
||||||
|
.description=Temperature1 of the coils system
|
||||||
|
#warnlimits=(0, 50)
|
||||||
|
value.unit='degC'
|
||||||
|
value.default = 23.45
|
||||||
|
|
||||||
|
[module T2]
|
||||||
|
class=secop.simulation.SimReadable
|
||||||
|
.description=Temperature2 of the coils system
|
||||||
|
#warnlimits=(0, 50)
|
||||||
|
value.unit='degC'
|
||||||
|
value.default = 23.45
|
||||||
|
|
||||||
|
[module T3]
|
||||||
|
class=secop.simulation.SimReadable
|
||||||
|
.description=Temperature3 of the coils system
|
||||||
|
#warnlimits=(0, 50)
|
||||||
|
value.unit='degC'
|
||||||
|
value.default = 23.45
|
||||||
|
|
||||||
|
[module T4]
|
||||||
|
class=secop.simulation.SimReadable
|
||||||
|
.description=Temperature4 of the coils system
|
||||||
|
#warnlimits=(0, 50)
|
||||||
|
value.unit='degC'
|
||||||
|
value.default = 23.45
|
||||||
|
|
||||||
|
[module currentsource]
|
||||||
|
class=secop.simulation.SimDrivable
|
||||||
|
.description=Device for the magnet power supply (current mode)
|
||||||
|
abslimits=(0,200)
|
||||||
|
speed=1
|
||||||
|
ramp=60
|
||||||
|
precision=0.02
|
||||||
|
current=0
|
||||||
|
voltage=10
|
||||||
|
#unit=A
|
||||||
|
.visibility=advanced
|
||||||
|
.extra_params = abslimits, speed, ramp, precision, current, voltage, window
|
||||||
|
abslimits.datatype = ["tuple", [["double"], ["double"]]]
|
||||||
|
abslimits.value = (0, 200)
|
||||||
|
abslimits.default = (0, 200)
|
||||||
|
abslimits.unit = 'A'
|
||||||
|
speed.datatype = ["double", 0, 10]
|
||||||
|
speed.default = 10
|
||||||
|
speed.unit = 'A/s'
|
||||||
|
ramp.datatype = ["double", 0, 600]
|
||||||
|
ramp.default = 600
|
||||||
|
ramp.unit = 'A/min'
|
||||||
|
precision.datatype = ["double"]
|
||||||
|
precision.default = 0.1
|
||||||
|
precision.unit = 'A'
|
||||||
|
current.datatype = ["double", 0, 200]
|
||||||
|
current.default = 0
|
||||||
|
current.unit = 'A'
|
||||||
|
voltage.datatype = ["double", 0, 10]
|
||||||
|
voltage.default = 0
|
||||||
|
voltage.unit = 'V'
|
||||||
|
window.datatype = ["double", 0, 120]
|
||||||
|
window.default = 10
|
||||||
|
window.unit = 's'
|
||||||
|
|
||||||
|
[module mf]
|
||||||
|
class=secop_mlz.amagnet.GarfieldMagnet
|
||||||
|
.description=magnetic field module, handling polarity switching and stuff
|
||||||
|
subdev_currentsource=currentsource
|
||||||
|
subdev_enable=enable
|
||||||
|
subdev_polswitch=polarity
|
||||||
|
subdev_symmetry=symmetry
|
||||||
|
target.unit='T'
|
||||||
|
value.unit='T'
|
||||||
|
userlimits=(-0.35, 0.35)
|
||||||
|
calibrationtable={'symmetric':[0.00186517, 0.0431937, -0.185956, 0.0599757, 0.194042],
|
||||||
|
'short': [0.0, 0.0, 0.0, 0.0, 0.0],
|
||||||
|
'asymmetric':[0.00136154, 0.027454, -0.120951, 0.0495289, 0.110689]}
|
||||||
|
.meaning=The magnetic field
|
||||||
|
.priority=100
|
||||||
|
.visibility=user
|
||||||
|
|
||||||
|
abslimits.default=-0.4,0.4
|
@ -605,7 +605,7 @@ DATATYPES = dict(
|
|||||||
enum=lambda kwds: EnumType('', **kwds),
|
enum=lambda kwds: EnumType('', **kwds),
|
||||||
struct=lambda named_subtypes: StructOf(
|
struct=lambda named_subtypes: StructOf(
|
||||||
**dict((n, get_datatype(t)) for n, t in list(named_subtypes.items()))),
|
**dict((n, get_datatype(t)) for n, t in list(named_subtypes.items()))),
|
||||||
command=lambda args, res: CommandType(map(get_datatype, args), res),
|
command=lambda args, res: CommandType(map(get_datatype, args), get_datatype(res)),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -71,7 +71,7 @@ class Has_PIDTable(HAS_PID):
|
|||||||
|
|
||||||
class HAS_Persistent(Feature):
|
class HAS_Persistent(Feature):
|
||||||
#extra_Status {
|
#extra_Status {
|
||||||
# 'decoupled' : Status.OK+1, # to be discussed.
|
# 'decoupled' : Status.IDLE+1, # to be discussed.
|
||||||
# 'coupling' : Status.BUSY+1, # to be discussed.
|
# 'coupling' : Status.BUSY+1, # to be discussed.
|
||||||
# 'coupled' : Status.BUSY+2, # to be discussed.
|
# 'coupled' : Status.BUSY+2, # to be discussed.
|
||||||
# 'decoupling' : Status.BUSY+3, # to be discussed.
|
# 'decoupling' : Status.BUSY+3, # to be discussed.
|
||||||
|
@ -78,7 +78,7 @@ def showCommandResultDialog(command, args, result, extras=''):
|
|||||||
m = QMessageBox()
|
m = QMessageBox()
|
||||||
if not args:
|
if not args:
|
||||||
args = ''
|
args = ''
|
||||||
m.setText('calling: %s(%s)\nyielded: %s\nqualifiers: %s' %
|
m.setText('calling: %s(%s)\nyielded: %r\nqualifiers: %s' %
|
||||||
(command, args, result, extras))
|
(command, args, result, extras))
|
||||||
m.exec_()
|
m.exec_()
|
||||||
|
|
||||||
|
@ -26,7 +26,6 @@
|
|||||||
from time import sleep
|
from time import sleep
|
||||||
|
|
||||||
from secop.lib import mkthread
|
from secop.lib import mkthread
|
||||||
from secop.protocol import status
|
|
||||||
from secop.errors import IsBusyError
|
from secop.errors import IsBusyError
|
||||||
|
|
||||||
|
|
||||||
@ -128,18 +127,18 @@ class SequencerMixin(object):
|
|||||||
|
|
||||||
def read_status(self, maxage=0):
|
def read_status(self, maxage=0):
|
||||||
if self.seq_is_alive():
|
if self.seq_is_alive():
|
||||||
return status.BUSY, u'moving: ' + self._seq_phase
|
return self.Status.BUSY, u'moving: ' + self._seq_phase
|
||||||
elif self._seq_error:
|
elif self._seq_error:
|
||||||
if self._seq_fault_on_error:
|
if self._seq_fault_on_error:
|
||||||
return status.ERROR, self._seq_error
|
return self.Status.ERROR, self._seq_error
|
||||||
return status.WARN, self._seq_error
|
return self.Status.WARN, self._seq_error
|
||||||
elif self._seq_stopped:
|
elif self._seq_stopped:
|
||||||
if self._seq_fault_on_stop:
|
if self._seq_fault_on_stop:
|
||||||
return status.ERROR, self._seq_stopped
|
return self.Status.ERROR, self._seq_stopped
|
||||||
return status.WARN, self._seq_stopped
|
return self.Status.WARN, self._seq_stopped
|
||||||
if hasattr(self, u'read_hw_status'):
|
if hasattr(self, u'read_hw_status'):
|
||||||
return self.read_hw_status(maxage)
|
return self.read_hw_status(maxage)
|
||||||
return status.OK, u''
|
return self.Status.IDLE, u''
|
||||||
|
|
||||||
def do_stop(self):
|
def do_stop(self):
|
||||||
if self.seq_is_alive():
|
if self.seq_is_alive():
|
||||||
|
@ -192,7 +192,7 @@ class Dispatcher(object):
|
|||||||
if moduleobj is None:
|
if moduleobj is None:
|
||||||
raise NoSuchModuleError(module=modulename)
|
raise NoSuchModuleError(module=modulename)
|
||||||
|
|
||||||
cmdspec = moduleobj.commands.get(command, None)
|
cmdspec = moduleobj.accessibles.get(command, None)
|
||||||
if cmdspec is None:
|
if cmdspec is None:
|
||||||
raise NoSuchCommandError(module=modulename, command=command)
|
raise NoSuchCommandError(module=modulename, command=command)
|
||||||
if len(cmdspec.datatype.argtypes) != len(arguments):
|
if len(cmdspec.datatype.argtypes) != len(arguments):
|
||||||
|
@ -31,6 +31,7 @@ except ImportError:
|
|||||||
|
|
||||||
from secop.lib import formatExtendedStack, formatException
|
from secop.lib import formatExtendedStack, formatException
|
||||||
from secop.protocol.messages import HELPREPLY, Message, HelpMessage
|
from secop.protocol.messages import HELPREPLY, Message, HelpMessage
|
||||||
|
from secop.errors import SECoPError
|
||||||
|
|
||||||
|
|
||||||
DEF_PORT = 10767
|
DEF_PORT = 10767
|
||||||
@ -161,6 +162,9 @@ class TCPRequestHandler(socketserver.BaseRequestHandler):
|
|||||||
msgObj = Message(*msg)
|
msgObj = Message(*msg)
|
||||||
msgObj.origin = origin.decode('latin-1')
|
msgObj.origin = origin.decode('latin-1')
|
||||||
msgObj = serverobj.dispatcher.handle_request(self, msgObj)
|
msgObj = serverobj.dispatcher.handle_request(self, msgObj)
|
||||||
|
except SECoPError as err:
|
||||||
|
msgObj.set_error(err.name, str(err), {'exception': formatException(),
|
||||||
|
'traceback': formatExtendedStack()})
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
# create Error Obj instead
|
# create Error Obj instead
|
||||||
msgObj.set_error(u'Internal', str(err), {'exception': formatException(),
|
msgObj.set_error(u'Internal', str(err), {'exception': formatException(),
|
||||||
@ -179,7 +183,7 @@ class TCPRequestHandler(socketserver.BaseRequestHandler):
|
|||||||
if data:
|
if data:
|
||||||
self._queue.append(data)
|
self._queue.append(data)
|
||||||
else:
|
else:
|
||||||
self.log.error('should asynq_queue %s' % data)
|
self.log.error('should async_queue empty data!')
|
||||||
|
|
||||||
def queue_reply(self, data):
|
def queue_reply(self, data):
|
||||||
"""called by dispatcher to queue (sync) replies"""
|
"""called by dispatcher to queue (sync) replies"""
|
||||||
@ -187,7 +191,7 @@ class TCPRequestHandler(socketserver.BaseRequestHandler):
|
|||||||
if data:
|
if data:
|
||||||
self._queue.appendleft(data)
|
self._queue.appendleft(data)
|
||||||
else:
|
else:
|
||||||
self.log.error('should queue %s' % data)
|
self.log.error('should queue empty data!')
|
||||||
|
|
||||||
def finish(self):
|
def finish(self):
|
||||||
"""called when handle() terminates, i.e. the socket closed"""
|
"""called when handle() terminates, i.e. the socket closed"""
|
||||||
@ -215,16 +219,8 @@ class TCPServer(socketserver.ThreadingTCPServer):
|
|||||||
if ':' in bindto:
|
if ':' in bindto:
|
||||||
bindto, _port = bindto.rsplit(':')
|
bindto, _port = bindto.rsplit(':')
|
||||||
portnum = int(_port)
|
portnum = int(_port)
|
||||||
# tcp is a byte stream, so we need Framers (to get frames)
|
|
||||||
# and encoders (to en/decode messages from frames)
|
|
||||||
interfaceopts.pop('framing') # HACK
|
|
||||||
interfaceopts.pop('encoding') # HACK
|
|
||||||
|
|
||||||
# self.framingCLS = FRAMERS[interfaceopts.pop('framing', 'none')]
|
|
||||||
# self.encodingCLS = ENCODERS[interfaceopts.pop('encoding', 'pickle')]
|
|
||||||
self.log.info("TCPServer binding to %s:%d" % (bindto, portnum))
|
self.log.info("TCPServer binding to %s:%d" % (bindto, portnum))
|
||||||
# self.log.debug("TCPServer using framing=%s" % self.framingCLS.__name__)
|
|
||||||
# self.log.debug("TCPServer using encoding=%s" % self.encodingCLS.__name__)
|
|
||||||
socketserver.ThreadingTCPServer.__init__(
|
socketserver.ThreadingTCPServer.__init__(
|
||||||
self, (bindto, portnum), TCPRequestHandler, bind_and_activate=True)
|
self, (bindto, portnum), TCPRequestHandler, bind_and_activate=True)
|
||||||
self.log.info("TCPServer initiated")
|
self.log.info("TCPServer initiated")
|
||||||
|
@ -29,7 +29,7 @@ from secop.protocol.errors import EXCEPTIONS
|
|||||||
|
|
||||||
IDENTREQUEST = u'*IDN?' # literal
|
IDENTREQUEST = u'*IDN?' # literal
|
||||||
# literal! first part is fixed!
|
# literal! first part is fixed!
|
||||||
IDENTREPLY = u'SINE2020&ISSE,SECoP,V2018-02-13,rc2'
|
IDENTREPLY = u'SINE2020&ISSE,SECoP,V2018-06-16,rc1'
|
||||||
|
|
||||||
DESCRIPTIONREQUEST = u'describe' # literal
|
DESCRIPTIONREQUEST = u'describe' # literal
|
||||||
DESCRIPTIONREPLY = u'describing' # +<id> +json
|
DESCRIPTIONREPLY = u'describing' # +<id> +json
|
||||||
|
@ -98,6 +98,8 @@ class SimWritable(SimBase, Writable):
|
|||||||
def write_target(self, value):
|
def write_target(self, value):
|
||||||
self.value = value
|
self.value = value
|
||||||
|
|
||||||
|
def _hw_wait(self):
|
||||||
|
pass
|
||||||
|
|
||||||
class SimDrivable(SimBase, Drivable):
|
class SimDrivable(SimBase, Drivable):
|
||||||
def __init__(self, logger, cfgdict, devname, dispatcher):
|
def __init__(self, logger, cfgdict, devname, dispatcher):
|
||||||
@ -126,4 +128,8 @@ class SimDrivable(SimBase, Drivable):
|
|||||||
else:
|
else:
|
||||||
self._value = self.target
|
self._value = self.target
|
||||||
sleep(0.3)
|
sleep(0.3)
|
||||||
self.status = self.Status.OK, ''
|
self.status = self.Status.IDLE, ''
|
||||||
|
|
||||||
|
def _hw_wait(self):
|
||||||
|
while self.status[0] == self.Status.BUSY:
|
||||||
|
sleep(0.3)
|
||||||
|
@ -144,7 +144,10 @@ class GarfieldMagnet(SequencerMixin, Drivable):
|
|||||||
|
|
||||||
def read_calibration(self, maxage=0):
|
def read_calibration(self, maxage=0):
|
||||||
try:
|
try:
|
||||||
return self.calibrationtable[self._symmetry.value]
|
try:
|
||||||
|
return self.calibrationtable[self._symmetry.value]
|
||||||
|
except KeyError:
|
||||||
|
return self.calibrationtable[self._symmetry.value.name]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
minslope = min(entry[0]
|
minslope = min(entry[0]
|
||||||
for entry in self.calibrationtable.values())
|
for entry in self.calibrationtable.values())
|
||||||
@ -217,10 +220,10 @@ class GarfieldMagnet(SequencerMixin, Drivable):
|
|||||||
# called from SequencerMixin.read_status if no sequence is running
|
# called from SequencerMixin.read_status if no sequence is running
|
||||||
if self._enable.value == 'Off':
|
if self._enable.value == 'Off':
|
||||||
return self.Status.WARN, 'Disabled'
|
return self.Status.WARN, 'Disabled'
|
||||||
if self._enable.read_status(maxage)[0] != self.Status.OK:
|
if self._enable.read_status(maxage)[0] != self.Status.IDLE:
|
||||||
return self._enable.status
|
return self._enable.status
|
||||||
if self._polswitch.value in ['0', 0]:
|
if self._polswitch.value in ['0', 0]:
|
||||||
return self.Status.OK, 'Shorted, ' + self._currentsource.status[1]
|
return self.Status.IDLE, 'Shorted, ' + self._currentsource.status[1]
|
||||||
if self._symmetry.value in ['short', 0]:
|
if self._symmetry.value in ['short', 0]:
|
||||||
return self._currentsource.status[
|
return self._currentsource.status[
|
||||||
0], 'Shorted, ' + self._currentsource.status[1]
|
0], 'Shorted, ' + self._currentsource.status[1]
|
||||||
|
Reference in New Issue
Block a user