diff --git a/adafruit_rfm69.py b/adafruit_rfm69.py index 073207b..084afd4 100644 --- a/adafruit_rfm69.py +++ b/adafruit_rfm69.py @@ -674,11 +674,14 @@ def frequency_deviation(self, val): self._write_u8(_REG_FDEV_MSB, fdev >> 8) self._write_u8(_REG_FDEV_LSB, fdev & 0xFF) - def send(self, data, timeout=2.): + def send(self, data, timeout=2., + tx_header=(_RH_BROADCAST_ADDRESS, _RH_BROADCAST_ADDRESS, 0, 0)): """Send a string of data using the transmitter. You can only send 60 bytes at a time (limited by chip's FIFO size and appended headers). - Note this appends a 4 byte header to be compatible with the RadioHead library. + This appends a 4 byte header to be compatible with the RadioHead library. + The tx_header defaults to using the Broadcast addresses. It may be overidden + by specifying a 4-tuple of bytes containing (To,From,ID,Flags) The timeout is just to prevent a hang (arbitrarily set to 2 seconds) """ # Disable pylint warning to not use length as a check for zero. @@ -687,6 +690,7 @@ def send(self, data, timeout=2.): # buffer be within an expected range of bounds. Disable this check. # pylint: disable=len-as-condition assert 0 < len(data) <= 60 + assert len(tx_header) == 4, "tx header must be 4-tuple (To,From,ID,Flags)" # pylint: enable=len-as-condition self.idle() # Stop receiving to clear FIFO and keep it clear. # Fill the FIFO with a packet to send. @@ -697,10 +701,10 @@ def send(self, data, timeout=2.): # Add 4 bytes of headers to match RadioHead library. # Just use the defaults for global broadcast to all receivers # for now. - self._BUFFER[2] = _RH_BROADCAST_ADDRESS # txHeaderTo - self._BUFFER[3] = _RH_BROADCAST_ADDRESS # txHeaderFrom - self._BUFFER[4] = 0 # txHeaderId - self._BUFFER[5] = 0 # txHeaderFlags + self._BUFFER[2] = tx_header[0] # Header: To + self._BUFFER[3] = tx_header[1] # Header: From + self._BUFFER[4] = tx_header[2] # Header: Id + self._BUFFER[5] = tx_header[3] # Header: Flags device.write(self._BUFFER, end=6) # Now send the payload. device.write(data) @@ -718,14 +722,27 @@ def send(self, data, timeout=2.): if timed_out: raise RuntimeError('Timeout during packet send') - def receive(self, timeout=0.5, keep_listening=True): + def receive(self, timeout=0.5, keep_listening=True, with_header=False, + rx_filter=_RH_BROADCAST_ADDRESS): """Wait to receive a packet from the receiver. Will wait for up to timeout_s amount of seconds for a packet to be received and decoded. If a packet is found the payload bytes are returned, otherwise None is returned (which indicates the timeout elapsed with no - reception). Note this assumes a 4-byte header is prepended to the data for compatibilty - with the RadioHead library (the header is not validated nor returned). If keep_listening - is True (the default) the chip will immediately enter listening mode after reception of - a packet, otherwise it will fall back to idle mode and ignore any future reception. + reception). + If keep_listening is True (the default) the chip will immediately enter listening mode + after reception of a packet, otherwise it will fall back to idle mode and ignore any + future reception. + A 4-byte header must be prepended to the data for compatibilty with the + RadioHead library. + The header consists of a 4 bytes (To,From,ID,Flags). The default setting will accept + any incomming packet and strip the header before returning the packet to the caller. + If with_header is True then the 4 byte header will be returned with the packet. + The payload then begins at packet[4]. + rx_fliter may be set to reject any "non-broadcast" packets that do not contain the + specfied "To" value in the header. + if rx_filter is set to 0xff (_RH_BROADCAST_ADDRESS) or if the "To" field (packet[[0]) + is equal to 0xff then the packet will be accepted and returned to the caller. + If rx_filter is not 0xff and packet[0] does not match rx_filter then + the packet is ignored and None is returned. """ # Make sure we are listening for packets. self.listen() @@ -760,13 +777,14 @@ def receive(self, timeout=0.5, keep_listening=True): device.readinto(self._BUFFER, end=fifo_length) packet = None else: - # Read the 4 bytes of the RadioHead header. - device.readinto(self._BUFFER, end=4) - # Ignore validating any of the header bytes. - # Now read the remaining packet payload as the result. - fifo_length -= 4 packet = bytearray(fifo_length) device.readinto(packet) + if (rx_filter != _RH_BROADCAST_ADDRESS and packet[0] != _RH_BROADCAST_ADDRESS + and packet[0] != rx_filter): + packet = None + if not with_header: # skip the header if not wanted + packet = packet[4:] + # Listen again if necessary and return the result packet. if keep_listening: self.listen()