utils.py 2.39 KB
Newer Older
Bach Dániel committed
1 2 3
from twisted.protocols.basic import LineReceiver
import json
import logging
4 5
import platform

6 7 8 9 10
try:
    # Python 2: "unicode" is built-in
    unicode
except NameError:
    unicode = str
Bach Dániel committed
11

Bach Dániel committed
12
logger = logging.getLogger()
13
system = platform.system()
Bach Dániel committed
14 15 16


class SerialLineReceiverBase(LineReceiver, object):
17
    MAX_LENGTH = 1024*1024*128
Bach Dániel committed
18

19 20
    def __init__(self, *args, **kwargs):
        if system == "FreeBSD":
21
            self.delimiter = b'\n'
22
        else:
23
            self.delimiter = b'\r'
24 25
        super(SerialLineReceiverBase, self).__init__(*args, **kwargs)

Bach Dániel committed
26
    def send_response(self, response, args):
27
#        logger.debug("send_response %s %s" % (response, args))
Bach Dániel committed
28 29 30 31 32 33 34 35 36 37 38 39 40 41
        self.transport.write(json.dumps({'response': response,
                                         'args': args}) + '\r\n')

    def send_command(self, command, args):
        self.transport.write(json.dumps({'command': command,
                                         'args': args}) + '\r\n')

    def handle_command(self, command, args):
        raise NotImplementedError("Subclass must implement abstract method")

    def handle_response(self, response, args):
        raise NotImplementedError("Subclass must implement abstract method")

    def lineReceived(self, data):
42 43 44 45 46
        logger.debug("lineReceived: %s", data)
        if (isinstance(data, unicode)):
            data = data.strip('\0')
        else:
            data = data.strip(b'\0')
Bach Dániel committed
47 48 49 50 51 52 53
        try:
            data = json.loads(data)
            args = data.get('args', {})
            if not isinstance(args, dict):
                args = {}
            command = data.get('command', None)
            response = data.get('response', None)
Bach Dániel committed
54
            logger.debug('[serial] valid json: %s' % (data, ))
Bach Dániel committed
55
        except (ValueError, KeyError) as e:
Bach Dániel committed
56
            logger.error('[serial] invalid json: %s (%s)' % (data, e))
57
            self.clearLineBuffer()
Bach Dániel committed
58 59 60
            return

        if command is not None and isinstance(command, unicode):
Bach Dániel committed
61
            logger.debug('received command: %s (%s)' % (command, args))
Bach Dániel committed
62 63 64
            try:
                self.handle_command(command, args)
            except Exception as e:
65
                logger.exception("Unhandled exception during line recived: ")
Bach Dániel committed
66
        elif response is not None and isinstance(response, unicode):
Bach Dániel committed
67
            logger.debug('received reply: %s (%s)' % (response, args))
68
            self.clearLineBuffer()
Bach Dániel committed
69
            self.handle_response(response, args)