Files

154 lines
5.5 KiB
Python

###############################################################################
#
# The MIT License (MIT)
#
# Copyright (c) Crossbar.io Technologies GmbH
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#
###############################################################################
import six
from os import environ
from twisted.internet.defer import inlineCallbacks
from twisted.internet.serialport import SerialPort
from twisted.protocols.basic import LineReceiver
from autobahn.twisted.wamp import ApplicationSession
class McuProtocol(LineReceiver):
"""
MCU serial communication protocol.
"""
# need a reference to our WS-MCU gateway factory to dispatch PubSub events
def __init__(self, session):
self.session = session
def connectionMade(self):
print('Serial port connected.')
def lineReceived(self, line):
print("Serial RX: {0}".format(line))
try:
# parse data received from MCU
data = [int(x) for x in line.split()]
except ValueError:
print('Unable to parse value {0}'.format(line))
else:
# create payload for WAMP event
payload = {u'id': data[0], u'value': data[1]}
# publish WAMP event to all subscribers on topic
self.session.publish(u"com.myapp.mcu.on_analog_value", payload)
def controlLed(self, turnOn):
"""
This method is exported as RPC and can be called by connected clients
"""
if turnOn:
payload = b'1'
else:
payload = b'0'
print("Serial TX: {0}".format(payload))
self.transport.write(payload)
class McuComponent(ApplicationSession):
"""
MCU WAMP application component.
"""
@inlineCallbacks
def onJoin(self, details):
print("MyComponent ready! Configuration: {}".format(self.config.extra))
port = self.config.extra['port']
baudrate = self.config.extra['baudrate']
serialProtocol = McuProtocol(self)
print('About to open serial port {0} [{1} baud] ..'.format(port, baudrate))
try:
serialPort = SerialPort(serialProtocol, port, reactor, baudrate=baudrate)
except Exception as e:
print('Could not open serial port: {0}'.format(e))
self.leave()
else:
yield self.register(serialProtocol.controlLed, u"com.myapp.mcu.control_led")
if __name__ == '__main__':
import sys
import argparse
# parse command line arguments
parser = argparse.ArgumentParser()
parser.add_argument("--baudrate", type=int, default=9600, choices=[300, 1200, 2400, 4800, 9600, 19200, 57600, 115200],
help='Serial port baudrate.')
parser.add_argument("--port", type=six.text_type, default=u'/dev/ttyACM0',
help='Serial port to use (e.g. 3 for a COM port on Windows, /dev/ttyATH0 for Arduino Yun, /dev/ttyACM0 for Serial-over-USB on RaspberryPi.')
parser.add_argument("--web", type=int, default=8000,
help='Web port to use for embedded Web server. Use 0 to disable.')
router_default = environ.get("AUTOBAHN_DEMO_ROUTER", u"ws://127.0.0.1:8080/ws")
parser.add_argument("--router", type=six.text_type, default=router_default,
help='WAMP router URL (a WAMP-over-WebSocket endpoint, default: "{}")'.format(router_default))
parser.add_argument("--realm", type=six.text_type, default=u'crossbardemo',
help='WAMP realm to join (default: "crossbardemo")')
args = parser.parse_args()
# import Twisted reactor
if sys.platform == 'win32':
# on Windows, we need to use the following reactor for serial support
# http://twistedmatrix.com/trac/ticket/3802
from twisted.internet import win32eventreactor
win32eventreactor.install()
# on Windows, we need port to be an integer
args.port = int(args.port)
from twisted.internet import reactor
print("Using Twisted reactor {0}".format(reactor.__class__))
# create embedded web server for static files
if args.web:
from twisted.web.server import Site
from twisted.web.static import File
reactor.listenTCP(args.web, Site(File(".")))
# run WAMP application component
from autobahn.twisted.wamp import ApplicationRunner
runner = ApplicationRunner(args.router, args.realm,
extra={'port': args.port, 'baudrate': args.baudrate})
# start the component and the Twisted reactor ..
runner.run(McuComponent)