Source code for arduinoserial

#!/usr/bin/env python
#
# Copyright 2007 John Wiseman <jjwiseman@yahoo.com>
#
# 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.


#   Copyright 2014 Marco Rigoni                                               #
#   ElettronicaOpenSource.com   elettronicaopensource@gmail.com               #
#   This program is free software: you can redistribute it and/or modify      #
#   it under the terms of the GNU General Public License as published by      #
#   the Free Software Foundation, either version 3 of the License, or         #
#   (at your option) any later version.                                       # 
#																			  #
#   This program is distributed in the hope that it will be useful,           #
#   but WITHOUT ANY WARRANTY; without even the implied warranty of            #
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             #
#   GNU General Public License for more details.                              #
#                                                                             #
#   You should have received a copy of the GNU General Public License         #
#   along with this program.  If not, see <http://www.gnu.org/licenses/>.     #

"""

..Note::

    Module not used , deprecated and to implement in the future


A port of Tod E. Kurt's arduino-serial.c.
<http://todbot.com/blog/2006/12/06/arduino-serial-c-code-to-talk-to-arduino/>



"""

import termios
import fcntl
import os
import sys
import time
import getopt
from globalVar import *           # import parameter globalVar.py
import thread,threading,time,string
import hw_node

hwNodeDict={}     #dictionary containing all the hw nodes objects   the key is the node address



# Map from the numbers to the termios constants (which are pretty much
# the same numbers).

BPS_SYMS = {
  4800:   termios.B4800,
  9600:   termios.B9600,
  19200:  termios.B19200,
  38400:  termios.B38400,
  57600:  termios.B57600,
  115200: termios.B115200
  }


# Indices into the termios tuple.

IFLAG = 0
OFLAG = 1
CFLAG = 2
LFLAG = 3
ISPEED = 4
OSPEED = 5
CC = 6


