Compare commits
45 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1e9cbd1499 | |||
| c48203e45e | |||
| 436f42c6f5 | |||
| ffb02e54f7 | |||
| 9536ee3551 | |||
| 0c5727e093 | |||
| 26561833a2 | |||
| c18fec4081 | |||
| d4adaff40d | |||
| 3d907bd11c | |||
| 806490322e | |||
| c217b1c264 | |||
| a4df743570 | |||
| 9f7413a1a5 | |||
| 43853ae49c | |||
| b96a7dec1c | |||
| 6a89ec8383 | |||
| 53057297d7 | |||
| 4cbc5a9ec9 | |||
| 034a2e4440 | |||
| 6b28b17823 | |||
| 8d722ad09f | |||
| 1fd0647d74 | |||
| c237718a2d | |||
| 868abb4ea2 | |||
| 4bde91d16b | |||
| f8440d38a4 | |||
|
|
e121c3ca8e | ||
| 974e729920 | |||
| 29343faf8a | |||
| 1a82818da4 | |||
| 6e4c53c881 | |||
| 0776b7575f | |||
| e841b7bf0e | |||
| 3bddd87609 | |||
| e213186295 | |||
| ead54b14a5 | |||
| b10102e052 | |||
| 09237e4118 | |||
| 5678530e6e | |||
| 807b9eb4e7 | |||
| 0290c06b66 | |||
| 083bd05b16 | |||
| 91dbc9f086 | |||
| ba0f4e62b6 |
112
devices.py
112
devices.py
@@ -27,10 +27,12 @@ connected to a SEC node
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import threading
|
import threading
|
||||||
|
import socket
|
||||||
|
import json
|
||||||
from nicos import config, session
|
from nicos import config, session
|
||||||
from nicos.core import Override, Param, Moveable, status, POLLER, SIMULATION, DeviceAlias, \
|
from nicos.core import Override, Param, Moveable, status, POLLER, SIMULATION, DeviceAlias, \
|
||||||
Device, anytype, listof, MASTER
|
Device, anytype, listof, MASTER
|
||||||
from nicos.devices.secop.devices import SecNodeDevice
|
from nicos_sinq.frappy_sinq.secop.devices import SecNodeDevice, SecopDevice, DefunctDevice
|
||||||
from nicos.core.utils import createThread
|
from nicos.core.utils import createThread
|
||||||
from nicos.utils.comparestrings import compare
|
from nicos.utils.comparestrings import compare
|
||||||
from nicos.devices.secop.devices import get_attaching_devices
|
from nicos.devices.secop.devices import get_attaching_devices
|
||||||
@@ -38,6 +40,8 @@ from nicos.commands.basic import AddSetup, CreateAllDevices, CreateDevice
|
|||||||
from nicos.utils import loggers
|
from nicos.utils import loggers
|
||||||
from servicemanager import FrappyManager, SeaManager, Reconnect, Keep
|
from servicemanager import FrappyManager, SeaManager, Reconnect, Keep
|
||||||
|
|
||||||
|
|
||||||
|
SECOP_UDP_PORT = 10767
|
||||||
SERVICES = FrappyManager.services
|
SERVICES = FrappyManager.services
|
||||||
|
|
||||||
|
|
||||||
@@ -113,6 +117,21 @@ def get_frappy_config():
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def send_other_udp(uri, instrument, device=None):
|
||||||
|
"""inform the feeder about the start of a frappy server"""
|
||||||
|
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||||
|
sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
|
||||||
|
msg = {
|
||||||
|
'SECoP': 'for_other_node',
|
||||||
|
'uri': uri,
|
||||||
|
'instrument': instrument,
|
||||||
|
}
|
||||||
|
if device:
|
||||||
|
msg['device'] = device
|
||||||
|
msg = json.dumps(msg, ensure_ascii=False, separators=(',', ':')).encode('utf-8')
|
||||||
|
sock.sendto(msg, ('255.255.255.255', SECOP_UDP_PORT))
|
||||||
|
|
||||||
|
|
||||||
class FrappyConfig(Device):
|
class FrappyConfig(Device):
|
||||||
# respect the order: e.g. temperature_regulation must be after temperature
|
# respect the order: e.g. temperature_regulation must be after temperature
|
||||||
# because it will not be added to envlist when temperature is the same device
|
# because it will not be added to envlist when temperature is the same device
|
||||||
@@ -163,8 +182,17 @@ class FrappyConfig(Device):
|
|||||||
before_check = before_change = prev_shown = None
|
before_check = before_change = prev_shown = None
|
||||||
cnt = 0
|
cnt = 0
|
||||||
self._back_to_normal = None
|
self._back_to_normal = None
|
||||||
|
current_exp = id(session.experiment.propinfo)
|
||||||
|
exp_changed = False
|
||||||
|
envlist = []
|
||||||
while not self._shutdown_event.wait(1):
|
while not self._shutdown_event.wait(1):
|
||||||
busy = session.daemon_device._controller.status >= 0
|
busy = session.daemon_device._controller.status >= 0
|
||||||
|
if id(session.experiment.propinfo) != current_exp:
|
||||||
|
# NewExperiment or FinishExperiment was called
|
||||||
|
current_exp = id(session.experiment.propinfo)
|
||||||
|
exp_changed = True
|
||||||
|
elif not exp_changed:
|
||||||
|
envlist = session.experiment.envlist
|
||||||
if self._restarting or (busy and cnt < 10):
|
if self._restarting or (busy and cnt < 10):
|
||||||
# do not check while restarting and check only every 10 sec when busy
|
# do not check while restarting and check only every 10 sec when busy
|
||||||
cnt += 1
|
cnt += 1
|
||||||
@@ -178,6 +206,17 @@ class FrappyConfig(Device):
|
|||||||
self._back_to_normal = None
|
self._back_to_normal = None
|
||||||
cnt = 0
|
cnt = 0
|
||||||
need_change, changes, fm = to_consider = self.to_consider()
|
need_change, changes, fm = to_consider = self.to_consider()
|
||||||
|
if exp_changed:
|
||||||
|
exp_changed = False
|
||||||
|
needed = set(self.needed_envalias()[0])
|
||||||
|
if needed == needed.intersection(envlist) and not session.experiment.envlist:
|
||||||
|
# restore envlist from previous experiment, as it was cleared by New/FinishExperiment
|
||||||
|
session.experiment.setEnvironment(envlist)
|
||||||
|
session.log.info('keep environment from previous experiment: %s', ', '.join(envlist))
|
||||||
|
continue
|
||||||
|
# trigger output of proposed SE change
|
||||||
|
prev_shown = None
|
||||||
|
need_change = True
|
||||||
if fm.state == before_change:
|
if fm.state == before_change:
|
||||||
continue
|
continue
|
||||||
if not need_change:
|
if not need_change:
|
||||||
@@ -327,9 +366,25 @@ class FrappyConfig(Device):
|
|||||||
CreateDevice(nodename)
|
CreateDevice(nodename)
|
||||||
cleanup_defunct()
|
cleanup_defunct()
|
||||||
CreateAllDevices()
|
CreateAllDevices()
|
||||||
|
fm = FrappyManager()
|
||||||
|
ins = config.instrument
|
||||||
|
fm.get_server_state(ins, new_cfg)
|
||||||
|
recorders = {}
|
||||||
for service, secnode in secnodes.items():
|
for service, secnode in secnodes.items():
|
||||||
if services.get(service) and secnode:
|
if services.get(service) and secnode:
|
||||||
|
cfg = fm.frappy_cfgs.get(service)
|
||||||
|
seacfg = fm.frappy2sea.get(cfg)
|
||||||
|
if secnode() and not seacfg:
|
||||||
|
if cfg:
|
||||||
|
recorders[service] = f'localhost:{fm.info[ins].get(service, 0)}/{cfg}'
|
||||||
|
else:
|
||||||
|
recorders[service] = secnode.uri
|
||||||
secnode._secnode.connect()
|
secnode._secnode.connect()
|
||||||
|
if recorders:
|
||||||
|
try:
|
||||||
|
fm.sea.sea_recorder(ins, recorders)
|
||||||
|
except Exception as e:
|
||||||
|
session.log.warning('error in command sea_recorder %r', e)
|
||||||
self.set_envalias()
|
self.set_envalias()
|
||||||
for secnode in remove_cfg:
|
for secnode in remove_cfg:
|
||||||
secnode.disable()
|
secnode.disable()
|
||||||
@@ -348,7 +403,7 @@ class FrappyConfig(Device):
|
|||||||
- frappy('restart') # restart all frappy servers
|
- frappy('restart') # restart all frappy servers
|
||||||
- frappy('reconnect') # reconnect to running frappy servers
|
- frappy('reconnect') # reconnect to running frappy servers
|
||||||
"""
|
"""
|
||||||
self._back_to_normal = None # reset 'back to normal' machanism
|
self._back_to_normal = None # reset 'back to normal' mechanism
|
||||||
stickarg = stick
|
stickarg = stick
|
||||||
|
|
||||||
need_change, changes, fm = to_consider = self.to_consider()
|
need_change, changes, fm = to_consider = self.to_consider()
|
||||||
@@ -597,8 +652,6 @@ class FrappyConfig(Device):
|
|||||||
to_remove = to_remove.difference(addedenv)
|
to_remove = to_remove.difference(addedenv)
|
||||||
prevenv = [k for k in session.experiment.envlist if k not in to_remove]
|
prevenv = [k for k in session.experiment.envlist if k not in to_remove]
|
||||||
envlist = prevenv + [k for k in addedenv if k not in prevenv]
|
envlist = prevenv + [k for k in addedenv if k not in prevenv]
|
||||||
if set(envlist) == set(prevenv):
|
|
||||||
envlist = None
|
|
||||||
|
|
||||||
predef_changes = []
|
predef_changes = []
|
||||||
for aliasname, cfg in predef_aliases:
|
for aliasname, cfg in predef_aliases:
|
||||||
@@ -609,7 +662,7 @@ class FrappyConfig(Device):
|
|||||||
|
|
||||||
def check_envalias(self):
|
def check_envalias(self):
|
||||||
envlist, new_aliases, predef_aliases = self.needed_envalias()
|
envlist, new_aliases, predef_aliases = self.needed_envalias()
|
||||||
if envlist:
|
if set(envlist) != set(session.experiment.envlist):
|
||||||
return f"envlist should be {', '.join(envlist)}"
|
return f"envlist should be {', '.join(envlist)}"
|
||||||
anew = [k for k, v in new_aliases.items() if v is not None]
|
anew = [k for k, v in new_aliases.items() if v is not None]
|
||||||
removed = set(new_aliases).difference(anew)
|
removed = set(new_aliases).difference(anew)
|
||||||
@@ -617,7 +670,7 @@ class FrappyConfig(Device):
|
|||||||
if anew:
|
if anew:
|
||||||
return f"aliases {', '.join(anew)} should change"
|
return f"aliases {', '.join(anew)} should change"
|
||||||
if removed:
|
if removed:
|
||||||
return f"aliases {', '.join(anew)} should be removed"
|
return f"aliases {', '.join(removed)} should be removed"
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def set_envalias(self):
|
def set_envalias(self):
|
||||||
@@ -629,9 +682,15 @@ class FrappyConfig(Device):
|
|||||||
if new_aliases or predef_aliases:
|
if new_aliases or predef_aliases:
|
||||||
for aliasname, devname in new_aliases.items():
|
for aliasname, devname in new_aliases.items():
|
||||||
if devname is None:
|
if devname is None:
|
||||||
session.destroyDevice(aliasname)
|
aliasdev = session.devices.get(aliasname)
|
||||||
session.configured_devices.pop(aliasname, None)
|
if aliasdev:
|
||||||
session.dynamic_devices.pop(aliasname, None)
|
aliastarget = session.devices.get(aliasdev.alias)
|
||||||
|
if isinstance(aliastarget, (SecopDevice, DefunctDevice)):
|
||||||
|
session.destroyDevice(aliasname)
|
||||||
|
session.configured_devices.pop(aliasname, None)
|
||||||
|
session.dynamic_devices.pop(aliasname, None)
|
||||||
|
elif aliastarget:
|
||||||
|
session.log.info('frappy_setup does not remove %s', aliasname)
|
||||||
else:
|
else:
|
||||||
dev = session.devices.get(devname)
|
dev = session.devices.get(devname)
|
||||||
devcfg = ('nicos.core.DeviceAlias', {})
|
devcfg = ('nicos.core.DeviceAlias', {})
|
||||||
@@ -660,15 +719,19 @@ class FrappyConfig(Device):
|
|||||||
|
|
||||||
applyAliasConfig() # for other aliases
|
applyAliasConfig() # for other aliases
|
||||||
|
|
||||||
if envlist is not None:
|
prev = set(session.experiment.envlist)
|
||||||
prev = session.experiment.envlist
|
remove = ', '.join(prev.difference(envlist))
|
||||||
removed = set(prev).difference(envlist)
|
session.experiment.setEnvironment(envlist)
|
||||||
session.experiment.setEnvironment(envlist)
|
show = []
|
||||||
if removed:
|
keep = ', '.join(d for d in envlist if d in prev)
|
||||||
session.log.info('removed %s from environment', ', '.join(removed))
|
if keep:
|
||||||
added = set(envlist).difference(prev)
|
show.append(f'keep {keep}')
|
||||||
if added:
|
add = ', '.join(d for d in envlist if d not in prev)
|
||||||
session.log.info('added %s to environment', ', '.join(added))
|
if add:
|
||||||
|
show.append(f'add {add}')
|
||||||
|
if remove:
|
||||||
|
show.append(f'remove {remove}')
|
||||||
|
session.log.info('environment: %s', '; '.join(show))
|
||||||
|
|
||||||
|
|
||||||
class FrappyNode(SecNodeDevice, Moveable):
|
class FrappyNode(SecNodeDevice, Moveable):
|
||||||
@@ -687,7 +750,13 @@ class FrappyNode(SecNodeDevice, Moveable):
|
|||||||
"set to 'general' if all parameters should appear in the datafile header",
|
"set to 'general' if all parameters should appear in the datafile header",
|
||||||
type=str, default='', settable=True),
|
type=str, default='', settable=True),
|
||||||
'quiet_init': Param('flag to set loglevel to error while initializing',
|
'quiet_init': Param('flag to set loglevel to error while initializing',
|
||||||
type=bool, default=True, settable=True)
|
type=bool, default=True, settable=True),
|
||||||
|
# duplicate from SecNodeDevice. needed for the case where the code for
|
||||||
|
# the SecNodeDevcice is not up to date, but the setup is already new
|
||||||
|
# does not yet have the i
|
||||||
|
'general_stop_whitelist': Param('module names to accept general stop',
|
||||||
|
type=listof(str), prefercache=False,
|
||||||
|
default=[], userparam=False),
|
||||||
}
|
}
|
||||||
|
|
||||||
_cfgvalue = None
|
_cfgvalue = None
|
||||||
@@ -717,6 +786,9 @@ class FrappyNode(SecNodeDevice, Moveable):
|
|||||||
def doRead(self, maxage=0):
|
def doRead(self, maxage=0):
|
||||||
return self._cfgvalue or ''
|
return self._cfgvalue or ''
|
||||||
|
|
||||||
|
def fix(self, reason=''):
|
||||||
|
"""ignore"""
|
||||||
|
|
||||||
def createDevices(self):
|
def createDevices(self):
|
||||||
super().createDevices()
|
super().createDevices()
|
||||||
if self.param_category:
|
if self.param_category:
|
||||||
@@ -830,8 +902,10 @@ class FrappyNode(SecNodeDevice, Moveable):
|
|||||||
if available_cfg is not None:
|
if available_cfg is not None:
|
||||||
raise ValueError('use "frappy_list()" to get a list of valid frappy configurations')
|
raise ValueError('use "frappy_list()" to get a list of valid frappy configurations')
|
||||||
uri = 'localhost:%d' % info[self.service]
|
uri = 'localhost:%d' % info[self.service]
|
||||||
|
send_other_udp(uri, config.instrument, device=cfg)
|
||||||
else:
|
else:
|
||||||
uri = cfg
|
uri = cfg
|
||||||
|
send_other_udp(uri, config.instrument)
|
||||||
if uri != self.uri:
|
if uri != self.uri:
|
||||||
self._disconnect(keeptarget=True)
|
self._disconnect(keeptarget=True)
|
||||||
if uri:
|
if uri:
|
||||||
|
|||||||
1598
secop/devices.py
Normal file
1598
secop/devices.py
Normal file
File diff suppressed because it is too large
Load Diff
@@ -7,5 +7,6 @@ devices = {
|
|||||||
device('nicos_sinq.frappy_sinq.devices.FrappyNode',
|
device('nicos_sinq.frappy_sinq.devices.FrappyNode',
|
||||||
description='main SEC node', unit='', async_only=True,
|
description='main SEC node', unit='', async_only=True,
|
||||||
prefix=environ.get('SE_PREFIX', 'se_'), auto_create=True, service='main',
|
prefix=environ.get('SE_PREFIX', 'se_'), auto_create=True, service='main',
|
||||||
|
general_stop_whitelist=['om', 'stickrot'],
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,26 +0,0 @@
|
|||||||
from os import environ
|
|
||||||
description = 'frappy main setup'
|
|
||||||
group = 'optional'
|
|
||||||
|
|
||||||
devices = {
|
|
||||||
'se_main':
|
|
||||||
device('nicos_sinq.frappy_sinq.devices.FrappyNode',
|
|
||||||
uri='pc12694:5000',
|
|
||||||
description='main SEC node', unit='',
|
|
||||||
prefix=environ.get('SE_PREFIX', ''), auto_create=True, service='main',
|
|
||||||
),
|
|
||||||
'timestamp': device('nicos_linse.common.lab.Timestamp', description='time, a dummy detector'),
|
|
||||||
}
|
|
||||||
|
|
||||||
startupcode = '''
|
|
||||||
printinfo("=======================================================================================")
|
|
||||||
printinfo("Welcome to the NICOS frappy secnode setup for PPMS!")
|
|
||||||
printinfo(" ")
|
|
||||||
printinfo("Usage:")
|
|
||||||
printinfo(" frappy(stick='<stick cfg>') # change sample-stick configuration")
|
|
||||||
printinfo(" frappy(addons='<addon1 cfg>,<addon2 cfg> ...') # change SE addons")
|
|
||||||
printinfo(" frappy(stick=None) # remove stick")
|
|
||||||
printinfo(" frappy(addons=None) # remove addons")
|
|
||||||
printinfo("=======================================================================================")
|
|
||||||
SetDetectors(timestamp)
|
|
||||||
'''
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
description = 'timestamp dummy detector for offline measurements'
|
|
||||||
group = 'optional'
|
|
||||||
|
|
||||||
devices = {
|
|
||||||
'timestamp': device('nicos_linse.common.lab.Timestamp', description='time, a dummy detector'),
|
|
||||||
}
|
|
||||||
|
|
||||||
startupcode = 'SetDetectors(timestamp)'
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user