A critical part of the project involves allowing one arduino board to communicate with a remote arduino board. Two computers mediate the connection and send the information via a secure connection (SSL). The code is below. At this stage it's very simple, all the action happens in the arduino code. What this python script does is take the serial output from one arduino board and feed it into the serial input for the other board. The code below the fold works but I imagine I'll change it before I'm finished, so please check the SVN web repository when I've installed that for the latest code.
The first two scripts are for testing, the full version is at bottom, but contains a lot more project-specific code.
simple ssl client
#!/usr/bin/env python # # Receive number from client where -10 < number < 10. # Send that number to attached arduino. # Also receive number from arduino, send that to client. Again, -10 < number < 10 # Log everything. # SUPERSEDED BY arduino_ssl_relay.py import socket import logging import re from serial import * logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(levelname)s %(message)s', filename='ssl_echo_client.log', filemode='w') NAME = "SSL Echo Client" def main(ip='192.168.1.101'): logging.info(NAME + "started") ser = Serial(port="/dev/ttyUSB0", baudrate=9600) logging.info("Serial startd on " + ser.portstr) HOST = ip # The remote host PORT = 50008 # The same port as used by the server s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((HOST, PORT)) logging.info("Connected to "+HOST+" at port "+ str(PORT)) data = '0' s.send('Hello, world') #ssl_data = s.recv(1024) while True: try: line = ser.readline() #read a '\n' terminated line logging.info("received from arduino: " + line) matches = re.search(r'log: arduino says computed pot_val: (\d{1,2})',line) if matches: val = matches.groups()[0] if int(val) > 0 and int(val) < 20: olddata = data data = val + "\n" if data != olddata: # only send if there's a change ssl_send = data s.send(data) logging.info("Sent data to server:" + data) else: logging.warning("Got an invalid value from arduino: " + val) finally: logging.warning("Closing sockets") s.close() ser.close() logging.warning("Shut down done") if __name__ == "__main__": main()
simple ssl echo server
# Echo server program # testing # SUPERSEDED BY arduino_ssl_relay.py import socket import re from serial import * def main(): HOST = '' # Symbolic name meaning the local host PORT = 50009 # Arbitrary non-privileged port s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.bind((HOST, PORT)) s.listen(1) conn, addr = s.accept() print 'Connected by', addr while 1: data = conn.recv(1024) if not data: break print 'Got data from client', data conn.send(data) # have it echo back whatever it gets until we have two setups conn.close() if __name__ == "__main__": main()
Combined (and a little more project specific
#!/usr/bin/env python # Arduino Serial SSL Relay # Relays output from one arduino to another arduino via SSL. # @author: Allen Riddell <http:> # @date: 2008-03-26 # For the Last Miles Project: http://dukevisualstudies/lastmiles/ # only supports IP4. # TODO # # * more detailed log information (ip address) # * simplify server and client connection variable (no s and conn, that's confusing) # * standardized transmission format -- when one has multiple messages (i.e. pot, and others) import socket import re import serial from optparse import OptionParser # logging import logging import sys logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(levelname)s %(message)s', filename='/tmp/arduino_ssl_relay.log', filemode='w') #DEBUG: change this to "a" when done # console logging console = logging.StreamHandler(sys.stdout) console.setLevel(logging.INFO) # formatter = logging.Formatter('%(message)s') # console.setFormatter(formatter) logger = logging.getLogger() logger.addHandler(console) # Constants PORT = 50009 # arbitrary ssl port DEV = "/dev/ttyUSB0" # port to which arduino is connected. /dev/ttyUSB0 on my linux box. def main(ip='', server=True, dev=DEV, port=PORT): # open serial connection to arduino, fail if not available. try: ser = serial.Serial(port=dev, baudrate=9600) except serial.serialutil.SerialException, e : # fix this. logging.warning("couldn't establish serial connection" + str(e)) logging.debug("Serial connection started on " + ser.portstr) # open ssl connection, fail if not available. HOST = ip # Symbolic name meaning the local host PORT = int(port) # Arbitrary non-privileged port s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) mode_name = "server" if server else "client" # SERVER SSL Setup if server: try: s.bind((HOST, PORT)) s.listen(1) logging.info("Starting " + mode_name + ", listening for connections.") conn, addr = s.accept() logging.info('Connected by' + str(addr)) except Exception, e: logging.critical("Couldn't establish connection: "+ str(e)) s.close() ser.close() sys.exit() # CLIENT SSL Setup else: try: s.connect((HOST, PORT)) logging.info("Connected to "+HOST+" at port "+ str(PORT)) s.settimeout(2) except socket.error, e: logging.critical("Couldn't establish connection: " + str(e)) s.close() ser.close() sys.exit() # ssl settings for both logging.debug("Socket timeout is: "+ str(s.gettimeout())) # main loop data = None sslsend = '10' + '\n' # default is to tell the servo not to move '10' ssldata = None line = None loop_count = 0 while True: # handle serial connection try: # line = ser.readline() #read a '\n' terminated line line = ser.read(256) if ser.inWaiting() > 256: wait = ser.inWaiting() logging.warning("serial info ser.inWaiting(): " + str(wait)) line = ser.read(ser.inWaiting()) except (KeyboardInterrupt, SystemExit): break if line: logging.debug("received from arduino: " + line[:-1]) # get rid of final '\n' matches = re.findall(r'log: arduino says computed pot_val: (\d{1,2})',line) if matches: val = matches[-1] # use last match if int(val) > 0 and int(val) < 20: olddata = data data = val + "\n" sslsend = data # if data != olddata: # only send if there's a change # sslsend = data # else: # sslsend = None # first send ssl data "sslsend" if sslsend: try: logging.debug("attempting to send ssl data") if server: conn.send(sslsend) else: s.send(sslsend) logging.debug("sent ssl data:" + sslsend[:-1]) except socket.timeout, e: logging.warning("failed to send ssl data:" + sslsend[:-1] + ", error: " + str(e)) continue except socket.error, e: logging.warning("failed to send ssl data:" + sslsend[:-1] + ", error: " + str(e)) break # receive ssl data "ssldata" oldssldata = ssldata try: logging.debug("attempting to receive ssl data") if server: ssldata = conn.recv(1024) else: ssldata = s.recv(1024) if ssldata: logging.debug("received ssl data:" + ssldata[:-1]) except socket.timeout, e: logging.warning("failed to receive ssl data, error: " + str(e)) continue except socket.error, e: logging.critical("failed to receive ssl data, error: " + str(e)) break except (KeyboardInterrupt, SystemExit): break # send ssldata to arduino if ssldata: ssldata = ssldata[:-1] #strip \n -- maybe use string.rstrip(os.linesep) if ssldata != oldssldata and len(ssldata) < 3: if int(ssldata) > 0 and int(ssldata) < 20: ser.write(ssldata + "\n") logging.info("sent arduino ssl data:" + ssldata) else: logging.warning("didn't receive data from remote connection") loop_count += 1 # shut down, close connections logging.critical("shutting down, closing sockets") s.close() ser.close() def parseOpts(): parser = OptionParser() parser.add_option("-c", "--client", dest="mode", default=SERVER, help="run in client mode (provide an IP to connect to) (IP4 only)") return parser.parse_args() if __name__ == "__main__": usage = "usage: %prog [options] ip_address" parser = OptionParser(usage=usage) parser.add_option("-d", "--device", dest="dev", default=DEV, help="Use an alternate serial device. Default is: "+DEV) parser.add_option("-p", "--port", dest="port", default=PORT, help="Use an alternate port. Default is: "+str(PORT)) (options, args) = parser.parse_args() if args: main(dev=options.dev,ip=args[0],port=options.port,server=False) else: main(dev=options.dev,port=options.port) </http:>
0 Responses to “Two Arduinos Connected By an SSL Relay”