def __init__(me, io = None, timeout = 0.01) : me.io = io me.timeout = timeout me.ibuf = "" me.scnt = 1 me.rx_when = tzlib.elapsed_time() - 10000.0 me.data = [] # queue of a_recording's driven by data coming in from the device if not me.io : me.reopen() pass
def read(me, how_many = 1, timeout = None) : timeout = timeout or me.timeout t = nt = tzlib.elapsed_time() r = "" while True : rr = me.ibuf[:how_many] me.ibuf = me.ibuf[how_many:] how_many -= len(rr) rc = len(rr) r += rr if not how_many : break rr = me.rx(how_many) how_many -= len(rr) rc += len(rr) r += rr if not how_many : break if rc : t = nt if nt - t >= timeout : if len(r) : break raise a_cms50_timeout_exception("read") nt = tzlib.elapsed_time() if not rc : time.sleep(min(0.1, timeout / 2.0)) pass # print "rxing", len(r), "%04x" % ( len(r) ), hexify(r) return(r)
def main(ident) : import TZCommandLineAtFile import TZKeyReady try : import tz_google_chart import tz_browser except ImportError : tz_google_chart = None if ident : sys.argv.insert(1, ident) sys.argv.insert(1, '--ident') program_name = sys.argv.pop(0) TZCommandLineAtFile.expand_at_sign_command_line_files(sys.argv) ident = "" port = 0 # my COM port, not yours port_list = 0 verbose = 0 help_str = """ %s (options) (output_files_base_name) I get the streaming data from a CMS50E Pulse Oximeter. Options: --port port_number Set the COM port number --port_list List possible ports (twice, list all available ports) --version Print the program version number. """ % ( os.path.basename(program_name) ) oi = tzlib.array_find(sys.argv, [ "--help", "-?", "?", "-h", "/h", "/?", "?" ] ) if oi >= 0 : print help_str sys.exit(254) while True : oi = tzlib.array_find(sys.argv, [ "--ident", "-i" ] ) if oi < 0 : break del sys.argv[oi] if (oi >= len(sys.argv)) or not len(sys.argv[oi]) : print "Program IDENT info not given!" sys.exit(101) ident = sys.argv.pop(oi) while True : oi = tzlib.array_find(sys.argv, [ "--version", "-v" ] ) if oi < 0 : break del sys.argv[oi] print "version", _program_version_str(ident) if not sys.argv : sys.exit(0) pass while True : oi = tzlib.array_find(sys.argv, [ "--port", "-p" ] ) if oi < 0 : break del sys.argv[oi] if (oi >= len(sys.argv)) or not len(sys.argv[oi]) : print "No COM port given!" sys.exit(102) port = sys.argv.pop(oi) while True : oi = tzlib.array_find(sys.argv, [ "--port_list" ] ) if oi < 0 : break del sys.argv[oi] port_list += 1 while True : oi = tzlib.array_find(sys.argv, [ "--verbose" ] ) if oi < 0 : break del sys.argv[oi] verbose += 1 ofile_name = None if len(sys.argv) >= 1 : ofile_name = sys.argv.pop(0) if ofile_name.startswith('-') : print "Put the whole path or a dot/slash before the output file name. Dashes are confusing: [%s]" % ofile_name sys.exit(104) pass if len(sys.argv) : print "I don't understand %s (--help for options)!" % ( sys.argv ) sys.exit(104) if port_list : tz_usb.find_likely_COM_ports(vendor_id = USB_VENDOR_ID, product_id = USB_PRODUCT_ID, list_level = port_list) if not port : port = tz_usb.find_likely_COM_ports(vendor_id = USB_VENDOR_ID, product_id = USB_PRODUCT_ID) if port : print "Using port", port[0], if len(port) > 1 : print "Found ports", port, print port = port[0] pass if not port : print "Please tell me a COM port to use with the --port option (e.g. --port 2 )!" sys.exit(103) try : port = int(port) cport = port - 1 except ValueError : cport = port try : io = serial.Serial(port = cport, baudrate = 19200, parity = "O", timeout = 0.001) # note: PC program sets 8O1. serial.Serial() multiplies timeout by 1000 before passing to windows (This 1 mill is minimum for windows. I don't know about other OS's.) except serial.SerialException : print "Port %s [%s] cannot be opened!" % ( str(port), str(cport) ) sys.exit(111) me = a_comm(io) samples = a_recording() if ofile_name : if os.path.splitext(ofile_name)[1].lower() == ".csv" : fo = output_files.a_file(ofile_name) fo.write(a_full_sample.csv_header + "\n") else : fo = None fn = get_output_file_name(ofile_name, program_name = program_name) print "Outputting to: ", samples.open_write_file(fn) pass prg = a_progress_rtn() stopped = 1000 finger = False lay = [] mx = -10000 mn = 10000 msa = [ 64 ] * 300 mss = float(sum(msa)) ts = tzlib.elapsed_time() rx_when = ts png_drs = [ 7.5, 15.0, 30.0, 60.0, 120.0, 10 * 60.0, 15 * 60.0, 60 * 60.0, 2 * 60 * 60.0, 6 * 60 * 60.0, 12 * 60 * 60.0, ] png_di = 0 sb = 0xf5 me.start_usb() # in case he's not turned it on (though we'll do this every half second of silence from the device, anyway print "Type ? for help" while True : try : s = me.read_sample(progress_rtn = prg.show_progress, verbose = verbose) if s : yy = s.y if False : msa.append(s.y) mss += s.y mss -= msa[0] del(msa[0]) else : mss = 64 if False : yy = ((s.y) * ((s.bc & 0xf) + 1)) / 4.5 # tends to flatten out in the middle when there is a change to low amplitude waves if False : if yy < 0 : yy = -math.log(-yy + math.e) else : yy = math.log( yy + math.e) pass pass mx = max(mx, yy) mn = min(mn, yy) if s.ac & 3 : print "@@@@ ac=%u" % s.ac lay.append(s.ac) if not finger : samples.append(a_finger_sample(True)) samples.append(s) if ofile_name : if fo : fo.write("%s\n" % s.csv_str()) samples.write_new_samples() ys = (' ' * int((100.0 * (yy - mn)) / max(1.0, (mx - mn)))) + '*' # avya = [ ox for ox in samples.samples[-5 * SAMPLE_RATE : ] if hasattr(ox, 'y') ] # avy = sum([ ox.y for ox in avya ]) / float(max(1, len(avya))) #dreamtcs might want to skip this print ( s.print_str() ) # (100.0 * yy) / (yy + (s.bc & 0xf)), ys ) if not finger : finger = True samples.flush_file() print "Finger" stopped = max(stopped - 10, 0) if len(samples.samples) > png_drs[-1] * SAMPLE_RATE * 2 : samples.flush_file() samples.forget_old_samples(png_drs[-1] * SAMPLE_RATE) rx_when = tzlib.elapsed_time() t = tzlib.elapsed_time() if t - ts > 59 : ts = t samples.flush_file() pass except a_cms50_no_finger_exception : if finger : finger = False samples.append(a_finger_sample(False)) print "No finger" samples.flush_file() pass except a_cms50_data_exception, msg : samples.flush_file() print msg # those bits are not, apparently, dupes of each other if not stopped : sys.exit(199) stopped -= 1 except ( a_cms50_exception, a_cms50_timeout_exception, ) : t = tzlib.elapsed_time() if t - rx_when > 0.5 : rx_when = t ts = t mx = -10000 mn = 10000 samples.flush_file() me.start_usb() pass
def read_sample(me, progress_rtn = None, verbose = 0, mismatch_callback = None) : s = None try : b = ord(me.read()) me.rx_when = tzlib.elapsed_time() if b == 128 : ba = [ b ] t = me.rx_when while (len(ba) < 5) and (t - me.rx_when < 0.1) : t = tzlib.elapsed_time() ba.append(ord(me.read())) me.scnt += 1 if False and (ba[1] in [ 0, 0xff ]) : # 321390_Kanograf_(8400).pdf if len(ba) == 5 : print "@@@@ %02x:%02x:%02x:%02x:%02x" % ( ba[0], ba[1], ba[2], ba[3], ba[4] ) else : print "@@@@", str(ba) pass raise a_cms50_no_finger_exception if b < 128 : # print "@@@@ toss read %02x" % b pass else : y = ord(me.read()) ay = ord(me.read()) if (b == 0xf2) and (y & 0x80) : me.ibuf = chr(b) + chr(y) + chr(ay) + me.ibuf dt = me.read_upload(progress_rtn = progress_rtn, verbose = verbose) if dt : me.data.append(dt) return(None) hr = ord(me.read()) if (ay == 0xf2) and (hr & 0x80) : me.ibuf = chr(ay) + chr(hr) + me.ibuf dt = me.read_upload(progress_rtn = progress_rtn, verbose = verbose) if dt : me.data.append(dt) return(None) hr |= ((ay & 0x40) << 1) ox = ord(me.read()) if ay & 0x80 : # me.ibuf = chr(ay) + chr(hr) + chr(ox) + me.ibuf # note: the few times this has happened have not indicated that this is a good idea - nor that interpreting the ay|hr|ox bytes as uploaded data is a good idea return(None) # punt as best we can bc = (b & ~(64 | 128)) ac = ay >> 4 # print "@@@@ %02x" % b, hr, ox, me.scnt, y, ay, bc, ac s = a_full_sample(hr, ox, me.scnt, y, ((b & 64) and True) or False, bc = bc, ac = ac & 3) if (ay & 0x0f) != (y / 8) : # apparently, these 4 bits are a dupe of the top 4 or the 7 bits in "y" - let's force that to be so - crashes when device dumps memory # print "@@@@ b=%02x ay & 0xf != y/8 ay:0x%02x != y:0x%02x" % ( b, ay, y ) # can happen if upload is starting if mismatch_callback : mismatch_callback(s, b, ay) # tell the caller this happened if he wants to know s = None me.scnt += 1 pass except ( a_cms50_exception, a_cms50_timeout_exception, ) : if tzlib.elapsed_time() - me.rx_when > 0.5 : me.scnt = 1 raise return(s)
while len(me.data) : dt = me.data.pop(0) # print "@@@@", len(dt.samples), len(dt.fd), "at", dt.tm / 3600, (dt.tm / 60) % 60 if len(dt.samples) : fn = get_output_file_name(ofile_name, program_name = program_name, ext = ".dat") # tzlib.write_whole_binary_file(fn, dt.fd) dfn = dt.write_file(fn) if not dfn : print "Probably no data to write, so file not written." else : print "Wrote driven upload to", fn, "and", dfn, len(dt.samples) pass pass mx = -10000 mn = 10000 ts = tzlib.elapsed_time() stopped = 1000 k = TZKeyReady.key_ready() if k : print if k in [ 'q', ] : break if k == '?' : if tz_google_chart : pcmd = (""" p Write .png file showing graph to a file named like %s. And write %s file with graphed data. """ % ( get_output_file_name(ofile_name, program_name = program_name, ext = ".png"), a_recording.FILE_EXT, ) ).rstrip()