class Node: def __init__(self): self._responses_cond = threading.Condition() self._responses = collections.deque() self._event_cond = threading.Condition() self._events = collections.deque() self._datas = queue.Queue() self.channels = {} self.ant = Ant() self._running = True self._worker_thread = threading.Thread(target=self._worker, name="ant.easy") self._worker_thread.start() def new_channel(self, ctype, network_number=0x00, ext_assign=None): size = len(self.channels) channel = Channel(size, self, self.ant) self.channels[size] = channel channel._assign(ctype, network_number, ext_assign) return channel def delete_channel(self): if len(self.channels) > 0: c = self.channels.pop(len(self.channels)-1) self.ant.unassign_channel(c.id) c.get_channel_status() del c def request_message(self, messageId): _logger.debug("requesting message %#02x", messageId) self.ant.request_message(0, messageId) _logger.debug("done requesting message %#02x", messageId) return self.wait_for_special(messageId) def set_network_key(self, network, key): self.ant.set_network_key(network, key) return self.wait_for_response(Message.ID.SET_NETWORK_KEY) def set_lib_config(self, value): # 0: Disabled # 0x20: Enables Rx Timestamp Output # 0x40: Enables RSSI Output # 0x80: Enables Channel ID Output self.ant.set_lib_config(value) return self.wait_for_response(Message.ID.LIB_CONFIG) def set_tx_power(self, value): # 0: low, 1...2, 3: High(0dBm), (4: N/A or High(4dbm)) self.ant.set_tx_power(value) return self.wait_for_response(Message.ID.SET_TRANSMIT_POWER) def wait_for_event(self, ok_codes): return wait_for_event(ok_codes, self._events, self._event_cond) def wait_for_response(self, event_id): return wait_for_response(event_id, self._responses, self._responses_cond) def wait_for_special(self, event_id): return wait_for_special(event_id, self._responses, self._responses_cond) def _worker_response(self, channel, event, data): self._responses_cond.acquire() self._responses.append((channel, event, data)) self._responses_cond.notify() self._responses_cond.release() def _worker_event(self, channel, event, data): if event == Message.Code.EVENT_RX_BURST_PACKET: self._datas.put(("burst", channel, data)) elif event == Message.Code.EVENT_RX_BROADCAST: self._datas.put(("broadcast", channel, data)) elif event == Message.Code.EVENT_TX: self._datas.put(("broadcast_tx", channel, data)) elif event == Message.Code.EVENT_RX_ACKNOWLEDGED: self._datas.put(("acknowledge", channel, data)) else: self._event_cond.acquire() self._events.append((channel, event, data)) self._event_cond.notify() self._event_cond.release() def _worker(self): self.ant.response_function = self._worker_response self.ant.channel_event_function = self._worker_event # TODO: check capabilities self.ant.start() def _main(self): while self._running: try: (data_type, channel, data) = self._datas.get(True, 1.0) self._datas.task_done() if data_type == "broadcast": self.channels[channel].on_broadcast_data(data) elif data_type == "burst": self.channels[channel].on_burst_data(data) elif data_type == "broadcast_tx": self.channels[channel].on_broadcast_tx_data(data) elif data_type == "acknowledge": self.channels[channel].on_acknowledge_data(data) else: _logger.warning("Unknown data type '%s': %r", data_type, data) except queue.Empty as e: pass def start(self): self._main() def stop(self): if self._running: _logger.debug("Stoping ant.easy") self._running = False self.ant.stop() self._worker_thread.join()