33 from .packet
import SUPPORTED_PROTOCOL_VERSION
34 from .packet
import PacketType
35 from .packet
import PacketDecoder
36 from .packet
import PacketFormater
38 from .uart_interface
import UartInterface
39 from .chsensors
import *
41 from .constants
import SPEED_OF_SOUND
46 if sys.version_info >= (3, 0):
48 get_tick = time.monotonic
60 return samples * 1e6 / fop
63 return int(round(t_us / 1e6 * fop))
66 return samples / fop * SPEED_OF_SOUND * 100.0
69 def __init__(self, do_process, poll_interval=30.0):
70 super(PollerThread, self).
__init__(name=
"_DeviceControlPollerThread")
76 while self.exit_flag.is_set()
is False:
89 Public interface for controlling the device. 90 Handlers can be set to process the data from the board. 95 Subclass it to catch event and from the device. 98 def ch_data_handler(self, rx_sensor_id, tx_sensor_id, timestamp, idata, qdata, target_detected, range_cm, amplitude):
119 def __init__(self, vid_pid=None, com_port='', baudrate=1000000, event_handler=EventHandler()):
129 PacketType.ASYNC_CH_DATA: functools.partial(self.
_user_event_handler, event_handler.ch_data_handler),
130 PacketType.ASYNC_PD_OUT: functools.partial(self.
_user_event_handler, event_handler.pd_data_handler),
131 PacketType.ASYNC_IMU_DATA: functools.partial(self.
_user_event_handler, event_handler.imu_data_handler),
132 PacketType.ASYNC_GRV_DATA: functools.partial(self.
_user_event_handler, event_handler.grv_data_handler),
133 PacketType.ASYNC_STATUS: functools.partial(self.
_user_event_handler, event_handler.status_handler),
134 PacketType.ASYNC_DEBUG_MESSAGE: functools.partial(self.
_user_event_handler, event_handler.device_msg_handler),
135 PacketType.RESP_ENABLE_IQSTREAM: functools.partial(self.
_resp_handler, PacketType.RESP_ENABLE_IQSTREAM),
136 PacketType.RESP_ENABLE_PDALGO: functools.partial(self.
_resp_handler, PacketType.RESP_ENABLE_PDALGO),
137 PacketType.RESP_ENABLE_IMU: functools.partial(self.
_resp_handler, PacketType.RESP_ENABLE_IMU),
138 PacketType.RESP_ENABLE_ASIC_DATA: functools.partial(self.
_resp_handler, PacketType.RESP_ENABLE_ASIC_DATA),
139 PacketType.RESP_GET_ALGO_CONFIG: functools.partial(self.
_resp_handler, PacketType.RESP_GET_ALGO_CONFIG),
140 PacketType.RESP_GET_PROTOCOL_VERSION: functools.partial(self.
_resp_handler, PacketType.RESP_GET_PROTOCOL_VERSION),
141 PacketType.RESP_GET_SENSOR_PARAM: functools.partial(self.
_resp_handler, PacketType.RESP_GET_SENSOR_PARAM),
142 PacketType.RESP_GET_SENSORS: functools.partial(self.
_resp_handler, PacketType.RESP_GET_SENSORS),
143 PacketType.RESP_GET_VERSION: functools.partial(self.
_resp_handler, PacketType.RESP_GET_VERSION),
144 PacketType.RESP_GET_STATUS: functools.partial(self.
_resp_handler, PacketType.RESP_GET_STATUS),
145 PacketType.RESP_SOFT_RESET: functools.partial(self.
_resp_handler, PacketType.RESP_SOFT_RESET),
146 PacketType.RESP_RESET_PDALGO: functools.partial(self.
_resp_handler, PacketType.RESP_RESET_PDALGO),
147 PacketType.RESP_RESET_SENSOR: functools.partial(self.
_resp_handler, PacketType.RESP_RESET_SENSOR),
148 PacketType.RESP_SET_ALGO_CONFIG: functools.partial(self.
_resp_handler, PacketType.RESP_SET_ALGO_CONFIG),
149 PacketType.RESP_SET_ODR: functools.partial(self.
_resp_handler, PacketType.RESP_SET_ODR),
150 PacketType.RESP_SET_RANGE_MM: functools.partial(self.
_resp_handler, PacketType.RESP_SET_RANGE_MM),
151 PacketType.RESP_SET_SAMPLE_RANGE: functools.partial(self.
_resp_handler, PacketType.RESP_SET_SAMPLE_RANGE),
152 PacketType.RESP_SET_PULSE_LENGTH: functools.partial(self.
_resp_handler, PacketType.RESP_SET_PULSE_LENGTH),
153 PacketType.RESP_SET_LOW_GAIN_RXLEN: functools.partial(self.
_resp_handler, PacketType.RESP_SET_LOW_GAIN_RXLEN),
154 PacketType.RESP_START: functools.partial(self.
_resp_handler, PacketType.RESP_START),
155 PacketType.RESP_STOP: functools.partial(self.
_resp_handler, PacketType.RESP_STOP),
176 except Exception
as e:
191 if resp[
'status'] != 0:
192 raise Exception(
"Failed to initialize the board after reset")
197 if resp_data[
'protocol_version'] != SUPPORTED_PROTOCOL_VERSION:
198 raise Exception(
"Protocol version missmatch (board supports version {}, expected version {})".format(
199 resp_data[
'protocol_version'], SUPPORTED_PROTOCOL_VERSION))
205 raise Exception(
'Failed to initialize the board, status=' + str(hex(status[0])))
226 return self.
_sync_bin_command(PacketType.CMD_GET_SENSOR_PARAM,
'B', args_tuple = (sensor_id,))
229 return self.
_sync_bin_command(PacketType.CMD_GET_ALGO_CONFIG,
"B", args_tuple = (sensor_id,))
232 resp = self.
_sync_bin_command(command=PacketType.CMD_SET_ALGO_CONFIG, code=
"I"*11, args_tuple=(int(algo_config[
'sensor_id']),
233 int(algo_config[
'odr_us']), int(algo_config[
'nb_samples']), int(algo_config[
'max_range']),
234 int(algo_config[
'min_range']), int(algo_config[
'op_freq_hz']), int(algo_config[
'sensitivity']),
235 int(algo_config[
'range_offset']), int(algo_config[
'range_nb_zones']),
236 int(algo_config[
'range_hysteresis']), int(algo_config[
'range_interval'])))
238 if resp[
'status'] != 0:
239 raise Exception(
"Failed to set algo config for sensor {}".format(algo_config[
'sensor_id']))
242 sensor_ids = self.
connected_sensors[
'sensor_ids']
if sensor_id
is None else list(sensor_id)
243 for sensor_id
in sensor_ids:
244 self.
_sync_bin_command(command=PacketType.CMD_SET_RANGE_MM, code=
"BI", args_tuple=(sensor_id, int(range_mm)))
247 algo_config[
'nb_samples'] = sensor_config[
'nb_samples']
251 sensor_ids = self.
connected_sensors[
'sensor_ids']
if sensor_id
is None else list(sensor_id)
252 for sensor_id
in sensor_ids:
253 self.
_sync_bin_command(command=PacketType.CMD_SET_SAMPLE_RANGE, code=
"BI", args_tuple=(sensor_id, int(nsamples)))
256 algo_config[
'nb_samples'] = sensor_config[
'nb_samples']
267 resp = self.
_sync_bin_command(PacketType.CMD_SET_ODR,
"BI", args_tuple=(sensor_id, int(odr_ms)))
268 if resp[
'status'] != 0:
269 raise Exception(
"Failed to set ODR for sensor {}".format(sensor_id))
271 algo_config[
'odr_us'] = 1000 * odr_ms
283 device_info[
'nb_sensors'] = connected_sensors[
'nb_sensors']
285 for sensor_id
in connected_sensors[
'sensor_ids']:
287 sensor_config[
'pulse_length_us'] = round(PulseConverter.samples2us(sensor_config[
'pulse_length'],
288 sensor_config[
'op_freq_hz']), 2)
289 device_info[
'sensors'][sensor_id] = {k: v
for k, v
in sensor_config.items()
if k !=
'sensor_id' }
291 if 'ch101fw' in device_info[
'versions']:
293 elif 'ch201fw' in device_info[
'versions']:
294 device_info[
'chsensor'] = Ch201Sensor()
296 device_info[
'chsensor'] =
ChSensor()
302 self.packet_decoder.reset()
306 self.worker_thread.start()
308 self.poller_thread.start()
313 self.poller_thread.stop()
314 self.poller_thread.join()
318 self.worker_queue.put(
None)
319 self.worker_queue.join()
323 self.worker_thread.join()
333 bcmd = PacketFormater.format_cmd_packet(command, code, *args_tuple)
335 return self.serial.write(bcmd)
338 expected_pkt = command | 0x80
343 self.response_event.clear()
346 if not self.response_event.wait(timeout):
347 raise Exception(
"Timeout after sending command 0x{:02x}".format(command))
349 raise Exception(
"Unexpected response. Receive 0x{:02x} instead of 0x{:02x}".format(expected_pkt, self.
response_pkt))
350 except Exception
as e:
360 self.serial.set_mode_nonblocking()
361 payload = self.serial.read(4096)
364 except Exception
as e:
369 handler = self.event_handlers.get(pkt_id,
None)
374 if not self.init_done_event.is_set():
376 self.init_done_event.set()
379 if not self.response_event.is_set():
380 if event_id >= 0x81
and event_id < 0xe0:
383 self.response_event.set()
386 self.worker_queue.put((user_event_cb, event_data, ))
391 item = self.worker_queue.get()
397 except Exception
as e:
399 self.worker_queue.task_done()
def checkProtocolVersion(self)
def pd_data_handler(self, sensor_id, timestamp, presence, rmin, rmax, score)
def _user_event_worker(self)
def setSRange(self, nsamples, sensor_id=None)
def disableAsicData(self)
def grv_data_handler(self, timestamp, grv_w, grv_x, grv_y, grv_z)
def imu_data_handler(self, timestamp, acc_x, acc_y, acc_z, gyr_x, gyr_y, gyr_z)
def status_handler(self, timestamp, status, error_count)
def _user_event_handler(self, user_event_cb, event_data)
def samples2cm(samples, fop)
def us2samples(t_us, fop)
def device_msg_handler(self, s)
def _init_done_handler(self, event_data)
def startDeviceProcessing(self)
def samples2us(samples, fop)
def __init__(self, do_process, poll_interval=30.0)
def setRange(self, range_mm, sensor_id=None)
def __init__(self, vid_pid=None, com_port='', baudrate=1000000, event_handler=EventHandler())
def setAlgoConfig(self, algo_config)
def exception_handler(self, exception)
def _sync_bin_command(self, command, code="", timeout=2, nb_retry=0, args_tuple=())
def _send_bin_command(self, command, code="", args_tuple=())
def disableIQStream(self)
def _read_from_serial(self)
def ch_data_handler(self, rx_sensor_id, tx_sensor_id, timestamp, idata, qdata, target_detected, range_cm, amplitude)
def getSensorConfig(self, sensor_id)
def stopDeviceProcessing(self)
def _pkt_handler(self, pkt_id, pkt_data)
def _resp_handler(self, event_id, event_data)
def getAlgoConfig(self, sensor_id)