diff --git a/gex/Client.py b/gex/Client.py index e3c6053..7a08e69 100644 --- a/gex/Client.py +++ b/gex/Client.py @@ -1,6 +1,7 @@ import serial import gex -from gex import TinyFrame, PayloadParser +from gex import TinyFrame, PayloadParser, TF, PayloadBuilder + class Client: """ GEX client """ @@ -79,7 +80,7 @@ class Client: self.tf.accept(rv) def send(self, cs, cmd, id=None, pld=None, listener=None): - """ Send a command to a unit """ + """ Send a command to a unit. If cs is None, cmd is used as message type """ if cs is None: return self.tf.query(type=cmd, id=id, pld=pld, listener=listener) @@ -91,12 +92,13 @@ class Client: self.tf.query(type=gex.MSG_UNIT_REQUEST, id=id, pld=buf, listener=listener) def query(self, cs, cmd, id=None, pld=None): - """ Query a unit """ + """ Query a unit. If cs is None, cmd is used as message type """ self._theframe = None def lst(tf, frame): self._theframe = frame + return TF.CLOSE self.send(cs, cmd, id=id, pld=pld, listener=lst) self.poll() @@ -104,6 +106,9 @@ class Client: if self._theframe is None: raise Exception("No response to query") + if self._theframe.type == gex.MSG_ERROR: + raise Exception("Error response: %s" % self._theframe.data.decode('utf-8')) + return self._theframe def query_raw(self, type, id=None, pld=None): @@ -113,3 +118,41 @@ class Client: def send_raw(self, type, id=None, pld=None): """ Send to GEX, without addressing a unit """ return self.send(cs=None, cmd=type, id=id, pld=pld) + + def bulk_read(self, cs, cmd, id=None, pld=None, chunk=1024): + """ Perform a bulk read. If cs is None, cmd is used as message type """ + + offer = self.query(cs=cs, cmd=cmd, id=id, pld=pld) + if offer.type != gex.MSG_BULK_READ_OFFER: + raise Exception("Bulk read rejected! %s" % offer.data.decode('utf-8')) + + # parse the offer + pp = PayloadParser(offer.data) + total = pp.u32() + # we don't need to worry much about the total size, + # this is for static buffers in C. + + at = 0 + buffer = bytearray() + while at < total: + # Ask for a chunk + pb = PayloadBuilder() + pb.u32(chunk) + + pollrv = self.query_raw(type=gex.MSG_BULK_READ_POLL, id=offer.id, pld=pb.close()) + + if pollrv.type in [gex.MSG_BULK_DATA, gex.MSG_BULK_END]: + buffer.extend(pollrv.data) + at += len(pollrv.data) + if pollrv.type == gex.MSG_BULK_END: + break + else: + raise Exception("Unexpected bulk frame type %d" % pollrv.type) + + return buffer + + def bulk_write(self, cs, cmd, bulk, id=None, pld=None): + """ Perform a bulk write. If cs is None, cmd is used as message type """ + + + diff --git a/main.py b/main.py index 9fc9188..daf3bca 100644 --- a/main.py +++ b/main.py @@ -4,8 +4,13 @@ import time import gex client = gex.Client() -led = gex.Pin(client, 'LED') -for i in range(0,10): - led.toggle() - time.sleep(.1) +buf = client.bulk_read(None, gex.MSG_INI_READ) +print(buf.decode('utf-8')) + +if False: + led = gex.Pin(client, 'LED') + + for i in range(0,10): + led.toggle() + time.sleep(.1)