Provide basic client Object
also improve the describing data and core params Change-Id: I645444f2a618fdfd40a729e1007c58def24d5ffb
This commit is contained in:
@ -116,7 +116,7 @@ class Dispatcher(object):
|
||||
listeners += list(self._dispatcher_active_connections)
|
||||
for conn in listeners:
|
||||
conn.queue_async_reply(msg)
|
||||
|
||||
|
||||
def announce_update(self, moduleobj, pname, pobj):
|
||||
"""called by modules param setters to notify subscribers of new values
|
||||
"""
|
||||
@ -142,7 +142,7 @@ class Dispatcher(object):
|
||||
self._dispatcher_connections.remove(conn)
|
||||
for _evt, conns in self._dispatcher_subscriptions.items():
|
||||
conns.discard(conn)
|
||||
|
||||
|
||||
def activate_connection(self, conn):
|
||||
self._dispatcher_active_connections.add(conn)
|
||||
|
||||
@ -188,6 +188,22 @@ class Dispatcher(object):
|
||||
dd[modulename] = descriptive_data
|
||||
return dn, dd
|
||||
|
||||
def get_descriptive_data(self):
|
||||
# XXX: be lazy and cache this?
|
||||
result = {}
|
||||
for modulename in self._dispatcher_export:
|
||||
module = self.get_module(modulename)
|
||||
dd = {'class' : module.__class__.__name__,
|
||||
'bases' : [b.__name__ for b in module.__class__.__bases__],
|
||||
'parameters': dict((pn,po.as_dict()) for pn,po in module.PARAMS.items()),
|
||||
'commands': dict((cn,co.as_dict()) for cn,co in module.CMDS.items()),
|
||||
'baseclass' : 'Readable',
|
||||
}
|
||||
result.setdefault('modules', {})[modulename] = dd
|
||||
result['equipment_id'] = self.equipment_id
|
||||
# XXX: what else?
|
||||
return result
|
||||
|
||||
def list_module_params(self, modulename):
|
||||
self.log.debug('list_module_params(%r)' % modulename)
|
||||
if modulename in self._dispatcher_export:
|
||||
@ -205,7 +221,7 @@ class Dispatcher(object):
|
||||
def _execute_command(self, modulename, command, arguments=None):
|
||||
if arguments is None:
|
||||
arguments = []
|
||||
|
||||
|
||||
moduleobj = self.get_module(modulename)
|
||||
if moduleobj is None:
|
||||
raise NoSuchmoduleError(module=modulename)
|
||||
@ -273,8 +289,7 @@ class Dispatcher(object):
|
||||
|
||||
def handle_Describe(self, conn, msg):
|
||||
# XXX:collect descriptive data
|
||||
# XXX:how to get equipment_id?
|
||||
return DescribeReply(equipment_id = self.equipment_id, description = self.list_modules())
|
||||
return DescribeReply(equipment_id = self.equipment_id, description = self.get_descriptive_data())
|
||||
|
||||
def handle_Poll(self, conn, msg):
|
||||
# XXX: trigger polling and force sending event
|
||||
@ -283,7 +298,7 @@ class Dispatcher(object):
|
||||
if conn in self._dispatcher_active_connections:
|
||||
return None # already send to myself
|
||||
return res # send reply to inactive conns
|
||||
|
||||
|
||||
def handle_Write(self, conn, msg):
|
||||
# notify all by sending WriteReply
|
||||
#msg1 = WriteReply(**msg.as_dict())
|
||||
@ -301,7 +316,7 @@ class Dispatcher(object):
|
||||
if conn in self._dispatcher_active_connections:
|
||||
return None # already send to myself
|
||||
return res # send reply to inactive conns
|
||||
|
||||
|
||||
def handle_Command(self, conn, msg):
|
||||
# notify all by sending CommandReply
|
||||
#msg1 = CommandReply(**msg.as_dict())
|
||||
@ -314,7 +329,7 @@ class Dispatcher(object):
|
||||
#if conn in self._dispatcher_active_connections:
|
||||
# return None # already send to myself
|
||||
return res # send reply to inactive conns
|
||||
|
||||
|
||||
def handle_Heartbeat(self, conn, msg):
|
||||
return HeartbeatReply(**msg.as_dict())
|
||||
|
||||
@ -331,14 +346,14 @@ class Dispatcher(object):
|
||||
except SECOPError as e:
|
||||
self.log.error('decide what to do here!')
|
||||
self.log.exception(e)
|
||||
res = Value(module=modulename, parameter=pname,
|
||||
value=pobj.value, t=pobj.timestamp,
|
||||
res = Value(module=modulename, parameter=pname,
|
||||
value=pobj.value, t=pobj.timestamp,
|
||||
unit=pobj.unit)
|
||||
if res.value != Ellipsis: # means we do not have a value at all so skip this
|
||||
self.broadcast_event(res)
|
||||
conn.queue_async_reply(ActivateReply(**msg.as_dict()))
|
||||
return None
|
||||
|
||||
|
||||
def handle_Deactivate(self, conn, msg):
|
||||
self.deactivate_connection(conn)
|
||||
conn.queue_async_reply(DeactivateReply(**msg.as_dict()))
|
||||
@ -353,7 +368,7 @@ class Dispatcher(object):
|
||||
(no handle_<messagename> method was defined)
|
||||
"""
|
||||
self.log.error('IGN: got unhandled request %s' % msg)
|
||||
return ErrorMessage(errorclass="InternalError",
|
||||
return ErrorMessage(errorclass="InternalError",
|
||||
errorstring = 'Got Unhandled Request %r' % msg)
|
||||
|
||||
|
||||
|
@ -25,6 +25,7 @@
|
||||
# implement as class as they may need some internal 'state' later on
|
||||
# (think compressors)
|
||||
|
||||
from secop.lib.parsing import format_time
|
||||
from secop.protocol.encoding import MessageEncoder
|
||||
from secop.protocol.messages import *
|
||||
from secop.protocol.errors import ProtocollError
|
||||
@ -42,7 +43,7 @@ DEMO_RE = re.compile(
|
||||
#"""
|
||||
# messagetypes:
|
||||
IDENTREQUEST = '*IDN?' # literal
|
||||
IDENTREPLY = 'Sine2020WP7.1&ISSE, SECoP, V2016-11-30, rc1' # literal
|
||||
IDENTREPLY = 'SECoP, SECoPTCP, V2016-11-30, rc1' # literal! first part 'SECoP' is fixed!
|
||||
DESCRIPTIONSREQUEST = 'describe' # literal
|
||||
DESCRIPTIONREPLY = 'describing' # +<id> +json
|
||||
ENABLEEVENTSREQUEST = 'activate' # literal
|
||||
@ -66,6 +67,12 @@ ERRORCLASSES = ['NoSuchDevice', 'NoSuchParameter', 'NoSuchCommand',
|
||||
'CommandRunning', 'Disabled',]
|
||||
# note: above strings need to be unique in the sense, that none is/or starts with another
|
||||
|
||||
def encode_value_data(vobj):
|
||||
q = vobj.qualifiers.copy()
|
||||
if 't' in q:
|
||||
q['t'] = format_time(q['t'])
|
||||
return vobj.value, q
|
||||
|
||||
class DemoEncoder(MessageEncoder):
|
||||
# map of msg to msgtype string as defined above.
|
||||
ENCODEMAP = {
|
||||
@ -88,7 +95,7 @@ class DemoEncoder(MessageEncoder):
|
||||
ErrorMessage : (ERRORREPLY, 'errorclass', 'errorinfo',),
|
||||
Value: (EVENT, lambda msg: "%s:%s" % (msg.module, msg.parameter or (msg.command+'()'))
|
||||
if msg.parameter or msg.command else msg.module,
|
||||
lambda msg: [msg.value, msg.qualifiers] if msg.qualifiers else [msg.value]),
|
||||
encode_value_data,),
|
||||
}
|
||||
DECODEMAP = {
|
||||
IDENTREQUEST : lambda spec, data: IdentifyRequest(),
|
||||
|
Reference in New Issue
Block a user