From dcf08edcf8a84f7db7532f9af333eadd8185e219 Mon Sep 17 00:00:00 2001 From: John Whittington Date: Mon, 30 Jan 2023 14:20:11 +0100 Subject: [PATCH] default to RX only for continous scan example --- examples/broadcast_send.py | 3 +-- examples/continuous_scan.py | 40 ++++++++++++++++++++++--------------- openant/base/ant.py | 20 ++++++++++++++++--- openant/base/driver.py | 7 +++++-- 4 files changed, 47 insertions(+), 23 deletions(-) diff --git a/examples/broadcast_send.py b/examples/broadcast_send.py index a89d9fd..b534602 100644 --- a/examples/broadcast_send.py +++ b/examples/broadcast_send.py @@ -7,7 +7,6 @@ # # For further details on Speed & Distance Sensor, check out the thisisant.com webpage -import array import logging import time @@ -33,7 +32,7 @@ class AntSendDemo: def __init__(self): self.ANTMessageCount = 0 - self.ANTMessagePayload = array.array("B", [0, 0, 0, 0, 0, 0, 0, 0]) + self.ANTMessagePayload = [0, 0, 0, 0, 0, 0, 0, 0] # Init Variables, needed self.LastStrideTime = 0 diff --git a/examples/continuous_scan.py b/examples/continuous_scan.py index 6ca37b2..f0a144d 100644 --- a/examples/continuous_scan.py +++ b/examples/continuous_scan.py @@ -1,8 +1,15 @@ -# ANT+ - Open Rx Scan Mode Example -# -# Open Rx demo working with OpenAnt Library (https://github.com/Tigge/openant) -# For further details on Open Rx Mode ("Continious Scann Mode"), check out the thisisant.com webpage +""" +ANT+ - Open Rx Scan Mode Example +Open Rx demo working with OpenAnt Library (https://github.com/Tigge/openant) + +The continuous scanning mode allows an ANT node to asynchronously receive transmissions from multiple devices, regardless of their respective message rates. In scanning mode, the radio is active full time, so it is able to receive messages from transmitting nodes at any time. +All channels on a Node must be closed prior to enabling continous scanning mode and only one channel can be used. + +TODO: the Node() should probably manage this. + +For further details on Open Rx Mode ("Continious Scann Mode"), check out the thisisant.com webpage, ANT AN14. +""" from openant.easy.node import Node from openant.easy.channel import Channel from openant.base.commons import format_list @@ -11,10 +18,18 @@ import logging import time +""" +Ref ANT AN14: +A node in continuous scanning mode can be configured for bidirectional or receive-only communication. +Even though the continuous scanning mode makes full use of the radio, receiving 100% of the time; if a scanning node is configured for bidirectional communication, it is still possible to transmit data in response to a message from a master. In this case, it will also automatically send acknowledgements when receiving acknowledged and burst data. This could be a problem if the scanning device is not the intended destination of the data. +""" +# See above and only use BIDIRECTIONAL_RECEIVE if wishing to TX and ACK +RX_MODE = Channel.Type.UNIDIRECTIONAL_RECEIVE_ONLY +# RX_MODE = Channel.Type.BIDIRECTIONAL_RECEIVE def main(): print("ANT+ Open Rx Scan Mode Demo") - logging.basicConfig(filename="example.log", level=logging.DEBUG) + logging.basicConfig(level=logging.DEBUG) TimeProgramStart = time.time() # get start time @@ -22,27 +37,19 @@ def on_data_scan(data): deviceNumber = data[10] * 256 + data[9] deviceType = data[11] ActualTime = time.time() - TimeProgramStart - print(ActualTime, "RX:", deviceNumber, ", ", deviceType, ":", format_list(data)) + print(f"{ActualTime:.3f} RX: {deviceNumber:05}, {deviceType:03}: {format_list(data)}") def on_data_ack_scan(data): deviceNumber = data[10] * 256 + data[9] deviceType = data[11] ActualTime = time.time() - TimeProgramStart - print( - ActualTime, - "RX-Ack:", - deviceNumber, - ", ", - deviceType, - ":", - format_list(data), - ) + print(f"{ActualTime:.3f} RX: {deviceNumber:05}, {deviceType:03}: {format_list(data)}") node = Node() node.set_network_key(0x00, ANTPLUS_NETWORK_KEY) # 1. Set Network Key # CHANNEL CONFIGURATION channel = node.new_channel( - Channel.Type.BIDIRECTIONAL_RECEIVE, 0x00, 0x00 + RX_MODE, 0x00, 0x00 ) # 2. Assign channel channel.on_broadcast_data = on_data_scan @@ -65,6 +72,7 @@ def on_data_ack_scan(data): channel.close() node.stop() finally: + channel.close() node.stop() logging.shutdown() # Shutdown Logger diff --git a/openant/base/ant.py b/openant/base/ant.py index e6e204c..7c6fbea 100644 --- a/openant/base/ant.py +++ b/openant/base/ant.py @@ -302,8 +302,22 @@ def open_channel(self, channel): message = Message(Message.ID.OPEN_CHANNEL, [channel]) self.write_message(message) - def open_rx_scan_mode(self): - message = Message(Message.ID.OPEN_RX_SCAN_MODE, [0, 1]) # [0-Channel, 1-Enable] + def open_rx_scan_mode(self, channel=0): + """ + Enable RX scanning mode + + In scanning mode, the radio is active in receive mode 100% of the time + so no other channels but the scanning channel can run. The scanning + channel picks up any message regardless of period that is being + transmitted on its RF frequency and matches its channel ID mask. It can + receive from multiple devices simultaneously. + + A CLOSE_ALL_CHANNELS message from ANT will indicate an invalid attempt + to start the scanning mode while any channels are open. + + :param channel int: channel number to use (doesn't really matter) + """ + message = Message(Message.ID.OPEN_RX_SCAN_MODE, [channel, 1]) # [Channel, 1-Enable] self.write_message(message) def close_channel(self, channel): @@ -361,7 +375,7 @@ def request_message(self, channel, messageId): def send_broadcast_data(self, channel, data): assert len(data) == 8 - message = Message(Message.ID.BROADCAST_DATA, array.array("B", [channel]) + data) + message = Message(Message.ID.BROADCAST_DATA, array.array("B", [channel] + data)) self.write_message(message) def send_acknowledged_data(self, channel, data): diff --git a/openant/base/driver.py b/openant/base/driver.py index 4e9b21f..a2df3e1 100644 --- a/openant/base/driver.py +++ b/openant/base/driver.py @@ -333,7 +333,7 @@ def open(self): ) _logger.debug( - "UBS Endpoint out: %s, %s", self._out, self._out.bEndpointAddress + "USB Endpoint out: %s, %s", self._out, self._out.bEndpointAddress ) self._in = usb.util.find_descriptor( @@ -344,13 +344,16 @@ def open(self): ) _logger.debug( - "UBS Endpoint in: %s, %s", self._in, self._in.bEndpointAddress + "USB Endpoint in: %s, %s", self._in, self._in.bEndpointAddress ) assert self._out is not None and self._in is not None def close(self): usb.util.dispose_resources(self.dev) + if self.dev is not None: + self.dev.attach_kernel_driver(0) + _logger.debug("usbdriver.closed") pass def read(self):