change update mechanism
Atoring just updates on the SecopInteractor does not work properly, as these updates depend on what the clients have already. As updates are polled internall anyway, store onm each client the state of the parameters it has looked up already and emit changes values only.
This commit is contained in:
13
base.py
13
base.py
@@ -48,6 +48,8 @@ class Client(HandlerBase):
|
||||
self.id = uuid.uuid4().hex[0:15]
|
||||
self.nodes = {}
|
||||
self.node_map = {}
|
||||
self.update_filter = set() # modules to be updated
|
||||
self.cache = {} # a dict to store the current state of all values
|
||||
if streams:
|
||||
for uri in streams:
|
||||
urisplit = uri.rsplit('://')
|
||||
@@ -69,12 +71,11 @@ class Client(HandlerBase):
|
||||
self.server = server
|
||||
self.instrument_name = instrument_name
|
||||
self.device_name = device_name # do not know if this is needed
|
||||
self.updates = {}
|
||||
|
||||
def poll(self):
|
||||
updates = sum((n.get_updates() for n in self.nodes.values()), start=[])
|
||||
updates = sum((n.get_updates(self.cache, self.update_filter) for n in self.nodes.values()), start=[])
|
||||
result = [dict(type='update', updates=updates)] if updates else []
|
||||
graph_updates = self.handlers.get('graphpoll', object)()
|
||||
graph_updates = self.handlers.get('graphpoll', type(None))()
|
||||
if graph_updates:
|
||||
result.append(graph_updates)
|
||||
return result
|
||||
@@ -91,11 +92,9 @@ class Client(HandlerBase):
|
||||
|
||||
def w_updateblock(self, path):
|
||||
if path == 'main': # TODO: change to "-main-"?
|
||||
for node in self.nodes.values():
|
||||
node.update_main()
|
||||
self.update_filter.add('') # ready to accept updates for main block
|
||||
else:
|
||||
node = self.node_map[path]
|
||||
node.update_params(path)
|
||||
self.update_filter.add(path)
|
||||
return dict(type='accept-block')
|
||||
|
||||
def w_console(self): # TODO: check if still used
|
||||
|
||||
73
secop.py
73
secop.py
@@ -48,17 +48,15 @@ class SecopInteractor(SecopClient):
|
||||
prio_par = ["value", "status", "target"]
|
||||
hide_par = ["baseclass", "class", "pollinterval"]
|
||||
skip_par = ["status2"]
|
||||
main_params = {'value', 'status', 'param'}
|
||||
|
||||
def __init__(self, uri, node_map, change_callback=None):
|
||||
super().__init__(uri)
|
||||
self.module_updates = set()
|
||||
self.param_updates = set()
|
||||
self.updates = {}
|
||||
self.change_callback = change_callback
|
||||
try:
|
||||
self.connect()
|
||||
self.update_node_map(node_map)
|
||||
self.register_callback(None, updateItem=self.updateItem, descriptiveDataChange=self.descChanged)
|
||||
self.register_callback(None, descriptiveDataChange=self.descChanged)
|
||||
except Exception as e:
|
||||
print(repr(e))
|
||||
|
||||
@@ -85,13 +83,9 @@ class SecopInteractor(SecopClient):
|
||||
component['name'] = f'{name}:value'
|
||||
component['title'] = name
|
||||
components.append(component)
|
||||
self.param_updates.add('value')
|
||||
self.param_updates.add('status')
|
||||
self.param_updates.add('target')
|
||||
|
||||
def get_components(self, path):
|
||||
module = self.modules[path]
|
||||
self.module_updates.add(path) # TODO: remove others?
|
||||
parameters = dict(module["parameters"])
|
||||
components = []
|
||||
for name in SecopInteractor.skip_par:
|
||||
@@ -111,38 +105,19 @@ class SecopInteractor(SecopClient):
|
||||
components.append(convert_cmd(path, name, cmd))
|
||||
return components
|
||||
|
||||
def updateItem(self, module, parameter, entry):
|
||||
key = module, parameter
|
||||
# print(key, entry)
|
||||
if module in self.module_updates or parameter in self.param_updates:
|
||||
name = f'{module}:{parameter}'
|
||||
if entry.readerror:
|
||||
item = {'name': name, 'error': str(entry.readerror)}
|
||||
elif parameter == 'status':
|
||||
# statuscode: 0: DISABLED, 1: IDLE, 2: WARN, 3: BUSY, 4: ERROR
|
||||
statuscode, statustext = entry[0]
|
||||
formatted = statuscode.name + (f', {statustext}' if statustext else '')
|
||||
item = {'name': name, 'value': str(entry), 'statuscode': entry[0][0] // 100,
|
||||
'formatted': formatted}
|
||||
else:
|
||||
item = {'name': name, 'value': str(entry), 'formatted': entry.formatted()}
|
||||
# print(item)
|
||||
self.updates[key] = item
|
||||
|
||||
def update_main(self):
|
||||
cache = self.cache
|
||||
for modname in self.modules:
|
||||
for param in 'value', 'status', 'target':
|
||||
key = modname, param
|
||||
if key in cache:
|
||||
self.updateItem(*key, cache[key])
|
||||
|
||||
def update_params(self, path):
|
||||
cache = self.cache
|
||||
for param in self.modules[path]['parameters']:
|
||||
key = path, param
|
||||
if key in cache:
|
||||
self.updateItem(*key, cache[key])
|
||||
def buildUpdateEvent(self, module, parameter, entry):
|
||||
name = f'{module}:{parameter}'
|
||||
if entry.readerror:
|
||||
item = {'name': name, 'error': str(entry.readerror)}
|
||||
elif parameter == 'status':
|
||||
# statuscode: 0: DISABLED, 1: IDLE, 2: WARN, 3: BUSY, 4: ERROR
|
||||
statuscode, statustext = entry[0]
|
||||
formatted = statuscode.name + (f', {statustext}' if statustext else '')
|
||||
item = {'name': name, 'value': str(entry), 'statuscode': entry[0][0] // 100,
|
||||
'formatted': formatted}
|
||||
else:
|
||||
item = {'name': name, 'value': str(entry), 'formatted': entry.formatted()}
|
||||
return item
|
||||
|
||||
def handle_command(self, command):
|
||||
"""handle command if we can, else return False"""
|
||||
@@ -170,12 +145,20 @@ class SecopInteractor(SecopClient):
|
||||
self.updates[module, parameter] = item
|
||||
return True
|
||||
# called a command
|
||||
formatted = self.execCommandFromString(module, parameter, strvalue)[0] # ignore qualifiers
|
||||
return {'name': f'{module}:{parameter}', 'value': str(result), 'formatted': formatted}
|
||||
item = self.execCommandFromString(module, parameter, strvalue)[0] # ignore qualifiers
|
||||
return {'name': f'{module}:{parameter}', 'value': str(item.value), 'formatted': item.formatted()}
|
||||
|
||||
def get_updates(self):
|
||||
updates, self.updates = self.updates, {}
|
||||
return list(updates.values())
|
||||
def get_updates(self, client_state, update_filter):
|
||||
updates = []
|
||||
main_params = self.main_params if '' in update_filter else ()
|
||||
for (module, param), item in self.cache.items():
|
||||
if param in main_params or module in update_filter:
|
||||
key = module, param
|
||||
prev = client_state.get(key)
|
||||
if prev is None or item.value != prev.value or item.readerror != prev.readerror:
|
||||
updates.append(self.buildUpdateEvent(module, param, item))
|
||||
client_state[key] = item
|
||||
return updates
|
||||
|
||||
def info(self):
|
||||
return ["na"]
|
||||
|
||||
Reference in New Issue
Block a user