summaryrefslogtreecommitdiffstats
path: root/scripts/remote/controller.py
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/remote/controller.py')
-rw-r--r--scripts/remote/controller.py173
1 files changed, 173 insertions, 0 deletions
diff --git a/scripts/remote/controller.py b/scripts/remote/controller.py
new file mode 100644
index 0000000000..a7257ecc97
--- /dev/null
+++ b/scripts/remote/controller.py
@@ -0,0 +1,173 @@
+#!/usr/bin/env python2
+# -*- coding: utf-8 -*-
+
+from __future__ import absolute_import, division, print_function
+
+import struct
+import logging
+import sys
+import os
+from threading import Thread
+from Queue import Queue, Empty
+from .ratpfs import RatpFSServer
+from .messages import *
+from .ratp import RatpError
+
+try:
+ from time import monotonic
+except:
+ from .missing import monotonic
+
+
+def unpack(data):
+ p_type, = struct.unpack("!H", data[:2])
+ logging.debug("unpack: %r data=%r", p_type, repr(data))
+ if p_type == BBType.command:
+ logging.debug("received: command")
+ return BBPacketCommand(raw=data)
+ elif p_type == BBType.command_return:
+ logging.debug("received: command_return")
+ return BBPacketCommandReturn(raw=data)
+ elif p_type == BBType.consolemsg:
+ logging.debug("received: consolemsg")
+ return BBPacketConsoleMsg(raw=data)
+ elif p_type == BBType.ping:
+ logging.debug("received: ping")
+ return BBPacketPing(raw=data)
+ elif p_type == BBType.pong:
+ logging.debug("received: pong")
+ return BBPacketPong(raw=data)
+ elif p_type == BBType.getenv_return:
+ logging.debug("received: getenv_return")
+ return BBPacketGetenvReturn(raw=data)
+ elif p_type == BBType.fs:
+ logging.debug("received: fs")
+ return BBPacketFS(raw=data)
+ elif p_type == BBType.fs_return:
+ logging.debug("received: fs_return")
+ return BBPacketFSReturn(raw=data)
+ else:
+ logging.debug("received: UNKNOWN")
+ return BBPacket(raw=data)
+
+
+class Controller(Thread):
+ def __init__(self, conn):
+ Thread.__init__(self)
+ self.daemon = True
+ self.conn = conn
+ self.fsserver = None
+ self.rxq = None
+ self.conn.connect(timeout=5.0)
+ self._txq = Queue()
+ self._stop = False
+ self.fsserver = RatpFSServer()
+
+ def _send(self, bbpkt):
+ self.conn.send(bbpkt.pack())
+
+ def _handle(self, bbpkt):
+ if isinstance(bbpkt, BBPacketConsoleMsg):
+ os.write(sys.stdout.fileno(), bbpkt.text)
+ elif isinstance(bbpkt, BBPacketPong):
+ print("pong",)
+ elif isinstance(bbpkt, BBPacketFS):
+ if self.fsserver != None:
+ self._send(self.fsserver.handle(bbpkt))
+
+ def _expect(self, bbtype, timeout=1.0):
+ if timeout is not None:
+ limit = monotonic()+timeout
+ while timeout is None or limit > monotonic():
+ pkt = self.conn.recv(0.1)
+ if not pkt:
+ continue
+ bbpkt = unpack(pkt)
+ if isinstance(bbpkt, bbtype):
+ return bbpkt
+ else:
+ self._handle(bbpkt)
+
+ def export(self, path):
+ self.fsserver = RatpFSServer(path)
+
+ def ping(self):
+ self._send(BBPacketPing())
+ r = self._expect(BBPacketPong)
+ logging.info("Ping: %r", r)
+ if not r:
+ return 1
+ else:
+ print("pong")
+ return 0
+
+ def command(self, cmd):
+ self._send(BBPacketCommand(cmd=cmd))
+ r = self._expect(BBPacketCommandReturn, timeout=None)
+ logging.info("Command: %r", r)
+ return r.exit_code
+
+ def getenv(self, varname):
+ self._send(BBPacketGetenv(varname=varname))
+ r = self._expect(BBPacketGetenvReturn)
+ return r.text
+
+ def close(self):
+ self.conn.close()
+
+ def run(self):
+ assert self.rxq is not None
+ try:
+ while not self._stop:
+ # receive
+ pkt = self.conn.recv()
+ if pkt:
+ bbpkt = unpack(pkt)
+ if isinstance(bbpkt, BBPacketConsoleMsg):
+ self.rxq.put((self, bbpkt.text))
+ else:
+ self._handle(bbpkt)
+ # send
+ try:
+ pkt = self._txq.get(block=False)
+ except Empty:
+ pkt = None
+ if pkt:
+ self._send(pkt)
+ except RatpError as detail:
+ print("Ratp error:", detail, file=sys.stderr);
+ self.rxq.put((self, None))
+ return
+
+ def start(self, queue):
+ assert self.rxq is None
+ self.rxq = queue
+ Thread.start(self)
+
+ def stop(self):
+ self._stop = True
+ self.join()
+ self._stop = False
+ self.rxq = None
+
+ def send_async(self, pkt):
+ self._txq.put(pkt)
+
+ def send_async_console(self, text):
+ self._txq.put(BBPacketConsoleMsg(text=text))
+
+ def send_async_ping(self):
+ self._txq.put(BBPacketPing())
+
+
+def main():
+ import serial
+ from .ratp import SerialRatpConnection
+ url = "rfc2217://192.168.23.176:3002"
+ port = serial.serial_for_url(url, 115200)
+ conn = SerialRatpConnection(port)
+ ctrl = Controller(conn)
+ return ctrl
+
+if __name__ == "__main__":
+ C = main()