#!/usr/bin/env python import serial import time import datetime from time import sleep from array import array EXPECT_ECHO_TYPE="ECHO_TYPE" EXPECT_ECHO_SUBTYPE="ECHO_SUBTYPE" EXPECT_ECHO_ZERO="ECHO_ZERO" EXPECT_ECHO_SIZEBYTE1="ECHO_SIZEBYTE1" EXPECT_ECHO_SIZEBYTE2="ECHO_SIZEBYTE2" EXPECT_ECHO_PAYLOAD="ECHO_PAYLOAD" EXPECT_ECHO_CHECKSUM1="ECHO_CHECKSUM1" EXPECT_ECHO_CHECKSUM2="ECHO_CHECKSUM2" EXPECT_WATCH_TYPE="WATCH_TYPE" EXPECT_WATCH_SUBTYPE="WATCH_SUBTYPE" EXPECT_WATCH_ZERO="WATCH_ZERO" EXPECT_WATCH_SIZEBYTE1="WATCH_SIZEBYTE1" EXPECT_WATCH_SIZEBYTE2="WATCH_SIZEBYTE2" EXPECT_WATCH_PAYLOAD="WATCH_PAYLOAD" EXPECT_WATCH_CHECKSUM1="WATCH_CHECKSUM1" EXPECT_WATCH_CHECKSUM2="WATCH_CHECKSUM2" EXPECT_WATCH_FINISHED="WATCH_FINISHED" ERROR="ERROR" class Parser: def __init__(self): self.state = EXPECT_ECHO_TYPE self.payload = "" self.numread = 0 def getState(self): return self.state def setState(self, newstate): #print "DEBUG: State switched from %s to %s" % (self.state, newstate) self.state = newstate def processByte(self,byte): self.numread += 1 #print " %02X" % ord(byte), #if (self.numread % 20 == 0): # print if (self.getState() == EXPECT_ECHO_TYPE): if (ord(byte) == 0xa3): self.setState(EXPECT_ECHO_SUBTYPE) # elif (ord(byte) == 0x5c): # self.setState(EXPECT_WATCH_SUBTYPE) else: self.setState(ERROR) print "ERROR: expected 0xa3 but got %02X" % ord(byte) elif (self.getState() == EXPECT_ECHO_SUBTYPE): self.echosubtype = byte self.setState(EXPECT_ECHO_ZERO) elif (self.getState() == EXPECT_ECHO_ZERO): if (ord(byte) != 0x00): self.setState(ERROR) print "ERROR: expected echo zero byte but got %02X" % ord(byte) else: self.setState(EXPECT_ECHO_SIZEBYTE1) elif (self.getState() == EXPECT_ECHO_SIZEBYTE1): self.echosize1 = ord(byte) self.setState(EXPECT_ECHO_SIZEBYTE2) elif (self.getState() == EXPECT_ECHO_SIZEBYTE2): self.echosize2 = ord(byte) self.setState(EXPECT_ECHO_CHECKSUM1) elif (self.getState() == EXPECT_ECHO_CHECKSUM1): self.echochecksum1 = byte self.setState(EXPECT_ECHO_CHECKSUM2) elif (self.getState() == EXPECT_ECHO_CHECKSUM2): self.echochecksum1 = byte self.setState(EXPECT_WATCH_TYPE) elif (self.getState() == EXPECT_WATCH_TYPE): if (ord(byte) == 0x5c): self.setState(EXPECT_WATCH_SUBTYPE) else: self.setState(ERROR) print "ERROR: expected 0x5c but got %02X" % ord(byte) elif (self.getState() == EXPECT_WATCH_SUBTYPE): self.watchsubtype = byte self.setState(EXPECT_WATCH_ZERO) elif (self.getState() == EXPECT_WATCH_ZERO): if (ord(byte) != 0x00): self.setState(ERROR) print "ERROR: expected echo zero byte but got %02X" % ord(byte) else: self.setState(EXPECT_WATCH_SIZEBYTE1) elif (self.getState() == EXPECT_WATCH_SIZEBYTE1): self.watchsize1 = ord(byte) self.setState(EXPECT_WATCH_SIZEBYTE2) elif (self.getState() == EXPECT_WATCH_SIZEBYTE2): self.watchsize2 = ord(byte) self.payload = "" if ((self.watchsize1*256 + self.watchsize2) == 0): self.setState(EXPECT_WATCH_CHECKSUM1) else: self.setState(EXPECT_WATCH_PAYLOAD) elif (self.getState() == EXPECT_WATCH_PAYLOAD): self.payload += byte #print " %02X" % ord(byte), #if (len(self.payload) % 16 == 0): #print " (%d of %d)" % (len(self.payload), (self.watchsize1*256+self.watchsize2) - 5) if (len(self.payload) == (self.watchsize1*256 + self.watchsize2) - 5): #print " (%d of %d)" % (len(self.payload), (self.watchsize1*256+self.watchsize2) - 5) self.setState(EXPECT_WATCH_CHECKSUM1) elif (self.getState() == EXPECT_WATCH_CHECKSUM1): self.watchchecksum1 = byte self.setState(EXPECT_WATCH_CHECKSUM2) elif (self.getState() == EXPECT_WATCH_CHECKSUM2): self.watchchecksum2 = byte self.setState(EXPECT_WATCH_FINISHED) elif (self.getState() == EXPECT_WATCH_FINISHED): print "Unexpected byte: %02X" % ord(byte) ser = serial.Serial('/dev/cu.usbserial', 9600, bytesize=serial.EIGHTBITS, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_TWO, timeout=2) # Clean everything off the input queue while ser.inWaiting() != 0: s = ser.read() ser.flushOutput() ser.flushInput() ser.write("\x34\xA6\x55\x55\x56\xB8\x25") sleep(0.150) parser = Parser() while parser.getState() != EXPECT_WATCH_TYPE: s = ser.read() parser.processByte(s) sleep(0.150) print "Get files" ser.write("\x34\xAC\x55\x55\x56\xB0\x26") sleep(0.150) parser = Parser() while parser.getState() != EXPECT_WATCH_FINISHED: s = ser.read() if (s == ""): print "READ TIMEOUT" break parser.processByte(s) filedata = parser.payload[5:] packetsremaining = ord(parser.payload[0]) & 127 print "***********************************************************" print "Total data size: %d" % (ord(parser.payload[1])*256 + ord(parser.payload[2])) print "Remaining packets: %d" % packetsremaining sleep(0.150) while packetsremaining > 0: ser.write("\x34\xA7\x55\x55\x56\xAC\x25") sleep(0.150) parser = Parser() while parser.getState() != EXPECT_WATCH_FINISHED: s = ser.read() if (s == ""): print "READ TIMEOUT" break parser.processByte(s) packetsremaining = ord(parser.payload[0]) & 127 print "Remaining packets: %d" % packetsremaining sleep(0.150) filedata += parser.payload[1:] ser.close() def bcd(byte): high = (byte & 0xf0) / 16 low = (byte & 0x0f) return high*10+low filecount = 0 offset = 0 while offset < len(filedata): thisoffset = offset offset += ord(filedata[thisoffset])+ord(filedata[thisoffset+1])*256 hours = bcd(ord(filedata[thisoffset+12]) & 127) # Check to see if we're in AM/PM mode if ord(filedata[thisoffset+13]) & 128 == 128: # If so, check to see if it's PM if ord(filedata[thisoffset+12]) & 128 == 128 and hours < 12: # If so, add 12 to the time hours += 12 print hours t = datetime.datetime( \ bcd(ord(filedata[thisoffset+14]))+2000, \ ord(filedata[thisoffset+15]) & 15, \ bcd(ord(filedata[thisoffset+13]) & 127), \ hours, \ bcd(ord(filedata[thisoffset+11])), \ bcd(ord(filedata[thisoffset+10]))) filename = "%s-%d.srd" % (time.strftime("%Y%m%d-%H%M%S",t.timetuple()), ord(filedata[thisoffset+2])) # filename = "%d-%d.srd" % (filecount, ord(filedata[thisoffset+2])) print "Writing %s" % filename file = open(filename,"w") file.write(filedata[thisoffset:offset-1]) file.close() filecount += 1