building an inflight entertainment system controller in twisted

24
TWISTED AS AN IOT CONTROLLER. BUILDING A 300+ SEAT IFE CONTROLLER IN TWISTED. / / David P. Novakovic @dpn dpn.name

Upload: david-novakovic

Post on 15-Jul-2015

198 views

Category:

Software


0 download

TRANSCRIPT

Page 1: Building an inflight entertainment system controller in twisted

TWISTED AS AN IOTCONTROLLER.

BUILDING A 300+ SEAT IFE CONTROLLER IN TWISTED. / / David P. Novakovic @dpn dpn.name

Page 2: Building an inflight entertainment system controller in twisted

QUICK OVERVIEWWTF is Twisted?IFE System DevicesIFE System requirementsCode examples

Page 3: Building an inflight entertainment system controller in twisted

TWISTED THE SLAYER OF NOOBSSUPER POWERFUL

ALSO CONTROVERSIALSeems to have a bad rep with people who don't use it.

Page 4: Building an inflight entertainment system controller in twisted

TWISTEDevent driven framework in pythonparticular focus on networking related thingsfrom web down to serial ports, tun/tap and udevasync io - single process can handle thousands of concurrentopen connections on a low end machineClean APIs for both callbacks and deferredsthread pool with deferred interfacelocking "primitives" - DeferredSemaphore, DeferredLock,DeferredQueue

Page 5: Building an inflight entertainment system controller in twisted

MORE TWISTEDApplication frameworkAsync unit testingIntegration with most major event loops(wx/gtk/qt/gevent/etc)third party libsklein - sinatra/flask style web frameworkcyclone - tornado port to twistedtreq - "requests" style libampoule - nice enough (if slightly neglected) process poolimplementation

Page 6: Building an inflight entertainment system controller in twisted

IFE STUFF.. YAY

Page 7: Building an inflight entertainment system controller in twisted

TRADITIONAL"dumb" screens heavy use of streaming contentvery heavy requirements on serversvery expensive to upgrade

GLIDEHeavier clientssystem can be upgraded by replacing playersplane doesnt need rewiring etcserver can remain fairly unchangedmore importantly don't need to be upgraded in lockstep

Page 8: Building an inflight entertainment system controller in twisted

GLIDE SOLUTIONplayers - embedded debianseat disconnect - custom embedded devicetriple redundant power supplies - switch + powercm controller - dual core atom running ubuntu LTS + lots ofembedded things attached

Page 9: Building an inflight entertainment system controller in twisted

SYSTEM

Page 10: Building an inflight entertainment system controller in twisted

SOME RELEVANT REQUIREMENTSmulticast commands out to embedded devices300+ seat updates over HTTP every secondlisten to audio stream over multicast (PA, pilot etc)low latency control of players ie. if pilot talks/decomptelneting into a streaming VLC process.some legacy - sync code needed to run in threadsrespond to and control hardware in the plane (overheadscreens etc)cabin crew inserting HDD with content (lock down usb)downloading content from the web (at gate)kiosk (lock down control keys/usb ports)manhole for debugging a running processssh reverse tunnel for remote access - conchtftp - firmware updates to players

Page 11: Building an inflight entertainment system controller in twisted

MULTICASTfrom twisted.internet import reactor, task, protocol

class MulticastSeatControl(protocol.DatagramProtocol):

def startProtocol(self): self.transport.joinGroup("228.0.0.5")

def sendSeatControl(self, bytes): self.transport.write(bytes, ("228.0.0.5", 8005))

def datagramReceived(self, datagram, address): print "Datagram %s from %s" % (repr(datagram), repr(address))

Page 12: Building an inflight entertainment system controller in twisted

HTTP INTERFACEimport jsonfrom klein import Klein

class DeviceAPI(object): app = Klein()

def __init__(self, cmc): self._cmc = {}

@app.route('/stat/<string:name>') def stat(self, request): body = json.loads(request.content.read()) self._cmc.logstat(body['something']) request.setHeader('Content-Type', 'application/json') return json.dumps({"status": "success"})</string:name>

Page 13: Building an inflight entertainment system controller in twisted

SERIAL PORTfrom twisted.internet.serialport import SerialPortfrom twisted.internet import reactorfrom twisted.protocols.basic import LineReceiver

