Remove obsolete protocol implementations
Change-Id: I9342ff3d00666238b6412b41a3785dadd96a7778 Reviewed-on: https://forge.frm2.tum.de/review/16273 Tested-by: JenkinsCodeReview <bjoern_pedersen@frm2.tum.de> Reviewed-by: Enrico Faulhaber <enrico.faulhaber@frm2.tum.de>
This commit is contained in:
parent
38c6729c84
commit
eeac276601
6
doc/source/playground/server/protocol/encoding.rst
Normal file
6
doc/source/playground/server/protocol/encoding.rst
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
SECoP Encoding
|
||||||
|
==============
|
||||||
|
|
||||||
|
.. automodule:: secop.protocol.encoding.secop
|
||||||
|
:members:
|
||||||
|
|
@ -1,6 +0,0 @@
|
|||||||
Demo V2
|
|
||||||
=======
|
|
||||||
|
|
||||||
.. automodule:: secop.protocol.encoding.demo_v2
|
|
||||||
:members:
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
|||||||
Demo V3
|
|
||||||
=======
|
|
||||||
|
|
||||||
.. automodule:: secop.protocol.encoding.demo_v2
|
|
||||||
:members:
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
|||||||
Demo V4
|
|
||||||
=======
|
|
||||||
|
|
||||||
.. automodule:: secop.protocol.encoding.demo_v2
|
|
||||||
:members:
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
|||||||
Demo V5
|
|
||||||
=======
|
|
||||||
|
|
||||||
.. automodule:: secop.protocol.encoding.demo_v2
|
|
||||||
:members:
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
|||||||
Encodings
|
|
||||||
=========
|
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
:maxdepth: 3
|
|
||||||
|
|
||||||
demo_v2
|
|
||||||
demo_v3
|
|
||||||
demo_v4
|
|
||||||
demo_v5
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
|||||||
Different protocols
|
protocol stack
|
||||||
===================
|
==============
|
||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
:maxdepth: 3
|
:maxdepth: 3
|
||||||
|
|
||||||
encoding/index
|
encoding
|
||||||
framing/index
|
framing/index
|
||||||
interface/index
|
interface/index
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ bindto=0.0.0.0
|
|||||||
bindport=10767
|
bindport=10767
|
||||||
# protocol to use for this interface
|
# protocol to use for this interface
|
||||||
framing=eol
|
framing=eol
|
||||||
encoding=demo
|
encoding=secop
|
||||||
|
|
||||||
[device enable]
|
[device enable]
|
||||||
class=secop_mlz.entangle.NamedDigitalOutput
|
class=secop_mlz.entangle.NamedDigitalOutput
|
||||||
|
@ -11,7 +11,7 @@ bindto=0.0.0.0
|
|||||||
bindport=10767
|
bindport=10767
|
||||||
# protocol to use for this interface
|
# protocol to use for this interface
|
||||||
framing=eol
|
framing=eol
|
||||||
encoding=demo
|
encoding=secop
|
||||||
|
|
||||||
[device automatik]
|
[device automatik]
|
||||||
class=secop_mlz.entangle.NamedDigitalOutput
|
class=secop_mlz.entangle.NamedDigitalOutput
|
||||||
|
@ -11,7 +11,7 @@ bindto=0.0.0.0
|
|||||||
bindport=10769
|
bindport=10769
|
||||||
# protocol to use for this interface
|
# protocol to use for this interface
|
||||||
framing=eol
|
framing=eol
|
||||||
encoding=demo
|
encoding=secop
|
||||||
|
|
||||||
|
|
||||||
[device cryo]
|
[device cryo]
|
||||||
|
@ -7,7 +7,7 @@ bindto=0.0.0.0
|
|||||||
bindport=10767
|
bindport=10767
|
||||||
# protocol to use for this interface
|
# protocol to use for this interface
|
||||||
framing=eol
|
framing=eol
|
||||||
encoding=demo
|
encoding=secop
|
||||||
|
|
||||||
[device heatswitch]
|
[device heatswitch]
|
||||||
class=secop_demo.modules.Switch
|
class=secop_demo.modules.Switch
|
||||||
|
@ -6,7 +6,7 @@ connectto=0.0.0.0
|
|||||||
port=10767
|
port=10767
|
||||||
interface = tcp
|
interface = tcp
|
||||||
framing=eol
|
framing=eol
|
||||||
encoding=text
|
encoding=secop
|
||||||
|
|
||||||
[interface testing]
|
[interface testing]
|
||||||
interface=tcp
|
interface=tcp
|
||||||
@ -14,7 +14,7 @@ bindto=0.0.0.0
|
|||||||
bindport=10767
|
bindport=10767
|
||||||
# protocol to use for this interface
|
# protocol to use for this interface
|
||||||
framing=eol
|
framing=eol
|
||||||
encoding=demo
|
encoding=secop
|
||||||
|
|
||||||
[device tc1]
|
[device tc1]
|
||||||
class=secop_demo.demo.CoilTemp
|
class=secop_demo.demo.CoilTemp
|
||||||
|
@ -14,7 +14,7 @@ bindto=0.0.0.0
|
|||||||
bindport=10768
|
bindport=10768
|
||||||
# protocol to use for this interface
|
# protocol to use for this interface
|
||||||
framing=eol
|
framing=eol
|
||||||
encoding=demo
|
encoding=secop
|
||||||
|
|
||||||
|
|
||||||
[device LN2]
|
[device LN2]
|
||||||
|
@ -26,20 +26,37 @@
|
|||||||
|
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
|
|
||||||
#from secop.lib.parsing import format_time
|
|
||||||
from secop.protocol.encoding import MessageEncoder
|
|
||||||
from secop.protocol.messages import *
|
|
||||||
#from secop.protocol.errors import ProtocolError
|
|
||||||
|
|
||||||
import ast
|
# Base class
|
||||||
|
class MessageEncoder(object):
|
||||||
|
"""en/decode a single Messageobject"""
|
||||||
|
|
||||||
|
def encode(self, msg):
|
||||||
|
"""encodes the given message object into a frame"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def decode(self, encoded):
|
||||||
|
"""decodes the given frame to a message object"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
|
||||||
import re
|
import re
|
||||||
import json
|
import json
|
||||||
|
|
||||||
|
#from secop.lib.parsing import format_time
|
||||||
|
from secop.protocol.messages import Value, IdentifyRequest, IdentifyReply, \
|
||||||
|
DescribeRequest, DescribeReply, ActivateRequest, ActivateReply, \
|
||||||
|
DeactivateRequest, DeactivateReply, CommandRequest, CommandReply, \
|
||||||
|
WriteRequest, WriteReply, PollRequest, HeartbeatRequest, HeartbeatReply, \
|
||||||
|
ErrorMessage, HelpMessage
|
||||||
|
#from secop.protocol.errors import ProtocolError
|
||||||
|
|
||||||
|
|
||||||
# each message is like <messagetype> [ \space <messageargs> [ \space
|
# each message is like <messagetype> [ \space <messageargs> [ \space
|
||||||
# <json> ]] \lf
|
# <json> ]] \lf
|
||||||
|
|
||||||
# note: the regex allow <> for spec for testing only!
|
# note: the regex allow <> for spec for testing only!
|
||||||
DEMO_RE = re.compile(
|
SECOP_RE = re.compile(
|
||||||
r"""^(?P<msgtype>[\*\?\w]+)(?:\s(?P<spec>[\w:<>]+)(?:\s(?P<json>.*))?)?$""",
|
r"""^(?P<msgtype>[\*\?\w]+)(?:\s(?P<spec>[\w:<>]+)(?:\s(?P<json>.*))?)?$""",
|
||||||
re.X)
|
re.X)
|
||||||
|
|
||||||
@ -113,7 +130,7 @@ def encode_error_msg(emsg):
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class DemoEncoder(MessageEncoder):
|
class SECoPEncoder(MessageEncoder):
|
||||||
# map of msg to msgtype string as defined above.
|
# map of msg to msgtype string as defined above.
|
||||||
ENCODEMAP = {
|
ENCODEMAP = {
|
||||||
IdentifyRequest: (IDENTREQUEST, ),
|
IdentifyRequest: (IDENTREQUEST, ),
|
||||||
@ -170,7 +187,7 @@ class DemoEncoder(MessageEncoder):
|
|||||||
DECODEMAP = {
|
DECODEMAP = {
|
||||||
IDENTREQUEST: lambda spec, data: IdentifyRequest(),
|
IDENTREQUEST: lambda spec, data: IdentifyRequest(),
|
||||||
# handled specially, listed here for completeness
|
# handled specially, listed here for completeness
|
||||||
IDENTREPLY: lambda spec, data: IdentifyReply(encoded),
|
# IDENTREPLY: lambda spec, data: IdentifyReply(encoded),
|
||||||
DESCRIPTIONSREQUEST: lambda spec, data: DescribeRequest(),
|
DESCRIPTIONSREQUEST: lambda spec, data: DescribeRequest(),
|
||||||
DESCRIPTIONREPLY: lambda spec, data: DescribeReply(equipment_id=spec[0], description=data),
|
DESCRIPTIONREPLY: lambda spec, data: DescribeReply(equipment_id=spec[0], description=data),
|
||||||
ENABLEEVENTSREQUEST: lambda spec, data: ActivateRequest(),
|
ENABLEEVENTSREQUEST: lambda spec, data: ActivateRequest(),
|
||||||
@ -187,7 +204,8 @@ class DemoEncoder(MessageEncoder):
|
|||||||
HELPREQUEST: lambda spec, data: HelpMessage(),
|
HELPREQUEST: lambda spec, data: HelpMessage(),
|
||||||
# HELPREPLY: lambda spec, data:None, # ignore this
|
# HELPREPLY: lambda spec, data:None, # ignore this
|
||||||
ERRORREPLY: lambda spec, data: ErrorMessage(errorclass=spec[0], errorinfo=data),
|
ERRORREPLY: lambda spec, data: ErrorMessage(errorclass=spec[0], errorinfo=data),
|
||||||
EVENT: lambda spec, data: Value(module=spec[0], parameter=spec[1], value=data[0], qualifiers=data[1] if len(data) > 1 else {}),
|
EVENT: lambda spec, data: Value(module=spec[0], parameter=spec[1], value=data[0],
|
||||||
|
qualifiers=data[1] if len(data) > 1 else {}),
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, *args, **kwds):
|
def __init__(self, *args, **kwds):
|
||||||
@ -235,7 +253,7 @@ class DemoEncoder(MessageEncoder):
|
|||||||
|
|
||||||
def decode(self, encoded):
|
def decode(self, encoded):
|
||||||
# first check beginning
|
# first check beginning
|
||||||
match = DEMO_RE.match(encoded)
|
match = SECOP_RE.match(encoded)
|
||||||
if not match:
|
if not match:
|
||||||
print(repr(encoded), repr(IDENTREPLY))
|
print(repr(encoded), repr(IDENTREPLY))
|
||||||
if encoded == IDENTREPLY: # XXX:better just check the first 2 parts...
|
if encoded == IDENTREPLY: # XXX:better just check the first 2 parts...
|
||||||
@ -277,7 +295,7 @@ class DemoEncoder(MessageEncoder):
|
|||||||
|
|
||||||
def tests(self):
|
def tests(self):
|
||||||
print("---- Testing encoding -----")
|
print("---- Testing encoding -----")
|
||||||
for msgclass, parts in sorted(self.ENCODEMAP.items()):
|
for msgclass in sorted(self.ENCODEMAP):
|
||||||
print(msgclass)
|
print(msgclass)
|
||||||
e = self.encode(
|
e = self.encode(
|
||||||
msgclass(
|
msgclass(
|
||||||
@ -305,3 +323,10 @@ class DemoEncoder(MessageEncoder):
|
|||||||
print(self.encode(d))
|
print(self.encode(d))
|
||||||
print()
|
print()
|
||||||
print("---- Testing done -----")
|
print("---- Testing done -----")
|
||||||
|
|
||||||
|
|
||||||
|
ENCODERS = {
|
||||||
|
'secop': SECoPEncoder,
|
||||||
|
}
|
||||||
|
|
||||||
|
__ALL__ = ['ENCODERS']
|
@ -1,61 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
# *****************************************************************************
|
|
||||||
# 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>
|
|
||||||
#
|
|
||||||
# *****************************************************************************
|
|
||||||
"""Encoding/decoding Messages"""
|
|
||||||
|
|
||||||
# implement as class as they may need some internal 'state' later on
|
|
||||||
# (think compressors)
|
|
||||||
|
|
||||||
# Base classes
|
|
||||||
|
|
||||||
|
|
||||||
class MessageEncoder(object):
|
|
||||||
"""en/decode a single Messageobject"""
|
|
||||||
|
|
||||||
def encode(self, messageobj):
|
|
||||||
"""encodes the given message object into a frame"""
|
|
||||||
raise NotImplemented
|
|
||||||
|
|
||||||
def decode(self, frame):
|
|
||||||
"""decodes the given frame to a message object"""
|
|
||||||
raise NotImplemented
|
|
||||||
|
|
||||||
|
|
||||||
from .demo_v2 import DemoEncoder as DemoEncoderV2
|
|
||||||
from .demo_v3 import DemoEncoder as DemoEncoderV3
|
|
||||||
from .demo_v4 import DemoEncoder as DemoEncoderV4
|
|
||||||
from .demo_v5 import DemoEncoder as DemoEncoderV5
|
|
||||||
from .text import TextEncoder
|
|
||||||
from .pickle import PickleEncoder
|
|
||||||
from .simplecomm import SCPEncoder
|
|
||||||
|
|
||||||
ENCODERS = {
|
|
||||||
'pickle': PickleEncoder,
|
|
||||||
'text': TextEncoder,
|
|
||||||
'demo_v2': DemoEncoderV2,
|
|
||||||
'demo_v3': DemoEncoderV3,
|
|
||||||
'demo_v4': DemoEncoderV4,
|
|
||||||
'demo_v5': DemoEncoderV5,
|
|
||||||
'demo': DemoEncoderV5,
|
|
||||||
'scp': SCPEncoder,
|
|
||||||
}
|
|
||||||
|
|
||||||
__ALL__ = ['ENCODERS']
|
|
@ -1,111 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
# *****************************************************************************
|
|
||||||
# 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>
|
|
||||||
#
|
|
||||||
# *****************************************************************************
|
|
||||||
"""Encoding/decoding Messages"""
|
|
||||||
|
|
||||||
# implement as class as they may need some internal 'state' later on
|
|
||||||
# (think compressors)
|
|
||||||
|
|
||||||
from __future__ import print_function
|
|
||||||
|
|
||||||
from secop.protocol.encoding import MessageEncoder
|
|
||||||
from secop.protocol import messages
|
|
||||||
from secop.lib.parsing import *
|
|
||||||
|
|
||||||
import re
|
|
||||||
|
|
||||||
DEMO_RE = re.compile(
|
|
||||||
r'^([!+-])?(\*|[a-z_][a-z_0-9]*)?(?:\:(\*|[a-z_][a-z_0-9]*))?(?:\:(\*|[a-z_][a-z_0-9]*))?(?:\=(.*))?'
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class DemoEncoder(MessageEncoder):
|
|
||||||
|
|
||||||
def decode(sef, encoded):
|
|
||||||
# match [!][*|devicename][: *|paramname [: *|propname]] [=value]
|
|
||||||
match = DEMO_RE.match(encoded)
|
|
||||||
if match:
|
|
||||||
novalue, devname, pname, propname, assign = match.groups()
|
|
||||||
if assign:
|
|
||||||
print("parsing", assign,)
|
|
||||||
assign = parse_args(assign)
|
|
||||||
print("->", assign)
|
|
||||||
return messages.DemoRequest(novalue, devname, pname, propname,
|
|
||||||
assign)
|
|
||||||
return messages.HelpRequest()
|
|
||||||
|
|
||||||
def encode(self, msg):
|
|
||||||
if isinstance(msg, messages.DemoReply):
|
|
||||||
return msg.lines
|
|
||||||
handler_name = '_encode_' + msg.__class__.__name__
|
|
||||||
handler = getattr(self, handler_name, None)
|
|
||||||
if handler is None:
|
|
||||||
print("Handler %s not yet implemented!" % handler_name)
|
|
||||||
try:
|
|
||||||
args = dict((k, msg.__dict__[k]) for k in msg.ARGS)
|
|
||||||
result = handler(**args)
|
|
||||||
except Exception as e:
|
|
||||||
print("Error encoding %r with %r!" % (msg, handler))
|
|
||||||
print(e)
|
|
||||||
return '~InternalError~'
|
|
||||||
return result
|
|
||||||
|
|
||||||
def _encode_AsyncDataUnit(self,
|
|
||||||
devname,
|
|
||||||
pname,
|
|
||||||
value,
|
|
||||||
timestamp,
|
|
||||||
error=None,
|
|
||||||
unit=''):
|
|
||||||
return '#%s:%s=%s;t=%.3f' % (devname, pname, value, timestamp)
|
|
||||||
|
|
||||||
def _encode_Error(self, error):
|
|
||||||
return '~Error~ %r' % error
|
|
||||||
|
|
||||||
def _encode_InternalError(self, error):
|
|
||||||
return '~InternalError~ %r' % error
|
|
||||||
|
|
||||||
def _encode_ProtocollError(self, msgtype, msgname, msgargs):
|
|
||||||
return '~ProtocolError~ %s.%s.%r' % (msgtype, msgname, msgargs)
|
|
||||||
|
|
||||||
def _encode_NoSuchModuleError(self, device):
|
|
||||||
return '~NoSuchModuleError~ %s' % device
|
|
||||||
|
|
||||||
def _encode_NoSuchParamError(self, device, param):
|
|
||||||
return '~NoSuchParameterError~ %s:%s' % (device, param)
|
|
||||||
|
|
||||||
def _encode_ParamReadonlyError(self, device, param):
|
|
||||||
return '~ParamReadOnlyError~ %s:%s' % (device, param)
|
|
||||||
|
|
||||||
def _encode_NoSuchCommandError(self, device, command):
|
|
||||||
return '~NoSuchCommandError~ %s.%s' % (device, command)
|
|
||||||
|
|
||||||
def _encode_CommandFailedError(self, device, command):
|
|
||||||
return '~CommandFailedError~ %s.%s' % (device, command)
|
|
||||||
|
|
||||||
def _encode_InvalidParamValueError(self, device, param, value):
|
|
||||||
return '~InvalidValueForParamError~ %s:%s=%r' % (device, param, value)
|
|
||||||
|
|
||||||
def _encode_HelpReply(self):
|
|
||||||
return [
|
|
||||||
'Help not yet implemented!',
|
|
||||||
'ask Markus Zolliker about the protocol'
|
|
||||||
]
|
|
@ -1,387 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
# *****************************************************************************
|
|
||||||
# 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>
|
|
||||||
#
|
|
||||||
# *****************************************************************************
|
|
||||||
"""Encoding/decoding Messages"""
|
|
||||||
|
|
||||||
# implement as class as they may need some internal 'state' later on
|
|
||||||
# (think compressors)
|
|
||||||
|
|
||||||
from __future__ import print_function
|
|
||||||
|
|
||||||
from secop.protocol.encoding import MessageEncoder
|
|
||||||
from secop.protocol.messages import *
|
|
||||||
from secop.protocol.errors import ProtocolError
|
|
||||||
|
|
||||||
import ast
|
|
||||||
import re
|
|
||||||
|
|
||||||
|
|
||||||
def floatify(s):
|
|
||||||
try:
|
|
||||||
return int(s)
|
|
||||||
except (ValueError, TypeError):
|
|
||||||
try:
|
|
||||||
return float(s)
|
|
||||||
except (ValueError, TypeError):
|
|
||||||
return s
|
|
||||||
|
|
||||||
|
|
||||||
def devspec(msg, result=''):
|
|
||||||
if isinstance(msg, Message):
|
|
||||||
devs = ','.join(msg.devs)
|
|
||||||
pars = ','.join(msg.pars)
|
|
||||||
props = ','.join(msg.props)
|
|
||||||
else:
|
|
||||||
devs = msg.dev
|
|
||||||
pars = msg.par
|
|
||||||
props = msg.prop
|
|
||||||
if devs:
|
|
||||||
result = '%s %s' % (result, devs)
|
|
||||||
if pars:
|
|
||||||
result = '%s:%s' % (result, pars)
|
|
||||||
if props:
|
|
||||||
result = '%s:%s' % (result, props)
|
|
||||||
return result.strip()
|
|
||||||
|
|
||||||
|
|
||||||
def encode_value(value, prefix='', targetvalue='', cmd=''):
|
|
||||||
result = [prefix]
|
|
||||||
if value.dev:
|
|
||||||
result.append(' ')
|
|
||||||
result.append(value.dev)
|
|
||||||
if value.param:
|
|
||||||
result.append(':%s' % value.param)
|
|
||||||
if value.prop:
|
|
||||||
result.append(':%s' % value.prop)
|
|
||||||
# only needed for WriteMessages
|
|
||||||
if targetvalue:
|
|
||||||
result.append('=%s' % repr(targetvalue))
|
|
||||||
# only needed for CommandMessages
|
|
||||||
if cmd:
|
|
||||||
result.append(':%s' % cmd)
|
|
||||||
if value.value != Ellipsis:
|
|
||||||
# results always have a ';'
|
|
||||||
result.append('=%s;' % repr(value.value))
|
|
||||||
result.append(';'.join('%s=%s' % (qn, repr(qv))
|
|
||||||
for qn, qv in value.qualifiers.items()))
|
|
||||||
return ''.join(result).strip()
|
|
||||||
|
|
||||||
|
|
||||||
DEMO_RE_ERROR = re.compile(
|
|
||||||
r"""^error\s(?P<errortype>\w+)\s(?P<msgtype>\w+)?(?:\s(?P<devs>\*|[\w,]+)(?:\:(?P<pars>\*|[\w,]+)(?:\:(?P<props>\*|[\w,]+))?)?)?(?:(?:\=(?P<target>[^=;\s"]*))|(?:\((?P<cmdargs>[^\)]*)\)))?(?:\s"(?P<errorstring>[^"]*)")$""",
|
|
||||||
re.X)
|
|
||||||
DEMO_RE_OTHER = re.compile(
|
|
||||||
r"""^(?P<msgtype>\w+)(?:\s(?P<devs>\*|[\w,]+)(?:\:(?P<pars>\*|[\w,]+)(?:\:(?P<props>\*|[\w,]+))?)?)?(?:(?:\=(?P<target>[^=;]*))|(?::(?P<cmd>\w+)\((?P<args>[^\)]*)\)))?(?:=(?P<readback>[^;]+);(?P<qualifiers>.*))?$""",
|
|
||||||
re.X)
|
|
||||||
|
|
||||||
|
|
||||||
class DemoEncoder(MessageEncoder):
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwds):
|
|
||||||
MessageEncoder.__init__(self, *args, **kwds)
|
|
||||||
self.result = [] # for decoding
|
|
||||||
self.expect_lines = 1
|
|
||||||
# self.tests()
|
|
||||||
|
|
||||||
def encode(self, msg):
|
|
||||||
"""msg object -> transport layer message"""
|
|
||||||
# fun for Humans
|
|
||||||
if isinstance(msg, HelpMessage):
|
|
||||||
r = ['#5']
|
|
||||||
r.append("help Try one of the following:")
|
|
||||||
r.append("help 'list' to query a list of modules")
|
|
||||||
r.append("help 'read <module>' to read a module")
|
|
||||||
r.append("help 'list <module>' to query a list of parameters")
|
|
||||||
r.append("help ... more to come")
|
|
||||||
return '\n'.join(r)
|
|
||||||
|
|
||||||
if isinstance(msg, (ListMessage, SubscribeMessage, UnsubscribeMessage,
|
|
||||||
TriggerMessage)):
|
|
||||||
msgtype = msg.MSGTYPE
|
|
||||||
if msg.result:
|
|
||||||
if msg.devs:
|
|
||||||
# msg.result is always a list!
|
|
||||||
return "%s=%s" % (devspec(msg, msgtype),
|
|
||||||
','.join(map(str, msg.result)))
|
|
||||||
return "%s=%s" % (msgtype, ','.join(map(str, msg.result)))
|
|
||||||
return devspec(msg, msgtype).strip()
|
|
||||||
|
|
||||||
if isinstance(msg, (ReadMessage, PollMessage, EventMessage)):
|
|
||||||
msgtype = msg.MSGTYPE
|
|
||||||
result = []
|
|
||||||
if len(msg.result or []) > 1:
|
|
||||||
result.append("#%d" % len(msg.result))
|
|
||||||
for val in msg.result or []:
|
|
||||||
# encode 1..N replies
|
|
||||||
result.append(encode_value(val, msgtype))
|
|
||||||
if not msg.result:
|
|
||||||
# encode a request (no results -> reply, else an error would
|
|
||||||
# have been sent)
|
|
||||||
result.append(devspec(msg, msgtype))
|
|
||||||
return '\n'.join(result)
|
|
||||||
|
|
||||||
if isinstance(msg, WriteMessage):
|
|
||||||
result = []
|
|
||||||
if len(msg.result or []) > 1:
|
|
||||||
result.append("#%d" % len(msg.result))
|
|
||||||
for val in msg.result or []:
|
|
||||||
# encode 1..N replies
|
|
||||||
result.append(
|
|
||||||
encode_value(
|
|
||||||
val, 'write', targetvalue=msg.target))
|
|
||||||
if not msg.result:
|
|
||||||
# encode a request (no results -> reply, else an error would
|
|
||||||
# have been sent)
|
|
||||||
result.append('%s=%r' % (devspec(msg, 'write'), msg.target))
|
|
||||||
return '\n'.join(result)
|
|
||||||
|
|
||||||
if isinstance(msg, CommandMessage):
|
|
||||||
result = []
|
|
||||||
if len(msg.result or []) > 1:
|
|
||||||
result.append("#%d" % len(msg.result))
|
|
||||||
for val in msg.result or []:
|
|
||||||
# encode 1..N replies
|
|
||||||
result.append(
|
|
||||||
encode_value(
|
|
||||||
val,
|
|
||||||
'command',
|
|
||||||
cmd='%s(%s)' % (msg.cmd, ','.join(msg.args))))
|
|
||||||
if not msg.result:
|
|
||||||
# encode a request (no results -> reply, else an error would
|
|
||||||
# have been sent)
|
|
||||||
result.append('%s:%s(%s)' % (devspec(msg, 'command'), msg.cmd,
|
|
||||||
','.join(msg.args)))
|
|
||||||
return '\n'.join(result)
|
|
||||||
|
|
||||||
if isinstance(msg, ErrorMessage):
|
|
||||||
return ('%s %s' % (devspec(msg, 'error %s' % msg.errortype),
|
|
||||||
msg.errorstring)).strip()
|
|
||||||
|
|
||||||
return 'Can not handle object %r!' % msg
|
|
||||||
|
|
||||||
def decode(self, encoded):
|
|
||||||
if encoded.startswith('#'):
|
|
||||||
# XXX: check if last message was complete
|
|
||||||
self.expect_lines = int(encoded[1:])
|
|
||||||
if self.result:
|
|
||||||
# XXX: also flag an error?
|
|
||||||
self.result = []
|
|
||||||
return None
|
|
||||||
|
|
||||||
if encoded == '':
|
|
||||||
return HelpMessage()
|
|
||||||
# now decode the message and append to self.result
|
|
||||||
msg = self.decode_single_message(encoded)
|
|
||||||
if msg:
|
|
||||||
# XXX: check if messagetype is the same as the already existing,
|
|
||||||
# else error
|
|
||||||
self.result.append(msg)
|
|
||||||
else:
|
|
||||||
# XXX: flag an error?
|
|
||||||
return HelpMessage()
|
|
||||||
|
|
||||||
self.expect_lines -= 1
|
|
||||||
if self.expect_lines <= 0:
|
|
||||||
# reconstruct a multi-reply-message from the entries
|
|
||||||
# return the first message, but extend the result list first
|
|
||||||
# if there is only 1 message, just return this
|
|
||||||
res = self.result.pop(0)
|
|
||||||
while self.result:
|
|
||||||
m = self.result.pop(0)
|
|
||||||
res.result.append(m.result[0])
|
|
||||||
self.expect_lines = 1
|
|
||||||
return res
|
|
||||||
|
|
||||||
# no complete message yet
|
|
||||||
return None
|
|
||||||
|
|
||||||
def decode_single_message(self, encoded):
|
|
||||||
# just decode a single message line
|
|
||||||
|
|
||||||
# 1) check for error msgs (more specific first)
|
|
||||||
m = DEMO_RE_ERROR.match(encoded)
|
|
||||||
if m:
|
|
||||||
return ErrorMessage(**m.groupdict())
|
|
||||||
|
|
||||||
# 2) check for 'normal' message
|
|
||||||
m = DEMO_RE_OTHER.match(encoded)
|
|
||||||
if m:
|
|
||||||
mgroups = m.groupdict()
|
|
||||||
msgtype = mgroups.pop('msgtype')
|
|
||||||
|
|
||||||
# reformat devspec
|
|
||||||
def helper(stuff, sep=','):
|
|
||||||
if not stuff:
|
|
||||||
return []
|
|
||||||
if sep in stuff:
|
|
||||||
return stuff.split(sep)
|
|
||||||
return [stuff]
|
|
||||||
|
|
||||||
devs = helper(mgroups.pop('devs'))
|
|
||||||
pars = helper(mgroups.pop('pars'))
|
|
||||||
props = helper(mgroups.pop('props'))
|
|
||||||
|
|
||||||
# sugar for listing stuff:
|
|
||||||
# map list -> list *
|
|
||||||
# map list x -> list x:*
|
|
||||||
# map list x:y -> list x:y:*
|
|
||||||
if msgtype == LIST:
|
|
||||||
if not devs:
|
|
||||||
devs = ['*']
|
|
||||||
elif devs[0] != '*':
|
|
||||||
if not pars:
|
|
||||||
pars = ['*']
|
|
||||||
elif pars[0] != '*':
|
|
||||||
if not props:
|
|
||||||
props = ['*']
|
|
||||||
|
|
||||||
# reformat cmdargs
|
|
||||||
args = ast.literal_eval(mgroups.pop('args') or '()')
|
|
||||||
if msgtype == COMMAND:
|
|
||||||
mgroups['args'] = args
|
|
||||||
|
|
||||||
# reformat qualifiers
|
|
||||||
print(mgroups)
|
|
||||||
quals = dict(
|
|
||||||
qual.split('=', 1)
|
|
||||||
for qual in helper(mgroups.pop('qualifiers', ';')))
|
|
||||||
|
|
||||||
# reformat value
|
|
||||||
result = []
|
|
||||||
readback = mgroups.pop('readback')
|
|
||||||
if readback or quals:
|
|
||||||
valargs = dict()
|
|
||||||
if devs:
|
|
||||||
valargs['dev'] = devs[0]
|
|
||||||
if pars:
|
|
||||||
valargs['par'] = pars[0]
|
|
||||||
if props:
|
|
||||||
valargs['prop'] = props[0]
|
|
||||||
result = [Value(floatify(readback), quals, **valargs)]
|
|
||||||
if msgtype == LIST and result:
|
|
||||||
result = [n.strip() for n in readback.split(',')]
|
|
||||||
|
|
||||||
# construct messageobj
|
|
||||||
if msgtype in MESSAGE:
|
|
||||||
return MESSAGE[msgtype](devs=devs,
|
|
||||||
pars=pars,
|
|
||||||
props=props,
|
|
||||||
result=result,
|
|
||||||
**mgroups)
|
|
||||||
|
|
||||||
return ErrorMessage(
|
|
||||||
errortype="SyntaxError", errorstring="Can't handle %r" % encoded)
|
|
||||||
|
|
||||||
def tests(self):
|
|
||||||
testmsg = [
|
|
||||||
'list',
|
|
||||||
'list *',
|
|
||||||
'list device',
|
|
||||||
'list device:param1,param2',
|
|
||||||
'list *:*',
|
|
||||||
'list *=ts,tcoil,mf,lhe,ln2;',
|
|
||||||
'read blub=12;t=3',
|
|
||||||
'command ts:stop()',
|
|
||||||
'command mf:quench(1,"now")',
|
|
||||||
'error GibbetNich query x:y:z=9 "blubub blah"',
|
|
||||||
'#3',
|
|
||||||
'read blub:a=12;t=3',
|
|
||||||
'read blub:b=13;t=3.1',
|
|
||||||
'read blub:c=14;t=3.3',
|
|
||||||
]
|
|
||||||
for m in testmsg:
|
|
||||||
print(repr(m))
|
|
||||||
print(self.decode(m))
|
|
||||||
print()
|
|
||||||
|
|
||||||
|
|
||||||
DEMO_RE_MZ = re.compile(
|
|
||||||
r"""^(?P<type>[a-z]+)? # request type word (read/write/list/...)
|
|
||||||
\ ? # optional space
|
|
||||||
(?P<device>[a-z][a-z0-9_]*)? # optional devicename
|
|
||||||
(?:\:(?P<param>[a-z0-9_]*) # optional ':'+paramname
|
|
||||||
(?:\:(?P<prop>[a-z0-9_]*))?)? # optinal ':' + propname
|
|
||||||
(?:(?P<op>[=\?])(?P<value>[^;]+)(?:\;(?P<quals>.*))?)?$""",
|
|
||||||
re.X)
|
|
||||||
|
|
||||||
|
|
||||||
class DemoEncoder_MZ(MessageEncoder):
|
|
||||||
|
|
||||||
def decode(sef, encoded):
|
|
||||||
m = DEMO_RE_MZ.match(encoded)
|
|
||||||
if m:
|
|
||||||
print("implement me !")
|
|
||||||
return HelpRequest()
|
|
||||||
|
|
||||||
def encode(self, msg):
|
|
||||||
"""msg object -> transport layer message"""
|
|
||||||
# fun for Humans
|
|
||||||
if isinstance(msg, HelpReply):
|
|
||||||
r = []
|
|
||||||
r.append("Try one of the following:")
|
|
||||||
r.append("'list' to query a list of modules")
|
|
||||||
r.append("'read <module>' to read a module")
|
|
||||||
r.append("'list <module>' to query a list of parameters")
|
|
||||||
r.append("... more to come")
|
|
||||||
return '\n'.join(r)
|
|
||||||
|
|
||||||
return {
|
|
||||||
ListModulesRequest: lambda msg: "list",
|
|
||||||
ListModulesReply: lambda msg: "list=%s" % ','.join(sorted(msg.list_of_devices)),
|
|
||||||
GetVersionRequest: lambda msg: "version",
|
|
||||||
GetVersionReply: lambda msg: "version=%r" % msg.version,
|
|
||||||
ListModuleParamsRequest: lambda msg: "list %s" % msg.device,
|
|
||||||
# do not include a '.' as param name!
|
|
||||||
ListModuleParamsReply: lambda msg: "list %s=%s" % (msg.device, ','.join(sorted(msg.params.keys()))),
|
|
||||||
ReadValueRequest: lambda msg: "read %s" % msg.device,
|
|
||||||
ReadValueReply: lambda msg: "read %s=%r" % (msg.device, msg.value),
|
|
||||||
WriteValueRequest: lambda msg: "write %s=%r" % (msg.device, msg.value),
|
|
||||||
WriteValueReply: lambda msg: "write %s=%r" % (msg.device, msg.readback_value),
|
|
||||||
ReadParamRequest: lambda msg: "read %s:%s" % (msg.device, msg.param),
|
|
||||||
ReadParamReply: lambda msg: "read %s:%s=%r" % (msg.device, msg.param, msg.value),
|
|
||||||
WriteParamRequest: lambda msg: "write %s:%s=%r" % (msg.device, msg.param, msg.value),
|
|
||||||
WriteParamReply: lambda msg: "write %s:%s=%r" % (msg.device, msg.param, msg.readback_value),
|
|
||||||
# extensions
|
|
||||||
ReadAllModulesRequest: lambda msg: "",
|
|
||||||
ReadAllModulesReply: lambda msg: "",
|
|
||||||
ListParamPropsRequest: lambda msg: "readprop %s:%s" % (msg.device, msg.param),
|
|
||||||
ListParamPropsReply: lambda msg: ["readprop %s:%s" % (msg.device, msg.param)] + ["%s:%s:%s=%s" % (msg.device, msg.param, k, v) for k, v in sorted(msg.props.items())],
|
|
||||||
ReadPropertyRequest: lambda msg: "readprop %s:%s:%s" % (msg.device, msg.param, msg.prop),
|
|
||||||
ReadPropertyReply: lambda msg: "readprop %s:%s:%s=%s" % (msg.device, msg.param, msg.prop, msg.value),
|
|
||||||
AsyncDataUnit: lambda msg: "",
|
|
||||||
SubscribeRequest: lambda msg: "subscribe %s:%s" % (msg.device, msg.param) if msg.param else ("subscribe %s" % msg.device),
|
|
||||||
SubscribeReply: lambda msg: "subscribe %s:%s" % (msg.device, msg.param) if msg.param else ("subscribe %s" % msg.device),
|
|
||||||
UnSubscribeRequest: lambda msg: "",
|
|
||||||
UnSubscribeReply: lambda msg: "",
|
|
||||||
CommandRequest: lambda msg: "command %s:%s" % (msg.device, msg.command),
|
|
||||||
CommandReply: lambda msg: "command %s:%s" % (msg.device, msg.command),
|
|
||||||
# errors
|
|
||||||
ErrorReply: lambda msg: "",
|
|
||||||
InternalError: lambda msg: "",
|
|
||||||
ProtocolError: lambda msg: "",
|
|
||||||
CommandFailedError: lambda msg: "error CommandError %s:%s %s" % (msg.device, msg.param, msg.error),
|
|
||||||
NoSuchCommandError: lambda msg: "error NoSuchCommand %s:%s" % (msg.device, msg.param, msg.error),
|
|
||||||
NoSuchModuleError: lambda msg: "error NoSuchModule %s" % msg.device,
|
|
||||||
NoSuchParamError: lambda msg: "error NoSuchParameter %s:%s" % (msg.device, msg.param),
|
|
||||||
ParamReadonlyError: lambda msg: "",
|
|
||||||
UnsupportedFeatureError: lambda msg: "",
|
|
||||||
InvalidParamValueError: lambda msg: "",
|
|
||||||
}[msg.__class__](msg)
|
|
@ -1,307 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
# *****************************************************************************
|
|
||||||
# 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>
|
|
||||||
#
|
|
||||||
# *****************************************************************************
|
|
||||||
"""Encoding/decoding Messages"""
|
|
||||||
|
|
||||||
# implement as class as they may need some internal 'state' later on
|
|
||||||
# (think compressors)
|
|
||||||
|
|
||||||
from __future__ import print_function
|
|
||||||
|
|
||||||
from secop.lib.parsing import format_time
|
|
||||||
from secop.protocol.encoding import MessageEncoder
|
|
||||||
from secop.protocol.messages import *
|
|
||||||
#from secop.protocol.errors import ProtocolError
|
|
||||||
|
|
||||||
import ast
|
|
||||||
import re
|
|
||||||
import json
|
|
||||||
|
|
||||||
# each message is like <messagetype> [ \space <messageargs> [ \space
|
|
||||||
# <json> ]] \lf
|
|
||||||
|
|
||||||
# note: the regex allow <> for spec for testing only!
|
|
||||||
DEMO_RE = re.compile(
|
|
||||||
r"""^(?P<msgtype>[\*\?\w]+)(?:\s(?P<spec>[\w:<>]+)(?:\s(?P<json>.*))?)?$""",
|
|
||||||
re.X)
|
|
||||||
|
|
||||||
#"""
|
|
||||||
# messagetypes:
|
|
||||||
IDENTREQUEST = '*IDN?' # literal
|
|
||||||
# literal! first part is fixed!
|
|
||||||
#IDENTREPLY = 'SECoP, SECoPTCP, V2016-11-30, rc1'
|
|
||||||
#IDENTREPLY = 'SINE2020&ISSE,SECoP,V2016-11-30,rc1'
|
|
||||||
IDENTREPLY = 'SINE2020&ISSE,SECoP,V2017-01-25,rc1'
|
|
||||||
DESCRIPTIONSREQUEST = 'describe' # literal
|
|
||||||
DESCRIPTIONREPLY = 'describing' # +<id> +json
|
|
||||||
ENABLEEVENTSREQUEST = 'activate' # literal
|
|
||||||
ENABLEEVENTSREPLY = 'active' # literal, is end-of-initial-data-transfer
|
|
||||||
DISABLEEVENTSREQUEST = 'deactivate' # literal
|
|
||||||
DISABLEEVENTSREPLY = 'inactive' # literal
|
|
||||||
COMMANDREQUEST = 'do' # +module:command +json args (if needed)
|
|
||||||
# +module:command +json args (if needed) # send after the command finished !
|
|
||||||
COMMANDREPLY = 'done'
|
|
||||||
# +module[:parameter] +json_value -> NO direct reply, calls TRIGGER internally!
|
|
||||||
WRITEREQUEST = 'change'
|
|
||||||
# +module[:parameter] +json_value # send with the read back value
|
|
||||||
WRITEREPLY = 'changed'
|
|
||||||
# +module[:parameter] -> NO direct reply, calls TRIGGER internally!
|
|
||||||
TRIGGERREQUEST = 'read'
|
|
||||||
EVENT = 'update' # +module[:parameter] +json_value (value, qualifiers_as_dict)
|
|
||||||
HEARTBEATREQUEST = 'ping' # +nonce_without_space
|
|
||||||
HEARTBEATREPLY = 'pong' # +nonce_without_space
|
|
||||||
ERRORREPLY = 'error' # +errorclass +json_extended_info
|
|
||||||
HELPREQUEST = 'help' # literal
|
|
||||||
HELPREPLY = 'helping' # +line number +json_text
|
|
||||||
ERRORCLASSES = [
|
|
||||||
'NoSuchModule',
|
|
||||||
'NoSuchParameter',
|
|
||||||
'NoSuchCommand',
|
|
||||||
'CommandFailed',
|
|
||||||
'ReadOnly',
|
|
||||||
'BadValue',
|
|
||||||
'CommunicationFailed',
|
|
||||||
'IsBusy',
|
|
||||||
'IsError',
|
|
||||||
'ProtocolError',
|
|
||||||
'InternalError',
|
|
||||||
'CommandRunning',
|
|
||||||
'Disabled',
|
|
||||||
]
|
|
||||||
|
|
||||||
# note: above strings need to be unique in the sense, that none is/or
|
|
||||||
# starts with another
|
|
||||||
|
|
||||||
|
|
||||||
def encode_cmd_result(msgobj):
|
|
||||||
q = msgobj.qualifiers.copy()
|
|
||||||
if 't' in q:
|
|
||||||
q['t'] = format_time(q['t'])
|
|
||||||
return msgobj.result, q
|
|
||||||
|
|
||||||
|
|
||||||
def encode_value_data(vobj):
|
|
||||||
q = vobj.qualifiers.copy()
|
|
||||||
if 't' in q:
|
|
||||||
q['t'] = format_time(q['t'])
|
|
||||||
return vobj.value, q
|
|
||||||
|
|
||||||
|
|
||||||
def encode_error_msg(emsg):
|
|
||||||
# note: result is JSON-ified....
|
|
||||||
return [
|
|
||||||
emsg.origin, dict((k, getattr(emsg, k)) for k in emsg.ARGS
|
|
||||||
if k != 'origin')
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
class DemoEncoder(MessageEncoder):
|
|
||||||
# map of msg to msgtype string as defined above.
|
|
||||||
ENCODEMAP = {
|
|
||||||
IdentifyRequest: (IDENTREQUEST, ),
|
|
||||||
IdentifyReply: (IDENTREPLY, ),
|
|
||||||
DescribeRequest: (DESCRIPTIONSREQUEST, ),
|
|
||||||
DescribeReply: (
|
|
||||||
DESCRIPTIONREPLY,
|
|
||||||
'equipment_id',
|
|
||||||
'description', ),
|
|
||||||
ActivateRequest: (ENABLEEVENTSREQUEST, ),
|
|
||||||
ActivateReply: (ENABLEEVENTSREPLY, ),
|
|
||||||
DeactivateRequest: (DISABLEEVENTSREQUEST, ),
|
|
||||||
DeactivateReply: (DISABLEEVENTSREPLY, ),
|
|
||||||
CommandRequest: (
|
|
||||||
COMMANDREQUEST,
|
|
||||||
lambda msg: "%s:%s" % (msg.module, msg.command),
|
|
||||||
'arguments', ),
|
|
||||||
CommandReply: (
|
|
||||||
COMMANDREPLY,
|
|
||||||
lambda msg: "%s:%s" % (msg.module, msg.command),
|
|
||||||
encode_cmd_result, ),
|
|
||||||
WriteRequest: (
|
|
||||||
WRITEREQUEST,
|
|
||||||
lambda msg: "%s:%s" % (
|
|
||||||
msg.module, msg.parameter) if msg.parameter else msg.module,
|
|
||||||
'value', ),
|
|
||||||
WriteReply: (
|
|
||||||
WRITEREPLY,
|
|
||||||
lambda msg: "%s:%s" % (
|
|
||||||
msg.module, msg.parameter) if msg.parameter else msg.module,
|
|
||||||
'value', ),
|
|
||||||
PollRequest: (
|
|
||||||
TRIGGERREQUEST,
|
|
||||||
lambda msg: "%s:%s" % (
|
|
||||||
msg.module, msg.parameter) if msg.parameter else msg.module,
|
|
||||||
),
|
|
||||||
HeartbeatRequest: (
|
|
||||||
HEARTBEATREQUEST,
|
|
||||||
'nonce', ),
|
|
||||||
HeartbeatReply: (
|
|
||||||
HEARTBEATREPLY,
|
|
||||||
'nonce', ),
|
|
||||||
HelpMessage: (HELPREQUEST, ),
|
|
||||||
ErrorMessage: (
|
|
||||||
ERRORREPLY,
|
|
||||||
"errorclass",
|
|
||||||
encode_error_msg, ),
|
|
||||||
Value: (
|
|
||||||
EVENT,
|
|
||||||
lambda msg: "%s:%s" % (msg.module, msg.parameter or (
|
|
||||||
msg.command + '()')) if msg.parameter or msg.command else msg.module,
|
|
||||||
encode_value_data, ),
|
|
||||||
}
|
|
||||||
DECODEMAP = {
|
|
||||||
IDENTREQUEST: lambda spec, data: IdentifyRequest(),
|
|
||||||
# handled specially, listed here for completeness
|
|
||||||
IDENTREPLY: lambda spec, data: IdentifyReply(encoded),
|
|
||||||
DESCRIPTIONSREQUEST: lambda spec, data: DescribeRequest(),
|
|
||||||
DESCRIPTIONREPLY: lambda spec, data: DescribeReply(equipment_id=spec[0], description=data),
|
|
||||||
ENABLEEVENTSREQUEST: lambda spec, data: ActivateRequest(),
|
|
||||||
ENABLEEVENTSREPLY: lambda spec, data: ActivateReply(),
|
|
||||||
DISABLEEVENTSREQUEST: lambda spec, data: DeactivateRequest(),
|
|
||||||
DISABLEEVENTSREPLY: lambda spec, data: DeactivateReply(),
|
|
||||||
COMMANDREQUEST: lambda spec, data: CommandRequest(module=spec[0], command=spec[1], arguments=data),
|
|
||||||
COMMANDREPLY: lambda spec, data: CommandReply(module=spec[0], command=spec[1], result=data),
|
|
||||||
WRITEREQUEST: lambda spec, data: WriteRequest(module=spec[0], parameter=spec[1], value=data),
|
|
||||||
WRITEREPLY: lambda spec, data: WriteReply(module=spec[0], parameter=spec[1], value=data),
|
|
||||||
TRIGGERREQUEST: lambda spec, data: PollRequest(module=spec[0], parameter=spec[1]),
|
|
||||||
HEARTBEATREQUEST: lambda spec, data: HeartbeatRequest(nonce=spec[0]),
|
|
||||||
HEARTBEATREPLY: lambda spec, data: HeartbeatReply(nonce=spec[0]),
|
|
||||||
HELPREQUEST: lambda spec, data: HelpMessage(),
|
|
||||||
# HELPREPLY: lambda spec, data:None, # ignore this
|
|
||||||
ERRORREPLY: lambda spec, data: ErrorMessage(errorclass=spec[0], errorinfo=data),
|
|
||||||
EVENT: lambda spec, data: Value(module=spec[0], parameter=spec[1], value=data[0], qualifiers=data[1] if len(data) > 1 else {}),
|
|
||||||
}
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwds):
|
|
||||||
MessageEncoder.__init__(self, *args, **kwds)
|
|
||||||
# self.tests()
|
|
||||||
|
|
||||||
def encode(self, msg):
|
|
||||||
"""msg object -> transport layer message"""
|
|
||||||
# fun for Humans
|
|
||||||
if isinstance(msg, HelpMessage):
|
|
||||||
text = """Try one of the following:
|
|
||||||
'%s' to query protocol version
|
|
||||||
'%s' to read the description
|
|
||||||
'%s <module>[:<parameter>]' to request reading a value
|
|
||||||
'%s <module>[:<parameter>] value' to request changing a value
|
|
||||||
'%s <module>[:<command>()]' to execute a command
|
|
||||||
'%s <nonce>' to request a heartbeat response
|
|
||||||
'%s' to activate async updates
|
|
||||||
'%s' to deactivate updates
|
|
||||||
""" % (IDENTREQUEST, DESCRIPTIONSREQUEST, TRIGGERREQUEST,
|
|
||||||
WRITEREQUEST, COMMANDREQUEST, HEARTBEATREQUEST,
|
|
||||||
ENABLEEVENTSREQUEST, DISABLEEVENTSREQUEST)
|
|
||||||
return '\n'.join('%s %d %s' % (HELPREPLY, i + 1, l.strip())
|
|
||||||
for i, l in enumerate(text.split('\n')[:-1]))
|
|
||||||
if isinstance(msg, HeartbeatRequest):
|
|
||||||
if msg.nonce:
|
|
||||||
return 'ping %s' % msg.nonce
|
|
||||||
return 'ping'
|
|
||||||
if isinstance(msg, HeartbeatReply):
|
|
||||||
if msg.nonce:
|
|
||||||
return 'pong %s' % msg.nonce
|
|
||||||
return 'pong'
|
|
||||||
for msgcls, parts in self.ENCODEMAP.items():
|
|
||||||
if isinstance(msg, msgcls):
|
|
||||||
# resolve lambdas
|
|
||||||
parts = [parts[0]] + [
|
|
||||||
p(msg) if callable(p) else getattr(msg, p)
|
|
||||||
for p in parts[1:]
|
|
||||||
]
|
|
||||||
if len(parts) > 1:
|
|
||||||
parts[1] = str(parts[1])
|
|
||||||
if len(parts) == 3:
|
|
||||||
parts[2] = json.dumps(parts[2])
|
|
||||||
return ' '.join(parts)
|
|
||||||
|
|
||||||
def decode(self, encoded):
|
|
||||||
# first check beginning
|
|
||||||
match = DEMO_RE.match(encoded)
|
|
||||||
if not match:
|
|
||||||
print(repr(encoded), repr(IDENTREPLY))
|
|
||||||
if encoded == IDENTREPLY: # XXX:better just check the first 2 parts...
|
|
||||||
return IdentifyReply(version_string=encoded)
|
|
||||||
|
|
||||||
return HelpMessage()
|
|
||||||
# return ErrorMessage(errorclass='Protocol',
|
|
||||||
# errorinfo='Regex did not match!',
|
|
||||||
# is_request=True)
|
|
||||||
msgtype, msgspec, data = match.groups()
|
|
||||||
if msgspec is None and data:
|
|
||||||
return ErrorMessage(
|
|
||||||
errorclass='Internal',
|
|
||||||
errorinfo='Regex matched json, but not spec!',
|
|
||||||
is_request=True,
|
|
||||||
origin=encoded)
|
|
||||||
|
|
||||||
if msgtype in self.DECODEMAP:
|
|
||||||
if msgspec and ':' in msgspec:
|
|
||||||
msgspec = msgspec.split(':', 1)
|
|
||||||
else:
|
|
||||||
msgspec = (msgspec, None)
|
|
||||||
if data:
|
|
||||||
try:
|
|
||||||
data = json.loads(data)
|
|
||||||
except ValueError as err:
|
|
||||||
return ErrorMessage(
|
|
||||||
errorclass='BadValue',
|
|
||||||
errorinfo=[repr(err), str(encoded)],
|
|
||||||
origin=encoded)
|
|
||||||
msg = self.DECODEMAP[msgtype](msgspec, data)
|
|
||||||
msg.setvalue("origin", encoded)
|
|
||||||
return msg
|
|
||||||
return ErrorMessage(
|
|
||||||
errorclass='Protocol',
|
|
||||||
errorinfo='%r: No Such Messagetype defined!' % encoded,
|
|
||||||
is_request=True,
|
|
||||||
origin=encoded)
|
|
||||||
|
|
||||||
def tests(self):
|
|
||||||
print("---- Testing encoding -----")
|
|
||||||
for msgclass, parts in sorted(self.ENCODEMAP.items()):
|
|
||||||
print(msgclass)
|
|
||||||
e = self.encode(
|
|
||||||
msgclass(
|
|
||||||
module='<module>',
|
|
||||||
parameter='<paramname>',
|
|
||||||
value=2.718,
|
|
||||||
equipment_id='<id>',
|
|
||||||
description='descriptive data',
|
|
||||||
command='<cmd>',
|
|
||||||
arguments='<arguments>',
|
|
||||||
nonce='<nonce>',
|
|
||||||
errorclass='InternalError',
|
|
||||||
errorinfo='nix'))
|
|
||||||
print(e)
|
|
||||||
print(self.decode(e))
|
|
||||||
print()
|
|
||||||
print("---- Testing decoding -----")
|
|
||||||
for msgtype, _ in sorted(self.DECODEMAP.items()):
|
|
||||||
msg = '%s a:b 3' % msgtype
|
|
||||||
if msgtype == EVENT:
|
|
||||||
msg = '%s a:b [3,{"t":193868}]' % msgtype
|
|
||||||
print(msg)
|
|
||||||
d = self.decode(msg)
|
|
||||||
print(d)
|
|
||||||
print(self.encode(d))
|
|
||||||
print()
|
|
||||||
print("---- Testing done -----")
|
|
@ -1,45 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
# *****************************************************************************
|
|
||||||
# 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>
|
|
||||||
#
|
|
||||||
# *****************************************************************************
|
|
||||||
"""Encoding/decoding Messages"""
|
|
||||||
|
|
||||||
# implement as class as they may need some internal 'state' later on
|
|
||||||
# (think compressors)
|
|
||||||
|
|
||||||
from secop.protocol.encoding import MessageEncoder
|
|
||||||
from secop.protocol import messages
|
|
||||||
from secop.lib.parsing import *
|
|
||||||
|
|
||||||
try:
|
|
||||||
import cPickle as pickle
|
|
||||||
except ImportError:
|
|
||||||
import pickle
|
|
||||||
|
|
||||||
|
|
||||||
class PickleEncoder(MessageEncoder):
|
|
||||||
|
|
||||||
def encode(self, messageobj):
|
|
||||||
"""msg object -> transport layer message"""
|
|
||||||
return pickle.dumps(messageobj)
|
|
||||||
|
|
||||||
def decode(self, encoded):
|
|
||||||
"""transport layer message -> msg object"""
|
|
||||||
return pickle.loads(encoded)
|
|
@ -1,212 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
# *****************************************************************************
|
|
||||||
# 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>
|
|
||||||
#
|
|
||||||
# *****************************************************************************
|
|
||||||
"""Encoding/decoding Messages"""
|
|
||||||
|
|
||||||
# implement as class as they may need some internal 'state' later on
|
|
||||||
# (think compressors)
|
|
||||||
|
|
||||||
from secop.protocol.encoding import MessageEncoder
|
|
||||||
from secop.protocol.messages import *
|
|
||||||
from secop.lib.parsing import *
|
|
||||||
|
|
||||||
import re
|
|
||||||
import ast
|
|
||||||
|
|
||||||
SCPMESSAGE = re.compile(
|
|
||||||
r'^(?:(?P<errorcode>[0-9@])\ )?(?P<device>[a-zA-Z0-9_\*]*)(?:/(?P<param>[a-zA-Z0-9_\*]*))+(?P<op>[-+=\?\ ])?(?P<value>.*)'
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class SCPEncoder(MessageEncoder):
|
|
||||||
|
|
||||||
def encode(self, msg):
|
|
||||||
"""msg object -> transport layer message"""
|
|
||||||
# fun for Humans
|
|
||||||
if isinstance(msg, HelpReply):
|
|
||||||
r = []
|
|
||||||
r.append("Try one of the following:")
|
|
||||||
r.append("'/version?' to query the current version")
|
|
||||||
r.append("'/modules?' to query the list of modules")
|
|
||||||
r.append(
|
|
||||||
"'<module>/parameters?' to query the list of params of a module"
|
|
||||||
)
|
|
||||||
r.append("'<module>/value?' to query the value of a module")
|
|
||||||
r.append("'<module>/status?' to query the status of a module")
|
|
||||||
r.append("'<module>/target=<new_value>' to move a module")
|
|
||||||
r.append(
|
|
||||||
"replies copy the request and are prefixed with an errorcode:")
|
|
||||||
r.append(
|
|
||||||
"0=OK,3=NoSuchCommand,4=NosuchModule,5=NoSuchParam,6=SyntaxError,7=BadValue,8=Readonly,9=Forbidden,@=Async"
|
|
||||||
)
|
|
||||||
r.append("extensions: @-prefix as error-code,")
|
|
||||||
r.append("'<module>/+' subscribe all params of module")
|
|
||||||
r.append("'<module>/<param>+' subscribe a param of a module")
|
|
||||||
r.append("use '-' instead of '+' to unsubscribe")
|
|
||||||
r.append("'<module>/commands?' list of commands")
|
|
||||||
r.append(
|
|
||||||
"'<module>/<command>@[possible args] execute command (ex. 'stop@')"
|
|
||||||
)
|
|
||||||
return '\n'.join(r)
|
|
||||||
|
|
||||||
return {
|
|
||||||
ListModulesRequest: lambda msg: "devices?",
|
|
||||||
ListModulesReply: lambda msg: "0 devices=" + repr(list(msg.list_of_devices)),
|
|
||||||
GetVersionRequest: lambda msg: "version?",
|
|
||||||
GetVersionReply: lambda msg: "0 version=%r" % msg.version,
|
|
||||||
ListModuleParamsRequest: lambda msg: "%s/parameters?" % msg.device,
|
|
||||||
ListModuleParamsReply: lambda msg: "0 %s/parameters=%r" % (msg.device, list(msg.params)),
|
|
||||||
ReadValueRequest: lambda msg: "%s/value?" % msg.device,
|
|
||||||
ReadValueReply: lambda msg: "0 %s/value?%r" % (msg.device, msg.value),
|
|
||||||
WriteValueRequest: lambda msg: "%s/value=%r" % (msg.device, msg.value),
|
|
||||||
WriteValueReply: lambda msg: "0 %s/value=%r" % (msg.device, msg.value),
|
|
||||||
ReadParamRequest: lambda msg: "%s/%s?" % (msg.device, msg.param),
|
|
||||||
ReadParamReply: lambda msg: "0 %s/%s?%r" % (msg.device, msg.param, msg.value),
|
|
||||||
WriteParamRequest: lambda msg: "%s/%s=%r" % (msg.device, msg.param, msg.value),
|
|
||||||
WriteParamReply: lambda msg: "0 %s/%s=%r" % (msg.device, msg.param, msg.readback_value),
|
|
||||||
# extensions
|
|
||||||
ReadAllModulesRequest: lambda msg: "*/value?",
|
|
||||||
ReadAllModulesReply: lambda msg: ["0 %s/value=%s" % (m.device, m.value) for m in msg.readValueReplies],
|
|
||||||
ListParamPropsRequest: lambda msg: "%s/%s/?" % (msg.device, msg.param),
|
|
||||||
ListParamPropsReply: lambda msg: ["0 %s/%s/%s" % (msg.device, msg.param, p) for p in msg.props],
|
|
||||||
AsyncDataUnit: lambda msg: "@ %s/%s=%r" % (msg.devname, msg.pname, msg.value),
|
|
||||||
SubscribeRequest: lambda msg: "%s/%s+" % (msg.devname, msg.pname),
|
|
||||||
# violates spec ! we would need the original request here....
|
|
||||||
SubscribeReply: lambda msg: "0 / %r" % [repr(s) for s in msg.subscriptions],
|
|
||||||
UnSubscribeRequest: lambda msg: "%s/%s+" % (msg.devname, msg.pname),
|
|
||||||
# violates spec ! we would need the original request here....
|
|
||||||
UnSubscribeReply: lambda msg: "0 / %r" % [repr(s) for s in msg.subscriptions],
|
|
||||||
# errors
|
|
||||||
# violates spec ! we would need the original request here....
|
|
||||||
ErrorReply: lambda msg: "1 /%r" % msg.error,
|
|
||||||
# violates spec ! we would need the original request here....
|
|
||||||
InternalError: lambda msg: "1 /%r" % msg.error,
|
|
||||||
# violates spec ! we would need the original request here....
|
|
||||||
ProtocollError: lambda msg: "6 /%r" % msg.error,
|
|
||||||
# violates spec ! we would need the original request here....
|
|
||||||
CommandFailedError: lambda msg: "1 %s/%s" % (msg.device, msg.command),
|
|
||||||
# violates spec ! we would need the original request here....
|
|
||||||
NoSuchCommandError: lambda msg: "3 %s/%s" % (msg.device, msg.command),
|
|
||||||
# violates spec ! we would need the original request here....
|
|
||||||
NoSuchModuleError: lambda msg: "4 %s/ %r" % (msg.device, msg.error),
|
|
||||||
# violates spec ! we would need the original request here....
|
|
||||||
NoSuchParamError: lambda msg: "5 %s/%s %r" % (msg.device, msg.param, msg.error),
|
|
||||||
# violates spec ! we would need the original request here....
|
|
||||||
ParamReadonlyError: lambda msg: "8 %s/%s %r" % (msg.device, msg.param, msg.error),
|
|
||||||
# violates spec ! we would need the original request here....
|
|
||||||
UnsupportedFeatureError: lambda msg: "3 / %r" % msg.feature,
|
|
||||||
# violates spec ! we would need the original request here....
|
|
||||||
InvalidParamValueError: lambda msg: "7 %s/%s=%r %r" % (msg.device, msg.param, msg.value, msg.error),
|
|
||||||
}[msg.__class__](msg)
|
|
||||||
|
|
||||||
def decode(self, encoded):
|
|
||||||
"""transport layer message -> msg object"""
|
|
||||||
match = SCPMESSAGE.match(encoded)
|
|
||||||
if not (match):
|
|
||||||
return HelpRequest()
|
|
||||||
err, dev, par, op, val = match.groups()
|
|
||||||
if val is not None:
|
|
||||||
try:
|
|
||||||
val = ast.literal_eval(val)
|
|
||||||
except Exception as e:
|
|
||||||
return SyntaxError('while decoding %r: %s' % (encoded, e))
|
|
||||||
if err == '@':
|
|
||||||
# async
|
|
||||||
if op == '=':
|
|
||||||
return AsyncDataUnit(dev, par, val)
|
|
||||||
return ProtocolError("Asyncupdates must have op = '='!")
|
|
||||||
elif err is None:
|
|
||||||
# request
|
|
||||||
if op == '+':
|
|
||||||
# subscribe
|
|
||||||
if dev:
|
|
||||||
if par:
|
|
||||||
return SubscribeRequest(dev, par)
|
|
||||||
return SubscribeRequest(dev, '*')
|
|
||||||
if op == '-':
|
|
||||||
# unsubscribe
|
|
||||||
if dev:
|
|
||||||
if par:
|
|
||||||
return UnsubscribeRequest(dev, par)
|
|
||||||
return UnsubscribeRequest(dev, '*')
|
|
||||||
if op == '?':
|
|
||||||
if dev is None:
|
|
||||||
# 'server' commands
|
|
||||||
if par == 'devices':
|
|
||||||
return ListModulesRequest()
|
|
||||||
elif par == 'version':
|
|
||||||
return GetVersionRequest()
|
|
||||||
return ProtocolError()
|
|
||||||
if par == 'parameters':
|
|
||||||
return ListModuleParamsRequest(dev)
|
|
||||||
elif par == 'value':
|
|
||||||
return ReadValueRequest(dev)
|
|
||||||
elif dev == '*' and par == 'value':
|
|
||||||
return ReadAllModulesRequest()
|
|
||||||
else:
|
|
||||||
return ReadParamRequest(dev, par)
|
|
||||||
elif op == '=':
|
|
||||||
if dev and (par == 'value'):
|
|
||||||
return WriteValueRequest(dev, val)
|
|
||||||
if par.endswith('/') and op == '?':
|
|
||||||
return ListParamPropsRequest(dev, par)
|
|
||||||
return WriteParamRequest(dev, par, val)
|
|
||||||
elif err == '0':
|
|
||||||
# reply
|
|
||||||
if dev == '':
|
|
||||||
if par == 'devices':
|
|
||||||
return ListModulesReply(val)
|
|
||||||
elif par == 'version':
|
|
||||||
return GetVersionReply(val)
|
|
||||||
return ProtocolError(encoded)
|
|
||||||
if par == 'parameters':
|
|
||||||
return ListModuleParamsReply(dev, val)
|
|
||||||
if par == 'value':
|
|
||||||
if op == '?':
|
|
||||||
return ReadValueReply(dev, val)
|
|
||||||
elif op == '=':
|
|
||||||
return WriteValueReply(dev, val)
|
|
||||||
return ProtocolError(encoded)
|
|
||||||
if op == '+':
|
|
||||||
return SubscribeReply(ast.literal_eval(dev))
|
|
||||||
if op == '-':
|
|
||||||
return UnSubscribeReply(ast.literal_eval(dev))
|
|
||||||
if op == '?':
|
|
||||||
return ReadParamReply(dev, par, val)
|
|
||||||
if op == '=':
|
|
||||||
return WriteParamReply(dev, par, val)
|
|
||||||
return ProtocolError(encoded)
|
|
||||||
else:
|
|
||||||
# error
|
|
||||||
if err in ('1', '2'):
|
|
||||||
return InternalError(encoded)
|
|
||||||
elif err == '3':
|
|
||||||
return NoSuchCommandError(dev, par)
|
|
||||||
elif err == '4':
|
|
||||||
return NoSuchModuleError(dev, encoded)
|
|
||||||
elif err == '5':
|
|
||||||
return NoSuchParamError(dev, par, val)
|
|
||||||
elif err == '7':
|
|
||||||
return InvalidParamValueError(dev, par, val, encoded)
|
|
||||||
elif err == '8':
|
|
||||||
return ParamReadonlyError(dev, par, encoded)
|
|
||||||
else: # err == 6 or other stuff
|
|
||||||
return ProtocollError(encoded)
|
|
@ -1,64 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
# *****************************************************************************
|
|
||||||
# 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>
|
|
||||||
#
|
|
||||||
# *****************************************************************************
|
|
||||||
"""Encoding/decoding Messages"""
|
|
||||||
|
|
||||||
# implement as class as they may need some internal 'state' later on
|
|
||||||
# (think compressors)
|
|
||||||
|
|
||||||
from secop.protocol.encoding import MessageEncoder
|
|
||||||
from secop.protocol import messages
|
|
||||||
from secop.lib.parsing import *
|
|
||||||
|
|
||||||
|
|
||||||
class TextEncoder(MessageEncoder):
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
# build safe namespace
|
|
||||||
ns = dict()
|
|
||||||
for n in dir(messages):
|
|
||||||
if n.endswith(('Request', 'Reply')):
|
|
||||||
ns[n] = getattr(messages, n)
|
|
||||||
self.namespace = ns
|
|
||||||
|
|
||||||
def encode(self, messageobj):
|
|
||||||
"""msg object -> transport layer message"""
|
|
||||||
# fun for Humans
|
|
||||||
if isinstance(messageobj, messages.HelpMessage):
|
|
||||||
return "Error: try one of the following requests:\n" + \
|
|
||||||
'\n'.join(['%s(%s)' % (getattr(messages, m).__name__,
|
|
||||||
', '.join(getattr(messages, m).ARGS))
|
|
||||||
for m in dir(messages)
|
|
||||||
if m.endswith('Request') and len(m) > len("Request")])
|
|
||||||
res = []
|
|
||||||
for k in messageobj.ARGS:
|
|
||||||
res.append('%s=%r' % (k, getattr(messageobj, k, None)))
|
|
||||||
result = '%s(%s)' % (messageobj.__class__.__name__, ', '.join(res))
|
|
||||||
return result
|
|
||||||
|
|
||||||
def decode(self, encoded):
|
|
||||||
"""transport layer message -> msg object"""
|
|
||||||
# WARNING: highly unsafe!
|
|
||||||
# think message='import os\nos.unlink('\')\n'
|
|
||||||
try:
|
|
||||||
return eval(encoded, self.namespace, {})
|
|
||||||
except SyntaxError:
|
|
||||||
return messages.HelpMessage()
|
|
Loading…
x
Reference in New Issue
Block a user