mirror of
https://github.com/Snigelson/pytimex.git
synced 2026-07-28 04:05:41 +00:00
Adding python code
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
# Data Blaster for Timex
|
||||
# Will not work with original adapter due to timing issues
|
||||
|
||||
import serial
|
||||
import sys
|
||||
import time
|
||||
|
||||
class Blaster:
|
||||
def __init__(self, portname, syncbuflen=16):
|
||||
self.port = serial.Serial(portname, 9600, timeout=0.1)
|
||||
time.sleep(2)
|
||||
self.sent = []
|
||||
self.syncbuflen = syncbuflen
|
||||
|
||||
def identify(self):
|
||||
self.port.write(b'x')
|
||||
indata = self.port.read(1)
|
||||
if indata != b'x':
|
||||
raise Exception("Transceiver not detected! (x error)")
|
||||
return False
|
||||
|
||||
self.port.write(b'?')
|
||||
time.sleep(0.2)
|
||||
indata = self.port.read(5)
|
||||
if indata != b'M764\0':
|
||||
print (indata)
|
||||
raise Exception("Transceiver not detected! (? error)")
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def _checksync(self):
|
||||
# print("Sent: "+str(self.sent))
|
||||
|
||||
inbytes = self.port.read(int(self.syncbuflen/2))
|
||||
if len(inbytes) == 0:
|
||||
return
|
||||
# print("Syncing {} byte(s)".format(len(inbytes)))
|
||||
for byt in inbytes:
|
||||
if byt != self.sent[0]:
|
||||
print("Expected {}, got {}".format(self.sent[0], byt))
|
||||
raise Exception("Out of sync!")
|
||||
self.sent.pop(0)
|
||||
|
||||
def send_sync(self, times55sync=128, timesAAsync=50):
|
||||
for sync in range(times55sync):
|
||||
self.blast(0x55)
|
||||
|
||||
for sync in range(timesAAsync):
|
||||
self.blast(0xAA)
|
||||
|
||||
def blast(self, data):
|
||||
self.port.write(bytes([data]))
|
||||
self.sent.append(data)
|
||||
|
||||
if len(self.sent)>self.syncbuflen:
|
||||
self._checksync()
|
||||
|
||||
def flush(self):
|
||||
while len(self.sent)>0:
|
||||
self._checksync()
|
||||
|
||||
if __name__ == "__main__":
|
||||
portname = sys.argv[1]
|
||||
|
||||
b = Blaster(portname, syncbuflen=16)
|
||||
|
||||
if not b.identify():
|
||||
print("Could not verify adapter :(")
|
||||
sys.exit(-1)
|
||||
|
||||
b.send_sync()
|
||||
|
||||
for p in range(10):
|
||||
b.blast(0x03)
|
||||
b.blast(0x02)
|
||||
b.blast(0x01)
|
||||
|
||||
b.flush()
|
||||
@@ -0,0 +1,229 @@
|
||||
import datetime
|
||||
from ._helpers import *
|
||||
|
||||
monthNamesAbbr = [
|
||||
"<unknown>", "Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
||||
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
|
||||
]
|
||||
|
||||
class TimexAppointment:
|
||||
def __init__(self, month=0, day=0, time=0, label=""):
|
||||
self.month=month
|
||||
self.day=day
|
||||
self.time=time
|
||||
self.label=label
|
||||
|
||||
def __str__(self):
|
||||
ctime = "{:02}:{:02}".format(int(self.time/4), (self.time&0x03)*15)
|
||||
return "Appointment on the {} of {} at {}, label \"{}\"".format(
|
||||
self.day, monthNamesAbbr[self.month], ctime, self.label)
|
||||
|
||||
def __bytes__(self):
|
||||
data = [self.month&0xFF, self.day&0xFF, self.time&0xFF]
|
||||
data = data + pack4to3(str2timex(self.label))
|
||||
data = [len(data)+1] + data
|
||||
return bytes(data)
|
||||
|
||||
class TimexTodo:
|
||||
def __init__(self, prio=1, label=""):
|
||||
self.prio=prio
|
||||
self.label=label
|
||||
|
||||
def __str__(self):
|
||||
return "Todo with priority {}, label \"{}\"".format(
|
||||
self.prio, self.label)
|
||||
|
||||
def __bytes__(self):
|
||||
data = [self.prio]
|
||||
data = data + pack4to3(str2timex(self.label))
|
||||
data = [len(data)+1] + data
|
||||
return bytes(data)
|
||||
|
||||
class TimexPhoneNumber:
|
||||
def __init__(self, number=1, label=""):
|
||||
self.number=number
|
||||
self.label=label
|
||||
|
||||
def __str__(self):
|
||||
return "Phone number {}, label \"{}\"".format(
|
||||
self.number, self.label)
|
||||
|
||||
def __bytes__(self):
|
||||
# Encoded as four bits per digit and LSD first, always 10 digits
|
||||
digits = [ord(x)-ord('0') for x in "{:010d}".format(self.number)[::-1]]
|
||||
data = [d[0]<<4|d[1] for d in zip(digits[0::2], digits[1::2]) ]
|
||||
data = data + pack4to3(str2timex(self.label))
|
||||
data = [len(data)+1] + data
|
||||
return bytes(data)
|
||||
|
||||
class TimexAnniversary:
|
||||
def __init__(self, month=0, day=0, label=""):
|
||||
self.month=month
|
||||
self.day=day
|
||||
self.label=label
|
||||
|
||||
def __str__(self):
|
||||
return "Anniversary on the {} of {}, label \"{}\"".format(
|
||||
self.day, monthNamesAbbr[self.month], self.label)
|
||||
|
||||
def __bytes__(self):
|
||||
data = [self.month&0xFF, self.day&0xFF]
|
||||
data = data + pack4to3(str2timex(self.label))
|
||||
data = [len(data)+1] + data
|
||||
return bytes(data)
|
||||
|
||||
class TimexTimezone:
|
||||
def __init__(self, offset, format, name):
|
||||
self.offset = offset
|
||||
self.format = format
|
||||
self.name = name
|
||||
|
||||
class TimexAlarm:
|
||||
def __init__(self, hour=0, minute=0, month=0, day=0, label="", audible=True):
|
||||
self.hour = hour
|
||||
self.minute = minute
|
||||
self.month = month
|
||||
self.day = day
|
||||
self.label = label
|
||||
self.audible = audible
|
||||
self.seq=0
|
||||
|
||||
def __bytes__(self):
|
||||
# TODO: Adapt for 150 series
|
||||
data = [self.seq] # TODO: Should be alarm sequence ID! (1-5)
|
||||
data += [self.hour, self.minute, self.month, self.day]
|
||||
|
||||
label = self.label
|
||||
if len(label)<8: # Min 8 chars, pad with space
|
||||
label +=" "*(8-len(label))
|
||||
label = label[:8] # Max 8 chars
|
||||
data += str2timex(label)
|
||||
|
||||
if self.audible:
|
||||
data += [1]
|
||||
else:
|
||||
data += [0]
|
||||
|
||||
pkgdata = makepkg([0x50]+data)
|
||||
|
||||
if not self.audible:
|
||||
data = [0, 0x61+self.seq, 0]
|
||||
pkgdata += makepkg([0x70]+data)
|
||||
|
||||
return bytes(pkgdata)
|
||||
|
||||
class TimexData:
|
||||
def __init__(self):
|
||||
self.appointments = []
|
||||
self.todos = []
|
||||
self.phonenumbers = []
|
||||
self.anniversaries = []
|
||||
self.alarms = []
|
||||
self.sendTime = False
|
||||
self.tz=[
|
||||
TimexTimezone(0, 24, "utc"),
|
||||
TimexTimezone(-5, 12, "est")
|
||||
]
|
||||
|
||||
def setTimezone(self, tzno, offset, format, name):
|
||||
if tzno not in [1,2]:
|
||||
raise Exception("Time zone number must be 1 or 2!")
|
||||
|
||||
# TODO: Move these checks to time zone class
|
||||
if format not in [12,24]:
|
||||
raise Exception("Time format must be 12 or 24!")
|
||||
|
||||
if len(name)>3:
|
||||
raise Exception("Max length for time zone name is 3 characters!")
|
||||
|
||||
self.tz[tzno-1] = TimexTimezone(offset, format, name)
|
||||
|
||||
def addAppointment(self, appointment):
|
||||
self.appointments.append(appointment)
|
||||
|
||||
def addNewAppointment(self, month=0, day=0, time=0, label=""):
|
||||
new = TimexAppointment(month, day, time, label)
|
||||
self.addAppointment(new)
|
||||
return new
|
||||
|
||||
def delAppointment(self, appointment):
|
||||
self.appointments = [a for a in self.appointments if a != appointment]
|
||||
|
||||
def addTodo(self, todo):
|
||||
self.todos.append(todo)
|
||||
|
||||
def addNewTodo(self, prio=1, label=""):
|
||||
new = TimexTodo(prio, label)
|
||||
self.addTodo(new)
|
||||
return new
|
||||
|
||||
def delTodo(self, todo):
|
||||
self.todos = [a for a in self.todos if a != todo]
|
||||
|
||||
def addPhoneNumber(self, phonenumber):
|
||||
self.phonenumbers.append(phonenumber)
|
||||
|
||||
def addNewPhoneNumber(self, number=1, label=""):
|
||||
new = TimexPhoneNumber(number, label)
|
||||
self.addPhoneNumber(new)
|
||||
return new
|
||||
|
||||
def delPhoneNumber(self, phonenumber):
|
||||
self.phonenumbers = [a for a in self.phonenumbers if a != phonenumber]
|
||||
|
||||
def addAnniversary(self, anniversary):
|
||||
self.anniversaries.append(anniversary)
|
||||
|
||||
def addNewAnniversary(self, month=0, day=0, label=""):
|
||||
new = TimexAnniversary(month, day, label)
|
||||
self.addAnniversary(new)
|
||||
return new
|
||||
|
||||
def delAnniversary(self, anniversary):
|
||||
self.anniversaries = [a for a in self.anniversaries if a != anniversary]
|
||||
|
||||
def addAlarm(self, alarm):
|
||||
self.alarms.append(alarm)
|
||||
|
||||
def addNewAlarm(self, hour=0, minute=0, month=0, day=0, label="", audible=True):
|
||||
new = TimexAlarm(hour, minute, month, day, label, audible)
|
||||
self.addAlarm(new)
|
||||
return new
|
||||
|
||||
def delAlarm(self, alarm):
|
||||
self.alarms = [a for a in self.alarms if a != alarm]
|
||||
|
||||
def __bytes__(self):
|
||||
data = b''
|
||||
data += bytes(makeSTART1())
|
||||
|
||||
if self.sendTime:
|
||||
now = datetime.datetime.utcnow()
|
||||
tz1time = now+datetime.timedelta(hours=self.tz[0].offset)
|
||||
tz2time = now+datetime.timedelta(hours=self.tz[1].offset)
|
||||
data += bytes(makeTZ(2, tz2time, self.tz[1].format))
|
||||
data += bytes(makeTZ(1, tz1time, self.tz[0].format))
|
||||
data += bytes(makeTZNAME(1, self.tz[0].name))
|
||||
data += bytes(makeTZNAME(2, self.tz[1].name))
|
||||
|
||||
if (
|
||||
len(self.appointments)>0 or
|
||||
len(self.todos)>0 or
|
||||
len(self.phonenumbers)>0 or
|
||||
len(self.anniversaries)>0
|
||||
):
|
||||
data += bytes(makeSTART2(1))
|
||||
data += bytes(makeDATA1(self.appointments, self.todos, self.phonenumbers, self.anniversaries))
|
||||
data += bytes(makeEND1())
|
||||
|
||||
# I don't know if all five alarms must be sent every time.
|
||||
# If so, make dummy alarms.
|
||||
if len(self.alarms)>0:
|
||||
i=1
|
||||
for a in self.alarms:
|
||||
data += makeALARM(a, i)
|
||||
i+=1
|
||||
|
||||
data += bytes(makeEND2())
|
||||
|
||||
return data
|
||||
@@ -0,0 +1,2 @@
|
||||
from .Blaster import *
|
||||
from .TimexData import *
|
||||
@@ -0,0 +1,189 @@
|
||||
from crccheck.crc import CrcArc
|
||||
|
||||
# Create character conversion table (to be verified)
|
||||
"""
|
||||
char set for labels is: (6 bits per char)
|
||||
0-9 : digits
|
||||
10-36: letters
|
||||
37-63: symbols:
|
||||
space !"#$%&'()*+,-./;\
|
||||
divide =
|
||||
bell (image, not sound)
|
||||
?
|
||||
"""
|
||||
char_conv = None
|
||||
def make_char_conv():
|
||||
global char_conv
|
||||
|
||||
# All lowercase characters. Using uppercase D for divide symbol and B for bell symbol
|
||||
dst = "0123456789abcdefghijklmnopqrstuvwxyz !\"#$%&'()*+,-./;\\D=B?"
|
||||
src = range(len(dst))
|
||||
char_conv = {k:v for k,v in zip(dst,src)}
|
||||
|
||||
# Convert string to timex string format using table from above
|
||||
def str2timex(string):
|
||||
if char_conv is None:
|
||||
make_char_conv()
|
||||
out = []
|
||||
for c in string:
|
||||
if not c in char_conv:
|
||||
raise Exception("Invalid character {} in string!".format(c))
|
||||
out.append(char_conv[c])
|
||||
return out
|
||||
|
||||
# Pack 4 bytes in 3, used for strings
|
||||
def pack4to3(indata):
|
||||
while len(indata)%4:
|
||||
# Add padding
|
||||
indata.append(0xff)
|
||||
|
||||
outdata = []
|
||||
while len(indata)>0:
|
||||
ch1 = indata.pop(0)
|
||||
ch2 = indata.pop(0)
|
||||
ch3 = indata.pop(0)
|
||||
ch4 = indata.pop(0)
|
||||
|
||||
outdata.append( ((ch2&0x03)<<6) | (ch1&0x3F) )
|
||||
outdata.append( ((ch3&0x0F)<<4) | ((ch2>>2)&0x0F) )
|
||||
outdata.append( ((ch4&0x3F)<<2) | ((ch3&0x30)>>4) )
|
||||
|
||||
return outdata
|
||||
|
||||
# Takes a list of bytes, returns list of bytes in package with length and checksum
|
||||
def makepkg(values):
|
||||
packet = []
|
||||
|
||||
packet.append(len(values)+3)
|
||||
|
||||
packet += values
|
||||
|
||||
p = CrcArc()
|
||||
p.process(packet)
|
||||
crc = p.final()
|
||||
|
||||
packet.append(crc>>8 & 0xFF)
|
||||
packet.append(crc & 0xFF)
|
||||
|
||||
return packet
|
||||
|
||||
# Just dump list of ints in hex, for debugging convenience
|
||||
def pkgstr(pkg):
|
||||
outstr = ""
|
||||
for b in pkg:
|
||||
outstr += "0x{:02x} ".format(b)
|
||||
return outstr[:-1]
|
||||
|
||||
### Packet makers
|
||||
|
||||
# Make start package. Currently only implemented for model 70.
|
||||
def makeSTART1():
|
||||
return makepkg([0x20, 0x00, 0x00, 0x01])
|
||||
|
||||
# num_data1: Number of data1 packets following
|
||||
def makeSTART2(num_data1):
|
||||
return makepkg([0x60, num_data1])
|
||||
|
||||
def makeEND1():
|
||||
return makepkg([0x62])
|
||||
|
||||
def makeEND2():
|
||||
return makepkg([0x21])
|
||||
|
||||
# Takes lists of TimexAppointment, TimexTodo, TimexPhoneNumber
|
||||
# and TimexAnniversary objects
|
||||
def makeDATA1(appts, todos, phones, anniversaries):
|
||||
# TODO: For now, this assumes everything fits in one packet.
|
||||
# If there is a lot of data, this may be split up over
|
||||
# more than one packet.
|
||||
data = [1] # Sequence ID
|
||||
data += [0,0] # Start index for appointments, to be filled later
|
||||
data += [0,0] # Start index for todos, to be filled later
|
||||
data += [0,0] # Start index for phone numbers, to be filled later
|
||||
data += [0,0] # Start index for anniversaries, to be filled later
|
||||
data += [len(appts)]
|
||||
data += [len(todos)]
|
||||
data += [len(phones)]
|
||||
data += [len(anniversaries)]
|
||||
data += [0x14] # The github repo had 0x60 here, with a question mark
|
||||
data += [0x03] # Time, in five minute intervals, to alarm before appointments
|
||||
|
||||
# Add appointments
|
||||
index = len(data)-1
|
||||
data[1] = (index&0xFF00) >> 8
|
||||
data[2] = (index&0x00FF)
|
||||
for a in appts:
|
||||
data += list(bytes(a))
|
||||
|
||||
# Add todos
|
||||
index = len(data)-1
|
||||
data[3] = (index&0xFF00) >> 8
|
||||
data[4] = (index&0x00FF)
|
||||
for a in todos:
|
||||
data += list(bytes(a))
|
||||
|
||||
# Add phone numbers
|
||||
index = len(data)-1
|
||||
data[5] = (index&0xFF00) >> 8
|
||||
data[6] = (index&0x00FF)
|
||||
for a in phones:
|
||||
data += list(bytes(a))
|
||||
|
||||
# Add anniversaries
|
||||
index = len(data)-1
|
||||
data[7] = (index&0xFF00) >> 8
|
||||
data[8] = (index&0x00FF)
|
||||
for a in anniversaries:
|
||||
data += list(bytes(a))
|
||||
|
||||
return makepkg([0x61]+data)
|
||||
|
||||
# Currently only implemented for model 70.
|
||||
def makeTZ(tzno, tztime, format):
|
||||
data = [tzno,
|
||||
tztime.hour, tztime.minute,
|
||||
tztime.month, tztime.day, tztime.year%100,
|
||||
tztime.weekday(), tztime.second]
|
||||
|
||||
if format == 12:
|
||||
data += [1]
|
||||
else:
|
||||
data += [2]
|
||||
|
||||
return makepkg([0x30]+data)
|
||||
|
||||
def makeTZNAME(tzno, tzname):
|
||||
if len(tzname)>3:
|
||||
raise Exception("Time zone name too long!")
|
||||
elif len(tzname)<3:
|
||||
tzname += " "*(3-len(tzname))
|
||||
|
||||
data = [tzno]
|
||||
data+= str2timex(tzname)
|
||||
return makepkg([0x31]+data)
|
||||
|
||||
# Takes an alarm number and a sequence ID (1-5)
|
||||
# Currently only implemented for model 70.
|
||||
def makeALARM(alarm, seq):
|
||||
data = [seq]
|
||||
data += [alarm.hour, alarm.minute, alarm.month, alarm.day]
|
||||
|
||||
label = alarm.label
|
||||
if len(label)<8: # Min 8 chars, pad with space
|
||||
label +=" "*(8-len(label))
|
||||
label = label[:8] # Max 8 chars
|
||||
data += str2timex(label) # NOT packed!
|
||||
|
||||
if alarm.audible:
|
||||
data += [1]
|
||||
else:
|
||||
data += [0]
|
||||
|
||||
pkgdata = makepkg([0x50]+data)
|
||||
|
||||
# Add that packet that's present after inaudible alarms
|
||||
if not alarm.audible:
|
||||
data = [0, 0x61+seq, 0]
|
||||
pkgdata += makepkg([0x70]+data)
|
||||
|
||||
return bytes(pkgdata)
|
||||
@@ -0,0 +1,66 @@
|
||||
import pytimex
|
||||
|
||||
def listhex(pkg):
|
||||
outstr = ""
|
||||
for b in pkg:
|
||||
outstr += "0x{:02x}, ".format(b)
|
||||
return outstr[:-1]
|
||||
|
||||
# Setup data to be sent
|
||||
d = pytimex.TimexData()
|
||||
|
||||
if 0:
|
||||
# Try all the features!
|
||||
a = d.addNewAppointment(5, 31, 0x27, "test")
|
||||
d.addNewTodo(3, "code stuff")
|
||||
d.addNewPhoneNumber(73579, "e.t. home")
|
||||
d.addNewAnniversary(6, 6, "national day")
|
||||
|
||||
# You can modify these later:
|
||||
a.label = "hello"
|
||||
|
||||
# Setup a good timezone and a silly one just for testing
|
||||
d.setTimezone(1, +2, 24, "cet")
|
||||
d.setTimezone(2, -4.5, 24, "hej")
|
||||
d.sendTime = True
|
||||
|
||||
# Add some alarms.
|
||||
# Don't know if you need to send all five at once or if you can overwrite them individually.
|
||||
d.addNewAlarm(9,0,0,0,"sample",True)
|
||||
d.addNewAlarm(hour=10, minute=15, month=0, day=30, label="plug meeting", audible=True)
|
||||
d.addNewAlarm(0, 0, 0, 0, "test", False)
|
||||
d.addNewAlarm(0, 0, 0, 0, "alarm #4", False)
|
||||
d.addNewAlarm(0, 0, 0, 0, "alarm #5", False)
|
||||
else:
|
||||
d.setTimezone(1, +2, 24, "cet")
|
||||
d.setTimezone(2, -4.5, 24, "hej")
|
||||
d.sendTime = True
|
||||
|
||||
# Get data to be transferred
|
||||
data = bytes(d)
|
||||
|
||||
# Show data, for debugging
|
||||
print("Data to be blasted:")
|
||||
print(listhex(data))
|
||||
|
||||
sys.exit(0)
|
||||
|
||||
# Initialize blaster
|
||||
b = pytimex.Blaster("/dev/ttyACM0", syncbuflen=16)
|
||||
|
||||
if not b.identify():
|
||||
print("Could not verify adapter :(")
|
||||
sys.exit(-1)
|
||||
|
||||
# Send synchronization byes (0x55 and 0xAA)
|
||||
b.send_sync()
|
||||
|
||||
# Blast data
|
||||
for databyte in data:
|
||||
b.blast(databyte)
|
||||
|
||||
# Flush and wait for all bytes to sync
|
||||
b.flush()
|
||||
|
||||
print("Done!")
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
import pytimex
|
||||
|
||||
def listhex(pkg):
|
||||
outstr = ""
|
||||
for b in pkg:
|
||||
outstr += "0x{:02x}, ".format(b)
|
||||
return outstr[:-1]
|
||||
|
||||
d = pytimex.TimexData()
|
||||
|
||||
#(self, hour=0, minute=0, month=0, day=0, label="", audible=True):
|
||||
d.addNewAlarm(9,0,0,0,"sample",True)
|
||||
d.addNewAlarm(1, 1, 5, 21, "cafe", True)
|
||||
d.addNewAlarm(0, 0, 0, 23, "babee", True)
|
||||
d.addNewAlarm(0, 0, 0, 0, "alarm #4", False)
|
||||
d.addNewAlarm(0, 0, 0, 0, "alarm #5", False)
|
||||
|
||||
data = bytes(d)
|
||||
print(listhex(data))
|
||||
@@ -0,0 +1,81 @@
|
||||
import serial
|
||||
import time
|
||||
import sys
|
||||
|
||||
|
||||
"""
|
||||
On reset the device can respond to 3 commands:
|
||||
|
||||
* 'x': Device detection, echo this so the PC knows you're there
|
||||
* '?': Device ID query, reply with "M764" and a null byte ('\0')
|
||||
* 'U': Reply with 'x' and enter transmit mode
|
||||
|
||||
In transmit mode, all bytes should be echoed back to the PC and the
|
||||
commands above should not be answered. Transmit mode is only left upon
|
||||
reset.
|
||||
|
||||
The device is powered from the CTS control line, so this is pulled down
|
||||
at the beginning of transmission to make sure the device is reset.
|
||||
"""
|
||||
|
||||
|
||||
if len(sys.argv) != 3 and len(sys.argv) != 4:
|
||||
print("Usage: {} <port> <log file> [bin|txt]".format(sys.argv[0]))
|
||||
sys.exit(-1)
|
||||
|
||||
serialPort = sys.argv[1]
|
||||
logFileName = sys.argv[2]
|
||||
|
||||
logText = False
|
||||
|
||||
if len(sys.argv) == 4:
|
||||
if sys.argv[4] == txt:
|
||||
logText = True
|
||||
|
||||
with serial.Serial(serialPort, 9600, timeout=0.1) as sp:
|
||||
|
||||
# Used to control state of device
|
||||
transmitState = False
|
||||
|
||||
def send(data):
|
||||
# print("Sending: '{}'".format(data))
|
||||
sp.write(data)
|
||||
|
||||
while True:
|
||||
while True:
|
||||
# CTS control line is used for powering device, and therefore also reset it
|
||||
if False and sp.cts == False:
|
||||
if transmitState:
|
||||
print("Leaving transmit state")
|
||||
logfile.close()
|
||||
transmitState = False
|
||||
inb = sp.read(1)
|
||||
if len(inb) != 0:
|
||||
break
|
||||
|
||||
print("Received: {}".format(inb))
|
||||
|
||||
if not transmitState:
|
||||
if inb == b"x":
|
||||
print("Received detection byte ('x')")
|
||||
send(inb)
|
||||
|
||||
elif inb == b"?":
|
||||
print("Received device ID query ('?')")
|
||||
send("M764\0".encode())
|
||||
|
||||
elif inb == b"U":
|
||||
print("Received sync byte, entering transmit state")
|
||||
transmitState = True
|
||||
logfile = open(logFileName, 'wb')
|
||||
send(inb)
|
||||
|
||||
else:
|
||||
print("Received unknown byte ({}) outside of transmit state".format(inb))
|
||||
|
||||
else:
|
||||
if logText:
|
||||
logfile.write(("0x{:02x} \n".format(ord(inb))).encode())
|
||||
else:
|
||||
logfile.write(inb)
|
||||
send(inb)
|
||||
Reference in New Issue
Block a user