diff --git a/LogAndStream/python_scripts/Bluetooth commands/SpeedTest/speedTest.py b/LogAndStream/python_scripts/Bluetooth commands/SpeedTest/speedTest.py new file mode 100644 index 0000000..c897857 --- /dev/null +++ b/LogAndStream/python_scripts/Bluetooth commands/SpeedTest/speedTest.py @@ -0,0 +1,138 @@ +#!/usr/bin/python +import binascii +import serial +import struct +import sys +import time + +from multiprocessing import Process + +import speedTestPlot as plot +import speedTestBle as ble + +from pc_ble_driver_py.observers import * +import logging + +global ser + +sleep_interval = 0.05 +framesize = 4 # 32-bit counter value +ddata = b"" + +time_s_overall_start = 0 +time_s_current_window_start = 0 +num_bytes_total = 0 +data_integrity_counter = 0 + + +def wait_for_ack(): + global ser + ddata = "" + ack = struct.pack('B', 0xff) + while ddata != ack: + ddata = ser.read(1) + if ddata != ack: + print("0x%02x" % int(ddata[0])) + print("ACK Received") + return + + +def bt_classic_parser(com_port, q, sample_index): + global ser, num_bytes_total, time_s_overall_start, time_s_current_window_start, ddata, data_integrity_counter + + ser = serial.Serial(com_port, 1000000) + ser.flushInput() + logger.info("port opening, done.") + + initialise_speed_test_vars() + + ser.write(struct.pack('BB', 0xA4, 1)) + wait_for_ack() + + while 1: + time_s_current = time.time_ns() / 1000000000 + + buf_len = ser.inWaiting() + if buf_len > 0: + ddata = ddata + ser.read(buf_len) + + process_new_data(q, time_s_current) + + time.sleep(sleep_interval) + + +def initialise_speed_test_vars(): + global num_bytes_total, time_s_overall_start, time_s_current_window_start, data_integrity_counter + time_s_overall_start = time.time_ns() / 1000000000 + time_s_current_window_start = time_s_overall_start + num_bytes_total = 0 + data_integrity_counter = 0 + + +def process_new_data(q, time_s_current): + global num_bytes_total, time_s_overall_start, time_s_current_window_start, ddata, data_integrity_counter + + counter_values = [] + end_index = 0 + data_integrity = [] + data_integrity_issue_flag = False + + if len(ddata) >= framesize: + + num_counter_values = len(ddata) // framesize + + fmt = '<' + ('I' * num_counter_values) + end_index = num_counter_values * framesize + num_bytes_total += end_index + + counter_values = struct.unpack(fmt, ddata[0:end_index]) + + for sample in counter_values: + data_integrity_issue_flag = True if data_integrity_counter == sample else False + data_integrity_counter = sample + 1 + data_integrity.append(data_integrity_issue_flag) + + if data_integrity_counter == 2 ** (framesize * 8): + data_integrity_counter = 0 + + if len(ddata) > end_index: + ddata = ddata[end_index:] + + data_rate_current = 0 if end_index == 0 else (end_index / 1024) / (time_s_current - time_s_current_window_start) + data_rate_overall = (num_bytes_total / 1024) / (time_s_current - time_s_overall_start) + + plot.plot_data(q, time_s_current_window_start, time_s_current, counter_values, data_rate_current, data_rate_overall, data_integrity) + + time_s_current_window_start = time_s_current + + sys.stdout.write("\rData Rate: Current = %i KB/s, Overall = %i KB/s, Data integrity = %s" % (data_rate_current, data_rate_overall, "OK" if data_integrity_issue_flag else "Bad")) + sys.stdout.flush() + + +if __name__ == '__main__': + if len(sys.argv) < 2: + print("no device specified") + print("You need to specify the serial port of the device you wish to connect to") + print("example:") + print(" *.py Com12") + print("or") + print(" *.py /dev/rfcomm0") + else: + plot.setup_plots() + + # ble.setup() + + # COM15 = A615 + # COM3 = D1E8 + # COM24 = Shimmer3r 32FD + # COM7 = Shimmer3r 29FD + + p = Process(target=bt_classic_parser, args=(sys.argv[1], plot.q, plot.sample_index)) + p.start() + + plot.start_thread() + + # p.terminate() + # p.join() + + print("All done") diff --git a/LogAndStream/python_scripts/Bluetooth commands/SpeedTest/speedTestBle.py b/LogAndStream/python_scripts/Bluetooth commands/SpeedTest/speedTestBle.py new file mode 100644 index 0000000..8c015d2 --- /dev/null +++ b/LogAndStream/python_scripts/Bluetooth commands/SpeedTest/speedTestBle.py @@ -0,0 +1,480 @@ + +import time +from pc_ble_driver_py.observers import * +from queue import * +from threading import Thread +import logging + +CONNECTIONS = 1 +CFG_TAG = 1 + +# Select DEBUG_BLE_MESSAGES = True to output out all BLE configuration steps to Console/Logger file +DEBUG_BLE_MESSAGES = True + +TARGET_MAC_ID = "A615" + +logging.basicConfig(level=logging.INFO, + format='%(asctime)-12s %(message)s', + datefmt='%m-%d %H:%M', + # filename=logger_path, + filemode='w') + +logger = logging.getLogger('root') + + +def init(conn_ic_id): + # noinspection PyGlobalUndefined + global config, BLEDriver, BLEAdvData, BLEEvtID, BLEAdapter, BLEEnableParams, BLEGapTimeoutSrc, BLEUUID, BLEUUIDBase, BLEConfigCommon, BLEConfig, BLEConfigConnGatt, BLEGapScanParams, BLEConfigConnGap, BLEGapConnParams, BLEGapIOCaps, BLEGapSecStatus, driver, util + from pc_ble_driver_py import config + + config.__conn_ic_id__ = conn_ic_id + # noinspection PyUnresolvedReferences + from pc_ble_driver_py.ble_driver import ( + BLEDriver, + BLEAdvData, + BLEEvtID, + BLEEnableParams, + BLEGapTimeoutSrc, + BLEUUID, + BLEUUIDBase, + BLEGapScanParams, + BLEGapConnParams, + BLEConfigCommon, + BLEConfig, + BLEConfigConnGatt, + BLEConfigConnGap, + + # Added by Shimmer + # BLEGapSecParams, + BLEGapIOCaps, + # BLEGapSecKDist, + # BLEGapRoles, + BLEGapSecStatus, + # BLEGapSecKeyset + + driver, + util, + ) + + # noinspection PyUnresolvedReferences + from pc_ble_driver_py.ble_adapter import BLEAdapter + + global nrf_sd_ble_api_ver + nrf_sd_ble_api_ver = config.sd_api_ver_get() + + # import pc_ble_driver_py.ble_driver_types as util + + +class NUSParser(BLEDriverObserver, BLEAdapterObserver): + def __init__(self, adapter): + super(NUSParser, self).__init__() + self.adapter = adapter + self.conn_q = Queue() + self.adapter.observer_register(self) + self.adapter.driver.observer_register(self) + self.adapter.default_mtu = 247 + + # # UUID associated with the Nordic UART Service + # self.nus_base = BLEUUIDBase([0x6E, 0x40, 0x00, 0x00, 0xB5, 0xA3, 0xF3, 0x93, 0xE0, 0xA9, 0xE5, 0x0E, 0x24, 0xDC, 0xCA, 0x9E]) + # self.nus_rx = BLEUUID(0x0002, self.nus_base) + # self.nus_tx = BLEUUID(0x0003, self.nus_base) + + # UUID associated with the Roving Networks UART Service + # 49535341 6DAA 4D02 ABF6 19569ACA69FE + self.nus_base = BLEUUIDBase([0x49, 0x53, 0x53, 0x43, 0xFE, 0x7D, 0x4A, 0xE5, 0x8F, 0xA9, 0x9F, 0xAF, 0xD2, 0x05, 0xE4, 0x55]) + # self.nus_rx = BLEUUID([0x49, 0x53, 0x53, 0x43, 0x1E, 0x4D, 0x4B, 0xD9, 0xBA, 0x61, 0x23, 0xC6, 0x47, 0x24, 0x96, 0x16], self.nus_base) + # self.nus_tx = BLEUUID([0x49, 0x53, 0x53, 0x43, 0x88, 0x41, 0x43, 0xF4, 0xA8, 0xD4, 0xEC, 0xBE, 0x34, 0x72, 0x9B, 0xB3], self.nus_base) + self.nus_rx = BLEUUID(0x9616, self.nus_base) + self.nus_tx = BLEUUID(0x9BB3, self.nus_base) + + def open(self): + self.adapter.driver.open() + if config.__conn_ic_id__ == "NRF51": + self.adapter.driver.ble_enable( + BLEEnableParams( + vs_uuid_count=1, + service_changed=0, + periph_conn_count=0, + central_conn_count=CONNECTIONS, + central_sec_count=0, + ) + ) + elif config.__conn_ic_id__ == "NRF52": + gatt_cfg = BLEConfigConnGatt() + gatt_cfg.att_mtu = self.adapter.default_mtu + gatt_cfg.tag = CFG_TAG + self.adapter.driver.ble_cfg_set(BLEConfig.conn_gatt, gatt_cfg) + + conn_cfg = BLEConfigConnGap() + conn_cfg.conn_count = CONNECTIONS + conn_cfg.event_length = 320 + self.adapter.driver.ble_cfg_set(BLEConfig.conn_gap, conn_cfg) + + self.adapter.driver.ble_enable() + self.adapter.driver.ble_vs_uuid_add(self.nus_base) + + def close(self): + self.adapter.driver.close() + + def connect_and_discover(self): + scan_duration = 1100 + scan_params = BLEGapScanParams(interval_ms=200, window_ms=150, timeout_s=scan_duration) + new_conn = None + + # i = 0 + # while 1: + # if i > 0: + # logger.info("\nPasskey rejected: Beginning Connection Retry no. {}" .format(i)) + # try: + # self.adapter.disconnect(new_conn) + # self.adapter.evt_sync[new_conn].wait(evt=BLEEvtID.gap_evt_disconnected) + # except: + # logger.info("\nException disconnecting") + # time.sleep(1) + # + # try: + # # Scan and connect + # self.adapter.driver.ble_gap_scan_start(scan_params) + # new_conn = self.conn_q.get(timeout=scan_duration) + # + # # Authenticate if requested to + # ASM_Device.passkey_enabled = False + # auth_success = False + # # Wait for security request. Note, this adds an unnecessary delay when connecting to sensors that don't have passkey set. + # result = self.adapter.evt_sync[new_conn].wait(evt=BLEEvtID.gap_evt_sec_request) + # if result is not None and 'bond' in result and result['bond'] == 1: + # ASM_Device.passkey_enabled = True + # + # Thread( + # target=self.adapter.authenticate, + # args=(new_conn, None), + # kwargs={"bond": True, "mitm": True, "io_caps": BLEGapIOCaps.keyboard_only}, + # ).start() + # + # result = self.adapter.evt_sync[new_conn].wait(evt=BLEEvtID.gap_evt_auth_status) + # + # auth_success = result is not None and "auth_status" in result and result["auth_status"] == BLEGapSecStatus.success + # + # # If passkey not set or authorisation has been successful, perform service discovery + # if not ASM_Device.passkey_enabled or auth_success: + # # Update PHY to 2MBPS + # req_phys = [driver.BLE_GAP_PHY_2MBPS, driver.BLE_GAP_PHY_2MBPS] + # logging.info(f"Central requesting: req_phys={req_phys}") + # resp = self.adapter.phy_update(new_conn, req_phys) + # result = self.adapter.evt_sync[new_conn].wait(evt=BLEEvtID.gap_evt_data_length_update) + # + # self.adapter.service_discovery(new_conn) + # if DEBUG_BLE_MESSAGES: + # logger.info('Service Discovery:') + # for s in self.adapter.db_conns[new_conn].services: + # logger.info('\t{}'.format(s)) + # for ch in s.chars: + # logger.info('\t\t{}'.format(ch)) + # + # # Nordic UART Service (NUS) + # self.adapter.enable_notification(conn_handle=new_conn, uuid=self.nus_tx) + # + # break + # except: + # logger.info("\nException connecting") + # + # i += 1 + + self.adapter.driver.ble_gap_scan_start(scan_params) + new_conn = self.conn_q.get(timeout=scan_duration) + + # Update PHY to 2MBPS + req_phys = [driver.BLE_GAP_PHY_2MBPS, driver.BLE_GAP_PHY_2MBPS] + logging.info(f"Central requesting: req_phys={req_phys}") + resp = self.adapter.phy_update(new_conn, req_phys) + result = self.adapter.evt_sync[new_conn].wait(evt=BLEEvtID.gap_evt_data_length_update) + + self.adapter.service_discovery(new_conn) + if DEBUG_BLE_MESSAGES: + logger.info('Service Discovery:') + for s in self.adapter.db_conns[new_conn].services: + logger.info('\t{}'.format(s)) + for ch in s.chars: + logger.info('\t\t{}'.format(ch)) + + # UART Service + self.adapter.enable_notification(conn_handle=new_conn, uuid=self.nus_tx) + + return new_conn + + def scan_and_check(self): + # This function is used in ASM_PendingEventsTest.py to perform a scan to confirm that the BLE has successfully + # Turned off once the Python has disconnected from the device. + self.adapter.driver.ble_gap_scan_start() + new_conn = None + try: + new_conn = self.conn_q.get(timeout=30) + return new_conn + except Empty: + self.close() + time.sleep(3) + return new_conn + + def on_gap_evt_connected(self, ble_driver, conn_handle, peer_addr, role, conn_params): + if DEBUG_BLE_MESSAGES: + logger.info('GAP_EVT->\tConnected: {}, {}'.format(conn_handle, conn_params)) + self.conn_q.put(conn_handle) + + def on_gap_evt_disconnected(self, ble_driver, conn_handle, reason): + if DEBUG_BLE_MESSAGES: + logger.info('GAP_EVT->\tDisconnected: {} {}'.format(conn_handle, reason)) + + def on_gap_evt_timeout(self, ble_driver, conn_handle, src): + if src == BLEGapTimeoutSrc.scan: + ble_driver.ble_gap_scan_start() + + def on_gap_evt_adv_report(self, ble_driver, conn_handle, peer_addr, rssi, adv_type, adv_data): + conn_params = BLEGapConnParams(min_conn_interval_ms=7.5, max_conn_interval_ms=7.5, conn_sup_timeout_ms=4000, slave_latency=0) + + dev_name_list = None + if BLEAdvData.Types.complete_local_name in adv_data.records: + dev_name_list = adv_data.records[BLEAdvData.Types.complete_local_name] + elif BLEAdvData.Types.short_local_name in adv_data.records: + dev_name_list = adv_data.records[BLEAdvData.Types.short_local_name] + else: + return + + dev_name = "".join(chr(e) for e in dev_name_list) + address_string = "".join("{0:02X}".format(b) for b in peer_addr.addr) + if DEBUG_BLE_MESSAGES: + logger.info('Received advertisement report, address: 0x{}, device_name: {}'.format(address_string, dev_name)) + + if address_string.endswith(TARGET_MAC_ID): + self.adapter.connect(address=peer_addr, conn_params=conn_params, tag=CFG_TAG) + + def on_gap_evt_phy_update(self, ble_driver, conn_handle, status, tx_phy, rx_phy): + phy_update = {"status": status, "tx_phy": tx_phy, "rx_phy": rx_phy} + + def on_notification(self, ble_adapter, conn_handle, uuid, data): + + # global IS_STREAMING_DATA + # + # # check if time diff from last received packet is too large, if so, clear the buf + # ts_ms = time.time() * 1000 + # if not self.asm_message_buffer.is_blank(): + # if (ts_ms - self.asm_message_buffer.previous_transfer_ts_ms) > Timeout_ms.BETWEEN_PACKETS: + # logger.info('Time diff too large from previous message, starting new message') + # self.asm_message_buffer = AsmMessage() + # + # self.asm_message_buffer.add_packet(data, ts_ms) + # + # if self.asm_message_buffer.is_payload_header_parsed and len(self.asm_message_buffer.payload) > self.asm_message_buffer.payload_length: + # logger.info('WARNING, Too many bytes received - resetting buffer') + # self.asm_message_buffer = AsmMessage() + # elif self.asm_message_buffer.is_full(): + # ASM_Device.latest_transfer_speed = self.asm_message_buffer.calculate_overall_transfer_time() + # self.asm_message_latest = self.asm_message_buffer + # self.asm_message_buffer = AsmMessage() + # if IS_STREAMING_DATA: + # Shimmer_Plotting.process_data(self.asm_message_latest.payload) + + logger.info('RX') + + def on_att_mtu_exchanged(self, ble_driver, conn_handle, att_mtu): + if DEBUG_BLE_MESSAGES: + logger.info('ATT MTU exchanged: conn_handle={} att_mtu={}'.format(conn_handle, att_mtu)) + + def on_gattc_evt_exchange_mtu_rsp(self, ble_driver, conn_handle, status, att_mtu): + if DEBUG_BLE_MESSAGES: + print("ATT MTU updated to {}".format(att_mtu)) + + def on_gap_evt_data_length_update(self, ble_driver, conn_handle, data_length_params): + if DEBUG_BLE_MESSAGES: + print("Max rx octets: {}".format(data_length_params.max_rx_octets)) + print("Max tx octets: {}".format(data_length_params.max_tx_octets)) + print("Max rx time: {}".format(data_length_params.max_rx_time_us)) + print("Max tx time: {}".format(data_length_params.max_tx_time_us)) + + def on_gatts_evt_exchange_mtu_request(self, ble_driver, conn_handle, client_mtu): + print("Client requesting to update ATT MTU to {} bytes".format(client_mtu)) + + def on_gap_evt_sec_params_request(self, ble_driver, conn_handle, peer_params): + if DEBUG_BLE_MESSAGES: + logger.info('GAP_EVT->\ton_gap_evt_sec_params_request: conn_handle={} peer_params={}'.format(conn_handle, peer_params)) + + def on_gap_evt_sec_info_request(self, ble_driver, conn_handle, peer_addr, master_id, enc_info, id_info, sign_info): + if DEBUG_BLE_MESSAGES: + logger.info('GAP_EVT->\ton_gap_evt_sec_info_request') + + def on_gap_evt_sec_request(self, ble_driver, conn_handle, bond, mitm, lesc, keypress): + if DEBUG_BLE_MESSAGES: + logger.info( + 'GAP_EVT->\ton_gap_evt_sec_request: conn_handle={} bond={} mitm={} lesc={} keypress={}'.format(conn_handle, bond, + mitm, + lesc, keypress)) + + def on_gap_evt_auth_status(self, ble_driver, conn_handle, error_src, bonded, sm1_levels, sm2_levels, kdist_own, + kdist_peer, auth_status): + if DEBUG_BLE_MESSAGES: + logger.info('GAP_EVT->\ton_gap_evt_auth_status={}'.format(auth_status)) + + def on_gap_evt_auth_key_request(self, ble_driver, conn_handle, **kwargs): + logger.info('GAP_EVT->\ton_gap_evt_auth_key_request.') + + # pk = util.list_to_uint8_array(ASM_Device.generatePasskey()) + # + # driver.sd_ble_gap_auth_key_reply( + # ble_driver.rpc_adapter, + # conn_handle, + # kwargs["key_type"], + # pk.cast(), + # ) + + # # Based on a combination of ble_adapter.py -> authenticate and https://devzone.nordicsemi.com/f/nordic-q-a/42974/bonding-with-pc-ble-driver-py + # def authenticate_asm(self, conn_handle): + # logger.info('Pairing started') + # + # kdist_own = BLEGapSecKDist(enc=1, + # id=1, + # sign=0, + # link=0) + # kdist_peer = BLEGapSecKDist(enc=1, + # id=1, + # sign=0, + # link=0) + # sec_params = BLEGapSecParams(bond=True, + # mitm=False, + # lesc=False, + # keypress=False, + # io_caps=BLEGapIOCaps.keyboard_only, + # oob=False, + # min_key_size=7, + # max_key_size=16, + # kdist_own=kdist_own, + # kdist_peer=kdist_peer) + # + # self.adapter.driver.ble_gap_authenticate(conn_handle, sec_params) + # self.adapter.evt_sync[conn_handle].wait(evt=BLEEvtID.gap_evt_sec_params_request) + # + # # sd_ble_gap_sec_params_reply ... In the central role, sec_params must be set to NULL, + # # as the parameters have already been provided during a previous call to + # # sd_ble_gap_authenticate. + # sec_params = None if self.adapter.db_conns[conn_handle].role == BLEGapRoles.central else sec_params + # self.adapter.driver.ble_gap_sec_params_reply(conn_handle, BLEGapSecStatus.success, sec_params=sec_params) + # if DEBUG_BLE_MESSAGES: + # logger.info("\tSec params replying done") + # + # # Send passcode + # self.adapter.evt_sync[conn_handle].wait(evt=BLEEvtID.gap_evt_auth_key_request) + # + # # key = util.list_to_uint8_array([0x39, 0x31, 0x34, 0x30, 0x32, 0x30]).cast() + # key = util.list_to_uint8_array(ASM_Device.generatePasskey()).cast() + # # BLE_GAP_AUTH_KEY_TYPE_PASSKEY = 0x01 + # res = self.adapter.driver.sd_ble_gap_auth_key_reply(conn_handle, 0x01, key) + # if DEBUG_BLE_MESSAGES: + # logger.info("\tKey reply finished with code: {}".format(res)) + # + # # Get pairing results and save key + # result = self.adapter.evt_sync[conn_handle].wait(evt=BLEEvtID.gap_evt_auth_status) + # + # if DEBUG_BLE_MESSAGES: + # logger.info("\tPairing Errors: {}".format(result['error_src'])) + # if result['auth_status'] == BLEGapSecStatus.success: + # if DEBUG_BLE_MESSAGES: + # logger.info("\tSuccess") + # self.adapter.db_conns[conn_handle]._keyset = BLEGapSecKeyset.from_c(self.adapter.driver._keyset) + # + # logger.info("Pairing finished") + # + # # result = self.evt_sync[conn_handle].wait(evt = BLEEvtID.gap_evt_auth_status) + # # # If success then keys are stored in self.driver._keyset. + # # if result['auth_status'] == BLEGapSecStatus.success: + # # self.db_conns[conn_handle]._keyset = BLEGapSecKeyset.from_c(self.driver._keyset) + # return result['auth_status'] + + # MN not working + def on_gap_evt_conn_param_update_request(self, conn_handle, conn_params): + if DEBUG_BLE_MESSAGES: + logger.info('on_gap_evt_conn_param_update_request={}'.format(conn_params)) + + # MN not working + def on_gap_evt_conn_param_update(self, conn_handle, conn_params): + if DEBUG_BLE_MESSAGES: + logger.info('EVT\ton_gap_evt_conn_param_update={}'.format(conn_params)) + + def write_req(self, conn_handle, data): + self.adapter.write_req(conn_handle=conn_handle, uuid=self.nus_rx, data=data) + + +class ASMCommands: + + def __init__(self, collector): + self.collector = collector + + def speed_test_start(self, new_conn): + logger.info('Command: Reading Status') + + data = bytearray([0xA4, 0x01]) + self.send_command(new_conn, data) + # self.wait_for_ack(1000) + + # self.send_command_simple(new_conn, AsmCommand.READ | asm_property) + # response = self.wait_for_response_and_check(asm_property, Timeout_ms.STANDARD) + # if isinstance(response, bool): + # logger.info("FAIL: read_status") + # return False + # else: + # ASM_Device.parse_status(response, asm_property) + # logger.info(space_string) + # return True + + def wait_for_response(self, property, timeout_ms): + loop_count = 0 + wait_interval_ms = 100 + loop_count_total = timeout_ms / wait_interval_ms + + while True: + time.sleep(wait_interval_ms / 1000.0) + loop_count += 1 + if loop_count >= loop_count_total: + return False + # if SEND_NACK_ON_CHUNKS : + # if len(self.collector.asm_message_buffer.payload) > send_nack_on: + # return len(self.collector.asm_message_buffer.payload) + # if self.collector.asm_message_latest.is_full(): + # if DEBUG_BLE_TXRX_PACKETS: + # logger.info('Complete Response Received') + # return self.collector.asm_message_latest + # # only need for the data tranmission at the moment but could be need for other reads with a large number of bytes being returned + # elif self.collector.asm_message_buffer.property == AsmProperty.DATA: + # # check for 'is alive' to make sure packets are coming in before considering a timeout on the overall transmission + # ts_ms = time.time() * 1000 + # ts_diff_last_msg_ms = ts_ms - self.collector.asm_message_buffer.previous_transfer_ts_ms + # # if the timeout is greater then the standard timeout, we'll check to see if individual packets are coming. + # if (timeout_ms > Timeout_ms.STANDARD) \ + # and ((loop_count * wait_interval_ms) > Timeout_ms.STANDARD) \ + # and ((self.collector.asm_message_buffer.previous_transfer_ts_ms == 0) or ( + # ts_diff_last_msg_ms > Timeout_ms.STANDARD)): + # logger.info('FAIL: Device is possibly not responding') + # return False + + def wait_for_ack(self, timeout_ms): + response = self.wait_for_response_and_check(None, timeout_ms) + if isinstance(response, bool): + if response: + logger.info("ACK - End of transmission") + else: + logger.info("FAIL: No ACK received") + return response + + +def setup(): + init("NRF52") + serial_port = "COM45" + + driver = BLEDriver(serial_port=serial_port, auto_flash=True) + adapter = BLEAdapter(driver) + collector = NUSParser(adapter) + + collector.open() + commands = ASMCommands(collector) + + for i in range(CONNECTIONS): + conn_handle = collector.connect_and_discover() + + # collector.close() diff --git a/LogAndStream/python_scripts/Bluetooth commands/SpeedTest/speedTestPlot.py b/LogAndStream/python_scripts/Bluetooth commands/SpeedTest/speedTestPlot.py new file mode 100644 index 0000000..f88a789 --- /dev/null +++ b/LogAndStream/python_scripts/Bluetooth commands/SpeedTest/speedTestPlot.py @@ -0,0 +1,285 @@ +#!/usr/bin/python +import multiprocessing +import numpy as np +import matplotlib.pyplot as plt +import matplotlib +from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk +from tkinter import * + +matplotlib.use('TkAgg') + +global fig, ax1, axes_dict, q, canvas, window +sample_index = {} + +tsChString = "Timestamp" +samples_to_plot = 1000 + +class ChannelDetails: + def __init__(self, name): + self.name = name + +class ChannelIds: + COUNTER = ChannelDetails("Counter") + DATA_RATE_CURRENT = ChannelDetails("Data Rate Current") + DATA_RATE_OVERALL = ChannelDetails("Data Rate Overall") + DATA_INTEGRITY = ChannelDetails("Data Integrity") + +class SensorObj: + def __init__(self, channels, title, units): + self.channels = channels + self.title = title + self.units = units + +class Sensors: + COUNTER = SensorObj({ChannelIds.COUNTER}, "Counter", "none") + DATA_RATE = SensorObj({ChannelIds.DATA_RATE_CURRENT, ChannelIds.DATA_RATE_OVERALL}, "Data Rate", "KB/s") + DATA_INTEGRITY = SensorObj({ChannelIds.DATA_INTEGRITY}, "Data Integrity", "boolean") + + +def setup_plots(): + global canvas, axes_dict, q, fig, window, sample_index + + sample_index.clear() + sample_index[Sensors.COUNTER.title] = 1 + sample_index[Sensors.DATA_RATE.title] = 1 + sample_index[Sensors.DATA_INTEGRITY.title] = 1 + + # Create a window + window = Tk() + window.protocol("WM_DELETE_WINDOW", on_closing) + + axes_dict = {} + + fig = plt.figure(figsize=(12, 8)) + canvas = FigureCanvasTkAgg(fig, master=window) + canvas.draw() + canvas.get_tk_widget().pack(side=TOP, fill=BOTH, expand=1) + canvas._tkcanvas.pack(side=TOP, fill=BOTH, expand=1) + + # plt.ion() + + # Create a queue to share data between process + q = multiprocessing.Queue() + + + # fig = plt.figure(figsize=(12, 8)) + # Adjust the left margin of the Plot Window to Allow Room for Labels + fig.subplots_adjust(left=0.18) + + # plt.title('Live Stream from Device {}'.format(asm_device.TARGET_MAC_ID)) + + sensor_list = [Sensors.COUNTER, Sensors.DATA_RATE, Sensors.DATA_INTEGRITY] + num_of_sensors = len(sensor_list) + + axes_list = fig.subplots(nrows=num_of_sensors, ncols=1, squeeze=False) + i = 0 + for sensor in sensor_list: + axis = axes_list[i][0] + axes_dict[sensor.title] = [sensor, axis] + axis.clear() + + axis.set_title('{}'.format(sensor.title)) + axis.set_ylabel(sensor.title + " (" + sensor.units + ")") + axis.set_xlabel('Sample Number') + axis.minorticks_on() + axis.grid(True, which='both') + axis.ticklabel_format(axis='both', style='plain') + leg = axis.legend(fancybox=True, fontsize='large', loc='upper right') + + for channel in sensor.channels: + line = axis.plot([], [], label=channel.name) + + axis.legend() + i += 1 + + # plt.show() + + +def start_thread(): + global window + + update_plot(q) + + window.mainloop() + + +class PlotObj(object): + def __init__(self, sensor_title, timestamp, sensor_data): + self.sensor_title = sensor_title + self.timestamp = timestamp + self.sensor_data = sensor_data + + def print_info(self): + print('key={}, data={}'.format(self.sensor_title, self.sensor_data)) + + +def plot_data(q, time_s_start, time_s_end, samples, data_rate_current, data_rate_overall, data_integrity): + # sensor_data_cal = {tsChString: [], Sensors.COUNTER: []} + # for sample in samples: + # sensor_data_cal.get(Sensors.COUNTER).append([sample]) + # sensor_data_cal[tsChString].append([sample_index[Sensors.COUNTER.title]]) + # sample_index[Sensors.COUNTER.title] += 1 + # sensor_data_cal[Sensors.COUNTER] = list(zip(*sensor_data_cal[Sensors.COUNTER])) + # add_data_from_sensors(sensor_data_cal, q) + + if len(samples) > 0: + sensor_data_cal = {tsChString: [], Sensors.COUNTER: []} + + time_diff = (time_s_end - time_s_start) / len(samples) + new_time = time_s_start + for sample in samples: + sensor_data_cal.get(Sensors.COUNTER).append([sample]) + sensor_data_cal[tsChString].append([new_time]) + new_time += time_diff + sensor_data_cal[Sensors.COUNTER] = list(zip(*sensor_data_cal[Sensors.COUNTER])) + add_data_from_sensors(sensor_data_cal, q) + + sensor_data_cal = {tsChString: [], Sensors.DATA_RATE: []} + sensor_data_cal.get(Sensors.DATA_RATE).append([data_rate_current, data_rate_overall]) + sensor_data_cal[tsChString].append(time_s_end) + # sensor_data_cal[tsChString].append(sample_index[Sensors.DATA_RATE.title]) + # sample_index[Sensors.DATA_RATE.title] += 1 + sensor_data_cal[Sensors.DATA_RATE] = list(zip(*sensor_data_cal[Sensors.DATA_RATE])) + add_data_from_sensors(sensor_data_cal, q) + + if len(data_integrity) > 0: + sensor_data_cal = {tsChString: [], Sensors.DATA_INTEGRITY: []} + time_diff = (time_s_end - time_s_start) / len(samples) + new_time = time_s_start + for sample in data_integrity: + sensor_data_cal.get(Sensors.DATA_INTEGRITY).append([sample]) + sensor_data_cal[tsChString].append([new_time]) + new_time += time_diff + sensor_data_cal[Sensors.DATA_INTEGRITY] = list(zip(*sensor_data_cal[Sensors.DATA_INTEGRITY])) + add_data_from_sensors(sensor_data_cal, q) + + +def add_data_from_sensors(data, q): + for key in data: + # TODO figure out why there would be a NoneType here + if key is None: + continue + + # TODO figure out why instance check isn't working here + # if isinstance(key, ASM_Device.SensorObj): + if key != tsChString: + sensor_data = data[key] + + if len(sensor_data) > 0: + plot_obj = PlotObj(key.title, data[tsChString], sensor_data) + q.put(plot_obj) + + +def update_plot(q_lcl): + global canvas, axes_dict, samples_to_plot + + something_was_plotted = False + + try: #Try to check if there is data in the queue + plot_obj = q_lcl.get_nowait() + + while plot_obj is not None: + if isinstance(plot_obj, str) and plot_obj == 'Q': + # print 'done' + pass + else: + # print result + + sensor_title = plot_obj.sensor_title + obj = axes_dict.get(sensor_title) + if obj is not None: + axis = obj[1] + if axis is not None: + lines = axis.get_lines() + + line_index = 0 + new_data_x = plot_obj.timestamp + + min_x = 10000000000 + max_x = 0 + min_y = 10000000000 + max_y = 0 + + for data_set in plot_obj.sensor_data: + # TODO Improve hacky approach + if isinstance(data_set, float): + data_set_to_plot = plot_obj.sensor_data + else: + data_set_to_plot = data_set + + line = lines[line_index] + + new_data_y = data_set_to_plot + + data_x = np.append(line.get_xdata(), new_data_x) + data_y = np.append(line.get_ydata(), new_data_y) + + # if len(data_x) > samples_to_plot: + # data_x = data_x[len(data_x) - samples_to_plot:len(data_x)] + # data_y = data_y[len(data_y) - samples_to_plot:len(data_y)] + + index_to_cull_from = 0 + endTime = data_x[len(data_x)-1] + for time_value in data_x: + if (endTime - time_value) <= 5: + break + index_to_cull_from += 1 + + data_x = data_x[index_to_cull_from:len(data_x)] + data_y = data_y[index_to_cull_from:len(data_y)] + + line.set_xdata(data_x) + line.set_ydata(data_y) + + axis.draw_artist(line) + # fig.draw_artist(axis) + + min_x = min(min_x, min(data_x)) + max_x = max(max_x, max(data_x)) + min_y = min(min_y, min(data_y)) + max_y = max(max_y, max(data_y)) + + line_index += 1 + + # TODO Improve hacky approach + if isinstance(data_set, float): + break + + axis.set_ylim(min_y, max_y + 1) # +1 to avoid singular transformation warning + axis.set_xlim(min_x, max_x + 1) + + something_was_plotted = True + # fig.canvas.draw_idle() + plot_obj = q_lcl.get_nowait() + # window.after(10, update_plot, q_lcl) + except Exception as ex: + # trace = [] + # tb = ex.__traceback__ + # while tb is not None: + # trace.append({ + # "filename": tb.tb_frame.f_code.co_filename, + # "name": tb.tb_frame.f_code.co_name, + # "lineno": tb.tb_lineno + # }) + # tb = tb.tb_next + if str(ex): + print(str({ + 'type' : type(ex).__name__, + 'message': str(ex), + # 'trace' : trace + })) + + if something_was_plotted: + canvas.draw() + # print "empty" + window.after(500, update_plot, q_lcl) + + +def on_closing(): + global window, q + # if messagebox.askokcancel("Quit", "Do you want to quit?"): + window.destroy() + q.close() + q.join_thread() + window.quit() + print("Plot closed") diff --git a/LogAndStream/python_scripts/Bluetooth commands/test_bt_cmds.py b/LogAndStream/python_scripts/Bluetooth commands/test_bt_cmds.py new file mode 100644 index 0000000..1255113 --- /dev/null +++ b/LogAndStream/python_scripts/Bluetooth commands/test_bt_cmds.py @@ -0,0 +1,1080 @@ +import time +import unittest + +from Shimmer_common import shimmer_comms_bluetooth, util_shimmer_time, util_shimmer +from Shimmer_common import shimmer_device, shimmer_app_common + + +def does_response_include_length_byte(get_cmd): + return (get_cmd == shimmer_comms_bluetooth.BtCmds.GET_DAUGHTER_CARD_ID_COMMAND + or get_cmd == shimmer_comms_bluetooth.BtCmds.GET_DAUGHTER_CARD_MEM_COMMAND + or get_cmd == shimmer_comms_bluetooth.BtCmds.GET_EXG_REGS_COMMAND + or get_cmd == shimmer_comms_bluetooth.BtCmds.GET_DIR_COMMAND + or get_cmd == shimmer_comms_bluetooth.BtCmds.GET_CONFIGTIME_COMMAND + or get_cmd == shimmer_comms_bluetooth.BtCmds.GET_SHIMMERNAME_COMMAND + or get_cmd == shimmer_comms_bluetooth.BtCmds.GET_EXPID_COMMAND + or get_cmd == shimmer_comms_bluetooth.BtCmds.GET_BT_VERSION_STR_COMMAND) + + +class TestShimmerBluetoothCommunication(unittest.TestCase): + shimmer = None + + @classmethod + def setUpClass(cls): + com_port = shimmer_app_common.get_selected_com_port(dock_ports=False) + if not com_port: + print("Supported COM port not found, exiting") + exit() + + cls.shimmer = shimmer_device.Shimmer3() + + if not cls.shimmer.setup_bluetooth_com_port(com_port, debug_txrx_packets=True): + exit() + + @classmethod + def tearDownClass(cls): + # cls._connection.destroy() + cls.shimmer.bluetooth_port.close_port() + print("All done") + + def bt_cmd_test_get_common(self, tx_cmd_byte, expected_response_cmd_byte, expected_response_len, + is_instream_response=False, delay_to_wait_for_response_ms=2000): + + if isinstance(tx_cmd_byte, list): + tx_cmd_byte_array = tx_cmd_byte + tx_cmd_byte = tx_cmd_byte_array[0] + else: + tx_cmd_byte_array = [tx_cmd_byte] + + i = 0 + + if tx_cmd_byte == shimmer_comms_bluetooth.BtCmds.GET_INFOMEM_COMMAND: + response = self.shimmer.bluetooth_port.read_configuration() + + self.assertFalse(isinstance(response, bool) or response is None or len(response) == 0, + "Error reading response") + + elif tx_cmd_byte == shimmer_comms_bluetooth.BtCmds.GET_CALIB_DUMP_COMMAND: + response = self.shimmer.bluetooth_port.read_calibration() + + self.assertFalse(isinstance(response, bool) or response is None or len(response) == 0, + "Error reading response") + + else: + if not self.shimmer.bluetooth_port.send_bluetooth(tx_cmd_byte_array): + self.assertTrue(False, "Error writing command") + + header_byte_count = 3 if is_instream_response else 2 + response = self.shimmer.bluetooth_port.wait_for_response(header_byte_count + expected_response_len, + delay_to_wait_for_response_ms) + + self.assertFalse(isinstance(response, bool) or response is None or len(response) == 0, + "Error reading response") + + # ACK + self.assertTrue(response[i] == shimmer_comms_bluetooth.BtCmds.ACK_COMMAND_PROCESSED) + i += 1 + if is_instream_response: + # INSTREAM_CMD_RESPONSE + self.assertTrue(response[i] == shimmer_comms_bluetooth.BtCmds.INSTREAM_CMD_RESPONSE) + i += 1 + # Response to command + self.assertTrue(response[i] == expected_response_cmd_byte) + i += 1 + + # Special cases + if tx_cmd_byte == shimmer_comms_bluetooth.BtCmds.INQUIRY_COMMAND: + # read each channel type for the num channels + idx_length_channels = 2 + 6 # +2 for header bytes + length_channels = response[idx_length_channels] + response_channels = self.shimmer.bluetooth_port.wait_for_response(length_channels) + if isinstance(response_channels, bool): + self.assertTrue(False, "Error reading inquiry response channels") + response = response + response_channels + + elif does_response_include_length_byte(tx_cmd_byte): + response = self.shimmer.bluetooth_port.wait_for_response(response[i]) + if isinstance(response, bool) or response is None or len(response) == 0: + if tx_cmd_byte == shimmer_comms_bluetooth.BtCmds.GET_DAUGHTER_CARD_ID_COMMAND: + self.assertTrue(False, "Error reading daughter card ID ") + elif tx_cmd_byte == shimmer_comms_bluetooth.BtCmds.GET_DAUGHTER_CARD_MEM_COMMAND: + self.assertTrue(False, "Error reading daughter card memory") + elif tx_cmd_byte == shimmer_comms_bluetooth.BtCmds.GET_EXG_REGS_COMMAND: + self.assertTrue(False, "Error reading exg regs") + elif tx_cmd_byte == shimmer_comms_bluetooth.BtCmds.GET_DIR_COMMAND: + self.assertTrue(False, "Error reading directory") + elif tx_cmd_byte == shimmer_comms_bluetooth.BtCmds.GET_CONFIGTIME_COMMAND: + self.assertTrue(False, "Error reading config time") + elif tx_cmd_byte == shimmer_comms_bluetooth.BtCmds.GET_SHIMMERNAME_COMMAND: + self.assertTrue(False, "Error reading directory") + elif tx_cmd_byte == shimmer_comms_bluetooth.BtCmds.GET_BT_VERSION_STR_COMMAND: + self.assertTrue(False, "Error bt version command") + else: + self.assertTrue(False, "Error - unhandled") + i = 0 + + # Clear CRC byte + if self.shimmer.bt_crc_byte_count > 0: + print("Clear CRC byte(s)") + self.shimmer.bluetooth_port.wait_for_response(1) + + return response[i:len(response)] + + def bt_cmd_test_set_common(self, set_cmd, set_bytes, get_cmd, response_cmd, set_delay_s=0.5, check_original_value=True): + + comparison_offset = 0 + length_to_read = len(set_bytes) + get_cmd_byte = get_cmd[0] if isinstance(get_cmd, list) else get_cmd + if does_response_include_length_byte(get_cmd_byte): + length_to_read = 1 + if (get_cmd_byte != shimmer_comms_bluetooth.BtCmds.GET_EXG_REGS_COMMAND + and get_cmd_byte != shimmer_comms_bluetooth.BtCmds.GET_DAUGHTER_CARD_ID_COMMAND + and get_cmd_byte != shimmer_comms_bluetooth.BtCmds.GET_DAUGHTER_CARD_MEM_COMMAND): + comparison_offset = 1 + + if check_original_value: + # Make sure the value being set isn't the same as the one that's already set in the Shimmer - otherwise it's not a valid test + print("Reading original setting from Shimmer:") + response = self.bt_cmd_test_get_common(get_cmd, response_cmd, length_to_read) + self.compare_set_get_arrays(set_bytes, response, comparison_offset, get_cmd_byte, True) + + bytes_to_send = set_cmd if isinstance(set_cmd, list) else [set_cmd] + bytes_to_send += set_bytes + + print("Writing new setting to Shimmer:") + # Special cases + if set_cmd == shimmer_comms_bluetooth.BtCmds.SET_INFOMEM_COMMAND: + result = self.shimmer.bluetooth_port.write_configuration(set_bytes) + if not result: + self.assertTrue(False) + elif set_cmd == shimmer_comms_bluetooth.BtCmds.SET_CALIB_DUMP_COMMAND: + result = self.shimmer.bluetooth_port.write_calibration(set_bytes) + if not result: + self.assertTrue(False) + else: + self.shimmer.bluetooth_port.send_bluetooth(bytes_to_send) + self.bt_cmd_test_wait_for_ack(2000) + + # Delay to allow the Shimmer to enact the changes + time.sleep(set_delay_s) + + print("Reading new setting from Shimmer:") + response = self.bt_cmd_test_get_common(get_cmd, response_cmd, length_to_read) + + # Compare what was sent with what has been received + if get_cmd_byte == shimmer_comms_bluetooth.BtCmds.GET_RWC_COMMAND: + ts_s_written = util_shimmer_time.shimmer_rtc_bytes_to_s(set_bytes) + ts_s_read = util_shimmer_time.shimmer_rtc_bytes_to_s(response) + + print("\r\nTime sent = %s\r\nTime received = %s" % ( + util_shimmer_time.seconds_to_time_str(ts_s_written, True), + util_shimmer_time.seconds_to_time_str(ts_s_read, True))) + + if (ts_s_read - ts_s_written) > (0.5 + set_delay_s): + self.assertTrue(False, "RWC time out of range") + else: + self.compare_set_get_arrays(set_bytes, response, comparison_offset, get_cmd_byte, False) + + def compare_set_get_arrays(self, set_bytes, response, comparison_offset, get_cmd_byte, check_original_value): + failed_indexes = [] + + for i in range(0, len(set_bytes) - comparison_offset): + if ((len(response) > i) + and ((check_original_value and (set_bytes[i + comparison_offset] is response[i])) + or (not check_original_value and (set_bytes[i + comparison_offset] is not response[i])))): + if (get_cmd_byte == shimmer_comms_bluetooth.BtCmds.GET_INFOMEM_COMMAND + and ((128 + 96) <= i <= (128 + 101))): + # print("Skipping MAC ID in infomem C") + continue + elif (get_cmd_byte == shimmer_comms_bluetooth.BtCmds.GET_CALIB_DUMP_COMMAND + and (2 <= i <= 9)): + # print("Skipping device and firmware version from calib file header") + continue + else: + failed_indexes += [i] + + if ((check_original_value and len(failed_indexes) == len(set_bytes) - comparison_offset) + or (not check_original_value and len(failed_indexes) > 0)): + print("Comparison offset = ", comparison_offset) + print("Failure indexes = ", failed_indexes) + print("Indexes = [", end="") + for x in range(len(set_bytes)): + print(f"{x:4}", end=" ") + print("]") + print("TX bytes =", + util_shimmer.byte_array_to_hex_string(set_bytes[comparison_offset:len(set_bytes)])) + print("RX bytes =", util_shimmer.byte_array_to_hex_string(response)) + + if check_original_value: + self.assertTrue(False, ( + "Original value in Shimmer equals test value and is therefore not a valid test of setting being changed")) + else: + self.assertTrue(False, ("RX byte != TX byte at indexes listed in console")) + + def bt_cmd_test_wait_for_ack(self, timeout_ms=500): + result = self.shimmer.bluetooth_port.wait_for_ack(timeout_ms) + if not result: + print("Error waiting for ACK") + self.assertTrue(False) + + # Clear CRC byte + if self.shimmer.bt_crc_byte_count > 0: + print("Clear CRC byte(s)") + self.shimmer.bluetooth_port.wait_for_response(1) + + def setUp(self): + print("") + self.shimmer.bluetooth_port.clear_serial_buffer() + # time.sleep(0.1) + + def test_01_get_inquiry_response(self): + print("\r\nTest 01 - Inquiry command:") + response = self.bt_cmd_test_get_common(shimmer_comms_bluetooth.BtCmds.INQUIRY_COMMAND, + shimmer_comms_bluetooth.BtCmds.INQUIRY_RESPONSE, 8) + + def test_02_reset_default_config(self, run_with_other_test=False): + if not run_with_other_test: + print("Test 02 - Reset Default config:") + self.shimmer.bluetooth_port.send_bluetooth( + [shimmer_comms_bluetooth.BtCmds.RESET_TO_DEFAULT_CONFIGURATION_COMMAND]) + self.bt_cmd_test_wait_for_ack() + + def test_03_reset_default_calib(self, run_with_other_test=False): + if not run_with_other_test: + print("Test 03 - Reset Default calib:") + self.shimmer.bluetooth_port.send_bluetooth( + [shimmer_comms_bluetooth.BtCmds.RESET_CALIBRATION_VALUE_COMMAND]) + self.bt_cmd_test_wait_for_ack() + + def test_04_get_shimmer_new_version(self): + print("Test 04 - Get new Shimmer version response command:") + response = self.bt_cmd_test_get_common(shimmer_comms_bluetooth.BtCmds.GET_DEVICE_VERSION_COMMAND, + shimmer_comms_bluetooth.BtCmds.DEVICE_VERSION_RESPONSE, 1) + self.shimmer.hw_ver = response[0] + + def test_05_get_fw_version(self): + print("Test 05 - Get FW response command") + response = self.bt_cmd_test_get_common(shimmer_comms_bluetooth.BtCmds.GET_FW_VERSION_COMMAND, + shimmer_comms_bluetooth.BtCmds.FW_VERSION_RESPONSE, 6) + self.shimmer.parse_fw_ver_bytes(response) + self.shimmer.print_hw_fw_revision() + + def test_06_get_daughter_card_id(self, run_with_other_test=False): + if not run_with_other_test: + print("Test 06 - Get daughter card id command:") + + # Read 1 byte as the first byte in the response is the length of the number of bytes in the rest of the response + response = self.bt_cmd_test_get_common( + [shimmer_comms_bluetooth.BtCmds.GET_DAUGHTER_CARD_ID_COMMAND, 0x03, 0x00], + shimmer_comms_bluetooth.BtCmds.DAUGHTER_CARD_ID_RESPONSE, 1) + + self.shimmer.parse_daughter_card_id(response) + self.shimmer.print_daughter_card_id() + + def test_07_get_sampling_rate(self): + print("Test 07 - Get sampling rate command:") + response = self.bt_cmd_test_get_common(shimmer_comms_bluetooth.BtCmds.GET_SAMPLING_RATE_COMMAND, + shimmer_comms_bluetooth.BtCmds.SAMPLING_RATE_RESPONSE, 2) + + def test_08_get_accel_sensitivity(self): + print("Test 08 - Get accelerometer sensitivity command:") + response = self.bt_cmd_test_get_common(shimmer_comms_bluetooth.BtCmds.GET_ACCEL_RANGE_COMMAND, + shimmer_comms_bluetooth.BtCmds.ACCEL_RANGE_RESPONSE, 1) + + def test_09_get_config_setup_bytes(self): + print("Test 09- Get Config Setup Bytes command:") + response = self.bt_cmd_test_get_common(shimmer_comms_bluetooth.BtCmds.GET_CONFIG_SETUP_BYTES_COMMAND, + shimmer_comms_bluetooth.BtCmds.CONFIG_SETUP_BYTES_RESPONSE, 4) + + def test_10_get_accel_calibration(self): + print("Test 10 - Get Accel Calibration Command:") + response = self.bt_cmd_test_get_common(shimmer_comms_bluetooth.BtCmds.GET_A_ACCEL_CALIBRATION_COMMAND, + shimmer_comms_bluetooth.BtCmds.A_ACCEL_CALIBRATION_RESPONSE, 21) + + def test_11_get_gyro_calibration(self): + print("Test 11 - Get Gyro Calibration Command:") + response = self.bt_cmd_test_get_common(shimmer_comms_bluetooth.BtCmds.GET_GYRO_CALIBRATION_COMMAND, + shimmer_comms_bluetooth.BtCmds.GYRO_CALIBRATION_RESPONSE, 21) + + def test_12_get_mag_calibration(self): + print("Test 12 - Get Mag Calibration Command:") + response = self.bt_cmd_test_get_common(shimmer_comms_bluetooth.BtCmds.GET_MAG_CALIBRATION_COMMAND, + shimmer_comms_bluetooth.BtCmds.MAG_CALIBRATION_RESPONSE, 21) + + def test_13_get_gsr_range(self): + print("Test 13 - Get GSR Command:") + response = self.bt_cmd_test_get_common(shimmer_comms_bluetooth.BtCmds.GET_GSR_RANGE_COMMAND, + shimmer_comms_bluetooth.BtCmds.GSR_RANGE_RESPONSE, 1) + + def test_14_all_calibration_response(self): + print("Test 14 - Get all calibration response command") + response = self.bt_cmd_test_get_common(shimmer_comms_bluetooth.BtCmds.GET_ALL_CALIBRATION_COMMAND, + shimmer_comms_bluetooth.BtCmds.ALL_CALIBRATION_RESPONSE, 4 * 21) + + def test_15_get_buffer_size(self): + print("Test 15 - Buffer size repsonse Command: ") + response = self.bt_cmd_test_get_common(shimmer_comms_bluetooth.BtCmds.GET_BUFFER_SIZE_COMMAND, + shimmer_comms_bluetooth.BtCmds.BUFFER_SIZE_RESPONSE, + 1) # get buffer size or response as 2 commands are mentioned + + def test_16_get_mag_gain(self): + print("Test 16 - Get mag gain command:") + response = self.bt_cmd_test_get_common(shimmer_comms_bluetooth.BtCmds.GET_MAG_GAIN_COMMAND, + shimmer_comms_bluetooth.BtCmds.MAG_GAIN_RESPONSE, 1) + + def test_17_get_charge_status_led(self): + print("Test 17 - Get Charge Status LED response command:") + response = self.bt_cmd_test_get_common(shimmer_comms_bluetooth.BtCmds.GET_CHARGE_STATUS_LED_COMMAND, + shimmer_comms_bluetooth.BtCmds.CHARGE_STATUS_LED_RESPONSE, 1) + if response[0] == 0: + print("Battery High") + elif response[0] == 1: + print("Battery Mid") + elif response[0] == 2: + print("Battery Low") + + def test_18_get_mag_sampling(self): + print("Test 18 - Get Mag sampling Command:") + response = self.bt_cmd_test_get_common(shimmer_comms_bluetooth.BtCmds.GET_MAG_SAMPLING_RATE_COMMAND, + shimmer_comms_bluetooth.BtCmds.MAG_SAMPLING_RATE_RESPONSE, 1) + + def test_19_get_accel_sampling_rate(self): + print("Test 19 - Get accel sampling rate response command:") + response = self.bt_cmd_test_get_common(shimmer_comms_bluetooth.BtCmds.GET_ACCEL_SAMPLING_RATE_COMMAND, + shimmer_comms_bluetooth.BtCmds.ACCEL_SAMPLING_RATE_RESPONSE, 1) + + def test_20_get_wr_accel_lpmode(self): + print("Test 20 - Get WR accel lpmode command:") + response = self.bt_cmd_test_get_common(shimmer_comms_bluetooth.BtCmds.GET_ACCEL_LPMODE_COMMAND, + shimmer_comms_bluetooth.BtCmds.ACCEL_LPMODE_RESPONSE, 1) + + def test_21_get_wr_accel_hrmode(self): + print("Test 21 - GET WR accel hrmode command:") + response = self.bt_cmd_test_get_common(shimmer_comms_bluetooth.BtCmds.GET_ACCEL_HRMODE_COMMAND, + shimmer_comms_bluetooth.BtCmds.ACCEL_HRMODE_RESPONSE, 1) + + def test_22_get_gyro_range(self): + print("Test 22 - Get gyro range command:") + response = self.bt_cmd_test_get_common(shimmer_comms_bluetooth.BtCmds.GET_GYRO_RANGE_COMMAND, + shimmer_comms_bluetooth.BtCmds.GYRO_RANGE_RESPONSE, 1) + + def test_23_get_gyro_sampling_rate(self): + print("Test 23 - Get gyro sampling rate command:") + response = self.bt_cmd_test_get_common(shimmer_comms_bluetooth.BtCmds.GET_GYRO_SAMPLING_RATE_COMMAND, + shimmer_comms_bluetooth.BtCmds.GYRO_SAMPLING_RATE_RESPONSE, 1) + + print(util_shimmer.byte_array_to_hex_string(response)) + + def test_24_get_BMPX80_Calibration_coefficients(self): + print("Test 24 - Get BMPX80 Calibration response command:") + + if not self.shimmer.is_expansion_board_set(): + self.test_06_get_daughter_card_id(True) + + if self.shimmer.is_bmp180_present(): + response = self.bt_cmd_test_get_common( + shimmer_comms_bluetooth.BtCmds.GET_BMP180_CALIBRATION_COEFFICIENTS_COMMAND, + shimmer_comms_bluetooth.BtCmds.BMP180_CALIBRATION_COEFFICIENTS_RESPONSE, 22) + elif self.shimmer.is_bmp280_present(): + response = self.bt_cmd_test_get_common( + shimmer_comms_bluetooth.BtCmds.GET_BMP280_CALIBRATION_COEFFICIENTS_COMMAND, + shimmer_comms_bluetooth.BtCmds.BMP280_CALIBRATION_COEFFICIENTS_RESPONSE, 24) + else: + print("Skipping test, BMPX80 not present in device") + + def test_25_get_alt_mag_sens_adj_vals_response(self): + # Shimmer3 utilising ICM-20948 instead of MPU9150/MPU9250 will only respond back with ACK as the ICM-20948 + # does not support changing the mag range. + print("Test 25 - Get alternative Mag Sens Adj Vals response command:") + + if not self.shimmer.is_expansion_board_set(): + self.test_06_get_daughter_card_id(True) + + if self.shimmer.is_icm20948_present(): + self.shimmer.bluetooth_port.send_bluetooth( + [shimmer_comms_bluetooth.BtCmds.GET_ALT_MAG_SENS_ADJ_VALS_COMMAND]) + self.bt_cmd_test_wait_for_ack() + else: + response = self.bt_cmd_test_get_common(shimmer_comms_bluetooth.BtCmds.GET_ALT_MAG_SENS_ADJ_VALS_COMMAND, + shimmer_comms_bluetooth.BtCmds.ALT_MAG_SENS_ADJ_VALS_RESPONSE, 1) + + def test_26_get_internal_exp_power_enable(self): + print("Test 26 - Get exp power enable response command:") + response = self.bt_cmd_test_get_common(shimmer_comms_bluetooth.BtCmds.GET_INTERNAL_EXP_POWER_ENABLE_COMMAND, + shimmer_comms_bluetooth.BtCmds.INTERNAL_EXP_POWER_ENABLE_RESPONSE, 1) + + def test_27_get_exg_regs(self): + print("Test 27 - Get ExG Regs command:") + # Expecting 3 additional bytes, exgChip index, exgStartAddr, exgLength + + # Chip 0 + response = self.bt_cmd_test_get_common([shimmer_comms_bluetooth.BtCmds.GET_EXG_REGS_COMMAND, 0, 0, 10], + shimmer_comms_bluetooth.BtCmds.EXG_REGS_RESPONSE, 1) + + # Chip 1 + response = self.bt_cmd_test_get_common([shimmer_comms_bluetooth.BtCmds.GET_EXG_REGS_COMMAND, 1, 0, 10], + shimmer_comms_bluetooth.BtCmds.EXG_REGS_RESPONSE, 1) + + def test_28_get_status(self, run_with_other_test=False): + if not run_with_other_test: + print("Test 28 - Get status command:") + response = self.bt_cmd_test_get_common(shimmer_comms_bluetooth.BtCmds.GET_STATUS_COMMAND, + shimmer_comms_bluetooth.BtCmds.STATUS_RESPONSE, 1, + is_instream_response=True) + + status = response[0] + self.shimmer.parse_status(status) + + def test_29_get_baud_rate(self): + print("Test 29 - Get baud rate response command:") + response = self.bt_cmd_test_get_common(shimmer_comms_bluetooth.BtCmds.GET_BT_COMMS_BAUD_RATE, + shimmer_comms_bluetooth.BtCmds.BT_COMMS_BAUD_RATE_RESPONSE, 1) + + def test_30_get_derived_channel_bytes(self): + print("Test 30 - Get Derived Channel Bytes response command:") + response = self.bt_cmd_test_get_common(shimmer_comms_bluetooth.BtCmds.GET_DERIVED_CHANNEL_BYTES, + shimmer_comms_bluetooth.BtCmds.DERIVED_CHANNEL_BYTES_RESPONSE, 8) + + def test_31_get_trial_config(self): + print("Test 31 - Get trial config command:") + response = self.bt_cmd_test_get_common(shimmer_comms_bluetooth.BtCmds.GET_TRIAL_CONFIG_COMMAND, + shimmer_comms_bluetooth.BtCmds.TRIAL_CONFIG_RESPONSE, 3) + + def test_32_get_center(self): + print("Test 32 - Get Center response command:") + # TODO GET_CENTER_COMMAND not currently supported in LogAndStream but could be added in the future + # response = self.bt_cmd_test_common(shimmer_comms_bluetooth.BtCmds.GET_CENTER_COMMAND, + # shimmer_comms_bluetooth.BtCmds.CENTER_RESPONSE, 1) + + def test_33_get_shimmer_name(self): + print("Test 33 - Get ShimmerName command:") + response = self.bt_cmd_test_get_common(shimmer_comms_bluetooth.BtCmds.GET_SHIMMERNAME_COMMAND, + shimmer_comms_bluetooth.BtCmds.SHIMMERNAME_RESPONSE, 1) + print(bytes(response)) + + def test_34_get_expID(self): + print("Test 34 - Get ExpID command:") + response = self.bt_cmd_test_get_common(shimmer_comms_bluetooth.BtCmds.GET_EXPID_COMMAND, + shimmer_comms_bluetooth.BtCmds.EXPID_RESPONSE, 1) + print(bytes(response)) + + def test_35_get_myID(self): + print("Test 35 - Get myID command:") # works + response = self.bt_cmd_test_get_common(shimmer_comms_bluetooth.BtCmds.GET_MYID_COMMAND, + shimmer_comms_bluetooth.BtCmds.MYID_RESPONSE, 1) + + def test_36_get_number_of_shimmers_in_trial(self): + print("Test 36 - Get nshimmer response command:") + response = self.bt_cmd_test_get_common(shimmer_comms_bluetooth.BtCmds.GET_NSHIMMER_COMMAND, + shimmer_comms_bluetooth.BtCmds.NSHIMMER_RESPONSE, 1) + + def test_37_get_ConfigTime(self): + print("Test 37- Get Config Time Response Command:") + response = self.bt_cmd_test_get_common(shimmer_comms_bluetooth.BtCmds.GET_CONFIGTIME_COMMAND, + shimmer_comms_bluetooth.BtCmds.CONFIGTIME_RESPONSE, 1) + print(util_shimmer_time.seconds_to_time_str(int(bytes(response)), True)) + + def test_38_get_dir(self): + print("Test 38 - Get dir response command:") + + self.test_28_get_status(True) + + if self.shimmer.status_is_docked: + self.assertTrue(False, "Shimmer must be undocked for this command to work reliably") + elif not self.shimmer.status_sd_in_slot: + self.assertTrue(False, "No SD card detected") + elif self.shimmer.status_sd_error: + self.assertTrue(False, "SD card error detected") + else: + response = self.bt_cmd_test_get_common(shimmer_comms_bluetooth.BtCmds.GET_DIR_COMMAND, + shimmer_comms_bluetooth.BtCmds.DIR_RESPONSE, 1, + is_instream_response=True) + print(bytes(response)) + + def test_39_get_infomem(self): + print("Test 39 - Get infomem response command:") + + response = self.bt_cmd_test_get_common(shimmer_comms_bluetooth.BtCmds.GET_INFOMEM_COMMAND, + shimmer_comms_bluetooth.BtCmds.INFOMEM_RESPONSE, 1) + + print("Config bytes: " + util_shimmer.byte_array_to_hex_string(response)) + + def test_40_get_calib_dump(self): + print("Test 40 - Get calib dump:") + + response = self.bt_cmd_test_get_common(shimmer_comms_bluetooth.BtCmds.GET_CALIB_DUMP_COMMAND, + shimmer_comms_bluetooth.BtCmds.RSP_CALIB_DUMP_COMMAND, 1) + + print("Calib bytes: " + util_shimmer.byte_array_to_hex_string(response)) + + # print(util_shimmer.byte_array_to_hex_string(calib_dump_concat)) + + def test_41_get_rwc(self): + print("Test 41- Get RWC response") + response = self.bt_cmd_test_get_common(shimmer_comms_bluetooth.BtCmds.GET_RWC_COMMAND, + shimmer_comms_bluetooth.BtCmds.RWC_RESPONSE, 8) + + ts_s = util_shimmer_time.shimmer_rtc_bytes_to_s(response) + print(util_shimmer_time.seconds_to_time_str(ts_s, True)) + + def test_42_get_vbatt(self): + print("Test 42 - Get VBatt response command") + response = self.bt_cmd_test_get_common(shimmer_comms_bluetooth.BtCmds.GET_VBATT_COMMAND, + shimmer_comms_bluetooth.BtCmds.VBATT_RESPONSE, 3, + is_instream_response=True) + batt_voltage = ((response[0] & 0xFF) << 8) + (response[0] & 0xFF) + charging_status = response[1] + print("batt_voltage: %03f , charging_status: %d" % (batt_voltage, charging_status)) + + def test_43_get_BT_FW_VERSION(self): + print("Test 43 - Get BT FW Version response command") + response = self.bt_cmd_test_get_common(shimmer_comms_bluetooth.BtCmds.GET_BT_VERSION_STR_COMMAND, + shimmer_comms_bluetooth.BtCmds.BT_VERSION_STR_RESPONSE, 1) + print(bytes(response)) + + def test_44_get_unique_serial_response(self): + print("Test 44 - Unique Serial Response") + response = self.bt_cmd_test_get_common(shimmer_comms_bluetooth.BtCmds.GET_UNIQUE_SERIAL_COMMAND, + shimmer_comms_bluetooth.BtCmds.UNIQUE_SERIAL_RESPONSE, 1) + print(response) + + def test_45_get_pres_oversampling_ratio(self): + print("Test 45 - Pres Oversampling") + response = self.bt_cmd_test_get_common(shimmer_comms_bluetooth.BtCmds.GET_PRES_OVERSAMPLING_RATIO_COMMAND, + shimmer_comms_bluetooth.BtCmds.PRES_OVERSAMPLING_RATIO_RESPONSE, 1) + print(response) + + def test_46_get_alt_accel_range(self): + print("Test 46 - ALT accel range") + response = self.bt_cmd_test_get_common(shimmer_comms_bluetooth.BtCmds.GET_ALT_ACCEL_RANGE_COMMAND, + shimmer_comms_bluetooth.BtCmds.ALT_ACCEL_RANGE_RESPONSE, 1) + print(response) + + def test_47_get_daughter_card_mem(self): + print("Test 47 - Get daughter card mem") + response = self.bt_cmd_test_get_common([shimmer_comms_bluetooth.BtCmds.GET_DAUGHTER_CARD_MEM_COMMAND, 10, 0, 0], + shimmer_comms_bluetooth.BtCmds.DAUGHTER_CARD_MEM_RESPONSE, 1) + print(response) + + # set commands + + def test_48_set_sampling_rate(self): + print("Test 48 - set accel sensitivity command ") + + sampling_rate_hz = 102.4 + sampling_rate_ticks = int(32768/sampling_rate_hz) + + tx_bytes = [sampling_rate_ticks & 0xFF, (sampling_rate_ticks >> 8) & 0xFF] + self.bt_cmd_test_set_common(shimmer_comms_bluetooth.BtCmds.SET_SAMPLING_RATE_COMMAND, + tx_bytes, + shimmer_comms_bluetooth.BtCmds.GET_SAMPLING_RATE_COMMAND, + shimmer_comms_bluetooth.BtCmds.SAMPLING_RATE_RESPONSE) + + def test_49_set_sensors(self): + print("Test 49 - set sensors command ") + + # Enable: LN Accel, Gyro, Mag, ExtCh7, ExtCh6, Battery, WR Accel, ExtCh15, IntCh1, IntCh12, IntCh13, IntCh14, Pressure (i.e., 11 analog ch and 11 digital ch) + tx_bytes = [0xE3, 0x3F, 0x84] + self.shimmer.bluetooth_port.send_bluetooth([shimmer_comms_bluetooth.BtCmds.SET_SENSORS_COMMAND] + tx_bytes) + self.bt_cmd_test_wait_for_ack() + + response = self.bt_cmd_test_get_common(shimmer_comms_bluetooth.BtCmds.INQUIRY_COMMAND, + shimmer_comms_bluetooth.BtCmds.INQUIRY_RESPONSE, 8) + if response[6] != 22: + self.assertTrue(False) + + # reenable default config: LN accel, gyro, mag and battery voltage enabled (i.e., 4 analog ch and 6 digital ch) + tx_bytes = [0xE0, 0x20, 0x00] + self.shimmer.bluetooth_port.send_bluetooth([shimmer_comms_bluetooth.BtCmds.SET_SENSORS_COMMAND] + tx_bytes) + self.bt_cmd_test_wait_for_ack() + + response = self.bt_cmd_test_get_common(shimmer_comms_bluetooth.BtCmds.INQUIRY_COMMAND, + shimmer_comms_bluetooth.BtCmds.INQUIRY_RESPONSE, 8) + if response[6] != 10: + self.assertTrue(False) + + def test_50_set_accel_sensitivity(self): + print("Test 50 - set accel sensitivity command ") + tx_bytes = [0x01] # default 0 + self.bt_cmd_test_set_common(shimmer_comms_bluetooth.BtCmds.SET_ACCEL_RANGE_COMMAND, + tx_bytes, + shimmer_comms_bluetooth.BtCmds.GET_ACCEL_RANGE_COMMAND, + shimmer_comms_bluetooth.BtCmds.ACCEL_RANGE_RESPONSE) + + def test_51_set_config_bytes(self): + print("Test 51 - set Config Bytes command ") + tx_bytes = [0x06, 0x01, 0x02, 0x03] # default + self.bt_cmd_test_set_common(shimmer_comms_bluetooth.BtCmds.SET_CONFIG_SETUP_BYTES_COMMAND, tx_bytes, + shimmer_comms_bluetooth.BtCmds.GET_CONFIG_SETUP_BYTES_COMMAND, + shimmer_comms_bluetooth.BtCmds.CONFIG_SETUP_BYTES_RESPONSE) + + def test_52_set_A_accel_calibration(self): + print("Test 52 - Set accel Calibration Command") + tx_bytes = [0x03, 0x00, 0x03, 0x00, 0x01, 0x11, 0x00, 0x00, 0x02, 0x00, 0x00, 0x15, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08] # default 0xff, 84 + self.bt_cmd_test_set_common(shimmer_comms_bluetooth.BtCmds.SET_A_ACCEL_CALIBRATION_COMMAND, tx_bytes, + shimmer_comms_bluetooth.BtCmds.GET_A_ACCEL_CALIBRATION_COMMAND, + shimmer_comms_bluetooth.BtCmds.A_ACCEL_CALIBRATION_RESPONSE) + + def test_53_set_wr_accel_calibration(self): + print("Test 53 - Set WR Accel Calibration Command") + tx_bytes = [0x03, 0x00, 0x03, 0x00, 0x01, 0x11, 0x00, 0x00, 0x02, 0x00, 0x00, 0x15, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08] # default off + self.bt_cmd_test_set_common(shimmer_comms_bluetooth.BtCmds.SET_ACCEL_CALIBRATION_COMMAND, tx_bytes, + shimmer_comms_bluetooth.BtCmds.GET_ACCEL_CALIBRATION_COMMAND, + shimmer_comms_bluetooth.BtCmds.ACCEL_CALIBRATION_RESPONSE) + + def test_54_set_gyro_calibration(self): + print("Test 54 - Set Gyro Calibration Command ") + tx_bytes = [0x03, 0x00, 0x03, 0x00, 0x01, 0x11, 0x00, 0x00, 0x02, 0x00, 0x00, 0x15, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08] + self.bt_cmd_test_set_common(shimmer_comms_bluetooth.BtCmds.SET_GYRO_CALIBRATION_COMMAND, tx_bytes, + shimmer_comms_bluetooth.BtCmds.GET_GYRO_CALIBRATION_COMMAND, + shimmer_comms_bluetooth.BtCmds.GYRO_CALIBRATION_RESPONSE) + + def test_55_set_mag_calibration(self): + print("Test 55 - Set Mag Calibration Command") + tx_bytes = [0x03, 0x00, 0x03, 0x00, 0x01, 0x11, 0x00, 0x00, 0x02, 0x00, 0x00, 0x15, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08] + self.bt_cmd_test_set_common(shimmer_comms_bluetooth.BtCmds.SET_MAG_CALIBRATION_COMMAND, tx_bytes, + shimmer_comms_bluetooth.BtCmds.GET_MAG_CALIBRATION_COMMAND, + shimmer_comms_bluetooth.BtCmds.MAG_CALIBRATION_RESPONSE) + + def test_56_set_mag_gain(self): + print("Test 56 - Set Mag gain command") + tx_bytes = [0x01] + self.bt_cmd_test_set_common(shimmer_comms_bluetooth.BtCmds.SET_MAG_GAIN_COMMAND, tx_bytes, + shimmer_comms_bluetooth.BtCmds.GET_MAG_GAIN_COMMAND, + shimmer_comms_bluetooth.BtCmds.MAG_GAIN_RESPONSE) + + def test_57_set_gsr_range(self): + print("Test 57- Set GSR Range Command") + tx_bytes = [0x03] + self.bt_cmd_test_set_common(shimmer_comms_bluetooth.BtCmds.SET_GSR_RANGE_COMMAND, tx_bytes, + shimmer_comms_bluetooth.BtCmds.GET_GSR_RANGE_COMMAND, + shimmer_comms_bluetooth.BtCmds.GSR_RANGE_RESPONSE) + + def test_58_set_mag_sampling_rate(self): + print("Test 58 - Set Mag Sampling rate command") + tx_bytes = [0x01] + self.bt_cmd_test_set_common(shimmer_comms_bluetooth.BtCmds.SET_MAG_SAMPLING_RATE_COMMAND, tx_bytes, + shimmer_comms_bluetooth.BtCmds.GET_MAG_SAMPLING_RATE_COMMAND, + shimmer_comms_bluetooth.BtCmds.MAG_SAMPLING_RATE_RESPONSE) + + def test_59_set_accel_sampling_rate(self): + print("Test 59 - Set Accel Sampling rate command") + tx_bytes = [0x01] + self.bt_cmd_test_set_common(shimmer_comms_bluetooth.BtCmds.SET_ACCEL_SAMPLING_RATE_COMMAND, tx_bytes, + shimmer_comms_bluetooth.BtCmds.GET_ACCEL_SAMPLING_RATE_COMMAND, + shimmer_comms_bluetooth.BtCmds.ACCEL_SAMPLING_RATE_RESPONSE) + + def test_60_set_wr_accel_lpmode(self): + print("Test 60 - Set wr lpmode command") + tx_bytes = [0x00] + self.bt_cmd_test_set_common(shimmer_comms_bluetooth.BtCmds.SET_ACCEL_LPMODE_COMMAND, tx_bytes, + shimmer_comms_bluetooth.BtCmds.GET_ACCEL_LPMODE_COMMAND, + shimmer_comms_bluetooth.BtCmds.ACCEL_LPMODE_RESPONSE) + + def test_61_set_wr_accel_hrmode(self): + print("Test 61 - Set wr accel hrmode command") + tx_bytes = [0x01] + self.bt_cmd_test_set_common(shimmer_comms_bluetooth.BtCmds.SET_ACCEL_HRMODE_COMMAND, tx_bytes, + shimmer_comms_bluetooth.BtCmds.GET_ACCEL_HRMODE_COMMAND, + shimmer_comms_bluetooth.BtCmds.ACCEL_HRMODE_RESPONSE) + + def test_62_set_gyro_range(self): + print("Test 62 - Gyro Range command") + tx_bytes = [0x01] + self.bt_cmd_test_set_common(shimmer_comms_bluetooth.BtCmds.SET_GYRO_RANGE_COMMAND, + tx_bytes, + shimmer_comms_bluetooth.BtCmds.GET_GYRO_RANGE_COMMAND, + shimmer_comms_bluetooth.BtCmds.GYRO_RANGE_RESPONSE) + + def test_63_set_gyro_sampling_rate(self): + print("Test 63 - Set Gyro Sampling Rate Command") + tx_bytes = [0x02] # default 1 + self.bt_cmd_test_set_common(shimmer_comms_bluetooth.BtCmds.SET_GYRO_SAMPLING_RATE_COMMAND, + tx_bytes, + shimmer_comms_bluetooth.BtCmds.GET_GYRO_SAMPLING_RATE_COMMAND, + shimmer_comms_bluetooth.BtCmds.GYRO_SAMPLING_RATE_RESPONSE) + + def test_64_set_internal_exp_power_enable(self): + print("Test 64 - Set Internal exp power enable command") + tx_bytes = [0x00] # Power on = 1, power off = 0 (default = 1) + self.bt_cmd_test_set_common(shimmer_comms_bluetooth.BtCmds.SET_INTERNAL_EXP_POWER_ENABLE_COMMAND, + tx_bytes, + shimmer_comms_bluetooth.BtCmds.GET_INTERNAL_EXP_POWER_ENABLE_COMMAND, + shimmer_comms_bluetooth.BtCmds.INTERNAL_EXP_POWER_ENABLE_RESPONSE) + + def test_65_set_exg_regs_response(self): + print("Test 65 - set_exg_regs_response") + # Chip 0 + # tx_bytes = [0x00, 0x80, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01] # default = ExG off + tx_bytes = [0x03, 0xAB, 0x10, 0x15, 0x15, 0x00, 0x00, 0x00, 0x02, 0x01] # Square wave @ 512 Hz + self.bt_cmd_test_set_common([shimmer_comms_bluetooth.BtCmds.SET_EXG_REGS_COMMAND, 0, 0, 10], tx_bytes, + [shimmer_comms_bluetooth.BtCmds.GET_EXG_REGS_COMMAND, 0, 0, 10], + shimmer_comms_bluetooth.BtCmds.EXG_REGS_RESPONSE) + # Chip 1 + # tx_bytes = [0x00, 0x80, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01] # default = ExG off + tx_bytes = [0x03, 0xA3, 0x10, 0x15, 0x15, 0x00, 0x00, 0x00, 0x02, 0x01] # Square wave @ 512 Hz + self.bt_cmd_test_set_common([shimmer_comms_bluetooth.BtCmds.SET_EXG_REGS_COMMAND, 1, 0, 10], tx_bytes, + [shimmer_comms_bluetooth.BtCmds.GET_EXG_REGS_COMMAND, 1, 0, 10], + shimmer_comms_bluetooth.BtCmds.EXG_REGS_RESPONSE) + + def test_66_set_daughter_card_id(self): + print("Test 66 - Set daughter card ID") + + if not self.shimmer.is_expansion_board_set(): + self.test_06_get_daughter_card_id(True) + + # Not going to risk changing the daughter card ID here so just going to try and write the same one back + tx_bytes = [self.shimmer.daughter_card_id, self.shimmer.daughter_card_rev_major, self.shimmer.daughter_card_rev_minor] + self.bt_cmd_test_set_common([shimmer_comms_bluetooth.BtCmds.SET_DAUGHTER_CARD_ID_COMMAND, 0x03, 0x00], + tx_bytes, + [shimmer_comms_bluetooth.BtCmds.GET_DAUGHTER_CARD_ID_COMMAND, 0x03, 0x00], + shimmer_comms_bluetooth.BtCmds.DAUGHTER_CARD_ID_RESPONSE, + check_original_value=False) + + def test_67_set_baud_rate(self): + print("Test 67 - Set baud Rate Command") + # NOTE Changing of BT baud rate no longer supported in firmware. The firmware now sets the max supported baud + # automatically. + + # tx_bytes = [0x05] # default 0 = 11.5.2k + # self.bt_cmd_test_set_common(shimmer_comms_bluetooth.BtCmds.SET_BT_COMMS_BAUD_RATE, tx_bytes, + # shimmer_comms_bluetooth.BtCmds.GET_BT_COMMS_BAUD_RATE, + # shimmer_comms_bluetooth.BtCmds.BT_COMMS_BAUD_RATE_RESPONSE) + + def test_68_set_derived_channel_bytes(self): + print("Test 68 - Set Derived Channel bytes Command") + tx_bytes = [0x00, 0x01, 0x02, 0x00, 0x00, 0x06, 0x05, 0x04] # default [0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00] + self.bt_cmd_test_set_common(shimmer_comms_bluetooth.BtCmds.SET_DERIVED_CHANNEL_BYTES, tx_bytes, + shimmer_comms_bluetooth.BtCmds.GET_DERIVED_CHANNEL_BYTES, + shimmer_comms_bluetooth.BtCmds.DERIVED_CHANNEL_BYTES_RESPONSE) + + def test_69_set_trial_config(self): + print("Test 69 - Set Trial Config Command") + tx_bytes = [0x00, 0x01, 0x37] # default = 0x31 0x00 0x36 + self.bt_cmd_test_set_common(shimmer_comms_bluetooth.BtCmds.SET_TRIAL_CONFIG_COMMAND, tx_bytes, + shimmer_comms_bluetooth.BtCmds.GET_TRIAL_CONFIG_COMMAND, + shimmer_comms_bluetooth.BtCmds.TRIAL_CONFIG_RESPONSE) + + def test_70_set_center(self): + print("Test 70 - Set Center Command") + # TODO SET_CENTER_COMMAND not currently supported in LogAndStream but could be added in the future + print("Skipping as not supported yet in LogAndStream") + # tx_bytes = [0x01] + # self.bt_cmd_test_set_common(shimmer_comms_bluetooth.BtCmds.SET_CENTER_COMMAND, tx_bytes, + # shimmer_comms_bluetooth.BtCmds.GET_CENTER_COMMAND, + # shimmer_comms_bluetooth.BtCmds.CENTER_RESPONSE) + + def test_71_set_shimmerName(self): + print("Test 71 - Set Shimmer Name Command ") + shimmer_name = "UnitTest71" + tx_bytes = [ord(c) for c in shimmer_name] + tx_bytes = [len(tx_bytes)] + tx_bytes + + self.bt_cmd_test_set_common(shimmer_comms_bluetooth.BtCmds.SET_SHIMMERNAME_COMMAND, tx_bytes, + shimmer_comms_bluetooth.BtCmds.GET_SHIMMERNAME_COMMAND, + shimmer_comms_bluetooth.BtCmds.SHIMMERNAME_RESPONSE) + + def test_72_set_ExpID(self): + print("Test 72 - Set ExpId command") + experiment_id = "UnitTest72" + tx_bytes = [ord(c) for c in experiment_id] + tx_bytes = [len(tx_bytes)] + tx_bytes + + self.bt_cmd_test_set_common(shimmer_comms_bluetooth.BtCmds.SET_EXPID_COMMAND, tx_bytes, + shimmer_comms_bluetooth.BtCmds.GET_EXPID_COMMAND, + shimmer_comms_bluetooth.BtCmds.EXPID_RESPONSE) + + def test_73_set_myID(self): + print("Test 73 - Set My ID command") + tx_bytes = [0x01] + self.bt_cmd_test_set_common(shimmer_comms_bluetooth.BtCmds.SET_MYID_COMMAND, tx_bytes, + shimmer_comms_bluetooth.BtCmds.GET_MYID_COMMAND, + shimmer_comms_bluetooth.BtCmds.MYID_RESPONSE) + + def test_74_set_NShimmer(self): + print("Test 74 - Set nShimmer command") + tx_bytes = [0x01] + self.bt_cmd_test_set_common(shimmer_comms_bluetooth.BtCmds.SET_NSHIMMER_COMMAND, tx_bytes, + shimmer_comms_bluetooth.BtCmds.GET_NSHIMMER_COMMAND, + shimmer_comms_bluetooth.BtCmds.NSHIMMER_RESPONSE) + + def test_75_set_ConfigTime(self): + print("Test 75 - Set ConfigTime Command") + test_config_time_s = "832103100" + tx_bytes = [ord(c) for c in test_config_time_s] + tx_bytes = [len(tx_bytes)] + tx_bytes + self.bt_cmd_test_set_common(shimmer_comms_bluetooth.BtCmds.SET_CONFIGTIME_COMMAND, tx_bytes, + shimmer_comms_bluetooth.BtCmds.GET_CONFIGTIME_COMMAND, + shimmer_comms_bluetooth.BtCmds.CONFIGTIME_RESPONSE) + + def test_76_set_InfoMem(self): + print("Test 76 - Set InfoMem Command") + # self.test_02_reset_default_config() + # self.test_03_reset_default_calib() + + # Config generated below from Consensys in-which: + # Trial name = UnitTests + # Sampling rate = 512 Hz + # Sensors Enabled = wr-accel, pressure & temperature and battery voltage + + tx_bytes = [0x40, 0x00, 0x01, 0x00, 0x30, 0x04, 0x71, 0xFF, 0x01, 0x08, 0x00, 0x80, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x01, 0x00, 0x80, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x0B, 0x00, + 0x00, 0x00, 0x08, 0xCD, 0x08, 0xCD, 0x08, 0xCD, 0x00, 0x5C, 0x00, 0x5C, 0x00, 0x5C, 0x00, 0x9C, + 0x00, 0x9C, 0x00, 0x00, 0x00, 0x00, 0x9C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x96, 0x19, + 0x96, 0x19, 0x96, 0x00, 0x9C, 0x00, 0x9C, 0x00, 0x00, 0x00, 0x00, 0x9C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x9B, 0x02, 0x9B, 0x02, 0x9B, 0x00, 0x9C, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, + 0x9C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x87, 0x06, 0x87, 0x06, 0x87, 0x00, 0x9C, 0x00, + 0x64, 0x00, 0x00, 0x00, 0x00, 0x9C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x68, 0x69, 0x6D, 0x6D, + 0x65, 0x72, 0x5F, 0x41, 0x36, 0x31, 0x35, 0x55, 0x6E, 0x69, 0x74, 0x54, 0x65, 0x73, 0x74, 0x73, + 0xFF, 0xFF, 0xFF, 0x66, 0x79, 0x2D, 0x6D, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + + self.bt_cmd_test_set_common(shimmer_comms_bluetooth.BtCmds.SET_INFOMEM_COMMAND, tx_bytes, + shimmer_comms_bluetooth.BtCmds.GET_INFOMEM_COMMAND, + shimmer_comms_bluetooth.BtCmds.INFOMEM_RESPONSE, 2) + + def test_77_set_calib_dump(self): + print("Test 77 - Set Calib Command") + tx_bytes = [0x52, 0x01, # Calib byte length + 0x03, 0x00, # Device version + 0x02, 0x00, 0x00, # Firmware identifier + 0x00, 0x16, 0x04, # FW version + + # 0x02 = SC_SENSOR_ANALOG_ACCEL + 0x02, 0x00, 0x00, 0x15, # 1 byte ID, 2 bytes Range, 1 byte data length + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # Calib timestamp + 0x08, 0xCD, 0x08, 0xCD, 0x08, 0xCD, 0x00, 0x5C, 0x00, 0x5C, 0x00, 0x5C, 0x00, 0x9C, 0x00, 0x9C, + 0x00, 0x00, 0x00, 0x00, 0x9C, # Calibration bytes + + # 0x1E = SC_SENSOR_GYRO + 0x1E, 0x00, 0x00, 0x15, # 1 byte ID, 2 bytes Range, 1 byte data length + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # Calib timestamp + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x2C, 0x33, 0x2C, 0x33, 0x2C, 0x00, 0x9C, 0x00, 0x9C, + 0x00, 0x00, 0x00, 0x00, 0x9C, # Calibration bytes + 0x1E, 0x00, 0x01, 0x15, # 1 byte ID, 2 bytes Range, 1 byte data length + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # Calib timestamp + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x96, 0x19, 0x96, 0x19, 0x96, 0x00, 0x9C, 0x00, 0x9C, + 0x00, 0x00, 0x00, 0x00, 0x9C, # Calibration bytes + 0x1E, 0x00, 0x02, 0x15, # 1 byte ID, 2 bytes Range, 1 byte data length + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # Calib timestamp + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0xD0, 0x0C, 0xD0, 0x0C, 0xD0, 0x00, 0x9C, 0x00, 0x9C, + 0x00, 0x00, 0x00, 0x00, 0x9C, # Calibration bytes + 0x1E, 0x00, 0x03, 0x15, # 1 byte ID, 2 bytes Range, 1 byte data length + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # Calib timestamp + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x68, 0x06, 0x68, 0x06, 0x68, 0x00, 0x9C, 0x00, 0x9C, + 0x00, 0x00, 0x00, 0x00, 0x9C, # Calibration bytes + + # 0x1F = SC_SENSOR_WR_ACCEL + 0x1F, 0x00, 0x00, 0x15, # 1 byte ID, 2 bytes Range, 1 byte data length + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # Calib timestamp + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x87, 0x06, 0x87, 0x06, 0x87, 0x00, 0x9C, 0x00, 0x64, + 0x00, 0x00, 0x00, 0x00, 0x9C, # Calibration bytes + 0x1F, 0x00, 0x01, 0x15, # 1 byte ID, 2 bytes Range, 1 byte data length + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # Calib timestamp + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD1, 0x00, 0xD1, 0x00, 0xD1, 0x00, 0x9C, 0x00, 0x64, + 0x00, 0x00, 0x00, 0x00, 0x9C, # Calibration bytes + 0x1F, 0x00, 0x02, 0x15, # 1 byte ID, 2 bytes Range, 1 byte data length + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # Calib timestamp + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x44, 0x03, 0x44, 0x03, 0x44, 0x00, 0x9C, 0x00, 0x64, + 0x00, 0x00, 0x00, 0x00, 0x9C, # Calibration bytes + 0x1F, 0x00, 0x03, 0x15, # 1 byte ID, 2 bytes Range, 1 byte data length + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # Calib timestamp + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xA2, 0x01, 0xA2, 0x01, 0xA2, 0x00, 0x9C, 0x00, 0x64, + 0x00, 0x00, 0x00, 0x00, 0x9C, # Calibration bytes + + # 0x20 = SC_SENSOR_WR_MAG + 0x20, 0x00, 0x00, 0x15, # 1 byte ID, 2 bytes Range, 1 byte data length + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # Calib timestamp + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x9B, 0x02, 0x9B, 0x02, 0x9B, 0x00, 0x9C, 0x00, 0x64, + 0x00, 0x00, 0x00, 0x00, 0x9C] # Calibration bytes + + self.bt_cmd_test_set_common(shimmer_comms_bluetooth.BtCmds.SET_CALIB_DUMP_COMMAND, tx_bytes, + shimmer_comms_bluetooth.BtCmds.GET_CALIB_DUMP_COMMAND, + shimmer_comms_bluetooth.BtCmds.RSP_CALIB_DUMP_COMMAND, 2) + + def test_78_set_crc(self): + print("Test 78 - Set CRC Command") + self.shimmer.bt_crc_byte_count = 1 # 1 = 1 byte CRC, 2 = 2 bytes CRC (default = 0) + self.shimmer.bluetooth_port.send_bluetooth( + [shimmer_comms_bluetooth.BtCmds.SET_CRC_COMMAND, self.shimmer.bt_crc_byte_count]) + self.bt_cmd_test_wait_for_ack() + + # Using inquiry command here to test whether CRC has been enabled + response = self.bt_cmd_test_get_common(shimmer_comms_bluetooth.BtCmds.INQUIRY_COMMAND, + shimmer_comms_bluetooth.BtCmds.INQUIRY_RESPONSE, 8) + + self.shimmer.bt_crc_byte_count = 0 # 1 = 1 byte CRC, 2 = 2 bytes CRC (default = 0) + self.shimmer.bluetooth_port.send_bluetooth( + [shimmer_comms_bluetooth.BtCmds.SET_CRC_COMMAND, self.shimmer.bt_crc_byte_count]) + self.bt_cmd_test_wait_for_ack() + + # Make sure CRC gets disabled + response = self.bt_cmd_test_get_common(shimmer_comms_bluetooth.BtCmds.INQUIRY_COMMAND, + shimmer_comms_bluetooth.BtCmds.INQUIRY_RESPONSE, 8) + + def test_79_set_rwc(self): + print("Test 79 - Set RWC command") + ts_ms = time.time() + tx_bytes = util_shimmer_time.ms_to_shimmer_rtc_bytes(ts_ms) + self.bt_cmd_test_set_common(shimmer_comms_bluetooth.BtCmds.SET_RWC_COMMAND, tx_bytes, + shimmer_comms_bluetooth.BtCmds.GET_RWC_COMMAND, + shimmer_comms_bluetooth.BtCmds.RWC_RESPONSE) + + def test_80_update_calib_dump(self): # not present in set + print("Test 80 - UPD Calib Dump Command") + self.shimmer.bluetooth_port.send_bluetooth([shimmer_comms_bluetooth.BtCmds.UPD_CALIB_DUMP_COMMAND]) + self.bt_cmd_test_wait_for_ack() + + def test_81_update_sdlog_cfg(self): + print("Test 81 - UPD SDlog Cfg Command") + self.shimmer.bluetooth_port.send_bluetooth([shimmer_comms_bluetooth.BtCmds.UPD_SDLOG_CFG_COMMAND]) + self.bt_cmd_test_wait_for_ack() + + # TODO set charge status not supported in LogAndStream + # def test_82_set_charge_status(self): + # print("Test 82 - Set charge status LED") + # + # tx_bytes = [0x01] + # self.bt_cmd_test_set_common(shimmer_comms_bluetooth.BtCmds.SET_CHARGE_STATUS_LED_COMMAND, tx_bytes, + # shimmer_comms_bluetooth.BtCmds.GET_CHARGE_STATUS_LED_COMMAND, + # shimmer_comms_bluetooth.BtCmds.CHARGE_STATUS_LED_RESPONSE) + + def test_83_set_alt_accel(self): + print("Test 83 - Set alt accel") + tx_bytes = [0x01] + self.bt_cmd_test_set_common(shimmer_comms_bluetooth.BtCmds.SET_ALT_ACCEL_RANGE_COMMAND, tx_bytes, + shimmer_comms_bluetooth.BtCmds.GET_ALT_ACCEL_RANGE_COMMAND, + shimmer_comms_bluetooth.BtCmds.ALT_ACCEL_RANGE_RESPONSE) + + def test_84_set_pres_oversampling_ratio(self): + print("Test 84 - Set pres oversampling ratio") + tx_bytes = [0x01] + self.bt_cmd_test_set_common(shimmer_comms_bluetooth.BtCmds.SET_PRES_OVERSAMPLING_RATIO_COMMAND, tx_bytes, + shimmer_comms_bluetooth.BtCmds.GET_PRES_OVERSAMPLING_RATIO_COMMAND, + shimmer_comms_bluetooth.BtCmds.PRES_OVERSAMPLING_RATIO_RESPONSE) + + def test_85_set_daughter_card_mem(self): + print("Test 85 - Set daughter card mem") + + shimmer_name = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." + tx_bytes = [ord(c) for c in shimmer_name] + + self.bt_cmd_test_set_common([shimmer_comms_bluetooth.BtCmds.SET_DAUGHTER_CARD_MEM_COMMAND, len(tx_bytes), 0, 0], + tx_bytes, + [shimmer_comms_bluetooth.BtCmds.GET_DAUGHTER_CARD_MEM_COMMAND, len(tx_bytes), 0, 0], + shimmer_comms_bluetooth.BtCmds.DAUGHTER_CARD_MEM_RESPONSE) + + # Reset the EEPROM memory + tx_bytes = [0xFF] * len(shimmer_name) + self.bt_cmd_test_set_common([shimmer_comms_bluetooth.BtCmds.SET_DAUGHTER_CARD_MEM_COMMAND, len(tx_bytes), 0, 0], + tx_bytes, + [shimmer_comms_bluetooth.BtCmds.GET_DAUGHTER_CARD_MEM_COMMAND, len(tx_bytes), 0, 0], + shimmer_comms_bluetooth.BtCmds.DAUGHTER_CARD_MEM_RESPONSE) + + # TODO decide what to do about this command + # def test_86_start_streaming_and_logging(self): + # print("Test 86 - streaming and logging") + # self.shimmer.bluetooth_port.send_bluetooth([shimmer_comms_bluetooth.BtCmds.START_SDBT_COMMAND]) + # self.bt_cmd_test_wait_for_ack() + + # TODO decide what to do about this command + # def test_87_stop_streaming_and_logging(self): + # print("Test 87 - streaming and logging") + # self.shimmer.bluetooth_port.send_bluetooth([shimmer_comms_bluetooth.BtCmds.STOP_SDBT_COMMAND]) + # self.bt_cmd_test_wait_for_ack() + + # TODO decide what to do about this command + # def test_88_set_data_rate_test(self): + # print("Test 88 - Set data rate test") + # self.assertTrue(False, "Test not implemented yet") + + def test_89_set_instream_response(self): + print(" Test 89: Instream response ack") + tx_bytes = [0x00] # default 1 + self.shimmer.bluetooth_port.send_bluetooth( + [shimmer_comms_bluetooth.BtCmds.SET_INSTREAM_RESPONSE_ACK_PREFIX_STATE] + tx_bytes) + self.bt_cmd_test_wait_for_ack() + + def test_90_set_sd_sync_response(self): + print("test 90: Set SD Sync") + + ts_ms = time.time() + tx_bytes = util_shimmer_time.ms_to_shimmer_rtc_bytes(ts_ms) + tx_bytes = [0x00] + tx_bytes + [0x00] # first byte is to mock whether sensor isSensing, last byte mocks CRC + self.shimmer.bluetooth_port.send_bluetooth( + [shimmer_comms_bluetooth.BtCmds.SET_SD_SYNC_COMMAND] + tx_bytes) + self.bt_cmd_test_wait_for_ack() + + # TODO decide what to do about this command + # def test_91_start_logging(self): + # print("Test 91 - Start logging") + # self.shimmer.bluetooth_port.send_bluetooth([shimmer_comms_bluetooth.BtCmds.START_LOGGING_COMMAND]) + # self.bt_cmd_test_wait_for_ack() + + # TODO decide what to do about this command + # def test_92_stop_logging(self): + # print("Test 92 - Stop logging") + # self.shimmer.bluetooth_port.send_bluetooth([shimmer_comms_bluetooth.BtCmds.STOP_LOGGING_COMMAND]) + # self.bt_cmd_test_wait_for_ack() + + def test_93_toggle_LED(self): + print("Test 93 - toggle LED") + + self.test_28_get_status(True) + red_led_state_before = self.shimmer.status_toggle_led_red + + self.shimmer.bluetooth_port.send_bluetooth([shimmer_comms_bluetooth.BtCmds.TOGGLE_LED_COMMAND]) + self.bt_cmd_test_wait_for_ack() + + self.test_28_get_status(True) + + red_led_state_after = self.shimmer.status_toggle_led_red + self.assertTrue(red_led_state_before != red_led_state_after, "LED state didn't change in status") + + # Turn LED off at end of test + if self.shimmer.status_toggle_led_red: + self.shimmer.bluetooth_port.send_bluetooth([shimmer_comms_bluetooth.BtCmds.TOGGLE_LED_COMMAND]) + self.bt_cmd_test_wait_for_ack() + + def test_94_dummy_command(self): + print("Test 94 - DummyCommand") + self.shimmer.bluetooth_port.send_bluetooth([shimmer_comms_bluetooth.BtCmds.DUMMY_COMMAND]) + self.bt_cmd_test_wait_for_ack() + + # TODO decide what to do about this command + # def test_95_Start_Streaming(self): + # print("Test 95 - Start Streaming") + # self.shimmer.bluetooth_port.send_bluetooth([shimmer_comms_bluetooth.BtCmds.START_STREAMING_COMMAND]) + # self.bt_cmd_test_wait_for_ack() + + # TODO decide what to do about this command + # def test_96_Stop_Streaming(self): + # print("Test 95 - Stop Streaming") + # self.shimmer.bluetooth_port.send_bluetooth([shimmer_comms_bluetooth.BtCmds.STOP_STREAMING_COMMAND]) + # self.bt_cmd_test_wait_for_ack() + + def test_99_reset_config_and_calib_after_testing(self): + print("\r\nResetting Shimmer's config and calibration\r\n") + self.test_02_reset_default_config(True) + self.test_03_reset_default_calib(True) + + +if __name__ == '__main__': + unittest.main() diff --git a/LogAndStream/python_scripts/Docked commands/example_01_uart_cmds.py b/LogAndStream/python_scripts/Docked commands/example_01_uart_cmds.py deleted file mode 100644 index 586df79..0000000 --- a/LogAndStream/python_scripts/Docked commands/example_01_uart_cmds.py +++ /dev/null @@ -1,146 +0,0 @@ -#!/usr/bin/python -import shimmer_app_common -import shimmer_device -import shimmer_uart -import util_shimmer_time - -com_port = shimmer_app_common.get_selected_com_port() -if not com_port: - print("Supported COM port not found, exiting") - exit() - -shimmer = shimmer_device.Shimmer3() - -if not shimmer.setup_dock_com_port(com_port, debug_txrx_packets=True): - exit() - -print("Read MAC ID:") -if not shimmer.dock_port.read_mac_id(): - print("Error, exiting") - exit() -print(shimmer.mac_id) -print("") - -print("Read HW/FW version:") -if not shimmer.dock_port.read_hw_fw_ver(): - print("Error, exiting") - exit() -shimmer.print_hw_fw_revision() -print("") - -print("Read Bluetooth version:") -if not shimmer.dock_port.read_bluetooth_ver(): - # Not all firmware versions support this command - print("Error") -print(shimmer.bluetooth_ver_str) -print("") - -print("Read battery:") -if not shimmer.dock_port.read_batt(): - print("Error, exiting") - exit() -shimmer.print_batt_status() -print("") - -print("Write time from PC:") -if not shimmer.dock_port.write_real_world_clock_from_pc_time(): - print("Error, exiting") - exit() -print("Success") -print("") - -print("Read real-time-clock config time:") -ts_ms = shimmer.dock_port.read_real_world_clock_config_time() -if isinstance(ts_ms, bool): - print("Error, exiting") - exit() -print(util_shimmer_time.seconds_to_time_str(ts_ms / 1000, True)) -print("") - -print("Read current time:") -ts_ms = shimmer.dock_port.read_current_time() -if isinstance(ts_ms, bool): - print("Error, exiting") - exit() -print(util_shimmer_time.seconds_to_time_str(ts_ms / 1000, True)) -print("") - -print("Read Daughter Card ID:") -if shimmer.dock_port.read_daughter_card_id(): - shimmer.print_daughter_card_id() -else: - print("No expansion board detected") -print("") - -print("Write Daughter Card ID:") -if shimmer.dock_port.write_daughter_card_id(shimmer.daughter_card_id, shimmer.daughter_card_rev_major, - shimmer.daughter_card_rev_minor) \ - and shimmer.dock_port.read_daughter_card_id(): - shimmer.print_daughter_card_id() -else: - print("No expansion board detected") -print("") - -print("Read Daughter Card Mem:") -eeprom_bytes_backup = None -eeprom_bytes = shimmer.dock_port.read_daughter_card_mem() -if isinstance(eeprom_bytes, bool): - print("No expansion board detected") -else: - print(shimmer_uart.byte_array_to_hex_string(eeprom_bytes)) - eeprom_bytes_backup = eeprom_bytes -print("") - -if eeprom_bytes_backup is not None: - print("Write Daughter Card Mem:") - # test_buf = [0xFF] * 128 - test_buf = [i for i in range(0, 128)] - result = shimmer.dock_port.write_daughter_card_mem(test_buf) - if result: - eeprom_bytes = shimmer.dock_port.read_daughter_card_mem() - print("Success" if test_buf == eeprom_bytes else "FAIL") - print("Restoring Daughter Card Mem contents") - result = shimmer.dock_port.write_daughter_card_mem(eeprom_bytes_backup) - else: - print("Error") - print("") - -print("Read Infomem:") -infomem_bytes_backup = None -infomem_bytes = shimmer.dock_port.read_infomem() -if isinstance(infomem_bytes, bool): - print("Error") -else: - print(shimmer_uart.byte_array_to_hex_string(infomem_bytes)) - infomem_bytes_backup = infomem_bytes -print("") - -if infomem_bytes_backup is not None: - print("Write Infomem:") - test_buf = [(i & 0xFF) for i in range(0, 384)] - result = shimmer.dock_port.write_infomem(test_buf) - if result: - infomem_bytes = shimmer.dock_port.read_infomem() - - result = True - for i in range(0, 384): - # Shimmer FW protects these bytes 224-229 as the MAC address is stored here - if 224 <= i <= 229: - pass - # TODO unsure why FW is masking byte index 213, bit 5 - elif i == 213 and (infomem_bytes[i] & 0xEF) == (test_buf[i] & 0xEF): - pass - elif infomem_bytes[i] != test_buf[i]: - print("Index=" + str(i) + ": " - + shimmer_uart.byte_array_to_hex_string([infomem_bytes[i]]) - + "!=" + shimmer_uart.byte_array_to_hex_string([test_buf[i]])) - result = False - break - print("Success" if result else "FAIL") - print("Restoring Infomem contents") - result = shimmer.dock_port.write_infomem(infomem_bytes_backup) - else: - print("Error") - print("") - -print("All done") diff --git a/LogAndStream/python_scripts/Docked commands/example_02_uart_cmd_only_current_time.py b/LogAndStream/python_scripts/Docked commands/example_02_uart_cmd_only_current_time.py index cacb435..b8a597d 100644 --- a/LogAndStream/python_scripts/Docked commands/example_02_uart_cmd_only_current_time.py +++ b/LogAndStream/python_scripts/Docked commands/example_02_uart_cmd_only_current_time.py @@ -1,9 +1,7 @@ #!/usr/bin/python import time -import shimmer_app_common -import shimmer_device -import util_shimmer_time +from Shimmer_common import util_shimmer_time, shimmer_device, shimmer_app_common com_port = shimmer_app_common.get_selected_com_port() if not com_port: diff --git a/LogAndStream/python_scripts/Docked commands/shimmer_device.py b/LogAndStream/python_scripts/Docked commands/shimmer_device.py deleted file mode 100644 index 5cf857c..0000000 --- a/LogAndStream/python_scripts/Docked commands/shimmer_device.py +++ /dev/null @@ -1,90 +0,0 @@ -import serial.tools.list_ports - -import shimmer_uart - - -def serial_ports_shimmer_dock(): - serial_port_list = serial_ports() - serial_port_list_filtered = [] - for item in serial_port_list: - if "USB Serial Port" in item.description \ - and (("PID=0403:6010" in item.hwid and item.hwid.endswith("B")) - or ("PID=0403:6011" in item.hwid and item.hwid.endswith("D"))): - serial_port_list_filtered += [item] - return serial_port_list_filtered - - -def serial_ports(): - ports = serial.tools.list_ports.comports() - # for port, desc, hwid in sorted(ports): - # print("{}: {} [{}]".format(port, desc, hwid)) - return ports - - -class Shimmer3: - mac_id = None - - hw_ver = None - fw_id = None - fw_ver_major = None - fw_ver_minor = None - fw_ver_internal = None - - daughter_card_id = None - daughter_card_rev_major = None - daughter_card_rev_minor = None - - bluetooth_ver_str = None - - batt_adc_value = None - charging_status = None - - def __init__(self): - self.dock_port = shimmer_uart.ShimmerUart(self) - - def setup_dock_com_port(self, com_port, debug_txrx_packets=False): - return self.dock_port.setup_serial_port(com_port, 115200, debug_txrx_packets) - - def parse_hw_fw_ver_bytes(self, byte_buf): - index = 0 - if len(byte_buf) == 7: - self.hw_ver = byte_buf[index] - index += 1 - elif len(byte_buf) == 8: - self.hw_ver = (byte_buf[index] | (byte_buf[index + 1] << 8)) - index += 2 - - self.fw_id = ((byte_buf[index]) | (byte_buf[index + 1] << 8)) - index += 2 - self.fw_ver_major = ((byte_buf[index]) | (byte_buf[index + 1] << 8)) - index += 2 - self.fw_ver_minor = byte_buf[index] - index += 1 - self.fw_ver_internal = byte_buf[index] - - def parse_daughter_card_id(self, byte_buf): - self.daughter_card_id = byte_buf[0] - self.daughter_card_rev_major = byte_buf[1] - self.daughter_card_rev_minor = byte_buf[2] - - def parse_infomem(self, byte_buf): - # TODO - return - - def set_bluetooth_ver_str(self, byte_buf): - self.bluetooth_ver_str = bytearray(byte_buf).decode("ASCII") - - def print_hw_fw_revision(self): - print("HW Revision: " + str(self.hw_ver)) - print("FW Revision: ID=" + str(self.fw_id) - + ", v" + str(self.fw_ver_major) - + "." + str(self.fw_ver_minor) - + "." + str(self.fw_ver_internal)) - - def print_daughter_card_id(self): - print("SR" + str(self.daughter_card_id) - + "." + str(self.daughter_card_rev_major) - + "." + str(self.daughter_card_rev_minor)) - - def print_batt_status(self): - print("ADC Value=" + str(self.batt_adc_value) + ", Charging status=" + str(self.charging_status)) diff --git a/LogAndStream/python_scripts/Docked commands/test_docked_cmds.py b/LogAndStream/python_scripts/Docked commands/test_docked_cmds.py new file mode 100644 index 0000000..411fac2 --- /dev/null +++ b/LogAndStream/python_scripts/Docked commands/test_docked_cmds.py @@ -0,0 +1,239 @@ +#!/usr/bin/python +import unittest + +from Shimmer_common import util_shimmer, util_shimmer_time, shimmer_device, shimmer_app_common + + +class TestShimmerDockCommunication(unittest.TestCase): + shimmer = None + eeprom_bytes_backup = None + infomem_bytes_backup = None + calib_bytes_backup = None + + @classmethod + def setUpClass(cls): + com_port = shimmer_app_common.get_selected_com_port() + if not com_port: + print("Supported COM port not found, exiting") + exit() + + cls.shimmer = shimmer_device.Shimmer3() + + if not cls.shimmer.setup_dock_com_port(com_port, debug_txrx_packets=True): + exit() + + @classmethod + def tearDownClass(cls): + # cls._connection.destroy() + print("All done") + + def test_01_read_mac_id(self): + print("Read MAC ID:") + if not self.shimmer.dock_port.read_mac_id(): + print("Error, exiting") + self.assertTrue(False) + print(self.shimmer.mac_id) + print("") + + def test_02_read_hw_fw_ver(self): + print("Read HW/FW version:") + if not self.shimmer.dock_port.read_hw_fw_ver(): + print("Error, exiting") + self.assertTrue(False) + self.shimmer.print_hw_fw_revision() + print("") + + def test_03_read_bluetooth_ver(self): + print("Read Bluetooth version:") + if not self.shimmer.dock_port.read_bluetooth_ver(): + # Not all firmware versions support this command + print("Error") + self.assertTrue(False) + print(self.shimmer.bluetooth_ver_str) + print("") + + def test_04_read_battery(self): + print("Read battery:") + if not self.shimmer.dock_port.read_batt(): + print("Error, exiting") + self.assertTrue(False) + self.shimmer.print_batt_status() + print("") + + def test_05_write_real_world_clock(self): + print("Write time from PC:") + if not self.shimmer.dock_port.write_real_world_clock_from_pc_time(): + print("Error, exiting") + self.assertTrue(False) + print("Success") + print("") + + def test_06_read_real_world_clock_config_time(self): + print("Read real-time-clock config time:") + ts_ms = self.shimmer.dock_port.read_real_world_clock_config_time() + if isinstance(ts_ms, bool): + print("Error, exiting") + self.assertTrue(False) + print(util_shimmer_time.seconds_to_time_str(ts_ms / 1000, True)) + print("") + + def test_07_read_current_time(self): + print("Read current time:") + ts_ms = self.shimmer.dock_port.read_current_time() + if isinstance(ts_ms, bool): + print("Error, exiting") + self.assertTrue(False) + print(util_shimmer_time.seconds_to_time_str(ts_ms / 1000, True)) + print("") + + def test_08_read_daughter_card_id(self): + print("Read Daughter Card ID:") + if self.shimmer.dock_port.read_daughter_card_id(): + self.shimmer.print_daughter_card_id() + else: + print("No expansion board detected") + print("") + + def test_09_write_daughter_card_id(self): + print("Write Daughter Card ID:") + if self.shimmer.daughter_card_id is None \ + or self.shimmer.daughter_card_rev_major is None \ + or self.shimmer.daughter_card_rev_minor is None: + self.assertTrue(False) + + if self.shimmer.dock_port.write_daughter_card_id(self.shimmer.daughter_card_id, + self.shimmer.daughter_card_rev_major, + self.shimmer.daughter_card_rev_minor) \ + and self.shimmer.dock_port.read_daughter_card_id(): + self.shimmer.print_daughter_card_id() + else: + print("No expansion board detected") + print("") + + def test_10_read_write_daughter_card_memory(self): + print("Read Daughter Card Mem:") + eeprom_bytes = self.shimmer.dock_port.read_daughter_card_mem() + if isinstance(eeprom_bytes, bool): + print("No expansion board detected") + else: + print(util_shimmer.byte_array_to_hex_string(eeprom_bytes)) + self.eeprom_bytes_backup = eeprom_bytes + print("") + + if self.eeprom_bytes_backup is not None: + print("Write Daughter Card Mem:") + # test_buf = [0xFF] * 128 + test_buf = [i for i in range(0, 128)] + result = self.shimmer.dock_port.write_daughter_card_mem(test_buf) + if result: + eeprom_bytes = self.shimmer.dock_port.read_daughter_card_mem() + print("Success" if test_buf == eeprom_bytes else "FAIL") + print("Restoring Daughter Card Mem contents") + result = self.shimmer.dock_port.write_daughter_card_mem(self.eeprom_bytes_backup) + self.assertTrue(result) + else: + self.assertTrue(False) + print("Error") + print("") + + def test_11_read_write_infomem(self): + print("Read Infomem:") + infomem_bytes = self.shimmer.dock_port.read_infomem() + if isinstance(infomem_bytes, bool): + print("Error") + self.assertTrue(False) + else: + print(util_shimmer.byte_array_to_hex_string(infomem_bytes)) + self.infomem_bytes_backup = infomem_bytes + print("") + + if self.infomem_bytes_backup is not None: + print("Write Infomem:") + test_buf = [(i & 0xFF) for i in range(0, 384)] + print("- Writing test buffer") + result = self.shimmer.dock_port.write_infomem(test_buf) + if result: + print("- Reading back") + infomem_bytes = self.shimmer.dock_port.read_infomem() + if isinstance(infomem_bytes, bool): + print("Error") + self.assertTrue(False) + else: + print(util_shimmer.byte_array_to_hex_string(infomem_bytes)) + + print("-Checking each byte") + result = True + for i in range(0, 384): + # Shimmer FW protects these bytes 224-229 as the MAC address is stored here + if 224 <= i <= 229: + pass + # TODO unsure why FW is masking byte index 213, bit 5 + elif i == 213 and (infomem_bytes[i] & 0xEF) == (test_buf[i] & 0xEF): + pass + elif infomem_bytes[i] != test_buf[i]: + print("Index=" + str(i) + ": " + + util_shimmer.byte_array_to_hex_string([infomem_bytes[i]]) + + "!=" + util_shimmer.byte_array_to_hex_string([test_buf[i]])) + result = False + break + print("Success" if result else "FAIL") + print("- Restoring Infomem contents") + resultRestore = self.shimmer.dock_port.write_infomem(self.infomem_bytes_backup) + self.assertTrue(result) + self.assertTrue(resultRestore) + else: + print("Error") + self.assertTrue(False) + print("") + + # def test_12_read_write_calibration(self): + # print("Read Calibration:") + # calib_bytes = self.shimmer.dock_port.read_calibration() + # if isinstance(calib_bytes, bool): + # print("Error") + # self.assertTrue(False) + # else: + # print(util_shimmer.byte_array_to_hex_string(calib_bytes)) + # self.calib_bytes_backup = calib_bytes + # print("") + # + # if self.calib_bytes_backup is not None: + # print("Write Calibration:") + # lenCalib = 1024 - 2 - 8 # 1024 = full memory size, minus 2 for length bytes, minus 8 for device version info + # test_buf = [lenCalib & 0xFF, (lenCalib >> 8) & 0xFF, 0, 0, 0, 0, 0, 0, 0, 0] + # test_buf += [(i & 0xFF) for i in range(0, lenCalib)] + # print("- Writing test buffer") + # result = self.shimmer.dock_port.write_calibration(test_buf) + # if result: + # print("- Reading back") + # calib_bytes = self.shimmer.dock_port.read_calibration() + # if isinstance(calib_bytes, bool): + # print("Error") + # self.assertTrue(False) + # else: + # print(util_shimmer.byte_array_to_hex_string(calib_bytes)) + # + # print("-Checking each byte") + # result = True + # for i in range(0, 1024): + # # Skip device version info + # if 2 <= i <= 9: + # pass + # elif calib_bytes[i] != test_buf[i]: + # print("Index=" + str(i) + ": " + # + util_shimmer.byte_array_to_hex_string([calib_bytes[i]]) + # + "!=" + util_shimmer.byte_array_to_hex_string([test_buf[i]])) + # result = False + # self.assertTrue(False) + # break + # print("Success" if result else "FAIL") + # print("- Restoring Infomem contents") + # result = self.shimmer.dock_port.write_calibration(self.calib_bytes_backup) + # else: + # print("Error") + # self.assertTrue(False) + # print("") + + +if __name__ == '__main__': + unittest.main() diff --git a/LogAndStream/python_scripts/Docked commands/shimmer_app_common.py b/LogAndStream/python_scripts/Shimmer_common/shimmer_app_common.py similarity index 77% rename from LogAndStream/python_scripts/Docked commands/shimmer_app_common.py rename to LogAndStream/python_scripts/Shimmer_common/shimmer_app_common.py index ea7f789..33ce5d9 100644 --- a/LogAndStream/python_scripts/Docked commands/shimmer_app_common.py +++ b/LogAndStream/python_scripts/Shimmer_common/shimmer_app_common.py @@ -1,12 +1,15 @@ import sys -import shimmer_device +from Shimmer_common import shimmer_device -def get_selected_com_port(): +def get_selected_com_port(dock_ports=True): com_port = '' if len(sys.argv) < 2: - options = shimmer_device.serial_ports_shimmer_dock() + if dock_ports: + options = shimmer_device.serial_ports_shimmer_dock() + else: + options = shimmer_device.serial_ports_bluetooth() if len(options) > 0: user_input = '' diff --git a/LogAndStream/python_scripts/Shimmer_common/shimmer_comms_bluetooth.py b/LogAndStream/python_scripts/Shimmer_common/shimmer_comms_bluetooth.py new file mode 100644 index 0000000..9cf1ab8 --- /dev/null +++ b/LogAndStream/python_scripts/Shimmer_common/shimmer_comms_bluetooth.py @@ -0,0 +1,346 @@ +import binascii +from turtle import delay + +import serial +import time +import struct + +import serial.win32 +from serial import SerialException, Serial +from Shimmer_common import util_shimmer + + +class BtCmds: + DATA_PACKET = 0x00 + INQUIRY_COMMAND = 0x01 + INQUIRY_RESPONSE = 0x02 + GET_SAMPLING_RATE_COMMAND = 0x03 + SAMPLING_RATE_RESPONSE = 0x04 + SET_SAMPLING_RATE_COMMAND = 0x05 + TOGGLE_LED_COMMAND = 0x06 + START_STREAMING_COMMAND = 0x07 # maintain compatibility with Shimmer2/2r BtStream + SET_SENSORS_COMMAND = 0x08 + SET_ACCEL_RANGE_COMMAND = 0x09 + ACCEL_RANGE_RESPONSE = 0x0A + GET_ACCEL_RANGE_COMMAND = 0x0B + SET_CONFIG_SETUP_BYTES_COMMAND = 0x0E + CONFIG_SETUP_BYTES_RESPONSE = 0x0F + GET_CONFIG_SETUP_BYTES_COMMAND = 0x10 + SET_A_ACCEL_CALIBRATION_COMMAND = 0x11 + A_ACCEL_CALIBRATION_RESPONSE = 0x12 + GET_A_ACCEL_CALIBRATION_COMMAND = 0x13 + SET_GYRO_CALIBRATION_COMMAND = 0x14 + GYRO_CALIBRATION_RESPONSE = 0x15 + GET_GYRO_CALIBRATION_COMMAND = 0x16 + SET_MAG_CALIBRATION_COMMAND = 0x17 + MAG_CALIBRATION_RESPONSE = 0x18 + GET_MAG_CALIBRATION_COMMAND = 0x19 + SET_ACCEL_CALIBRATION_COMMAND = 0x1A + ACCEL_CALIBRATION_RESPONSE = 0x1B + GET_ACCEL_CALIBRATION_COMMAND = 0x1C + STOP_STREAMING_COMMAND = 0x20 # maintain compatibility with Shimmer2/2r BtStream + SET_GSR_RANGE_COMMAND = 0x21 + GSR_RANGE_RESPONSE = 0x22 + GET_GSR_RANGE_COMMAND = 0x23 + # DEPRECATED_GET_DEVICE_VERSION_COMMAND = 0x24 + DEVICE_VERSION_RESPONSE = 0x25 # maintain compatibility with Shimmer2/2r BtStream + SET_EMG_CALIBRATION_COMMAND = 0x26 + EMG_CALIBRATION_RESPONSE = 0x27 + GET_EMG_CALIBRATION_COMMAND = 0x28 + SET_ECG_CALIBRATION_COMMAND = 0x29 + ECG_CALIBRATION_RESPONSE = 0x2A + GET_ECG_CALIBRATION_COMMAND = 0x2B + GET_ALL_CALIBRATION_COMMAND = 0x2C + ALL_CALIBRATION_RESPONSE = 0x2D + GET_FW_VERSION_COMMAND = 0x2E # maintain compatibility with Shimmer2/2r BtStream + FW_VERSION_RESPONSE = 0x2F # maintain compatibility with Shimmer2/2r BtStream + SET_CHARGE_STATUS_LED_COMMAND = 0x30 + CHARGE_STATUS_LED_RESPONSE = 0x31 + GET_CHARGE_STATUS_LED_COMMAND = 0x32 + BUFFER_SIZE_RESPONSE = 0x35 + GET_BUFFER_SIZE_COMMAND = 0x36 + SET_MAG_GAIN_COMMAND = 0x37 + MAG_GAIN_RESPONSE = 0x38 + GET_MAG_GAIN_COMMAND = 0x39 + SET_MAG_SAMPLING_RATE_COMMAND = 0x3A + MAG_SAMPLING_RATE_RESPONSE = 0x3B + GET_MAG_SAMPLING_RATE_COMMAND = 0x3C + UNIQUE_SERIAL_RESPONSE = 0x3D + GET_UNIQUE_SERIAL_COMMAND = 0x3E + GET_DEVICE_VERSION_COMMAND = 0x3F + SET_ACCEL_SAMPLING_RATE_COMMAND = 0x40 + ACCEL_SAMPLING_RATE_RESPONSE = 0x41 + GET_ACCEL_SAMPLING_RATE_COMMAND = 0x42 + SET_ACCEL_LPMODE_COMMAND = 0x43 + ACCEL_LPMODE_RESPONSE = 0x44 + GET_ACCEL_LPMODE_COMMAND = 0x45 + SET_ACCEL_HRMODE_COMMAND = 0x46 + ACCEL_HRMODE_RESPONSE = 0x47 + GET_ACCEL_HRMODE_COMMAND = 0x48 + SET_GYRO_RANGE_COMMAND = 0x49 + GYRO_RANGE_RESPONSE = 0x4A + GET_GYRO_RANGE_COMMAND = 0x4B + SET_GYRO_SAMPLING_RATE_COMMAND = 0x4C + GYRO_SAMPLING_RATE_RESPONSE = 0x4D + GET_GYRO_SAMPLING_RATE_COMMAND = 0x4E + SET_ALT_ACCEL_RANGE_COMMAND = 0x4F + ALT_ACCEL_RANGE_RESPONSE = 0x50 + GET_ALT_ACCEL_RANGE_COMMAND = 0x51 + SET_PRES_OVERSAMPLING_RATIO_COMMAND = 0x52 + PRES_OVERSAMPLING_RATIO_RESPONSE = 0x53 + GET_PRES_OVERSAMPLING_RATIO_COMMAND = 0x54 + BMP180_CALIBRATION_COEFFICIENTS_RESPONSE = 0x58 + GET_BMP180_CALIBRATION_COEFFICIENTS_COMMAND = 0x59 + RESET_TO_DEFAULT_CONFIGURATION_COMMAND = 0x5A + RESET_CALIBRATION_VALUE_COMMAND = 0x5B + ALT_MAG_SENS_ADJ_VALS_RESPONSE = 0x5C + GET_ALT_MAG_SENS_ADJ_VALS_COMMAND = 0x5D + SET_INTERNAL_EXP_POWER_ENABLE_COMMAND = 0x5E + INTERNAL_EXP_POWER_ENABLE_RESPONSE = 0x5F + GET_INTERNAL_EXP_POWER_ENABLE_COMMAND = 0x60 + SET_EXG_REGS_COMMAND = 0x61 + EXG_REGS_RESPONSE = 0x62 + GET_EXG_REGS_COMMAND = 0x63 + SET_DAUGHTER_CARD_ID_COMMAND = 0x64 + DAUGHTER_CARD_ID_RESPONSE = 0x65 + GET_DAUGHTER_CARD_ID_COMMAND = 0x66 + SET_DAUGHTER_CARD_MEM_COMMAND = 0x67 + DAUGHTER_CARD_MEM_RESPONSE = 0x68 + GET_DAUGHTER_CARD_MEM_COMMAND = 0x69 + SET_BT_COMMS_BAUD_RATE = 0x6A + BT_COMMS_BAUD_RATE_RESPONSE = 0x6B + GET_BT_COMMS_BAUD_RATE = 0x6C + SET_DERIVED_CHANNEL_BYTES = 0x6D + DERIVED_CHANNEL_BYTES_RESPONSE = 0x6E + GET_DERIVED_CHANNEL_BYTES = 0x6F + START_SDBT_COMMAND = 0x70 + STATUS_RESPONSE = 0x71 + GET_STATUS_COMMAND = 0x72 + SET_TRIAL_CONFIG_COMMAND = 0x73 + TRIAL_CONFIG_RESPONSE = 0x74 + GET_TRIAL_CONFIG_COMMAND = 0x75 + SET_CENTER_COMMAND = 0x76 + CENTER_RESPONSE = 0x77 + GET_CENTER_COMMAND = 0x78 + SET_SHIMMERNAME_COMMAND = 0x79 + SHIMMERNAME_RESPONSE = 0x7a + GET_SHIMMERNAME_COMMAND = 0x7b + SET_EXPID_COMMAND = 0x7c + EXPID_RESPONSE = 0x7d + GET_EXPID_COMMAND = 0x7e + SET_MYID_COMMAND = 0x7F + MYID_RESPONSE = 0x80 + GET_MYID_COMMAND = 0x81 + SET_NSHIMMER_COMMAND = 0x82 + NSHIMMER_RESPONSE = 0x83 + GET_NSHIMMER_COMMAND = 0x84 + SET_CONFIGTIME_COMMAND = 0x85 + CONFIGTIME_RESPONSE = 0x86 + GET_CONFIGTIME_COMMAND = 0x87 + DIR_RESPONSE = 0x88 + GET_DIR_COMMAND = 0x89 + INSTREAM_CMD_RESPONSE = 0x8A + SET_CRC_COMMAND = 0x8B + SET_INFOMEM_COMMAND = 0x8C + INFOMEM_RESPONSE = 0x8D + GET_INFOMEM_COMMAND = 0x8E + SET_RWC_COMMAND = 0x8F + RWC_RESPONSE = 0x90 + GET_RWC_COMMAND = 0x91 + START_LOGGING_COMMAND = 0x92 + STOP_LOGGING_COMMAND = 0x93 + VBATT_RESPONSE = 0x94 + GET_VBATT_COMMAND = 0x95 + DUMMY_COMMAND = 0x96 + STOP_SDBT_COMMAND = 0x97 + SET_CALIB_DUMP_COMMAND = 0x98 + RSP_CALIB_DUMP_COMMAND = 0x99 + GET_CALIB_DUMP_COMMAND = 0x9A + UPD_CALIB_DUMP_COMMAND = 0x9B + UPD_SDLOG_CFG_COMMAND = 0x9C + BMP280_CALIBRATION_COEFFICIENTS_RESPONSE = 0x9F + GET_BMP280_CALIBRATION_COEFFICIENTS_COMMAND = 0xA0 + GET_BT_VERSION_STR_COMMAND = 0xA1 + BT_VERSION_STR_RESPONSE = 0xA2 + SET_INSTREAM_RESPONSE_ACK_PREFIX_STATE = 0xA3 + SET_DATA_RATE_TEST_MODE = 0xA4 + DATA_RATE_TEST_RESPONSE = 0xA5 + SET_SD_SYNC_COMMAND = 0xE0 + SD_SYNC_RESPONSE = 0xE1 + ACK_COMMAND_PROCESSED = 0xFF + + +class ShimmerBluetooth: + serial_port_timeout_ms = 500 + debug_tx_rx_packets = False + + ser = None + shimmer_device = None + + def __init__(self, shimmer): + self.shimmer_device = shimmer + + def setup_serial_port(self, com_port, baud_rate, debug_txrx_packets=False): + ShimmerBluetooth.debug_tx_rx_packets = debug_txrx_packets + + try: + self.ser = serial.Serial(com_port, baud_rate, timeout=self.serial_port_timeout_ms / 1000) + if self.ser.is_open: + self.ser.flushInput() + print("port opening, done.") + return True + else: + print("can't open port.") + return False + except SerialException: + print("Serial port exception.") + return False + + def clear_serial_buffer(self): + self.ser.flushInput() + self.ser.flushOutput() + + def close_port(self): + self.ser.close() + + def write_calibration(self, calib_bytes=None, timeout_ms=2000): + + if calib_bytes is None: + calib_bytes = [] + len_calib_bytes = len(calib_bytes) + + # calib_bytes = [(len_calib_bytes & 0xFF), ((len_calib_bytes >> 8) & 0xFF)] + calib_bytes + for i in range(0, len_calib_bytes, 128): + bytes_remaining = len_calib_bytes - i + buf_len = 128 if bytes_remaining > 128 else bytes_remaining + + if not self.send_bluetooth( + [BtCmds.SET_CALIB_DUMP_COMMAND, buf_len, i & 0xFF, (i >> 8) & 0xFF] + calib_bytes[i:i + buf_len]): + return False + + if not self.wait_for_ack(timeout_ms): + return False + + return True + + def read_calibration(self, timeout_ms=500): + + calib_dump_concat = [] + overall_mem_length = 0 + length_read_so_far = 0 + first_read = True + while length_read_so_far == 0 or length_read_so_far < overall_mem_length: + length_left_to_read = 128 if first_read else overall_mem_length - length_read_so_far + 2 + length_to_read = 128 if (length_left_to_read >= 128) else length_left_to_read + address = length_read_so_far + + if not self.send_bluetooth([BtCmds.GET_CALIB_DUMP_COMMAND, length_to_read, address & 0xFF, + (address >> 8) & 0xFF]): + return False + + if not self.wait_for_ack(timeout_ms): + return False + + rsp_byte = self.wait_for_response(1) + if rsp_byte[0] != BtCmds.RSP_CALIB_DUMP_COMMAND: + return False + + # +3 for 1 length byte followed byte 2 bytes address + rx_bytes = self.wait_for_response(length_to_read + 3, timeout_ms) + if len(rx_bytes) == 0: + return False + + calib_dump_concat += rx_bytes[3:len(rx_bytes)] + + if first_read: + overall_mem_length = (calib_dump_concat[1] << 8) | calib_dump_concat[0] + first_read = False + + length_read_so_far += length_to_read + + return calib_dump_concat + + def write_configuration(self, tx_bytes=None, timeout_ms=500): + + if tx_bytes is None: + tx_bytes = [] + len_tx_bytes = len(tx_bytes) + + for i in range(0, len_tx_bytes, 128): + bytes_remaining = len_tx_bytes - i + buf_len = 128 if bytes_remaining > 128 else bytes_remaining + + if not self.send_bluetooth( + [BtCmds.SET_INFOMEM_COMMAND, + buf_len, + i & 0xFF, (i >> 8) & 0xFF] + tx_bytes[i:i + buf_len]): + return False + + if not self.wait_for_ack(timeout_ms): + return False + + return True + + def read_configuration(self, timeout_ms=500): + + len_config_bytes = 384 + config_bytes = [] + for i in range(0, len_config_bytes, 128): + bytes_remaining = len_config_bytes - i + buf_len = 128 if bytes_remaining > 128 else bytes_remaining + + if not self.send_bluetooth([BtCmds.GET_INFOMEM_COMMAND, buf_len, i & 0xFF, (i >> 8) & 0xFF]): + return False + + if not self.wait_for_ack(timeout_ms): + return False + + rx_bytes = self.wait_for_response(buf_len + 2, timeout_ms) + if len(rx_bytes) == 0: + return False + + config_bytes += rx_bytes[2:len(rx_bytes)] + + return config_bytes + + def wait_for_ack(self, timeout_ms=500): + response = self.wait_for_response(1, timeout_ms) + return True if response[0] is BtCmds.ACK_COMMAND_PROCESSED else False + + def wait_for_response(self, expected_len, timeout_ms=500): + flag = True + + loop_count = 0 + wait_interval_ms = 100 + loop_count_total = timeout_ms / wait_interval_ms + + rx_buf = [] + + while flag: + time.sleep(wait_interval_ms / 1000) + loop_count += 1 + if loop_count >= loop_count_total: + print("Timeout while waiting for response") + break + + buf_len = self.ser.inWaiting() + if buf_len >= expected_len: + data_read = self.ser.read(expected_len) + if isinstance(data_read, str): + rx_buf += bytearray.fromhex(binascii.hexlify(data_read)) + else: + rx_buf += data_read + + if self.debug_tx_rx_packets: + print("UART RX: " + util_shimmer.byte_array_to_hex_string(rx_buf)) + + break + + return rx_buf + + def send_bluetooth(self, tx_buf): + if self.debug_tx_rx_packets: + print("UART TX: " + util_shimmer.byte_array_to_hex_string(tx_buf)) + self.ser.write(tx_buf) + time.sleep(0.1) + return True diff --git a/LogAndStream/python_scripts/Docked commands/shimmer_uart.py b/LogAndStream/python_scripts/Shimmer_common/shimmer_comms_docked.py similarity index 88% rename from LogAndStream/python_scripts/Docked commands/shimmer_uart.py rename to LogAndStream/python_scripts/Shimmer_common/shimmer_comms_docked.py index 6dc7fc5..44ebc8d 100644 --- a/LogAndStream/python_scripts/Docked commands/shimmer_uart.py +++ b/LogAndStream/python_scripts/Shimmer_common/shimmer_comms_docked.py @@ -4,8 +4,9 @@ import serial from serial import SerialException -import shimmer_crc as shimmerCrc -import util_shimmer_time +from Shimmer_common import shimmer_crc as shimmerCrc +from Shimmer_common import util_shimmer_time +from Shimmer_common import util_shimmer PACKET_HEADER = 0x24 # "$" @@ -45,6 +46,7 @@ class MainProcessor: INFOMEM = 0x06 # LED0_STATE = 0x07 # Used by Shimmer SPAN # DEVICE_BOOT = 0x08 # Not in use + CALIBRATION = 0x07 class Bat: # ENABLE = 0x00 # Not in use @@ -59,42 +61,6 @@ class Bluetooth: VER = 0x03 -def byte_array_to_hex_string(data): - hex_str = "" - first_byte = True - for b in data: - if not first_byte: - hex_str += ' ' - hex_str += "0x%0.2X" % b - first_byte = False - return '[' + hex_str + ']' - - -def byte_array_to_int(data, lsb_order=True, is_signed=False): - number = 0 - i = 0 - - for b in data: - if lsb_order: - number += (b << i * 8) - else: - number = (number << 8) + b - i += 1 - - # two's compliment - if is_signed: - bit_length = len(data) * 8 - # sign_offset = 2 ** (bit_length - 1) - # number -= sign_offset - # Copied from Java implementation but I'm not sure if the maths is exactly correct - if number >= (1 << (bit_length - 1)): - number = -((number ^ ((2 ** bit_length) - 1)) + 1) - - # print('data={}, lsb_order={}, is_signed={}, number={}'.format(byte_array_to_hex_string(data), lsb_order, is_signed, number)) - - return number - - def assemble_tx_packet(uart_cmd=None, uart_component=None, uart_property=None, uart_args=None): if uart_args is None: packet = [PACKET_HEADER, uart_cmd, 2, uart_component, uart_property] @@ -176,7 +142,7 @@ def read_batt(self): if len(response) < 3: return False else: - self.shimmer_device.batt_adc_value = byte_array_to_int(response[0:2]) + self.shimmer_device.batt_adc_value = util_shimmer.byte_array_to_int(response[0:2]) self.shimmer_device.charging_status = response[2] & 0xC0 return True @@ -197,7 +163,7 @@ def read_real_world_clock_config_time(self): response = self.send_uart(tx_buf) if len(response) >= 8: - ts_ticks = byte_array_to_int(response) + ts_ticks = util_shimmer.byte_array_to_int(response) ts_ms = ts_ticks / 32.768 return ts_ms else: @@ -209,7 +175,7 @@ def read_current_time(self): response = self.send_uart(tx_buf) if len(response) >= 8: - ts_ticks = byte_array_to_int(response) + ts_ticks = util_shimmer.byte_array_to_int(response) ts_ms = ts_ticks / 32.768 return ts_ms else: @@ -300,6 +266,27 @@ def write_infomem_b(self, byte_buf): response = self.set_mem_command(UartComponent.MAIN_PROCESSOR, UartProperty.MainProcessor.INFOMEM, 256, byte_buf) return response + def read_calibration(self): + calib_mem = [] + for i in range(0, 1024, 128): + mem = self.get_mem_command(UartComponent.MAIN_PROCESSOR, UartProperty.MainProcessor.CALIBRATION, i, 128) + if isinstance(mem, bool): + return mem + else: + calib_mem += mem + + # # TODO parse calibration + # self.shimmer_device.parse_infomem(response) + + return calib_mem + + def write_calibration(self, byte_buf): + for i in range(0, 1024, 128): + result = self.set_mem_command(UartComponent.MAIN_PROCESSOR, UartProperty.MainProcessor.CALIBRATION, i, byte_buf[i:i+128]) + if not result: + return result + return result + def get_mem_command(self, uart_component, uart_property, address, size): args = [size & 0xFF] if uart_component == UartComponent.DAUGHTER_CARD and uart_property == UartProperty.DaughterCard.CARD_ID: @@ -363,7 +350,7 @@ def wait_for_response(self): or rx_buf[1] == UartPacketCmd.BAD_ARG_RESPONSE \ or rx_buf[1] == UartPacketCmd.BAD_CRC_RESPONSE: if self.debug_tx_rx_packets: - print("UART RX: " + byte_array_to_hex_string(rx_buf)) + print("UART RX: " + util_shimmer.byte_array_to_hex_string(rx_buf)) rx_buf = rx_buf[1] break @@ -373,7 +360,7 @@ def wait_for_response(self): print("CRC fail") else: if self.debug_tx_rx_packets: - print("UART RX: " + byte_array_to_hex_string(rx_buf)) + print("UART RX: " + util_shimmer.byte_array_to_hex_string(rx_buf)) rx_buf = rx_buf[5:len(rx_buf) - 2] break @@ -386,7 +373,7 @@ def wait_for_response(self): def send_uart(self, tx_buf): if self.debug_tx_rx_packets: - print("UART TX: " + byte_array_to_hex_string(tx_buf)) + print("UART TX: " + util_shimmer.byte_array_to_hex_string(tx_buf)) self.ser.write(tx_buf) time.sleep(0.1) response = self.wait_for_response() diff --git a/LogAndStream/python_scripts/Docked commands/shimmer_crc.py b/LogAndStream/python_scripts/Shimmer_common/shimmer_crc.py similarity index 100% rename from LogAndStream/python_scripts/Docked commands/shimmer_crc.py rename to LogAndStream/python_scripts/Shimmer_common/shimmer_crc.py diff --git a/LogAndStream/python_scripts/Shimmer_common/shimmer_device.py b/LogAndStream/python_scripts/Shimmer_common/shimmer_device.py new file mode 100644 index 0000000..5e78ee6 --- /dev/null +++ b/LogAndStream/python_scripts/Shimmer_common/shimmer_device.py @@ -0,0 +1,198 @@ +import serial.tools.list_ports +from enum import Enum + +from Shimmer_common import shimmer_comms_docked, shimmer_comms_bluetooth + + +class SrBoardCodes(Enum): + EXP_BRD_BR_AMP = 8 + EXP_BRD_GSR = 14 + SHIMMER3_IMU = 31 + EXP_BRD_PROTO3_MINI = 36 + EXP_BRD_EXG = 37 + EXP_BRD_PROTO3_DELUXE = 38 + EXP_BRD_ADXL377_ACCEL_200G = 44 + EXP_BRD_EXG_UNIFIED = 47 + EXP_BRD_GSR_UNIFIED = 48 + EXP_BRD_BR_AMP_UNIFIED = 49 + EXP_BRD_H3LIS331DL_ACCEL_HIGH_G = 55 + SHIMMER_GQ_LR = 56 + SHIMMER_GQ_SR = 57 + SHIMMER_ECG_MD = 59 + + +def serial_ports_shimmer_dock(): + serial_port_list = serial_ports() + serial_port_list_filtered = [] + for item in serial_port_list: + if "USB Serial Port" in item.description \ + and (("PID=0403:6010" in item.hwid and item.hwid.endswith("B")) + or ("PID=0403:6011" in item.hwid and item.hwid.endswith("D"))): + serial_port_list_filtered += [item] + return serial_port_list_filtered + + +def serial_ports_bluetooth(): + serial_port_list = serial_ports() + serial_port_list_filtered = [] + for item in serial_port_list: + if "Bluetooth" in item.description: + serial_port_list_filtered += [item] + return serial_port_list_filtered + + +def serial_ports(): + ports = serial.tools.list_ports.comports() + # for port, desc, hwid in sorted(ports): + # print("{}: {} [{}]".format(port, desc, hwid)) + return ports + + +class Shimmer3: + mac_id = None + + hw_ver = None + fw_id = None + fw_ver_major = None + fw_ver_minor = None + fw_ver_internal = None + + daughter_card_id = None + daughter_card_rev_major = None + daughter_card_rev_minor = None + + bluetooth_ver_str = None + + batt_adc_value = None + charging_status = None + + status_toggle_led_red = None + status_sd_error = None + status_sd_in_slot = None + status_is_streaming = None + status_is_logging = None + status_is_rwc_time_set = None + status_is_sensing = None + status_is_docked = None + + bt_crc_byte_count = 0 + + def __init__(self): + self.dock_port = shimmer_comms_docked.ShimmerUart(self) + self.bluetooth_port = shimmer_comms_bluetooth.ShimmerBluetooth(self) + + def setup_dock_com_port(self, com_port, debug_txrx_packets=False): + return self.dock_port.setup_serial_port(com_port, 115200, debug_txrx_packets) + + def setup_bluetooth_com_port(self, com_port, debug_txrx_packets=False): + return self.bluetooth_port.setup_serial_port(com_port, 1000000, debug_txrx_packets) + + def parse_hw_fw_ver_bytes(self, byte_buf): + index = 0 + if len(byte_buf) == 7: + self.hw_ver = byte_buf[index] + index += 1 + elif len(byte_buf) == 8: + self.hw_ver = (byte_buf[index] | (byte_buf[index + 1] << 8)) + index += 2 + + self.parse_fw_ver_bytes(byte_buf, index) + + def parse_fw_ver_bytes(self, byte_buf, index=0): + self.fw_id = ((byte_buf[index]) | (byte_buf[index + 1] << 8)) + index += 2 + self.fw_ver_major = ((byte_buf[index]) | (byte_buf[index + 1] << 8)) + index += 2 + self.fw_ver_minor = byte_buf[index] + index += 1 + self.fw_ver_internal = byte_buf[index] + + def parse_daughter_card_id(self, byte_buf): + self.daughter_card_id = byte_buf[0] + self.daughter_card_rev_major = byte_buf[1] + self.daughter_card_rev_minor = byte_buf[2] + + def parse_infomem(self, byte_buf): + # TODO + return + + def set_bluetooth_ver_str(self, byte_buf): + self.bluetooth_ver_str = bytearray(byte_buf).decode("ASCII") + + def print_hw_fw_revision(self): + print("HW Revision: " + str(self.hw_ver)) + print("FW Revision: ID=" + str(self.fw_id) + + ", v" + str(self.fw_ver_major) + + "." + str(self.fw_ver_minor) + + "." + str(self.fw_ver_internal)) + + def print_daughter_card_id(self): + print("SR" + str(self.daughter_card_id) + + "." + str(self.daughter_card_rev_major) + + "." + str(self.daughter_card_rev_minor)) + + def print_batt_status(self): + print("ADC Value=" + str(self.batt_adc_value) + ", Charging status=" + str(self.charging_status)) + + def parse_status(self, status): + + self.status_toggle_led_red = (status >> 7) & 0x01 + self.status_sd_error = (status >> 6) & 0x01 + self.status_sd_in_slot = (status >> 5) & 0x01 + self.status_is_streaming = (status >> 4) & 0x01 + self.status_is_logging = (status >> 3) & 0x01 + self.status_is_rwc_time_set = (status >> 2) & 0x01 + self.status_is_sensing = (status >> 1) & 0x01 + self.status_is_docked = (status >> 0) & 0x01 + print("0x%02x , Red LED state: %d, sd error: %d, sd in slot: %d, isStreaming: %d, isLogging: %d, " + "isRwcTimeSet: %d, isSensing: %d, isDocked: %d" % (status, self.status_toggle_led_red, + self.status_sd_error, + self.status_sd_in_slot, + self.status_is_streaming, + self.status_is_logging, + self.status_is_rwc_time_set, + self.status_is_sensing, + self.status_is_docked)) + + def is_expansion_board_set(self): + return (self.daughter_card_id is not None + and self.daughter_card_rev_major is not None + and self.daughter_card_rev_minor is not None) + + def is_icm20948_present(self): + return ((self.daughter_card_id == SrBoardCodes.SHIMMER3_IMU.value and (self.daughter_card_rev_major == 9 + or self.daughter_card_rev_major == 10)) + or (self.daughter_card_id == SrBoardCodes.EXP_BRD_EXG_UNIFIED.value and (self.daughter_card_rev_major == 5 + or self.daughter_card_rev_major == 6)) + or (self.daughter_card_id == SrBoardCodes.EXP_BRD_GSR_UNIFIED.value and (self.daughter_card_rev_major == 4 + or self.daughter_card_rev_major == 5)) + or (self.daughter_card_id == SrBoardCodes.EXP_BRD_BR_AMP_UNIFIED.value and self.daughter_card_rev_major == 3) + or (self.daughter_card_id == SrBoardCodes.EXP_BRD_PROTO3_DELUXE.value and (self.daughter_card_rev_major == 3 + or self.daughter_card_rev_major == 4)) + or (self.daughter_card_id == SrBoardCodes.EXP_BRD_PROTO3_MINI.value and (self.daughter_card_rev_major == 3 + or self.daughter_card_rev_major == 4)) + or (self.daughter_card_id == SrBoardCodes.EXP_BRD_ADXL377_ACCEL_200G.value and ( + self.daughter_card_rev_major == 2 or self.daughter_card_rev_major == 3))) + + def is_bmp180_present(self): + return ((self.daughter_card_id == SrBoardCodes.SHIMMER3_IMU.value and self.daughter_card_rev_major <= 5) + or self.daughter_card_id == SrBoardCodes.EXP_BRD_EXG.value + or (self.daughter_card_id == SrBoardCodes.EXP_BRD_EXG_UNIFIED.value and self.daughter_card_rev_major <= 2) + or self.daughter_card_id == SrBoardCodes.EXP_BRD_GSR.value + or (self.daughter_card_id == SrBoardCodes.EXP_BRD_GSR_UNIFIED.value and self.daughter_card_rev_major <= 2) + or self.daughter_card_id == SrBoardCodes.EXP_BRD_BR_AMP.value + or (self.daughter_card_id == SrBoardCodes.EXP_BRD_BR_AMP_UNIFIED.value and self.daughter_card_rev_major == 1) + or (self.daughter_card_id == SrBoardCodes.EXP_BRD_PROTO3_DELUXE.value and self.daughter_card_rev_major <= 2) + or (self.daughter_card_id == SrBoardCodes.EXP_BRD_PROTO3_MINI.value and self.daughter_card_rev_major <= 2) + or (self.daughter_card_id == SrBoardCodes.EXP_BRD_ADXL377_ACCEL_200G.value and self.daughter_card_rev_major == 1)) + + def is_bmp280_present(self): + return ((not self.is_bmp180_present()) and + (self.daughter_card_rev_major == 171 + or (self.daughter_card_id == SrBoardCodes.SHIMMER3_IMU.value and self.daughter_card_rev_major <= 10) + or (self.daughter_card_id == SrBoardCodes.EXP_BRD_EXG_UNIFIED.value and self.daughter_card_rev_major <= 6) + or (self.daughter_card_id == SrBoardCodes.EXP_BRD_GSR_UNIFIED.value and self.daughter_card_rev_major <= 5) + or (self.daughter_card_id == SrBoardCodes.EXP_BRD_BR_AMP_UNIFIED.value and self.daughter_card_rev_major <= 3) + or (self.daughter_card_id == SrBoardCodes.EXP_BRD_PROTO3_DELUXE.value and self.daughter_card_rev_major <= 4) + or (self.daughter_card_id == SrBoardCodes.EXP_BRD_PROTO3_MINI.value and self.daughter_card_rev_major <= 4) + or (self.daughter_card_id == SrBoardCodes.EXP_BRD_ADXL377_ACCEL_200G.value and self.daughter_card_rev_major <= 3))) diff --git a/LogAndStream/python_scripts/Shimmer_common/util_shimmer.py b/LogAndStream/python_scripts/Shimmer_common/util_shimmer.py new file mode 100644 index 0000000..69eed41 --- /dev/null +++ b/LogAndStream/python_scripts/Shimmer_common/util_shimmer.py @@ -0,0 +1,35 @@ + +def byte_array_to_hex_string(data): + hex_str = "" + first_byte = True + for b in data: + if not first_byte: + hex_str += ' ' + hex_str += "0x%0.2X" % b + first_byte = False + return '[' + hex_str + ']' + + +def byte_array_to_int(data, lsb_order=True, is_signed=False): + number = 0 + i = 0 + + for b in data: + if lsb_order: + number += (b << i * 8) + else: + number = (number << 8) + b + i += 1 + + # two's compliment + if is_signed: + bit_length = len(data) * 8 + # sign_offset = 2 ** (bit_length - 1) + # number -= sign_offset + # Copied from Java implementation but I'm not sure if the maths is exactly correct + if number >= (1 << (bit_length - 1)): + number = -((number ^ ((2 ** bit_length) - 1)) + 1) + + # print('data={}, lsb_order={}, is_signed={}, number={}'.format(byte_array_to_hex_string(data), lsb_order, is_signed, number)) + + return number diff --git a/LogAndStream/python_scripts/Docked commands/util_shimmer_time.py b/LogAndStream/python_scripts/Shimmer_common/util_shimmer_time.py similarity index 88% rename from LogAndStream/python_scripts/Docked commands/util_shimmer_time.py rename to LogAndStream/python_scripts/Shimmer_common/util_shimmer_time.py index e1f5054..2b4f941 100644 --- a/LogAndStream/python_scripts/Docked commands/util_shimmer_time.py +++ b/LogAndStream/python_scripts/Shimmer_common/util_shimmer_time.py @@ -18,6 +18,11 @@ def ms_to_shimmer_rtc_bytes(ts_ms): return time_bytes +def shimmer_rtc_bytes_to_s(time_bytes): + ts_ticks = int.from_bytes(time_bytes, "little") + ts_ms = ts_ticks / 32768 + return ts_ms + def seconds_to_time_str(seconds, show_microseconds): if seconds >= (2 ** 31) - 1: return "Not valid"