class SensorProtocol(LineReceiver): def connectionMade(self): print "Connected to serial port."

def lineReceived(self, line): print "Received line:", line

def send_our_command(self, command): self.sendLine("command:%s" % command)

def connect_serial_port(): return SerialPort(SensorProtocol(), "/dev/ttyACM0", reactor, 115200, rtscts=False, xonxoff=False, timeout=1)

Page 14: Building an inflight entertainment system controller in twisted

DJANGO

WAIT.. WHAT?Yep, ORM is used a fair bit, as is admin.

Page 15: Building an inflight entertainment system controller in twisted

DJANGOfrom django.core.handlers.wsgi import WSGIHandlerfrom twisted.python import threadpoolfrom twisted.internet import reactorfrom somewhere import Root

def gimme_some_django(): pool = threadpool.ThreadPool() wsgi_resource = wsgi.WSGIResource(reactor, pool, WSGIHandler()) r = Root(wsgi_resource) s = server.Site(r) pool.start() return internet.TCPServer(8082, s)

eg. django admin available at http://localhost:8082/admin/

https://github.com/clemesha/twisted-wsgi-django

Page 16: Building an inflight entertainment system controller in twisted

YET MOREclass VLCRemoteControlProtocol(LineReceiver): ...

class UDevMonitor(abstract.FileDescriptor): ...

Page 17: Building an inflight entertainment system controller in twisted

AND TELNET INTO YOUR OWN PROCESS..import twisted.manhole.telnetfrom twisted.internet.endpoints import TCP4ServerEndpoint

def start_manhole(service): f = twisted.manhole.telnet.ShellFactory() f.username = "b" f.password = "b" f.namespace["var1"] = service endpoint = TCP4ServerEndpoint(reactor, 7777) endpoint.listen(f)

Page 18: Building an inflight entertainment system controller in twisted

TIE IT ALL TOGETHERApplication frameworkUnit Testing

Page 19: Building an inflight entertainment system controller in twisted

APPLICATION FRAMEWORKTWISTD

Daemonises optionallypidfilelog filesError catchallhttp://twistedmatrix.com/documents/13.2.0/core/howto/basics.html

Page 20: Building an inflight entertainment system controller in twisted

CREATE SERVICESclass IOTCServer(Service): def startService(self): self.serialport = connect_serial_port() p = MulticastSeatControl() reactor.listenMulticast(8005, p) start_manhole(self) self.mc_looper = task.LoopingCall(p.sendSeatControl, "s1:on,s2:on") self.mc_looper.start(1)

def stopService(self): self.serialport.transport.loseConnection() self.mc_looper.stop()

def get_http_service(iots_instance): device_api = DeviceAPI(iots_instance) server.Site(device.api.app.resource()) return internet.TCPServer(8082)

Page 21: Building an inflight entertainment system controller in twisted

TWISTD PLUGINclass Options(usage.Options): optParameters = [["serialport", "s", "/dev/ttyACM0", "Serial port."]

class ServiceMaker(object): tapname = "iotc" description = "The IOTC Server" options = Options

def makeService(self, options): service_parent = service.MultiService() iots = IOTCServer() iots.setServiceParent(service_parent) http_service = get_http_service() http_service.setServiceParent(service_parent) django_service = gimme_some_django() django_service.setServiceParent(service_parent) return service_parentserviceMaker = ServiceMaker()

yourproject/twisted/plugins/iotc_plugin.py$ twistd -r epoll -n iotc --serialport=/dev/ttyACM0

Page 22: Building an inflight entertainment system controller in twisted

UNIT TESTINGTwisted TrialWrapper around pyunit "unittest"Allows tests to return deferred responsessubclass twisted.trial.unittest.TestCaserun tests: trial yourpackageSome helpers to let you mock wire-level connectionshttp://twistedmatrix.com/documents/11.1.0/core/howto/trial.html

Page 23: Building an inflight entertainment system controller in twisted

BUILD AWESOME THINGS!DIGECOR IS HIRING

If you enjoy working on this kind of stuff, let me know and I'llforward your details onto digEcor.

@dpn

Page 24: Building an inflight entertainment system controller in twisted

THE ENDDAVID NOVAKOVIC - DPN.NAME