[docs]def bps_to_termios_sym(bps): return BPS_SYMS[bps] #hwNodeDict[0]=hw_node.HwNode("base","arduino_2009",0) #make the first node , the base station one
[docs]class SerialPort: def __init__(self, serialport, bps): """Takes the string name of the serial port (e.g. "/dev/tty.usbserial","COM1") and a baud rate (bps) and connects to that port at that speed and 8N1. Opens the port in fully raw mode so you can send binary data. """ self.port=serialport self.busy=0 #the error controll is done by the arduin_handler.py self.fd = os.open(serialport, os.O_RDWR | os.O_NOCTTY | os.O_NDELAY) self.status=1 #except: # print "serial arduino error" # self.fd ="" # self.status=0 attrs = termios.tcgetattr(self.fd) bps_sym = bps_to_termios_sym(bps) # Set I/O speed. attrs[ISPEED] = bps_sym attrs[OSPEED] = bps_sym # 8N1 attrs[CFLAG] &= ~termios.PARENB attrs[CFLAG] &= ~termios.CSTOPB attrs[CFLAG] &= ~termios.CSIZE attrs[CFLAG] |= termios.CS8 # No flow control attrs[CFLAG] &= ~termios.CRTSCTS # Turn on READ & ignore contrll lines. attrs[CFLAG] |= termios.CREAD | termios.CLOCAL # Turn off software flow control. attrs[IFLAG] &= ~(termios.IXON | termios.IXOFF | termios.IXANY) # Make raw. attrs[LFLAG] &= ~(termios.ICANON | termios.ECHO | termios.ECHOE | termios.ISIG) attrs[OFLAG] &= ~termios.OPOST # It's complicated--See # http://unixwiz.net/techtips/termios-vmin-vtime.html attrs[CC][termios.VMIN] = 0; attrs[CC][termios.VTIME] = 20; termios.tcsetattr(self.fd, termios.TCSANOW, attrs) os.system("cat "+self.port) self.usb="" #n = os.read(self.fd) self.incomingBuffer='' self.removeFromInBuffer='' try: self.usb = open(self.port, 'rw') self.status=1 except: print "no device"+self.port+"found" self.status=0 self.dataAvaible=0 self.t_read = threading.Thread(target=self.read_data) self.t_read.daemon = True #make the thread a daemon thread self.t_read.start() self.exit=0
[docs] def read_data(self): # thread function '''Outputs data from serial port to sys.stdout.''' print "read_data thread executed" ignore = '' #'\r' filedev=self.port self.dataAvaible=0 while (self.exit==0): if self.exit==1: break tmpRm=self.removeFromInBuffer buf='' if len(tmpRm)>0: self.incomingBuffer.replace(tmpRm, ""); #remove from buffer the part just readed self.removeFromInBuffer='' buf='' done=0 while done==0: if self.exit==1: break try: byte = self.usb.read(1) except: byte=-1 self.status=0 continue if byte in ignore: continue if not byte: #nothing on incoming serial buffer done=1 print "end of serial packet" if (ord(byte)==10): # 10 is the value for new line (\n) end of packet on incoming serial buffer done=1 print "end of serial packet len=0" else: #print "in byte="+byte+" end of in byte" buf=buf+byte #at this point i should have a full packet message if len(buf)>0: #a=bin(a) if len(buf)>5: if (buf[0]=='U')&(buf[2]=='r'): #arduino is sending a digital status pins byte received_node_address=buf[1] section_index=buf[3] data_register=buf[4] rx_check_byte=buf[5] check_byte=checksum(('U',received_node_address,'r',section_index,data_register)) if check_byte==rx_check_byte: print "check ok" answer_byte='U'+node_address+'C'+check_byte self.write(answer_byte) #send the check byte if len(buf)>4: if (buf[0]=='U')&(buf[2]=='q'): #arduino is asking for pins mode configuration (input or output) received_node_address=buf[1] hw_type=buf[3] rx_check_byte=buf[4] if received_node_address in hwNodeDict: # a node with that address exist yet pin_mode_list=hwNodeDict[received_node_address].getNodeSectionMode() k=0 for a in pin_mode_list: #for each section of the pin mode list send it to arduino check_byte=checksum(('U',received_node_address,'m',k,a)) self.write('U'+received_node_address+'m'+k+a+check_byte) k=k+1 else: # address not in the dictionary if hw_type==0: hw_type="arduino_2009" if hw_type==1: hw_type="arduino_promini" #a=hw_node.HwNode('new_node'+received_node_address,hw_type,received_node_address) #hwNodeDict[received_node_address]=a #banana insert here a url query to create the node pin_mode_list=hwNodeDict[received_node_address].getNodeSectionMode() k=0 for b in pin_mode_list: #for each section of the pin mode list send it to arduino check_byte=checksum(('U',received_node_address,'m',k,b)) self.write('U'+received_node_address+'m'+k+b+check_byte) k=k+1 check_byte=checksum(('U',received_node_address,'f')) #tell arduino that the pins configuration is ended self.write('U'+received_node_address+'f'+check_byte) #self.write(byte) send the configuration #self.write('\n') self.dataAvaible=1 print "serial input="+buf self.incomingBuffer=self.incomingBuffer+buf print "incoming buffer="+self.incomingBuffer else: self.dataAvaible=0
[docs] def waitForData(self,times): j=0 while j<(times*1000000): if (self.dataAvaible==1): return(1) if (self.exit==1): return(-1) j=j+0.1 return(-1)
[docs] def read(self): print "arduinoserial read executed" #buf = "" #buf=os.popen("cat < "+self.port).read() tmp=self.incomingBuffer self.removeFromInBuffer=self.removeFromInBuffer+tmp self.incomingBuffer='' print "readed serial port="+tmp return tmp
[docs] def sendDigitalWrite(self,node_address,pin,status): # tells arduino to write the register pins as readed from the hw_node class where the status of the pin is modified # according the parameter passed to sendDigitalWrite() if node_address in hwNodeDict.keys(): hwNodeDict[node_address].setDigitalPinOutputStatus(pin,status) #set the pin status in the class according to the parameter received section=pin//8 section_pins_status=str(hwNodeDict[node_address].getNodeSectionStatusByPin(pin)) msg="U0s"+str(section)+section_pins_status+'0' print "writing register to arduino pin" while (rx_check_byte!=check_byte): print ("wait for correct answer to dw") os.system("echo "+msg+" >> "+self.port) #write the message os.system("echo \n >> "+self.port) #write the closing message byte \n self.waitForData(10) rx_check_byte=self.read() else: print "error address node not in node dictionary" return
[docs] def write(self, str): if str[0:2]=="dw": #if the cmd is to set arduino pins...then make sure arduino answer ok print "writing to arduino pin" #check_byte=checksum(str2....) while (rx_check_byte!=check_byte): print ("wait for correct answer to dw") os.system("echo "+str+" >> "+self.port) os.system("echo \n >> "+self.port) self.waitForData(10) rx_check_byte=self.read() return if (str[0]=='U')&(str[2]=='m'): #if the cmd is to change pin mode of arduino...then make sure arduino answer ok print "writing pin configuration to arduino" #check_byte=checksum(str2....) rx_check_byte=0 j=0 while (rx_check_byte!=check_byte)&(j<15): j=j+1 os.system("echo "+str+" >> "+self.port) os.system("echo \n >> "+self.port) self.waitForData(10) rx_message=self.read() rx_check_byte=rx_message[3] return if (str[0]=='U')&(str[2]=='f'): #if the cmd is to write end of the change pin mode of arduino...then make sure arduino answer ok print "writing pin configuration to arduino" #check_byte=checksum(str2....) rx_check_byte=0 j=0 while (rx_check_byte!=check_byte)&(j<15): j=j+1 os.system("echo "+str+" >> "+self.port) os.system("echo \n >> "+self.port) self.waitForData(10) rx_message=self.read() rx_check_byte=rx_message[3] return #os.write(self.fd, str) # while self.busy==1: # time.sleep(0.01) # self.busy=1 #os.system("echo "+str+" >> "+self.port) #self.busy=0 return
[docs] def digitalWriteSection(self,node_address,section,section_status): print "i write a section status to arduino" # def write_byte(self, byte): # os.write(self.fd, chr(byte))
[docs] def isOpen(self): #print " called isOpen" return(self.status) #def open(): # return(1) # def __del__(self): # print "class arduinoserial destroyed" # try: # os.close(self.fd) # except: # print "tried to close serial port"
[docs] def make_new_node(self,node_name,hwType,node_address): if node_address not in hwNodeDict: hwNodeDict[node_address]=hw_node.HwNode(node_name,hwType,node_address) return(1) else: print "address already used" return(-1)
[docs] def setPinMode(self,node_address,pinNumber,mode): if node_address in hwNodeDict: hwNodeDict[node_address].setPinMode(pinNumber,mode) #set the pin mode in the hardware_node self.sendPinModeToArduino() # to implement else: print "error node address not found in the dictionary" return (-1)
[docs] def close(self): self.exit=1 print "class arduinoserial destroyed" try: os.close(self.fd) except: print "tried to close serial port"