diff --git a/HISTORY.md b/HISTORY.md index 5f2eae0..cf7965d 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,6 +1,21 @@ # CHANGELOG --- +## 2.6.12, 02/02/2024 +- [INS502] Resolve ping packet(0xcc01) parse issue. + +## 2.6.11, 12/06/2023 +- [RTK350LA] Optimized the RTK350LA rtcm log naming. + +## 2.6.10, 11/13/2023 +- [INS502] Support INS502 data logging. + +## 2.6.9, 10/04/2023 +- [RTK350LA] Support to decode RTK350LA output data. + +## 2.6.8, 09/28/2023 +- [INS402] Support algorithm parameters configuration in cli mode. + ## 2.6.7, 02/15/2023 - [INS402] Add ins402 parse command - [INS401] Add parameter configuration type to be filtered to resolve timeout issue diff --git a/README.md b/README.md index ada02b8..718c075 100644 --- a/README.md +++ b/README.md @@ -25,56 +25,56 @@ Run the CLI software and connect with the INS401 system for the first time, ther ## Commands -#### Log data +### Log data Run the following command to log all data output from Ethernet port to binary files, and streaming GNSS RTK correction data through Ethernet port to the unit (e.g. on Ubuntu) -## INS401 +#### INS401 ```shell ./acenav -i 100base-t1 ``` -## INS402 +#### INS402 ```shell ./acenav -i 100base-t1 --device-type INS402 ``` A “data” subfolder will be created for the first time, and every session of data logging will be stored in a subfolder inside the “data” folder. -#### Parse Data +### Parse Data Run the following command to parse the logged data into text or csv files, -## ins401 +#### INS401 ```shell ./acenav parse -t ins401 -p ``` -## ins402 +#### INS402 ```shell ./acenav parse -t ins402 -p ``` -#### Save Settings +### Save Settings If user changed the GNSS/INS user settings in the "ins401.json" or "ins402.json" file, and wants to make it effective, run the data logging command with "-s" option like below, and the changed user settings will be saved into flash -## ins401 +#### INS401 ```shell ./acenav -i 100base-t1 -s ``` -## ins402 +#### INS402 ```shell ./acenav -i 100base-t1 --device-type INS402 -s ``` -## Firmware Upgrade +### Firmware Upgrade -# INS401 Firmware Upgrade +#### INS401 INS401 supports In-Application Programming (IAP) firmware upgrade through the Ethernet interface, run the executable with the CLI option, and prompt for user input @@ -96,7 +96,7 @@ eg: After successful FW upgrade, the INS401 system restarts and starts logging data automatically. -# INS402 Firmware Upgrade +#### INS402 INS402 supports In-Application Programming (IAP) firmware upgrade through the Ethernet interface, run the executable with the CLI option, and prompt for user input @@ -117,20 +117,28 @@ eg: After successful FW upgrade, the INS402 system restarts and starts logging data automatically. -## Set the Unit Serial Number -# ins401 +### Set the Unit Serial Number +#### INS401 ```shell ./acenav -i 100base-t1 -sn ``` -# ins402 +#### INS402 ```shell ./acenav -i 100base-t1 --device-type INS402 -sn ``` -# canfd app +### Configure Algorithm Parameters(Only support INS402 now) +```shell +./acenav -i 100base-t1 --device-type INS402 --cli +# console display with connection information +# prompt for user input, type in command and file path after the arrow symbol +>>configure +``` + +## CAN-FD app -### run +### Run please run $Env:PYTHONPATH="./src/aceinna/devices/widgets;"+$Env:PYTHONPATH in powershell to set env:PYTHONPATH then ```shell cmd @@ -142,5 +150,5 @@ set "canfd_type": "canfd", + run with can set "canfd_type": "can" -#### Parse +### Parse Data ./acenav parse -t ins401c -p diff --git a/src/aceinna/__init__.py b/src/aceinna/__init__.py index 21524c4..59f0ef4 100644 --- a/src/aceinna/__init__.py +++ b/src/aceinna/__init__.py @@ -1,3 +1,3 @@ # Package Version -VERSION = '2.6.7' +VERSION = '2.6.12' PACKAGE_NAME = 'acenav' diff --git a/src/aceinna/bootstrap/canfd_driver.py b/src/aceinna/bootstrap/canfd_driver.py index ab8c4aa..228dcd9 100644 --- a/src/aceinna/bootstrap/canfd_driver.py +++ b/src/aceinna/bootstrap/canfd_driver.py @@ -642,14 +642,14 @@ def send_base_data(self, data): data_len = len_base_data - index data_len_l = data_len & 0xff data_len_h = (data_len >> 8) & 0xff - data_to_send[0:2] = [data_len_h, data_len_l] - data_to_send[2:] = base_data[index:] + data_to_send[0] = data_len_l + data_to_send[1:] = base_data[index:] else: data_len = self.valid_base_len data_len_l = data_len & 0xff data_len_h = (data_len >> 8) & 0xff - data_to_send[0:2] = [data_len_h, data_len_l] - data_to_send[2:] = base_data[index:index+self.valid_base_len] + data_to_send[0] = data_len_l + data_to_send[1:] = base_data[index:index+self.valid_base_len] try: if self.can_type == 'canfd': self.canfd_handle.write(self.base_id, data_to_send, False, False, True) @@ -661,6 +661,7 @@ def send_base_data(self, data): all_data_len-= self.valid_base_len index+= self.valid_base_len self.all_base_len+= len_base_data + time.sleep(0.01) sys.stdout.write("\rsend base data len {0}".format(self.all_base_len)) def receive_parse_all(self): diff --git a/src/aceinna/bootstrap/cli.py b/src/aceinna/bootstrap/cli.py index a6dcc9c..74ddb45 100644 --- a/src/aceinna/bootstrap/cli.py +++ b/src/aceinna/bootstrap/cli.py @@ -1,382 +1 @@ -""" -Command line entry -""" -import os -import sys -import time -import threading -from os import getpid -import psutil -import re -# from .web import Webserver -from ..models import WebserverArgs - -from ..core.driver import (Driver, DriverEvents) -from ..core.device_context import DeviceContext -from ..core.tunnel_base import TunnelEvents - -from ..framework import AppLogger -from ..framework.utils import resource -from ..framework.constants import APP_TYPE -from ..framework.context import APP_CONTEXT - - -class CommandLine: - '''Command line entry class - ''' - options = None - _tunnel = None - _driver = None - webserver_running = False - supported_commands = [] - input_string = None - current_command = None - - def __init__(self, **kwargs): - self._build_options(**kwargs) - APP_CONTEXT.mode = APP_TYPE.CLI - APP_CONTEXT.para_path = kwargs['para_path'] - # self.communication = 'uart' - # self.device_provider = None - # self.communicator = None - - # self.webserver = Webserver(**kwargs) - - def listen(self): - ''' - Prepare components, initialize the application - ''' - # prepare driver - threading.Thread(target=self._prepare_driver).start() - # prepage logger - self._prepare_logger() - - def handle_discovered(self, device_provider): - device_context = DeviceContext(device_provider) - APP_CONTEXT.device_context = device_context - - if self._tunnel: - self._tunnel.notify('discovered') - - def handle_lost(self): - if self._tunnel: - self._tunnel.notify('lost') - - def handle_upgrade_finished(self): - if self._tunnel: - self._tunnel.notify( - 'continous', 'upgrade_complete', {'success': True}) - - def handle_upgrade_fail(self, code, message): - if self._tunnel: - self._tunnel.notify('continous', 'upgrade_complete', { - 'success': False, 'code': code, 'message': message}) - - def handle_error(self, error, message): - if self._tunnel: - self._tunnel.notify('lost') - - def handle_request(self, method, converted_method, parameters): - result = self._driver.execute(converted_method, parameters) - if self._tunnel: - self._tunnel.notify('invoke', method, result) - - def handle_receive_continous_data(self, packet_type, data): - if self._tunnel: - self._tunnel.notify('continous', packet_type, data) - - def _prepare_driver(self): - self._driver = Driver(self.options) - - self._driver.on(DriverEvents.Discovered, - self.handle_discovered) - - self._driver.on(DriverEvents.Lost, - self.handle_lost) - - self._driver.on(DriverEvents.UpgradeFinished, - self.handle_upgrade_finished) - - self._driver.on(DriverEvents.UpgradeFail, - self.handle_upgrade_fail) - - self._driver.on(DriverEvents.Error, - self.handle_error) - - self._driver.on(DriverEvents.Continous, - self.handle_receive_continous_data) - - self._driver.detect() - - self.setup_command_handler() - - def _prepare_logger(self): - ''' - Set default log handler: console logger, file logger - ''' - executor_path = resource.get_executor_path() - log_level = 'info' - if self.options.debug: - log_level = 'debug' - - console_log = self.options.console_log - - APP_CONTEXT.set_logger( - AppLogger( - filename=os.path.join(executor_path, 'loggers', 'trace.log'), - gen_file=True, - level=log_level, - console_log=console_log - )) - - APP_CONTEXT.set_print_logger( - AppLogger( - filename=os.path.join( - executor_path, 'loggers', 'print_' + time.strftime('%Y%m%d_%H%M%S') + '.log'), - gen_file=True, - level=log_level - )) - - def setup_command_handler(self): - ''' - Prepare command - ''' - self.supported_commands = self._driver.execute('get_command_lines') - - cmd_flag = True - - while True: - if cmd_flag: - token = input(">>") - else: - token = input("") - - self.input_string = re.split(r'\s+', token) - if token.strip() == 'exit': - break - - if self.webserver_running and token.strip() != 'stop': - print("server is on-going, please stop it") - continue - - for command in self.supported_commands: - if command['name'] == self.input_string[0]: - self.current_command = command - eval('self.%s()' % (command['function'])) - cmd_flag = False - break - else: - self.help_handler() - - self.exit_handler() - return True - - def start_webserver(self): - ''' - Start websocket server - ''' - import tornado.ioloop - if sys.version_info[0] > 2: - import asyncio - asyncio.set_event_loop(asyncio.new_event_loop()) - - event_loop = tornado.ioloop.IOLoop.current() - - self._tunnel = WebServer(self.options, event_loop) - self._tunnel.on(TunnelEvents.Request, self.handle_request) - self._tunnel.setup() - - def _build_options(self, **kwargs): - self.options = WebserverArgs(**kwargs) - - # command handler - def help_handler(self): - ''' - Help handler - ''' - if len(self.supported_commands) > 0: - print("Usage: ") - for command in self.supported_commands: - print(command['name'] + " : " + command['description']) - else: - print("No more command line.") - - def connect_handler(self): - ''' - Connect to device, may no need it later - ''' - print(self._driver.execute('get_device_info')) - - def upgrade_handler(self): - '''upgrade command is used for firmware upgrade and followed by file name - ''' - input_args = len(self.input_string) - if input_args == 1: - print("Usage:") - print("upgrade file_name") - else: - if self.options and self.options.interface == '100base-t1': - params = self.input_string - else: - params = self.input_string[1] - - # TODO: check device is idel - self._driver.execute('upgrade_framework', params) - return True - - def record_handler(self): - '''record command is used to save the outputs into local machine - ''' - # TODO: check device is idel - if APP_CONTEXT.device_context.runtime_status != 'LOGGING': - self._driver.execute('start_data_log') - return True - - def stop_handler(self): - '''record command is used to save the outputs into local machine - ''' - # TODO: check device is idel - if APP_CONTEXT.device_context.runtime_status == 'LOGGING': - self._driver.execute('stop_data_log') - - if self.webserver_running: - self._tunnel.stop_ws_server() - self.webserver_running = False - return True - - def get_handler(self): - ''' - Get parameter of device - ''' - input_args = len(self.input_string) - conf = self._driver.execute('get_conf') - - input_params_properties = conf['data']['inputParams'] - select_param = None - if (input_args == 1): - print("Usage: get [options]") - print("Option: ") - i = 2 - while i < len(input_params_properties): - print(input_params_properties[i]['argument']) - i += 1 - return True - else: - i = 2 - while i < len(input_params_properties): - select_param = input_params_properties[i] - if (select_param['argument'] == self.input_string[1]): - break - i += 1 - if (i == len(input_params_properties)): - print("Usage: get [options]") - print("Option: ") - i = 2 - while i < len(input_params_properties): - print(input_params_properties[i]['argument']) - i += 1 - return True - - param = self._driver.execute( - 'get_param', {'paramId': select_param['paramId']}) - print(param['data']['value']) - return True - - def set_handler(self): - ''' - Set parameter of device - ''' - input_args = len(self.input_string) - conf = self._driver.execute('get_conf') - input_params_properties = conf['data']['inputParams'] - select_param = None - not_in_options = False - options = [] - - if input_args == 1: - print("Usage: set ") - i = 2 - while i < len(input_params_properties): - print(input_params_properties[i]['argument']) - i += 1 - return True - else: - i = 2 - while i < len(input_params_properties): - select_param = input_params_properties[i] - if (select_param['argument'] == self.input_string[1]): - break - i += 1 - - if input_args == 2: - if i == len(input_params_properties): - print("Usage: set ") - i = 2 - while i < len(input_params_properties): - print(input_params_properties[i]['argument']) - i += 1 - else: - print("Usage: set " + select_param['argument'] + " ") - print("values: ") - print(select_param['options']) - return True - - if select_param.__contains__('options'): - for item in select_param['options']: - if isinstance(item, dict): - options.append(int(item['key'])) - else: - options.append(item) - - if select_param['type'] == 'int64': - self.input_string[2] = int(self.input_string[2]) - - if select_param['type'] == "char8" and self.input_string[2] not in select_param['options']: - not_in_options = True - - if select_param['type'] == "int64" and\ - self.input_string[2] not in options: - not_in_options = True - - if not_in_options: - print("Usage: set " + select_param['argument'] + " ") - print("values: ") - print(select_param['options']) - return True - - conf = self._driver.execute('set_param', { - 'paramId': select_param['paramId'], - 'value': self.input_string[2] - }) - - # TODO: display a response message to user - - return True - - def save_handler(self): - ''' - Save device configuration - ''' - self._driver.execute('save_config') - return True - - def server_start_handler(self): - ''' - start a websocket server - ''' - return True - - def exit_handler(self): - ''' - Exit current process - ''' - # self.webserver.stop() - # self.webserver_running = False - pid = getpid() - process = psutil.Process(pid) - process.kill() - - def run_handler(self): - '''used by customers - ''' - return True +""" Command line entry """ import os import sys import time import threading from os import getpid import psutil import re # from .web import Webserver from ..models import WebserverArgs from ..core.driver import (Driver, DriverEvents) from ..core.device_context import DeviceContext from ..core.tunnel_base import TunnelEvents from ..framework import AppLogger from ..framework.utils import resource from ..framework.constants import APP_TYPE from ..framework.context import APP_CONTEXT class CommandLine: '''Command line entry class ''' options = None _tunnel = None _driver = None webserver_running = False supported_commands = [] input_string = None current_command = None def __init__(self, **kwargs): self._build_options(**kwargs) APP_CONTEXT.mode = APP_TYPE.CLI APP_CONTEXT.para_path = kwargs['para_path'] # self.communication = 'uart' # self.device_provider = None # self.communicator = None # self.webserver = Webserver(**kwargs) def listen(self): ''' Prepare components, initialize the application ''' # prepare driver threading.Thread(target=self._prepare_driver).start() # prepage logger self._prepare_logger() def handle_discovered(self, device_provider): device_context = DeviceContext(device_provider) APP_CONTEXT.device_context = device_context if self._tunnel: self._tunnel.notify('discovered') def handle_lost(self): if self._tunnel: self._tunnel.notify('lost') def handle_upgrade_finished(self): if self._tunnel: self._tunnel.notify( 'continous', 'upgrade_complete', {'success': True}) def handle_upgrade_fail(self, code, message): if self._tunnel: self._tunnel.notify('continous', 'upgrade_complete', { 'success': False, 'code': code, 'message': message}) def handle_error(self, error, message): if self._tunnel: self._tunnel.notify('lost') def handle_request(self, method, converted_method, parameters): result = self._driver.execute(converted_method, parameters) if self._tunnel: self._tunnel.notify('invoke', method, result) def handle_receive_continous_data(self, packet_type, data): if self._tunnel: self._tunnel.notify('continous', packet_type, data) def _prepare_driver(self): self._driver = Driver(self.options) self._driver.on(DriverEvents.Discovered, self.handle_discovered) self._driver.on(DriverEvents.Lost, self.handle_lost) self._driver.on(DriverEvents.UpgradeFinished, self.handle_upgrade_finished) self._driver.on(DriverEvents.UpgradeFail, self.handle_upgrade_fail) self._driver.on(DriverEvents.Error, self.handle_error) self._driver.on(DriverEvents.Continous, self.handle_receive_continous_data) self._driver.detect() self.setup_command_handler() def _prepare_logger(self): ''' Set default log handler: console logger, file logger ''' executor_path = resource.get_executor_path() log_level = 'info' if self.options.debug: log_level = 'debug' console_log = self.options.console_log APP_CONTEXT.set_logger( AppLogger( filename=os.path.join(executor_path, 'loggers', 'trace.log'), gen_file=True, level=log_level, console_log=console_log )) APP_CONTEXT.set_print_logger( AppLogger( filename=os.path.join( executor_path, 'loggers', 'print_' + time.strftime('%Y%m%d_%H%M%S') + '.log'), gen_file=True, level=log_level )) def setup_command_handler(self): ''' Prepare command ''' self.supported_commands = self._driver.execute('get_command_lines') cmd_flag = True while True: if cmd_flag: token = input(">>") else: token = input("") self.input_string = re.split(r'\s+', token) if token.strip() == 'exit': break if self.webserver_running and token.strip() != 'stop': print("server is on-going, please stop it") continue for command in self.supported_commands: if command['name'] == self.input_string[0]: self.current_command = command try: eval('self.%s()' % (command['function'])) except Exception as e: print('Invalid command, please check your input.', e) cmd_flag = False break else: self.help_handler() self.exit_handler() return True def start_webserver(self): ''' Start websocket server ''' import tornado.ioloop if sys.version_info[0] > 2: import asyncio asyncio.set_event_loop(asyncio.new_event_loop()) event_loop = tornado.ioloop.IOLoop.current() self._tunnel = WebServer(self.options, event_loop) self._tunnel.on(TunnelEvents.Request, self.handle_request) self._tunnel.setup() def _build_options(self, **kwargs): self.options = WebserverArgs(**kwargs) # command handler def help_handler(self): ''' Help handler ''' if len(self.supported_commands) > 0: print("Usage: ") for command in self.supported_commands: print(command['name'] + " : " + command['description']) else: print("No more command line.") def connect_handler(self): ''' Connect to device, may no need it later ''' print(self._driver.execute('get_device_info')) def upgrade_handler(self): '''upgrade command is used for firmware upgrade and followed by file name ''' input_args = len(self.input_string) if input_args == 1: print("Usage:") print("upgrade file_name") else: if self.options and self.options.interface == '100base-t1': params = self.input_string else: params = self.input_string[1] # TODO: check device is idel self._driver.execute('upgrade_framework', params) return True def configure_handler(self): input_args = len(self.input_string) if input_args == 1: print("Usage:") print("confgiure config_file_name") else: if self.options and self.options.interface == '100base-t1': params = self.input_string else: params = self.input_string[1] # TODO: check device is idel self._driver.execute('configure_algorithm', params) return True def record_handler(self): '''record command is used to save the outputs into local machine ''' # TODO: check device is idel if APP_CONTEXT.device_context.runtime_status != 'LOGGING': self._driver.execute('start_data_log') return True def stop_handler(self): '''record command is used to save the outputs into local machine ''' # TODO: check device is idel if APP_CONTEXT.device_context.runtime_status == 'LOGGING': self._driver.execute('stop_data_log') if self.webserver_running: self._tunnel.stop_ws_server() self.webserver_running = False return True def get_handler(self): ''' Get parameter of device ''' input_args = len(self.input_string) conf = self._driver.execute('get_conf') input_params_properties = conf['data']['inputParams'] select_param = None if (input_args == 1): print("Usage: get [options]") print("Option: ") i = 2 while i < len(input_params_properties): print(input_params_properties[i]['argument']) i += 1 return True else: i = 2 while i < len(input_params_properties): select_param = input_params_properties[i] if (select_param['argument'] == self.input_string[1]): break i += 1 if (i == len(input_params_properties)): print("Usage: get [options]") print("Option: ") i = 2 while i < len(input_params_properties): print(input_params_properties[i]['argument']) i += 1 return True param = self._driver.execute( 'get_param', {'paramId': select_param['paramId']}) print(param['data']['value']) return True def set_handler(self): ''' Set parameter of device ''' input_args = len(self.input_string) conf = self._driver.execute('get_conf') input_params_properties = conf['data']['inputParams'] select_param = None not_in_options = False options = [] if input_args == 1: print("Usage: set ") i = 2 while i < len(input_params_properties): print(input_params_properties[i]['argument']) i += 1 return True else: i = 2 while i < len(input_params_properties): select_param = input_params_properties[i] if (select_param['argument'] == self.input_string[1]): break i += 1 if input_args == 2: if i == len(input_params_properties): print("Usage: set ") i = 2 while i < len(input_params_properties): print(input_params_properties[i]['argument']) i += 1 else: print("Usage: set " + select_param['argument'] + " ") print("values: ") print(select_param['options']) return True if select_param.__contains__('options'): for item in select_param['options']: if isinstance(item, dict): options.append(int(item['key'])) else: options.append(item) if select_param['type'] == 'int64': self.input_string[2] = int(self.input_string[2]) if select_param['type'] == "char8" and self.input_string[2] not in select_param['options']: not_in_options = True if select_param['type'] == "int64" and\ self.input_string[2] not in options: not_in_options = True if not_in_options: print("Usage: set " + select_param['argument'] + " ") print("values: ") print(select_param['options']) return True conf = self._driver.execute('set_param', { 'paramId': select_param['paramId'], 'value': self.input_string[2] }) # TODO: display a response message to user return True def save_handler(self): ''' Save device configuration ''' self._driver.execute('save_config') return True def server_start_handler(self): ''' start a websocket server ''' return True def exit_handler(self): ''' Exit current process ''' # self.webserver.stop() # self.webserver_running = False pid = getpid() process = psutil.Process(pid) process.kill() def run_handler(self): '''used by customers ''' return True \ No newline at end of file diff --git a/src/aceinna/bootstrap/log_parser.py b/src/aceinna/bootstrap/log_parser.py index 78b6584..82e127f 100644 --- a/src/aceinna/bootstrap/log_parser.py +++ b/src/aceinna/bootstrap/log_parser.py @@ -53,7 +53,11 @@ def do_parse(log_type, folder_path, kml_rate, dr_parse): elif log_type == 'ins401' or log_type == 'ins402': lib.decode_ins401(bytes(file_path, encoding='utf8'), bytes(dr_parse, encoding='utf8'), kml_rate) elif log_type == 'ins401c': - lib.decode_ins401c(bytes(file_path, encoding='utf8')) + lib.decode_ins401c(bytes(file_path, encoding='utf8')) + elif log_type == 'rtk350la': + lib.decode_rtk350la(bytes(file_path, encoding='utf8')) + elif log_type == 'ins502': + lib.decode_ins502(bytes(file_path, encoding='utf8')) class LogParser: @@ -70,9 +74,9 @@ def listen(self): ''' self._validate_params() - do_parse(self._options.log_type, - self._options.path, - self._options.kml_rate, + do_parse(self._options.log_type, + self._options.path, + self._options.kml_rate, self._options.powerdr) os._exit(1) diff --git a/src/aceinna/devices/base/beidou_provider_base.py b/src/aceinna/devices/base/beidou_provider_base.py index f8597f4..046bd5c 100644 --- a/src/aceinna/devices/base/beidou_provider_base.py +++ b/src/aceinna/devices/base/beidou_provider_base.py @@ -236,7 +236,9 @@ def _build_app_info(self, text): self.app_info = { 'app_name': app_name, - 'version': text + # Tag20230530 modify by wrj, change key to firmware from version, to keep same with ins401 script + # 'version': text + 'firmware': text } def load_properties(self): diff --git a/src/aceinna/devices/base/rtk_provider_base.py b/src/aceinna/devices/base/rtk_provider_base.py index 0229d9f..9fcbccc 100644 --- a/src/aceinna/devices/base/rtk_provider_base.py +++ b/src/aceinna/devices/base/rtk_provider_base.py @@ -1,1090 +1 @@ -import os -import time -import json -import datetime -import threading -import math -import re -import collections -import serial -import serial.tools.list_ports -from ..widgets import NTRIPClient -from ...framework.utils import ( - helper, resource -) -from ...framework.context import APP_CONTEXT -from ...framework.utils.firmware_parser import parser as firmware_content_parser -from ...framework.utils.print import (print_green, print_yellow, print_red) -from ..base import OpenDeviceBase -from ..configs.rtk_predefine import ( - APP_STR, get_rtk_products, get_configuratin_file_mapping -) -from ..decorator import with_device_message -from ...models import InternalCombineAppParseRule -from ..upgrade_workers import ( - FirmwareUpgradeWorker, - JumpApplicationWorker, - JumpBootloaderWorker, - UPGRADE_EVENT, - UPGRADE_GROUP -) -from ..parsers.rtk330l_field_parser import encode_value -from abc import ABCMeta, abstractmethod -from ..ping.rtk330l import ping - - -class RTKProviderBase(OpenDeviceBase): - ''' - RTK Series UART provider - ''' - __metaclass__ = ABCMeta - - def __init__(self, communicator, *args): - super(RTKProviderBase, self).__init__(communicator) - self.type = 'RTK' - self.server_update_rate = 100 - self.sky_data = [] - self.pS_data = [] - self.ps_dic = collections.OrderedDict() - self.inspva_flag = 0 - self.bootloader_baudrate = 115200 - self.app_config_folder = '' - self.device_info = None - self.app_info = None - self.parameters = None - self.setting_folder_path = None - self.data_folder = None - self.debug_serial_port = None - self.rtcm_serial_port = None - self.user_logf = None - self.debug_logf = None - self.rtcm_logf = None - self.debug_c_f = None - self.ntrip_rtcm_logf = None - self.enable_data_log = False - self.is_app_matched = False - self.ntrip_client_enable = False - self.nmea_buffer = [] - self.nmea_sync = 0 - self.config_file_name = 'openrtk.json' - self.device_category = 'RTK' - self.prepare_folders() - self.ntrip_client = None - self.rtk_log_file_name = '' - self.connected = False - self.port_index_define = { - 'user': 0, - 'rtcm': 1, - 'debug': 2, - } - - def prepare_folders(self): - ''' - Prepare folders for data storage and configuration - ''' - - executor_path = resource.get_executor_path() - setting_folder_name = 'setting' - - data_folder_path = os.path.join(executor_path, 'data') - if not os.path.isdir(data_folder_path): - os.makedirs(data_folder_path) - self.data_folder = data_folder_path - - # copy contents of app_config under executor path - self.setting_folder_path = os.path.join( - executor_path, setting_folder_name) - - all_products = get_rtk_products() - config_file_mapping = get_configuratin_file_mapping() - - for product in all_products: - product_folder = os.path.join(self.setting_folder_path, product) - if not os.path.isdir(product_folder): - os.makedirs(product_folder) - - for app_name in all_products[product]: - app_name_path = os.path.join(product_folder, app_name) - app_name_config_path = os.path.join( - app_name_path, config_file_mapping[product]) - - if not os.path.isfile(app_name_config_path): - if not os.path.isdir(app_name_path): - os.makedirs(app_name_path) - app_config_content = resource.get_content_from_bundle( - setting_folder_name, - os.path.join(product, - app_name, - config_file_mapping[product])) - if app_config_content is None: - continue - - with open(app_name_config_path, "wb") as code: - code.write(app_config_content) - - @property - def is_in_bootloader(self): - ''' Check if the connected device is in bootloader mode - ''' - if not self.app_info or not self.app_info.__contains__('version'): - return False - - version = self.app_info['version'] - version_splits = version.split(',') - if len(version_splits) == 1: - if 'bootloader' in version_splits[0].lower(): - return True - - return False - - def bind_device_info(self, device_access, device_info, app_info): - self._build_device_info(device_info) - self._build_app_info(app_info) - self.connected = True - - port_name = device_access.port - try: - str_split = device_info.split() - str_split.pop(3) - device_info = ' '.join(str_split) - except Exception as e: - print(e) - self._device_info_string = '# Connected {0} with UART on {1} #\nDevice: {2} \nFirmware: {3}'\ - .format(self.device_category, port_name, device_info, app_info) - - return self._device_info_string - - def _build_device_info(self, text): - ''' - Build device info - ''' - split_text = [x for x in text.split(' ') if x != ''] - sn = split_text[4] - # remove the prefix of SN - if sn.find('SN:') == 0: - sn = sn[3:] - - self.device_info = { - 'name': split_text[0], - 'imu': split_text[1], - 'pn': split_text[2], - 'firmware_version': split_text[3], - 'sn': sn - } - - def _build_app_info(self, text): - ''' - Build app info - ''' - app_version = text - - split_text = app_version.split(' ') - app_name = next( - (item for item in APP_STR if item in split_text), None) - - if not app_name: - app_name = 'RTK_INS' - self.is_app_matched = False - else: - self.is_app_matched = True - - self.app_info = { - 'app_name': app_name, - 'version': text - } - - def load_properties(self): - product_name = self.device_info['name'] - app_name = self.app_info['app_name'] - - # Load config from user working path - local_config_file_path = os.path.join( - os.getcwd(), self.config_file_name) - if os.path.isfile(local_config_file_path): - with open(local_config_file_path) as json_data: - self.properties = json.load(json_data) - return - - # Load the openimu.json based on its app - app_file_path = os.path.join( - self.setting_folder_path, product_name, app_name, self.config_file_name) - - if not self.is_app_matched: - print_yellow( - 'Failed to extract app version information from unit.' + - '\nThe supported application list is {0}.'.format(APP_STR) + - '\nTo keep runing, use INS configuration as default.' + - '\nYou can choose to place your json file under execution path if it is an unknown application.') - - with open(app_file_path) as json_data: - self.properties = json.load(json_data) - - def ntrip_client_thread(self): - # print('new ntrip client') - self.ntrip_client = NTRIPClient(self.properties) - self.ntrip_client.on('parsed', self.handle_rtcm_data_parsed) - if self.device_info.__contains__('sn') and self.device_info.__contains__('pn'): - self.ntrip_client.set_connect_headers({ - 'Ntrip-Sn': self.device_info['sn'], - 'Ntrip-Pn': self.device_info['pn'] - }) - self.ntrip_client.run() - - def handle_rtcm_data_parsed(self, data): - bytes_data = bytearray(data) - if self.communicator.can_write() and not self.is_upgrading: - self.communicator.write(bytes_data) - - self.ntrip_rtcm_logf.write(bytes_data) - - def build_connected_serial_port_info(self): - if not self.communicator.serial_port: - return None, None - - user_port = self.communicator.serial_port.port - user_port_num = '' - port_name = '' - for i in range(len(user_port)-1, -1, -1): - if (user_port[i] >= '0' and user_port[i] <= '9'): - user_port_num = user_port[i] + user_port_num - else: - port_name = user_port[:i+1] - break - return user_port_num, port_name - - def after_setup(self): - local_time = time.localtime() - formatted_dir_time = time.strftime("%Y%m%d_%H%M%S", local_time) - formatted_file_time = time.strftime("%Y_%m_%d_%H_%M_%S", local_time) - debug_port = '' - rtcm_port = '' - set_user_para = self.cli_options and self.cli_options.set_user_para - - # save original baudrate - if hasattr(self.communicator, 'serial_port'): - self.original_baudrate = self.communicator.serial_port.baudrate - - if self.data_folder is None: - raise Exception( - 'Data folder does not exists, please check if the application has create folder permission') - - try: - self.rtk_log_file_name = os.path.join( - self.data_folder, '{0}_log_{1}'.format(self.device_category.lower(), formatted_dir_time)) - os.mkdir(self.rtk_log_file_name) - except: - raise Exception( - 'Cannot create log folder, please check if the application has create folder permission') - - # set parameters from predefined parameters - if set_user_para: - result = self.set_params( - self.properties["initial"]["userParameters"]) - if (result['packetType'] == 'success'): - self.save_config() - - # check saved result - self.check_predefined_result() - - # start ntrip client - if self.properties["initial"].__contains__("ntrip") \ - and not self.ntrip_client \ - and not self.is_in_bootloader \ - and not self.cli_options.use_cli: - - self.ntrip_rtcm_logf = open(os.path.join(self.rtk_log_file_name, 'ntrip_rtcm_{0}.bin'.format( - formatted_file_time)), "wb") - - thead = threading.Thread(target=self.ntrip_client_thread) - thead.start() - - try: - if (self.properties["initial"]["useDefaultUart"]): - user_port_num, port_name = self.build_connected_serial_port_info() - if not user_port_num or not port_name: - return False - debug_port = port_name + \ - str(int(user_port_num) + self.port_index_define['debug']) - rtcm_port = port_name + \ - str(int(user_port_num) + self.port_index_define['rtcm']) - else: - for x in self.properties["initial"]["uart"]: - if x['enable'] == 1: - if x['name'] == 'DEBUG': - debug_port = x["value"] - elif x['name'] == 'GNSS': - rtcm_port = x["value"] - - self.user_logf = open(os.path.join( - self.rtk_log_file_name, 'user_{0}.bin'.format(formatted_file_time)), "wb") - - if rtcm_port != '': - print_green('{0} log GNSS UART {1}'.format( - self.device_category, rtcm_port)) - self.rtcm_serial_port = serial.Serial( - rtcm_port, '460800', timeout=0.1) - if self.rtcm_serial_port.isOpen(): - self.rtcm_logf = open( - os.path.join(self.rtk_log_file_name, 'rtcm_rover_{0}.bin'.format( - formatted_file_time)), "wb") - thead = threading.Thread( - target=self.thread_rtcm_port_receiver, args=(self.rtk_log_file_name,)) - thead.start() - - if debug_port != '': - print_green('{0} log DEBUG UART {1}'.format( - self.device_category, debug_port)) - self.debug_serial_port = serial.Serial( - debug_port, '460800', timeout=0.1) - if self.debug_serial_port.isOpen(): - self.debug_logf = open( - os.path.join(self.rtk_log_file_name, 'rtcm_base_{0}.bin'.format( - formatted_file_time)), "wb") - thead = threading.Thread( - target=self.thread_debug_port_receiver, args=(self.rtk_log_file_name,)) - thead.start() - - self.save_device_info() - except Exception as ex: - if self.debug_serial_port is not None: - if self.debug_serial_port.isOpen(): - self.debug_serial_port.close() - if self.rtcm_serial_port is not None: - if self.rtcm_serial_port.isOpen(): - self.rtcm_serial_port.close() - self.debug_serial_port = None - self.rtcm_serial_port = None - APP_CONTEXT.get_logger().logger.error(ex) - print_red( - 'Can not log GNSS UART or DEBUG UART, pls check uart driver and connection!') - return False - - def nmea_checksum(self, data): - data = data.replace("\r", "").replace("\n", "").replace("$", "") - nmeadata, cksum = re.split('\*', data) - calc_cksum = 0 - for s in nmeadata: - calc_cksum ^= ord(s) - return int(cksum, 16), calc_cksum - - def on_read_raw(self, data): - for bytedata in data: - if bytedata == 0x24: - self.nmea_buffer = [] - self.nmea_sync = 0 - self.nmea_buffer.append(chr(bytedata)) - else: - self.nmea_buffer.append(chr(bytedata)) - if self.nmea_sync == 0: - if bytedata == 0x0D: - self.nmea_sync = 1 - elif self.nmea_sync == 1: - if bytedata == 0x0A: - try: - str_nmea = ''.join(self.nmea_buffer) - cksum, calc_cksum = self.nmea_checksum( - str_nmea) - if cksum == calc_cksum: - if str_nmea.find("$GPGGA") != -1 or str_nmea.find("$GNGGA") != -1: - if self.ntrip_client: - self.ntrip_client.send(str_nmea) - #self.add_output_packet('gga', str_nmea) - # print(str_nmea, end='') - APP_CONTEXT.get_print_logger().info(str_nmea.replace('\r\n', '')) - # else: - # print("nmea checksum wrong {0} {1}".format(cksum, calc_cksum)) - except Exception as e: - # print('NMEA fault:{0}'.format(e)) - pass - self.nmea_buffer = [] - self.nmea_sync = 0 - - if self.user_logf is not None: - self.user_logf.write(data) - - @abstractmethod - def thread_debug_port_receiver(self, *args, **kwargs): - pass - - @abstractmethod - def thread_rtcm_port_receiver(self, *args, **kwargs): - pass - - def on_receive_output_packet(self, packet_type, data, *args, **kwargs): - ''' - Listener for getting output packet - ''' - # $GPGGA,080319.00,3130.4858508,N,12024.0998832,E,4,25,0.5,12.459,M,0.000,M,2.0,*46 - if packet_type == 'gN': - if self.ntrip_client: - # $GPGGA - gpgga = '$GNGGA' #'$GPGGA' - # time - timeOfWeek = float(data['GPS_TimeofWeek']) - 18 - dsec = int(timeOfWeek) - msec = timeOfWeek - dsec - sec = dsec % 86400 - hour = int(sec / 3600) - minute = int(sec % 3600 / 60) - second = sec % 60 - gga_time = format(hour*10000 + minute*100 + - second + msec, '09.2f') - gpgga = gpgga + ',' + gga_time - # latitude - latitude = float(data['latitude']) * 180 / 2147483648.0 - if latitude >= 0: - latflag = 'N' - else: - latflag = 'S' - latitude = math.fabs(latitude) - lat_d = int(latitude) - lat_m = (latitude-lat_d) * 60 - lat_dm = format(lat_d*100 + lat_m, '012.7f') - gpgga = gpgga + ',' + lat_dm + ',' + latflag - # longitude - longitude = float(data['longitude']) * 180 / 2147483648.0 - if longitude >= 0: - lonflag = 'E' - else: - lonflag = 'W' - longitude = math.fabs(longitude) - lon_d = int(longitude) - lon_m = (longitude-lon_d) * 60 - lon_dm = format(lon_d*100 + lon_m, '013.7f') - gpgga = gpgga + ',' + lon_dm + ',' + lonflag - # positionMode - gpgga = gpgga + ',' + str(data['positionMode']) - # svs - gpgga = gpgga + ',' + str(data['numberOfSVs']) - # hop - gpgga = gpgga + ',' + format(float(data['hdop']), '03.1f') - # height - gpgga = gpgga + ',' + \ - format(float(data['height']), '06.3f') + ',M' - # - gpgga = gpgga + ',0.000,M' - # diffage - gpgga = gpgga + ',' + \ - format(float(data['diffage']), '03.1f') + ',' - # ckm - checksum = 0 - for i in range(1, len(gpgga)): - checksum = checksum ^ ord(gpgga[i]) - str_checksum = hex(checksum) - if str_checksum.startswith("0x"): - str_checksum = str_checksum[2:] - gpgga = gpgga + '*' + str_checksum + '\r\n' - APP_CONTEXT.get_print_logger().info(gpgga) - self.ntrip_client.send(gpgga) - return - - elif packet_type == 'pS': - try: - if data['latitude'] != 0.0 and data['longitude'] != 0.0: - if self.pS_data: - if self.pS_data['GPS_Week'] == data['GPS_Week']: - if data['GPS_TimeofWeek'] - self.pS_data['GPS_TimeofWeek'] >= 0.2: - self.add_output_packet('pos', data) - self.pS_data = data - - if data['insStatus'] >= 3 and data['insStatus'] <= 5: - ins_status = 'INS_INACTIVE' - if data['insStatus'] == 3: - ins_status = 'INS_SOLUTION_GOOD' - elif data['insStatus'] == 4: - ins_status = 'INS_SOLUTION_FREE' - elif data['insStatus'] == 5: - ins_status = 'INS_ALIGNMENT_COMPLETE' - - ins_pos_type = 'INS_INVALID' - if data['insPositionType'] == 1: - ins_pos_type = 'INS_SPP' - elif data['insPositionType'] == 4: - ins_pos_type = 'INS_RTKFIXED' - elif data['insPositionType'] == 5: - ins_pos_type = 'INS_RTKFLOAT' - - inspva = '#INSPVA,%s,%10.2f, %s, %s,%12.8f,%13.8f,%8.3f,%9.3f,%9.3f,%9.3f,%9.3f,%9.3f,%9.3f' %\ - (data['GPS_Week'], data['GPS_TimeofWeek'], ins_status, ins_pos_type, - data['latitude'], data['longitude'], data['height'], - data['velocityNorth'], data['velocityEast'], data['velocityUp'], - data['roll'], data['pitch'], data['heading']) - APP_CONTEXT.get_print_logger().info(inspva) - else: - self.add_output_packet('pos', data) - self.pS_data = data - else: - self.add_output_packet('pos', data) - self.pS_data = data - except Exception as e: - pass - - elif packet_type == 'sK': - if self.sky_data: - if self.sky_data[0]['timeOfWeek'] == data[0]['timeOfWeek']: - self.sky_data.extend(data) - else: - self.add_output_packet('skyview', self.sky_data) - self.add_output_packet('snr', self.sky_data) - self.sky_data = [] - self.sky_data.extend(data) - else: - self.sky_data.extend(data) - - elif packet_type == 'g1': - self.ps_dic['positionMode'] = data['position_type'] - self.ps_dic['numberOfSVs'] = data['number_of_satellites_in_solution'] - self.ps_dic['hdop'] = data['hdop'] - self.ps_dic['age'] = data['diffage'] - if self.inspva_flag == 0: - self.ps_dic['GPS_Week'] = data['GPS_Week'] - self.ps_dic['GPS_TimeofWeek'] = data['GPS_TimeOfWeek'] * 0.001 - self.ps_dic['latitude'] = data['latitude'] - self.ps_dic['longitude'] = data['longitude'] - self.ps_dic['height'] = data['height'] - self.ps_dic['velocityMode'] = 1 - self.ps_dic['velocityNorth'] = data['north_vel'] - self.ps_dic['velocityEast'] = data['east_vel'] - self.ps_dic['velocityUp'] = data['up_vel'] - self.ps_dic['latitude_std'] = data['latitude_standard_deviation'] - self.ps_dic['longitude_std'] = data['longitude_standard_deviation'] - self.ps_dic['height_std'] = data['height_standard_deviation'] - self.ps_dic['north_vel_std'] = data['north_vel_standard_deviation'] - self.ps_dic['east_vel_std'] = data['east_vel_standard_deviation'] - self.ps_dic['up_vel_std'] = data['up_vel_standard_deviation'] - self.add_output_packet('pos', self.ps_dic) - - elif packet_type == 'i1': - self.inspva_flag = 1 - if data['GPS_TimeOfWeek'] % 200 == 0: - self.ps_dic['GPS_Week'] = data['GPS_Week'] - self.ps_dic['GPS_TimeofWeek'] = data['GPS_TimeOfWeek'] * 0.001 - self.ps_dic['latitude'] = data['latitude'] - self.ps_dic['longitude'] = data['longitude'] - self.ps_dic['height'] = data['height'] - if data['ins_position_type'] != 1 and data['ins_position_type'] != 4 and data['ins_position_type'] != 5: - self.ps_dic['velocityMode'] = 2 - else: - self.ps_dic['velocityMode'] = 1 - self.ps_dic['insStatus'] = data['ins_status'] - self.ps_dic['insPositionType'] = data['ins_position_type'] - self.ps_dic['velocityNorth'] = data['north_velocity'] - self.ps_dic['velocityEast'] = data['east_velocity'] - self.ps_dic['velocityUp'] = data['up_velocity'] - self.ps_dic['roll'] = data['roll'] - self.ps_dic['pitch'] = data['pitch'] - self.ps_dic['heading'] = data['heading'] - self.ps_dic['latitude_std'] = data['latitude_std'] - self.ps_dic['longitude_std'] = data['longitude_std'] - self.ps_dic['height_std'] = data['height_std'] - self.ps_dic['north_vel_std'] = data['north_velocity_std'] - self.ps_dic['east_vel_std'] = data['east_velocity_std'] - self.ps_dic['up_vel_std'] = data['up_velocity_std'] - self.ps_dic['roll_std'] = data['roll_std'] - self.ps_dic['pitch_std'] = data['pitch_std'] - self.ps_dic['heading_std'] = data['heading_std'] - self.add_output_packet('pos', self.ps_dic) - - elif packet_type == 'y1': - if self.sky_data: - if self.sky_data[0]['GPS_TimeOfWeek'] == data[0]['GPS_TimeOfWeek']: - self.sky_data.extend(data) - else: - self.add_output_packet('skyview', self.sky_data) - self.add_output_packet('snr', self.sky_data) - self.sky_data = [] - self.sky_data.extend(data) - else: - self.sky_data.extend(data) - - else: - output_packet_config = next( - (x for x in self.properties['userMessages']['outputPackets'] - if x['name'] == packet_type), None) - if output_packet_config and output_packet_config.__contains__('active') \ - and output_packet_config['active']: - timeOfWeek = int(data['GPS_TimeOfWeek']) % 60480000 - data['GPS_TimeOfWeek'] = timeOfWeek / 1000 - self.add_output_packet('imu', data) - - @abstractmethod - def build_worker(self, rule, content): - ''' Build upgarde worker by rule and content - ''' - pass - - - def after_jump_bootloader_command(self): - pass - - - def after_jump_app_command(self): - # rtk330l ping device - can_ping = False - - while not can_ping: - self.communicator.reset_buffer() # clear input and output buffer - info = ping(self.communicator, None) - if info: - can_ping = True - time.sleep(0.5) - pass - - def get_upgrade_workers(self, firmware_content): - workers = [] - rules = [ - InternalCombineAppParseRule('rtk', 'rtk_start:', 4), - InternalCombineAppParseRule('ins', 'ins_start:', 4), - InternalCombineAppParseRule('sdk', 'sdk_start:', 4), - ] - - parsed_content = firmware_content_parser(firmware_content, rules) - # foreach parsed content, if empty, skip register into upgrade center - device_info = self.get_device_connection_info() - for _, rule in enumerate(parsed_content): - content = parsed_content[rule] - if len(content) == 0: - continue - - worker = self.build_worker(rule, content) - if not worker: - continue - if (device_info['modelName'] == 'RTK330L') and (rule == 'sdk') and ((int(device_info['serialNumber']) <= 2178200080) and (int(device_info['serialNumber']) >= 2178200001)): - continue - else: - workers.append(worker) - # prepare jump bootloader worker and jump application workder - # append jump bootloader worker before the first firmware upgrade workder - # append jump application worker after the last firmware uprade worker - start_index = -1 - end_index = -1 - for i, worker in enumerate(workers): - if isinstance(worker, FirmwareUpgradeWorker): - start_index = i if start_index == -1 else start_index - end_index = i - - jump_bootloader_command = helper.build_bootloader_input_packet( - 'JI') - jumpBootloaderWorker = JumpBootloaderWorker( - self.communicator, - command=jump_bootloader_command, - listen_packet='JI', - wait_timeout_after_command=1) - jumpBootloaderWorker.on( - UPGRADE_EVENT.AFTER_COMMAND, self.after_jump_bootloader_command) - - jump_application_command = helper.build_bootloader_input_packet('JA') - jumpApplicationWorker = JumpApplicationWorker( - self.communicator, - command=jump_application_command, - listen_packet='JA', - wait_timeout_after_command=1) - jumpApplicationWorker.on( - UPGRADE_EVENT.AFTER_COMMAND, self.after_jump_app_command) - - if start_index > -1 and end_index > -1: - workers.insert( - start_index, jumpBootloaderWorker) - workers.insert( - end_index+2, jumpApplicationWorker) - return workers - - def get_device_connection_info(self): - return { - 'modelName': self.device_info['name'], - 'deviceType': self.type, - 'serialNumber': self.device_info['sn'], - 'partNumber': self.device_info['pn'], - 'firmware': self.device_info['firmware_version'] - } - - def check_predefined_result(self): - local_time = time.localtime() - formatted_file_time = time.strftime("%Y_%m_%d_%H_%M_%S", local_time) - file_path = os.path.join( - self.rtk_log_file_name, - 'parameters_predefined_{0}.json'.format(formatted_file_time) - ) - # save parameters to data log folder after predefined parameters setup - result = self.get_params() - if result['packetType'] == 'inputParams': - with open(file_path, 'w') as outfile: - json.dump(result['data'], outfile) - - # compare saved parameters with predefined parameters - hashed_predefined_parameters = helper.collection_to_dict( - self.properties["initial"]["userParameters"], key='paramId') - hashed_current_parameters = helper.collection_to_dict( - result['data'], key='paramId') - - success_count = 0 - fail_count = 0 - fail_parameters = [] - for key in hashed_predefined_parameters: - if hashed_current_parameters[key]['value'] == \ - hashed_predefined_parameters[key]['value']: - success_count += 1 - else: - fail_count += 1 - fail_parameters.append( - hashed_predefined_parameters[key]['name']) - - check_result = 'Predefined Parameters are saved. Success ({0}), Fail ({1})'.format( - success_count, fail_count) - if success_count == len(hashed_predefined_parameters.keys()): - print_green(check_result) - - if fail_count > 0: - print_yellow(check_result) - print_yellow('The failed parameters: {0}'.format(fail_parameters)) - - def save_device_info(self): - ''' Save device configuration - File name: configuration.json - ''' - if self.is_in_bootloader: - return - - result = self.get_params() - - device_configuration = None - file_path = os.path.join( - self.data_folder, self.rtk_log_file_name, 'configuration.json') - - if not os.path.exists(file_path): - device_configuration = [] - else: - with open(file_path) as json_data: - device_configuration = (list)(json.load(json_data)) - - if result['packetType'] == 'inputParams': - session_info = dict() - session_info['time'] = time.strftime( - "%Y-%m-%d %H:%M:%S", time.localtime()) - session_info['device'] = self.device_info - session_info['app'] = self.app_info - session_info['interface'] = self.cli_options.interface - if session_info['interface'] == 'uart': - session_info['path'] = self.communicator.serial_port.port - parameters_configuration = dict() - for item in result['data']: - param_name = item['name'] - param_value = item['value'] - parameters_configuration[param_name] = param_value - - session_info['parameters'] = parameters_configuration - device_configuration.append(session_info) - - with open(file_path, 'w') as outfile: - json.dump(device_configuration, outfile, - indent=4, ensure_ascii=False) - - def after_upgrade_completed(self): - self.communicator.reset_buffer() - pass - - def get_operation_status(self): - if self.is_logging: - return 'LOGGING' - - return 'IDLE' - - # command list - def server_status(self, *args): # pylint: disable=invalid-name - ''' - Get server connection status - ''' - return { - 'packetType': 'ping', - 'data': {'status': '1'} - } - - def get_device_info(self, *args): # pylint: disable=invalid-name - ''' - Get device information - ''' - return { - 'packetType': 'deviceInfo', - 'data': [ - {'name': 'Product Name', 'value': self.device_info['name']}, - {'name': 'IMU', 'value': self.device_info['imu']}, - {'name': 'PN', 'value': self.device_info['pn']}, - {'name': 'Firmware Version', - 'value': self.device_info['firmware_version']}, - {'name': 'SN', 'value': self.device_info['sn']}, - {'name': 'App Version', 'value': self.app_info['version']} - ] - } - - def get_log_info(self): - ''' - Build information for log - ''' - return { - "type": self.type, - "model": self.device_info['name'], - "logInfo": { - "pn": self.device_info['pn'], - "sn": self.device_info['sn'], - "rtkProperties": json.dumps(self.properties) - } - } - - def get_conf(self, *args): # pylint: disable=unused-argument - ''' - Get json configuration - ''' - return { - 'packetType': 'conf', - 'data': { - 'outputs': self.properties['userMessages']['outputPackets'], - 'inputParams': self.properties['userConfiguration'] - } - } - - @with_device_message - def get_params(self, *args): # pylint: disable=unused-argument - ''' - Get all parameters - ''' - has_error = False - parameter_values = [] - - if self.app_info['app_name'] == 'RTK_INS': - conf_parameters = self.properties['userConfiguration'] - conf_parameters_len = len(conf_parameters)-1 - step = 10 - - for i in range(2, conf_parameters_len, step): - start_byte = i - end_byte = i+step-1 if i+step < conf_parameters_len else conf_parameters_len - time.sleep(0.2) - command_line = helper.build_packet( - 'gB', [start_byte, end_byte]) - result = yield self._message_center.build(command=command_line, timeout=10) - if result['error']: - has_error = True - break - - parameter_values.extend(result['data']) - else: - command_line = helper.build_input_packet('gA') - result = yield self._message_center.build(command=command_line, timeout=3) - if result['error']: - has_error = True - - parameter_values = result['data'] - - if not has_error: - self.parameters = parameter_values - yield { - 'packetType': 'inputParams', - 'data': parameter_values - } - - yield { - 'packetType': 'error', - 'data': 'No Response' - } - - @with_device_message - def get_param(self, params, *args): # pylint: disable=unused-argument - ''' - Update paramter value - ''' - command_line = helper.build_input_packet( - 'gP', properties=self.properties, param=params['paramId']) - # self.communicator.write(command_line) - # result = self.get_input_result('gP', timeout=1) - result = yield self._message_center.build(command=command_line) - - data = result['data'] - error = result['error'] - - if error: - yield { - 'packetType': 'error', - 'data': 'No Response' - } - - if data: - self.parameters = data - yield { - 'packetType': 'inputParam', - 'data': data - } - - yield { - 'packetType': 'error', - 'data': 'No Response' - } - - @with_device_message - def set_params(self, params, *args): # pylint: disable=unused-argument - ''' - Update paramters value - ''' - input_parameters = self.properties['userConfiguration'] - grouped_parameters = {} - - for parameter in params: - exist_parameter = next( - (x for x in input_parameters if x['paramId'] == parameter['paramId']), None) - - if exist_parameter: - has_group = grouped_parameters.__contains__( - exist_parameter['category']) - if not has_group: - grouped_parameters[exist_parameter['category']] = [] - - current_group = grouped_parameters[exist_parameter['category']] - - current_group.append( - {'paramId': parameter['paramId'], 'value': parameter['value'], 'type': exist_parameter['type']}) - - for group in grouped_parameters.values(): - message_bytes = [] - for parameter in group: - message_bytes.extend( - encode_value('int8', parameter['paramId']) - ) - message_bytes.extend( - encode_value(parameter['type'], parameter['value']) - ) - # print('parameter type {0}, value {1}'.format( - # parameter['type'], parameter['value'])) - # result = self.set_param(parameter) - command_line = helper.build_packet( - 'uB', message_bytes) - # for s in command_line: - # print(hex(s)) - - result = yield self._message_center.build(command=command_line) - - packet_type = result['packet_type'] - data = result['data'] - - if packet_type == 'error': - yield { - 'packetType': 'error', - 'data': { - 'error': data - } - } - break - - if data > 0: - yield { - 'packetType': 'error', - 'data': { - 'error': data - } - } - break - - yield { - 'packetType': 'success', - 'data': { - 'error': 0 - } - } - - @with_device_message - def set_param(self, params, *args): # pylint: disable=unused-argument - ''' - Update paramter value - ''' - command_line = helper.build_input_packet( - 'uP', properties=self.properties, param=params['paramId'], value=params['value']) - # self.communicator.write(command_line) - # result = self.get_input_result('uP', timeout=1) - result = yield self._message_center.build(command=command_line) - - error = result['error'] - data = result['data'] - if error: - yield { - 'packetType': 'error', - 'data': { - 'error': data - } - } - - yield { - 'packetType': 'success', - 'data': { - 'error': data - } - } - - @with_device_message - def save_config(self, *args): # pylint: disable=unused-argument - ''' - Save configuration - ''' - command_line = helper.build_input_packet('sC') - # self.communicator.write(command_line) - # result = self.get_input_result('sC', timeout=2) - result = yield self._message_center.build(command=command_line, timeout=2) - - data = result['data'] - error = result['error'] - if data: - yield { - 'packetType': 'success', - 'data': error - } - - yield { - 'packetType': 'success', - 'data': error - } - - @with_device_message - def reset_params(self, params, *args): # pylint: disable=unused-argument - ''' - Reset params to default - ''' - command_line = helper.build_input_packet('rD') - result = yield self._message_center.build(command=command_line, timeout=2) - - error = result['error'] - data = result['data'] - if error: - yield { - 'packetType': 'error', - 'data': { - 'error': error - } - } - - yield { - 'packetType': 'success', - 'data': data - } - - def upgrade_framework(self, params, *args): # pylint: disable=unused-argument - ''' - Upgrade framework - ''' - file = '' - if isinstance(params, str): - file = params - - if isinstance(params, dict): - file = params['file'] - - # start a thread to do upgrade - if not self.is_upgrading: - self.is_upgrading = True - self._message_center.pause() - - if self._logger is not None: - self._logger.stop_user_log() - - self.thread_do_upgrade_framework(file) - print("Upgrade RTK330LA firmware started at:[{0}].".format( - datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'))) - return { - 'packetType': 'success' - } +import os import time import json import datetime import threading import math import re import collections import serial import serial.tools.list_ports from ..widgets import NTRIPClient from ...framework.utils import ( helper, resource ) from ...framework.context import APP_CONTEXT from ...framework.utils.firmware_parser import parser as firmware_content_parser from ...framework.utils.print import (print_green, print_yellow, print_red) from ..base import OpenDeviceBase from ..configs.rtk_predefine import ( APP_STR, get_rtk_products, get_configuratin_file_mapping ) from ..decorator import with_device_message from ...models import InternalCombineAppParseRule from ..upgrade_workers import ( FirmwareUpgradeWorker, JumpApplicationWorker, JumpBootloaderWorker, UPGRADE_EVENT, UPGRADE_GROUP ) from ..parsers.rtk330l_field_parser import encode_value from abc import ABCMeta, abstractmethod from ..ping.rtk330l import ping class RTKProviderBase(OpenDeviceBase): ''' RTK Series UART provider ''' __metaclass__ = ABCMeta def __init__(self, communicator, *args): super(RTKProviderBase, self).__init__(communicator) self.type = 'RTK' self.server_update_rate = 100 self.sky_data = [] self.pS_data = [] self.ps_dic = collections.OrderedDict() self.inspva_flag = 0 self.bootloader_baudrate = 115200 self.app_config_folder = '' self.device_info = None self.app_info = None self.parameters = None self.setting_folder_path = None self.data_folder = None self.debug_serial_port = None self.rtcm_serial_port = None self.user_logf = None self.debug_logf = None self.rtcm_logf = None self.debug_c_f = None self.ntrip_rtcm_logf = None self.enable_data_log = False self.is_app_matched = False self.ntrip_client_enable = False self.nmea_buffer = [] self.nmea_sync = 0 self.config_file_name = 'openrtk.json' self.device_category = 'RTK' self.prepare_folders() self.ntrip_client = None self.rtk_log_file_name = '' self.connected = False self.port_index_define = { 'user': 0, 'rtcm': 1, 'debug': 2, } def prepare_folders(self): ''' Prepare folders for data storage and configuration ''' executor_path = resource.get_executor_path() setting_folder_name = 'setting' data_folder_path = os.path.join(executor_path, 'data') if not os.path.isdir(data_folder_path): os.makedirs(data_folder_path) self.data_folder = data_folder_path # copy contents of app_config under executor path self.setting_folder_path = os.path.join( executor_path, setting_folder_name) all_products = get_rtk_products() config_file_mapping = get_configuratin_file_mapping() for product in all_products: product_folder = os.path.join(self.setting_folder_path, product) if not os.path.isdir(product_folder): os.makedirs(product_folder) for app_name in all_products[product]: app_name_path = os.path.join(product_folder, app_name) app_name_config_path = os.path.join( app_name_path, config_file_mapping[product]) if not os.path.isfile(app_name_config_path): if not os.path.isdir(app_name_path): os.makedirs(app_name_path) app_config_content = resource.get_content_from_bundle( setting_folder_name, os.path.join(product, app_name, config_file_mapping[product])) if app_config_content is None: continue with open(app_name_config_path, "wb") as code: code.write(app_config_content) @property def is_in_bootloader(self): ''' Check if the connected device is in bootloader mode ''' if not self.app_info or not self.app_info.__contains__('version'): return False version = self.app_info['version'] version_splits = version.split(',') if len(version_splits) == 1: if 'bootloader' in version_splits[0].lower(): return True return False def bind_device_info(self, device_access, device_info, app_info): self._build_device_info(device_info) self._build_app_info(app_info) self.connected = True port_name = device_access.port try: str_split = device_info.split() str_split.pop(3) device_info = ' '.join(str_split) except Exception as e: print(e) self._device_info_string = '# Connected {0} with UART on {1} #\nDevice: {2} \nFirmware: {3}'\ .format(self.device_category, port_name, device_info, app_info) return self._device_info_string def _build_device_info(self, text): ''' Build device info ''' split_text = [x for x in text.split(' ') if x != ''] sn = split_text[4] # remove the prefix of SN if sn.find('SN:') == 0: sn = sn[3:] self.device_info = { 'name': split_text[0], 'imu': split_text[1], 'pn': split_text[2], 'firmware_version': split_text[3], 'sn': sn } def _build_app_info(self, text): ''' Build app info ''' app_version = text split_text = app_version.split(' ') app_name = next( (item for item in APP_STR if item in split_text), None) if not app_name: app_name = 'RTK_INS' self.is_app_matched = False else: self.is_app_matched = True self.app_info = { 'app_name': app_name, 'version': text } def load_properties(self): product_name = self.device_info['name'] app_name = self.app_info['app_name'] # Load config from user working path local_config_file_path = os.path.join( os.getcwd(), self.config_file_name) if os.path.isfile(local_config_file_path): with open(local_config_file_path) as json_data: self.properties = json.load(json_data) return # Load the openimu.json based on its app app_file_path = os.path.join( self.setting_folder_path, product_name, app_name, self.config_file_name) if not self.is_app_matched: print_yellow( 'Failed to extract app version information from unit.' + '\nThe supported application list is {0}.'.format(APP_STR) + '\nTo keep runing, use INS configuration as default.' + '\nYou can choose to place your json file under execution path if it is an unknown application.') with open(app_file_path) as json_data: self.properties = json.load(json_data) def ntrip_client_thread(self): # print('new ntrip client') self.ntrip_client = NTRIPClient(self.properties) self.ntrip_client.on('parsed', self.handle_rtcm_data_parsed) if self.device_info.__contains__('sn') and self.device_info.__contains__('pn'): self.ntrip_client.set_connect_headers({ 'Ntrip-Sn': self.device_info['sn'], 'Ntrip-Pn': self.device_info['pn'] }) self.ntrip_client.run() def handle_rtcm_data_parsed(self, data): bytes_data = bytearray(data) if self.communicator.can_write() and not self.is_upgrading: self.communicator.write(bytes_data) self.ntrip_rtcm_logf.write(bytes_data) def build_connected_serial_port_info(self): if not self.communicator.serial_port: return None, None user_port = self.communicator.serial_port.port user_port_num = '' port_name = '' for i in range(len(user_port)-1, -1, -1): if (user_port[i] >= '0' and user_port[i] <= '9'): user_port_num = user_port[i] + user_port_num else: port_name = user_port[:i+1] break return user_port_num, port_name def after_setup(self): local_time = time.localtime() formatted_dir_time = time.strftime("%Y%m%d_%H%M%S", local_time) formatted_file_time = time.strftime("%Y_%m_%d_%H_%M_%S", local_time) debug_port = '' rtcm_port = '' set_user_para = self.cli_options and self.cli_options.set_user_para # save original baudrate if hasattr(self.communicator, 'serial_port'): self.original_baudrate = self.communicator.serial_port.baudrate if self.data_folder is None: raise Exception( 'Data folder does not exists, please check if the application has create folder permission') try: self.rtk_log_file_name = os.path.join( self.data_folder, '{0}_log_{1}'.format(self.device_category.lower(), formatted_dir_time)) os.mkdir(self.rtk_log_file_name) except: raise Exception( 'Cannot create log folder, please check if the application has create folder permission') # set parameters from predefined parameters if set_user_para: result = self.set_params( self.properties["initial"]["userParameters"]) if (result['packetType'] == 'success'): self.save_config() # check saved result self.check_predefined_result() # start ntrip client if self.properties["initial"].__contains__("ntrip") \ and not self.ntrip_client \ and not self.is_in_bootloader \ and not self.cli_options.use_cli: self.ntrip_rtcm_logf = open(os.path.join(self.rtk_log_file_name, 'ntrip_rtcm_{0}.bin'.format( formatted_file_time)), "wb") thead = threading.Thread(target=self.ntrip_client_thread) thead.start() try: if (self.properties["initial"]["useDefaultUart"]): user_port_num, port_name = self.build_connected_serial_port_info() if not user_port_num or not port_name: return False debug_port = port_name + \ str(int(user_port_num) + self.port_index_define['debug']) rtcm_port = port_name + \ str(int(user_port_num) + self.port_index_define['rtcm']) else: for x in self.properties["initial"]["uart"]: if x['enable'] == 1: if x['name'] == 'DEBUG': debug_port = x["value"] elif x['name'] == 'GNSS': rtcm_port = x["value"] self.user_logf = open(os.path.join( self.rtk_log_file_name, 'user_{0}.bin'.format(formatted_file_time)), "wb") if rtcm_port != '': print_green('{0} log GNSS UART {1}'.format( self.device_category, rtcm_port)) self.rtcm_serial_port = serial.Serial( rtcm_port, '460800', timeout=0.1) if self.rtcm_serial_port.isOpen(): self.rtcm_logf = open( os.path.join(self.rtk_log_file_name, 'rtcm_rover_{0}.bin'.format( formatted_file_time)), "wb") thead = threading.Thread( target=self.thread_rtcm_port_receiver, args=(self.rtk_log_file_name,)) thead.start() if debug_port != '': print_green('{0} log DEBUG UART {1}'.format( self.device_category, debug_port)) self.debug_serial_port = serial.Serial( debug_port, '460800', timeout=0.1) if self.debug_serial_port.isOpen(): self.debug_logf = open( os.path.join(self.rtk_log_file_name, 'rtcm_base_{0}.bin'.format( formatted_file_time)), "wb") thead = threading.Thread( target=self.thread_debug_port_receiver, args=(self.rtk_log_file_name,)) thead.start() self.save_device_info() except Exception as ex: if self.debug_serial_port is not None: if self.debug_serial_port.isOpen(): self.debug_serial_port.close() if self.rtcm_serial_port is not None: if self.rtcm_serial_port.isOpen(): self.rtcm_serial_port.close() self.debug_serial_port = None self.rtcm_serial_port = None APP_CONTEXT.get_logger().logger.error(ex) print_red( 'Can not log GNSS UART or DEBUG UART, pls check uart driver and connection!') return False def nmea_checksum(self, data): data = data.replace("\r", "").replace("\n", "").replace("$", "") nmeadata, cksum = re.split('\*', data) calc_cksum = 0 for s in nmeadata: calc_cksum ^= ord(s) return int(cksum, 16), calc_cksum def on_read_raw(self, data): for bytedata in data: if bytedata == 0x24: self.nmea_buffer = [] self.nmea_sync = 0 self.nmea_buffer.append(chr(bytedata)) else: self.nmea_buffer.append(chr(bytedata)) if self.nmea_sync == 0: if bytedata == 0x0D: self.nmea_sync = 1 elif self.nmea_sync == 1: if bytedata == 0x0A: try: str_nmea = ''.join(self.nmea_buffer) cksum, calc_cksum = self.nmea_checksum( str_nmea) if cksum == calc_cksum: if str_nmea.find("$GPGGA") != -1 or str_nmea.find("$GNGGA") != -1: if self.ntrip_client: self.ntrip_client.send(str_nmea) #self.add_output_packet('gga', str_nmea) # print(str_nmea, end='') APP_CONTEXT.get_print_logger().info(str_nmea.replace('\r\n', '')) # else: # print("nmea checksum wrong {0} {1}".format(cksum, calc_cksum)) except Exception as e: # print('NMEA fault:{0}'.format(e)) pass self.nmea_buffer = [] self.nmea_sync = 0 if self.user_logf is not None: self.user_logf.write(data) @abstractmethod def thread_debug_port_receiver(self, *args, **kwargs): pass @abstractmethod def thread_rtcm_port_receiver(self, *args, **kwargs): pass def on_receive_output_packet(self, packet_type, data, *args, **kwargs): ''' Listener for getting output packet ''' # $GPGGA,080319.00,3130.4858508,N,12024.0998832,E,4,25,0.5,12.459,M,0.000,M,2.0,*46 if packet_type == 'gN': if self.ntrip_client: # $GPGGA gpgga = '$GNGGA' #'$GPGGA' # time timeOfWeek = float(data['GPS_TimeofWeek']) - 18 dsec = int(timeOfWeek) msec = timeOfWeek - dsec sec = dsec % 86400 hour = int(sec / 3600) minute = int(sec % 3600 / 60) second = sec % 60 gga_time = format(hour*10000 + minute*100 + second + msec, '09.2f') gpgga = gpgga + ',' + gga_time # latitude latitude = float(data['latitude']) * 180 / 2147483648.0 if latitude >= 0: latflag = 'N' else: latflag = 'S' latitude = math.fabs(latitude) lat_d = int(latitude) lat_m = (latitude-lat_d) * 60 lat_dm = format(lat_d*100 + lat_m, '012.7f') gpgga = gpgga + ',' + lat_dm + ',' + latflag # longitude longitude = float(data['longitude']) * 180 / 2147483648.0 if longitude >= 0: lonflag = 'E' else: lonflag = 'W' longitude = math.fabs(longitude) lon_d = int(longitude) lon_m = (longitude-lon_d) * 60 lon_dm = format(lon_d*100 + lon_m, '013.7f') gpgga = gpgga + ',' + lon_dm + ',' + lonflag # positionMode gpgga = gpgga + ',' + str(data['positionMode']) # svs gpgga = gpgga + ',' + str(data['numberOfSVs']) # hop gpgga = gpgga + ',' + format(float(data['hdop']), '03.1f') # height gpgga = gpgga + ',' + \ format(float(data['height']), '06.3f') + ',M' # gpgga = gpgga + ',0.000,M' # diffage gpgga = gpgga + ',' + \ format(float(data['diffage']), '03.1f') + ',' # ckm checksum = 0 for i in range(1, len(gpgga)): checksum = checksum ^ ord(gpgga[i]) str_checksum = hex(checksum) if str_checksum.startswith("0x"): str_checksum = str_checksum[2:] gpgga = gpgga + '*' + str_checksum + '\r\n' APP_CONTEXT.get_print_logger().info(gpgga) self.ntrip_client.send(gpgga) return elif packet_type == 'pS': try: if data['latitude'] != 0.0 and data['longitude'] != 0.0: if self.pS_data: if self.pS_data['GPS_Week'] == data['GPS_Week']: if data['GPS_TimeofWeek'] - self.pS_data['GPS_TimeofWeek'] >= 0.2: self.add_output_packet('pos', data) self.pS_data = data if data['insStatus'] >= 3 and data['insStatus'] <= 5: ins_status = 'INS_INACTIVE' if data['insStatus'] == 3: ins_status = 'INS_SOLUTION_GOOD' elif data['insStatus'] == 4: ins_status = 'INS_SOLUTION_FREE' elif data['insStatus'] == 5: ins_status = 'INS_ALIGNMENT_COMPLETE' ins_pos_type = 'INS_INVALID' if data['insPositionType'] == 1: ins_pos_type = 'INS_SPP' elif data['insPositionType'] == 4: ins_pos_type = 'INS_RTKFIXED' elif data['insPositionType'] == 5: ins_pos_type = 'INS_RTKFLOAT' inspva = '#INSPVA,%s,%10.2f, %s, %s,%12.8f,%13.8f,%8.3f,%9.3f,%9.3f,%9.3f,%9.3f,%9.3f,%9.3f' %\ (data['GPS_Week'], data['GPS_TimeofWeek'], ins_status, ins_pos_type, data['latitude'], data['longitude'], data['height'], data['velocityNorth'], data['velocityEast'], data['velocityUp'], data['roll'], data['pitch'], data['heading']) APP_CONTEXT.get_print_logger().info(inspva) else: self.add_output_packet('pos', data) self.pS_data = data else: self.add_output_packet('pos', data) self.pS_data = data except Exception as e: pass elif packet_type == 'sK': if self.sky_data: if self.sky_data[0]['timeOfWeek'] == data[0]['timeOfWeek']: self.sky_data.extend(data) else: self.add_output_packet('skyview', self.sky_data) self.add_output_packet('snr', self.sky_data) self.sky_data = [] self.sky_data.extend(data) else: self.sky_data.extend(data) elif packet_type == 'g1': self.ps_dic['positionMode'] = data['position_type'] self.ps_dic['numberOfSVs'] = data['number_of_satellites_in_solution'] self.ps_dic['hdop'] = data['hdop'] self.ps_dic['age'] = data['diffage'] if self.inspva_flag == 0: self.ps_dic['GPS_Week'] = data['GPS_Week'] self.ps_dic['GPS_TimeofWeek'] = data['GPS_TimeOfWeek'] * 0.001 self.ps_dic['latitude'] = data['latitude'] self.ps_dic['longitude'] = data['longitude'] self.ps_dic['height'] = data['height'] self.ps_dic['velocityMode'] = 1 self.ps_dic['velocityNorth'] = data['north_vel'] self.ps_dic['velocityEast'] = data['east_vel'] self.ps_dic['velocityUp'] = data['up_vel'] self.ps_dic['latitude_std'] = data['latitude_standard_deviation'] self.ps_dic['longitude_std'] = data['longitude_standard_deviation'] self.ps_dic['height_std'] = data['height_standard_deviation'] self.ps_dic['north_vel_std'] = data['north_vel_standard_deviation'] self.ps_dic['east_vel_std'] = data['east_vel_standard_deviation'] self.ps_dic['up_vel_std'] = data['up_vel_standard_deviation'] self.add_output_packet('pos', self.ps_dic) elif packet_type == 'i1': self.inspva_flag = 1 if data['GPS_TimeOfWeek'] % 200 == 0: self.ps_dic['GPS_Week'] = data['GPS_Week'] self.ps_dic['GPS_TimeofWeek'] = data['GPS_TimeOfWeek'] * 0.001 self.ps_dic['latitude'] = data['latitude'] self.ps_dic['longitude'] = data['longitude'] self.ps_dic['height'] = data['height'] if data['ins_position_type'] != 1 and data['ins_position_type'] != 4 and data['ins_position_type'] != 5: self.ps_dic['velocityMode'] = 2 else: self.ps_dic['velocityMode'] = 1 self.ps_dic['insStatus'] = data['ins_status'] self.ps_dic['insPositionType'] = data['ins_position_type'] self.ps_dic['velocityNorth'] = data['north_velocity'] self.ps_dic['velocityEast'] = data['east_velocity'] self.ps_dic['velocityUp'] = data['up_velocity'] self.ps_dic['roll'] = data['roll'] self.ps_dic['pitch'] = data['pitch'] self.ps_dic['heading'] = data['heading'] self.ps_dic['latitude_std'] = data['latitude_std'] self.ps_dic['longitude_std'] = data['longitude_std'] self.ps_dic['height_std'] = data['height_std'] self.ps_dic['north_vel_std'] = data['north_velocity_std'] self.ps_dic['east_vel_std'] = data['east_velocity_std'] self.ps_dic['up_vel_std'] = data['up_velocity_std'] self.ps_dic['roll_std'] = data['roll_std'] self.ps_dic['pitch_std'] = data['pitch_std'] self.ps_dic['heading_std'] = data['heading_std'] self.add_output_packet('pos', self.ps_dic) elif packet_type == 'y1': if self.sky_data: if self.sky_data[0]['GPS_TimeOfWeek'] == data[0]['GPS_TimeOfWeek']: self.sky_data.extend(data) else: self.add_output_packet('skyview', self.sky_data) self.add_output_packet('snr', self.sky_data) self.sky_data = [] self.sky_data.extend(data) else: self.sky_data.extend(data) else: output_packet_config = next( (x for x in self.properties['userMessages']['outputPackets'] if x['name'] == packet_type), None) if output_packet_config and output_packet_config.__contains__('active') \ and output_packet_config['active']: timeOfWeek = int(data['GPS_TimeOfWeek']) % 60480000 data['GPS_TimeOfWeek'] = timeOfWeek / 1000 self.add_output_packet('imu', data) @abstractmethod def build_worker(self, rule, content): ''' Build upgarde worker by rule and content ''' pass def after_jump_bootloader_command(self): pass def after_jump_app_command(self): # rtk330l ping device can_ping = False while not can_ping: self.communicator.reset_buffer() # clear input and output buffer info = ping(self.communicator, None) if info: can_ping = True time.sleep(0.5) pass def get_upgrade_workers(self, firmware_content): workers = [] rules = [ InternalCombineAppParseRule('rtk', 'rtk_start:', 4), InternalCombineAppParseRule('ins', 'ins_start:', 4), InternalCombineAppParseRule('sdk', 'sdk_start:', 4), ] parsed_content = firmware_content_parser(firmware_content, rules) # foreach parsed content, if empty, skip register into upgrade center device_info = self.get_device_connection_info() for _, rule in enumerate(parsed_content): content = parsed_content[rule] if len(content) == 0: continue worker = self.build_worker(rule, content) if not worker: continue if (device_info['modelName'] == 'RTK330L') and (rule == 'sdk') and ((int(device_info['serialNumber']) <= 2178200080) and (int(device_info['serialNumber']) >= 2178200001)): continue else: workers.append(worker) # prepare jump bootloader worker and jump application workder # append jump bootloader worker before the first firmware upgrade workder # append jump application worker after the last firmware uprade worker start_index = -1 end_index = -1 for i, worker in enumerate(workers): if isinstance(worker, FirmwareUpgradeWorker): start_index = i if start_index == -1 else start_index end_index = i jump_bootloader_command = helper.build_bootloader_input_packet( 'JI') jumpBootloaderWorker = JumpBootloaderWorker( self.communicator, command=jump_bootloader_command, listen_packet='JI', wait_timeout_after_command=1) jumpBootloaderWorker.on( UPGRADE_EVENT.AFTER_COMMAND, self.after_jump_bootloader_command) jump_application_command = helper.build_bootloader_input_packet('JA') jumpApplicationWorker = JumpApplicationWorker( self.communicator, command=jump_application_command, listen_packet='JA', wait_timeout_after_command=1) jumpApplicationWorker.on( UPGRADE_EVENT.AFTER_COMMAND, self.after_jump_app_command) if start_index > -1 and end_index > -1: workers.insert( start_index, jumpBootloaderWorker) workers.insert( end_index+2, jumpApplicationWorker) return workers def get_device_connection_info(self): return { 'modelName': self.device_info['name'], 'deviceType': self.type, 'serialNumber': self.device_info['sn'], 'partNumber': self.device_info['pn'], 'firmware': self.device_info['firmware_version'] } def check_predefined_result(self): local_time = time.localtime() formatted_file_time = time.strftime("%Y_%m_%d_%H_%M_%S", local_time) file_path = os.path.join( self.rtk_log_file_name, 'parameters_predefined_{0}.json'.format(formatted_file_time) ) # save parameters to data log folder after predefined parameters setup result = self.get_params() if result['packetType'] == 'inputParams': with open(file_path, 'w') as outfile: json.dump(result['data'], outfile) # compare saved parameters with predefined parameters hashed_predefined_parameters = helper.collection_to_dict( self.properties["initial"]["userParameters"], key='paramId') hashed_current_parameters = helper.collection_to_dict( result['data'], key='paramId') success_count = 0 fail_count = 0 fail_parameters = [] for key in hashed_predefined_parameters: if hashed_current_parameters[key]['value'] == \ hashed_predefined_parameters[key]['value']: success_count += 1 else: fail_count += 1 fail_parameters.append( hashed_predefined_parameters[key]['name']) check_result = 'Predefined Parameters are saved. Success ({0}), Fail ({1})'.format( success_count, fail_count) if success_count == len(hashed_predefined_parameters.keys()): print_green(check_result) if fail_count > 0: print_yellow(check_result) print_yellow('The failed parameters: {0}'.format(fail_parameters)) def save_device_info(self): ''' Save device configuration File name: configuration.json ''' if self.is_in_bootloader: return result = self.get_params() device_configuration = None file_path = os.path.join( self.data_folder, self.rtk_log_file_name, 'configuration.json') if not os.path.exists(file_path): device_configuration = [] else: with open(file_path) as json_data: device_configuration = (list)(json.load(json_data)) if result['packetType'] == 'inputParams': session_info = dict() session_info['time'] = time.strftime( "%Y-%m-%d %H:%M:%S", time.localtime()) session_info['device'] = self.device_info session_info['app'] = self.app_info session_info['interface'] = self.cli_options.interface if session_info['interface'] == 'uart': session_info['path'] = self.communicator.serial_port.port parameters_configuration = dict() for item in result['data']: param_name = item['name'] param_value = item['value'] parameters_configuration[param_name] = param_value session_info['parameters'] = parameters_configuration device_configuration.append(session_info) with open(file_path, 'w') as outfile: json.dump(device_configuration, outfile, indent=4, ensure_ascii=False) def after_upgrade_completed(self): self.communicator.reset_buffer() pass def get_operation_status(self): if self.is_logging: return 'LOGGING' return 'IDLE' # command list def server_status(self, *args): # pylint: disable=invalid-name ''' Get server connection status ''' return { 'packetType': 'ping', 'data': {'status': '1'} } def get_device_info(self, *args): # pylint: disable=invalid-name ''' Get device information ''' return { 'packetType': 'deviceInfo', 'data': [ {'name': 'Product Name', 'value': self.device_info['name']}, {'name': 'IMU', 'value': self.device_info['imu']}, {'name': 'PN', 'value': self.device_info['pn']}, {'name': 'Firmware Version', 'value': self.device_info['firmware_version']}, {'name': 'SN', 'value': self.device_info['sn']}, {'name': 'App Version', 'value': self.app_info['version']} ] } def get_log_info(self): ''' Build information for log ''' return { "type": self.type, "model": self.device_info['name'], "logInfo": { "pn": self.device_info['pn'], "sn": self.device_info['sn'], "rtkProperties": json.dumps(self.properties) } } def get_conf(self, *args): # pylint: disable=unused-argument ''' Get json configuration ''' return { 'packetType': 'conf', 'data': { 'outputs': self.properties['userMessages']['outputPackets'], 'inputParams': self.properties['userConfiguration'] } } @with_device_message def get_params(self, *args): # pylint: disable=unused-argument ''' Get all parameters ''' has_error = False parameter_values = [] if self.app_info['app_name'] == 'RTK_INS': conf_parameters = self.properties['userConfiguration'] conf_parameters_len = len(conf_parameters)-1 step = 10 for i in range(2, conf_parameters_len, step): start_byte = i end_byte = i+step-1 if i+step < conf_parameters_len else conf_parameters_len time.sleep(0.2) command_line = helper.build_packet( 'gB', [start_byte, end_byte]) result = yield self._message_center.build(command=command_line, timeout=10) if result['error']: has_error = True break parameter_values.extend(result['data']) else: command_line = helper.build_input_packet('gA') result = yield self._message_center.build(command=command_line, timeout=3) if result['error']: has_error = True parameter_values = result['data'] if not has_error: self.parameters = parameter_values yield { 'packetType': 'inputParams', 'data': parameter_values } yield { 'packetType': 'error', 'data': 'No Response' } @with_device_message def get_param(self, params, *args): # pylint: disable=unused-argument ''' Update paramter value ''' command_line = helper.build_input_packet( 'gP', properties=self.properties, param=params['paramId']) # self.communicator.write(command_line) # result = self.get_input_result('gP', timeout=1) result = yield self._message_center.build(command=command_line) data = result['data'] error = result['error'] if error: yield { 'packetType': 'error', 'data': 'No Response' } if data: self.parameters = data yield { 'packetType': 'inputParam', 'data': data } yield { 'packetType': 'error', 'data': 'No Response' } @with_device_message def set_params(self, params, *args): # pylint: disable=unused-argument ''' Update paramters value ''' input_parameters = self.properties['userConfiguration'] grouped_parameters = {} for parameter in params: exist_parameter = next( (x for x in input_parameters if x['paramId'] == parameter['paramId']), None) if exist_parameter: has_group = grouped_parameters.__contains__( exist_parameter['category']) if not has_group: grouped_parameters[exist_parameter['category']] = [] current_group = grouped_parameters[exist_parameter['category']] current_group.append( {'paramId': parameter['paramId'], 'value': parameter['value'], 'type': exist_parameter['type']}) for group in grouped_parameters.values(): message_bytes = [] for parameter in group: message_bytes.extend( encode_value('int8', parameter['paramId']) ) message_bytes.extend( encode_value(parameter['type'], parameter['value']) ) # print('parameter type {0}, value {1}'.format( # parameter['type'], parameter['value'])) # result = self.set_param(parameter) command_line = helper.build_packet( 'uB', message_bytes) # for s in command_line: # print(hex(s)) result = yield self._message_center.build(command=command_line) packet_type = result['packet_type'] data = result['data'] if packet_type == 'error': yield { 'packetType': 'error', 'data': { 'error': data } } break if data > 0: yield { 'packetType': 'error', 'data': { 'error': data } } break yield { 'packetType': 'success', 'data': { 'error': 0 } } @with_device_message def set_param(self, params, *args): # pylint: disable=unused-argument ''' Update paramter value ''' command_line = helper.build_input_packet( 'uP', properties=self.properties, param=params['paramId'], value=params['value']) # self.communicator.write(command_line) # result = self.get_input_result('uP', timeout=1) result = yield self._message_center.build(command=command_line) error = result['error'] data = result['data'] if error: yield { 'packetType': 'error', 'data': { 'error': data } } yield { 'packetType': 'success', 'data': { 'error': data } } @with_device_message def save_config(self, *args): # pylint: disable=unused-argument ''' Save configuration ''' command_line = helper.build_input_packet('sC') # self.communicator.write(command_line) # result = self.get_input_result('sC', timeout=2) result = yield self._message_center.build(command=command_line, timeout=2) data = result['data'] error = result['error'] if data: yield { 'packetType': 'success', 'data': error } yield { 'packetType': 'success', 'data': error } @with_device_message def reset_params(self, params, *args): # pylint: disable=unused-argument ''' Reset params to default ''' command_line = helper.build_input_packet('rD') result = yield self._message_center.build(command=command_line, timeout=2) error = result['error'] data = result['data'] if error: yield { 'packetType': 'error', 'data': { 'error': error } } yield { 'packetType': 'success', 'data': data } def upgrade_framework(self, params, *args): # pylint: disable=unused-argument ''' Upgrade framework ''' file = '' if isinstance(params, str): file = params if isinstance(params, dict): file = params['file'] # start a thread to do upgrade if not self.is_upgrading: self.is_upgrading = True self._message_center.pause() if self._logger is not None: self._logger.stop_user_log() self.thread_do_upgrade_framework(file) print("Upgrade RTK330LA firmware started at:[{0}].".format( datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'))) return { 'packetType': 'success' } \ No newline at end of file diff --git a/src/aceinna/devices/configs/ins401_predefine.py b/src/aceinna/devices/configs/ins401_predefine.py index 4f6f22c..6c82904 100644 --- a/src/aceinna/devices/configs/ins401_predefine.py +++ b/src/aceinna/devices/configs/ins401_predefine.py @@ -26,4 +26,15 @@ def get_ins402_configuratin_file_mapping(): 'INS402':'ins402.json' } +def get_ins502_products(): + return { + 'INS502':['RTK_INS'] + } + + +def get_ins502_configuratin_file_mapping(): + return { + 'INS502':'ins502.json' + } + APP_STR = ['RAWDATA', 'RTK', 'RTK_INS', 'RTK_INS_CANFD'] diff --git a/src/aceinna/devices/configs/rtk_predefine.py b/src/aceinna/devices/configs/rtk_predefine.py index a5380f6..34e7fbc 100644 --- a/src/aceinna/devices/configs/rtk_predefine.py +++ b/src/aceinna/devices/configs/rtk_predefine.py @@ -1,11 +1,12 @@ """ -predefined params for openrtk +predefined params for openrtk """ def get_rtk_products(): return { - 'RTK330L': ['RTK_INS'] + 'RTK330L': ['RTK_INS'], + 'RTK350L': ['RTK_INS'] } @@ -19,7 +20,8 @@ def get_app_names(): def get_configuratin_file_mapping(): return { - 'RTK330L': 'RTK330L.json' + 'RTK330L': 'RTK330L.json', + 'RTK350L': 'RTK350LA.json' } diff --git a/src/aceinna/devices/device_manager.py b/src/aceinna/devices/device_manager.py index 5302089..8c395a4 100644 --- a/src/aceinna/devices/device_manager.py +++ b/src/aceinna/devices/device_manager.py @@ -1 +1,103 @@ -from .ping import ping_tool from .rtkl.uart_provider import Provider as RTKLUartProvider from .rtkl.uart_provider import beidouProvider as beidouUartProvider from .ins401.ethernet_provider_ins401 import Provider as INS401EthernetProvider from .ins401.ethernet_provider_ins402 import Provider as INS402EthernetProvider from ..framework.context import APP_CONTEXT from ..framework.utils.print import print_green from ..framework.constants import INTERFACES def create_provider(device_type, communicator): if communicator.type == INTERFACES.UART: if device_type == 'RTKL': return RTKLUartProvider(communicator) elif device_type == 'beidou': return beidouUartProvider(communicator) if communicator.type==INTERFACES.ETH_100BASE_T1: if device_type == 'INS401': return INS401EthernetProvider(communicator) elif device_type == 'INS402': return INS402EthernetProvider(communicator) return None class DeviceManager: ''' Manage devices ''' device_list = [] @staticmethod def build_provider(communicator, device_access, ping_info): if ping_info is None: return None device_type = ping_info['device_type'] device_info = ping_info['device_info'] app_info = ping_info['app_info'] provider = None # find provider from cached device_list for index in range(len(DeviceManager.device_list)): exist_device = DeviceManager.device_list[index] if exist_device['device_type'] == device_type and \ exist_device['communicator_type'] == communicator.type: provider = exist_device['provider'] provider.communicator = communicator break if provider is None: provider = create_provider(device_type, communicator) if provider is None: return None DeviceManager.device_list.append({ 'device_type': device_type, 'communicator_type': communicator.type, 'provider': provider }) else: communicator.upgrading_flag = False format_device_info = provider.bind_device_info( device_access, device_info, app_info) print_green(format_device_info) APP_CONTEXT.get_logger().logger.info( 'Connected Device info {0}'.format(format_device_info)) return provider @staticmethod def ping(communicator, *args): ''' Find device with ping command uart: communicator, device_type lan: communicator ''' if communicator.type == INTERFACES.UART: device_access = args[0] filter_device_type = args[1] ping_result = ping_tool.do_ping( communicator.type, device_access, filter_device_type) if ping_result is not None: return DeviceManager.build_provider(communicator, device_access, ping_result) if communicator.type == INTERFACES.ETH_100BASE_T1: device_access = args[0] ping_result = ping_tool.do_ping(communicator.type, device_access, None) if ping_result is not None: return DeviceManager.build_provider(communicator, device_access, ping_result) return None \ No newline at end of file +from .ping import ping_tool +from .rtkl.uart_provider import Provider as RTKLUartProvider +from .rtk350la.uart_provider import Provider as RTK350LAUartProvider +from .rtkl.uart_provider import beidouProvider as beidouUartProvider +from .ins401.ethernet_provider_ins401 import Provider as INS401EthernetProvider +from .ins401.ethernet_provider_ins402 import Provider as INS402EthernetProvider +from .ins401.ethernet_provider_ins502 import Provider as INS502EthernetProvider +from ..framework.context import APP_CONTEXT +from ..framework.utils.print import print_green +from ..framework.constants import INTERFACES + +def create_provider(device_type, communicator): + if communicator.type == INTERFACES.UART: + if device_type == 'RTKL': + return RTKLUartProvider(communicator) + elif device_type == 'beidou': + return beidouUartProvider(communicator) + elif device_type == 'RTK350LA': + return RTK350LAUartProvider(communicator) + + if communicator.type==INTERFACES.ETH_100BASE_T1: + if device_type == 'INS401': + return INS401EthernetProvider(communicator) + elif device_type == 'INS402': + return INS402EthernetProvider(communicator) + elif device_type == 'INS502': + return INS502EthernetProvider(communicator) + + return None + + +class DeviceManager: + ''' + Manage devices + ''' + device_list = [] + + @staticmethod + def build_provider(communicator, device_access, ping_info): + if ping_info is None: + return None + + device_type = ping_info['device_type'] + device_info = ping_info['device_info'] + app_info = ping_info['app_info'] + + provider = None + # find provider from cached device_list + for index in range(len(DeviceManager.device_list)): + exist_device = DeviceManager.device_list[index] + if exist_device['device_type'] == device_type and \ + exist_device['communicator_type'] == communicator.type: + provider = exist_device['provider'] + provider.communicator = communicator + break + + if provider is None: + provider = create_provider(device_type, communicator) + if provider is None: + return None + + DeviceManager.device_list.append({ + 'device_type': device_type, + 'communicator_type': communicator.type, + 'provider': provider + }) + else: + communicator.upgrading_flag = False + + format_device_info = provider.bind_device_info( + device_access, device_info, app_info) + + print_green(format_device_info) + + APP_CONTEXT.get_logger().logger.info( + 'Connected Device info {0}'.format(format_device_info)) + return provider + + @staticmethod + def ping(communicator, *args): + ''' + Find device with ping command + uart: communicator, device_type + lan: communicator + ''' + if communicator.type == INTERFACES.UART: + device_access = args[0] + filter_device_type = args[1] + + ping_result = ping_tool.do_ping( + communicator.type, device_access, filter_device_type) + if ping_result is not None: + return DeviceManager.build_provider(communicator, device_access, ping_result) + if communicator.type == INTERFACES.ETH_100BASE_T1: + device_access = args[0] + filter_device_type = args[1] + + ping_result = ping_tool.do_ping(communicator.type, device_access, + filter_device_type) + if ping_result is not None: + return DeviceManager.build_provider(communicator, device_access, ping_result) + + return None diff --git a/src/aceinna/devices/ins401/ethernet_provider_base.py b/src/aceinna/devices/ins401/ethernet_provider_base.py index 4b17656..776ec5a 100644 --- a/src/aceinna/devices/ins401/ethernet_provider_base.py +++ b/src/aceinna/devices/ins401/ethernet_provider_base.py @@ -855,7 +855,6 @@ def get_upgrade_workers(self, firmware_content): ins_len = len(content) & 0xFFFF self.ins_crc = helper.calc_crc(content[0:ins_len]) - if rule == 'sdk': if self.sdk_upgrade_flag: worker = self.build_worker(rule, content) diff --git a/src/aceinna/devices/ins401/ethernet_provider_ins402.py b/src/aceinna/devices/ins401/ethernet_provider_ins402.py index 41625a5..1f991ce 100644 --- a/src/aceinna/devices/ins401/ethernet_provider_ins402.py +++ b/src/aceinna/devices/ins401/ethernet_provider_ins402.py @@ -14,11 +14,12 @@ from ...framework.utils.firmware_parser import parser as firmware_content_parser from ..base.provider_base import OpenDeviceBase from ..configs.ins401_predefine import (APP_STR, get_ins402_products, - get_ins402_configuratin_file_mapping) + get_ins402_configuratin_file_mapping) from ..decorator import with_device_message from ...models import InternalCombineAppParseRule from ..parsers.ins401_field_parser import encode_value -from ...framework.utils.print import (print_yellow, print_green, print_blue) +from ...framework.utils.print import ( + print_yellow, print_green, print_blue, print_red) from ..ins401.mountangle.mountangle import MountAngle from ..ins401.ethernet_provider_base import Provider_base from ..upgrade_workers import ( @@ -32,6 +33,7 @@ GNZDA_DATA_LEN = 39 + class Provider(Provider_base): ''' INS401 Ethernet 100base-t1 provider @@ -92,7 +94,7 @@ def load_properties(self): with open(local_config_file_path) as json_data: self.properties = json.load(json_data) return - + # Load the openimu.json based on its app product_name = self.device_info['name'] app_name = 'RTK_INS' # self.app_info['app_name'] @@ -139,7 +141,7 @@ def after_setup(self): # check saved result self.check_predefined_result() - + self.set_unit_sn_message() if set_mount_angle: @@ -160,9 +162,9 @@ def after_setup(self): if not self.is_upgrading and not self.with_upgrade_error: # start ntrip client if self.properties["initial"].__contains__("ntrip") \ - and not self.ntrip_client \ - and not self.is_in_bootloader \ - and not self.cli_options.use_cli: + and not self.ntrip_client \ + and not self.is_in_bootloader \ + and not self.cli_options.use_cli: threading.Thread(target=self.ntrip_client_thread).start() @@ -170,30 +172,29 @@ def after_setup(self): print('Exception in after setup', e) return False - - def set_mountangle_config(self, result = []): + def set_mountangle_config(self, result=[]): # copy contents of app_config under executor path setting_folder_path = os.path.join(resource.get_executor_path(), - 'setting') + 'setting') # Load the openimu.json based on its app product_name = 'INS402' app_name = 'RTK_INS' # self.app_info['app_name'] app_file_path = os.path.join(setting_folder_path, product_name, - app_name, 'ins401.json') + app_name, 'ins401.json') with open(app_file_path, 'r') as json_data: self.properties = json.load(json_data) - + # update mountangle config file - with open(app_file_path, 'w') as json_data: - userParameters = self.properties["initial"]["userParameters"] + with open(app_file_path, 'w') as json_data: + userParameters = self.properties["initial"]["userParameters"] for i in range(3): userParameters[9 + i]['value'] = result[i] - - json.dump(self.properties, - json_data, - indent=4, - ensure_ascii=False) + + json.dump(self.properties, + json_data, + indent=4, + ensure_ascii=False) # setting params with open(app_file_path, 'r') as json_data: @@ -223,19 +224,23 @@ def on_receive_output_packet(self, packet_type, data, *args, **kwargs): if self.mountangle: payload_len = struct.unpack(' 2: + if len(params) > 2: # rtk ins sdk imu each upgrade - for param in params: + for param in params: if param == 'rtk': self.rtk_upgrade_flag = True @@ -272,13 +277,13 @@ def upgrade_framework(self, params, *args): # pylint: disable=unused-argument self.sdk_2_upgrade_flag = True if param == 'imu_boot': - self.imu_boot_upgrade_flag = True + self.imu_boot_upgrade_flag = True if param == 'imu': self.imu_upgrade_flag = True - elif len(params) == 2: - # rtk ins sdk imu upgrade, the imu boot upgrade depends on + elif len(params) == 2: + # rtk ins sdk imu upgrade, the imu boot upgrade depends on # whether the imu boot is merged into the firmware self.rtk_upgrade_flag = True self.ins_upgrade_flag = True @@ -297,7 +302,149 @@ def upgrade_framework(self, params, *args): # pylint: disable=unused-argument self._logger.stop_user_log() self.thread_do_upgrade_framework(file) - print("Upgrade INS401 firmware started at:[{0}].".format( + print("Upgrade INS402 firmware started at:[{0}].".format( datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'))) return {'packetType': 'success'} + + def configure_algorithm(self, params, *args): + file = '' + if isinstance(params[1], str): + file = params[1] + + can_download, content = self.download_firmware(file) + if not can_download: + print_red('Cannot find configuration file') + return False + + content_size = len(content) + block_size = 1024 + block_number = math.ceil(content_size/block_size) + step_result = False + # send prepare command + step_result = self.configure_do_send_prepare( + content_size, block_number) + if not step_result: + print_red('Failed to prepare configration') + return False + + # send packet command + step_result = self.configure_do_send_packet(content, block_size) + if not step_result: + print_red('Failed to send configuration packet') + return False + + print('Configure succeed, restarting...') + # do reset + step_result = self.configure_do_reset() + if not step_result: + print_red('Restart failed') + return False + + print_green('Restart succeed') + return True + + def configure_do_send_prepare(self, content_size, block_number): + content_size_bytes = struct.pack(' timeout: + return False + + result = self.send_ping_command() + if result['packetType'] == 'success': + return True + + time.sleep(1) + + @with_device_message + def send_configure_command(self, message_bytes): + command_config = b'\xa4\x0a' + + command_line = helper.build_ethernet_packet( + self.communicator.get_dst_mac(), + self.communicator.get_src_mac(), + command_config, list(message_bytes) + ) + + result = yield self._message_center.build(command=command_line.actual_command) + + error = result['error'] + data = result['data'] + response_code = -1 + + if error: + yield {'packetType': 'error', 'data': data} + + try: + if data[0] == 0x0a: + response_code = struct.unpack(' 0: + yield {'packetType': 'error', 'data': response_code} + + yield {'packetType': 'success', 'data': data} + + @with_device_message + def send_ping_command(self): + command_ping = b'\x01\xcc' + + command_line = helper.build_ethernet_packet( + self.communicator.get_dst_mac(), + self.communicator.get_src_mac(), + command_ping + ) + # self.communicator.write(command.actual_command) + result = yield self._message_center.build(command=command_line.actual_command) + + error = result['error'] + data = result['data'] + + if error: + yield {'packetType': 'error', 'data': data} + + yield {'packetType': 'success', 'data': data} diff --git a/src/aceinna/devices/ins401/ethernet_provider_ins502.py b/src/aceinna/devices/ins401/ethernet_provider_ins502.py new file mode 100644 index 0000000..7a97d32 --- /dev/null +++ b/src/aceinna/devices/ins401/ethernet_provider_ins502.py @@ -0,0 +1,400 @@ +import os +import struct +import time +import json +import datetime +import threading +import math +import struct +from ...framework.utils import (helper, resource) +from ...framework.context import APP_CONTEXT +from ..configs.ins401_predefine import (APP_STR, get_ins502_products, + get_ins502_configuratin_file_mapping) +from ..decorator import with_device_message +from ..parsers.ins401_field_parser import encode_value +from ...framework.utils.print import ( + print_yellow, print_green, print_blue, print_red) +from ..ins401.ethernet_provider_base import Provider_base + +GNZDA_DATA_LEN = 39 + + +class Provider(Provider_base): + ''' + INS502 Ethernet 100base-t1 provider + ''' + + def __init__(self, communicator, *args): + super(Provider, self).__init__(communicator) + self.type = 'INS502' + self.prepare_folders() + self.rtcm_rover2_logf = None + + def prepare_folders(self): + ''' + Prepare folders for data storage and configuration + ''' + executor_path = resource.get_executor_path() + setting_folder_name = 'setting' + + data_folder_path = os.path.join(executor_path, 'data') + if not os.path.isdir(data_folder_path): + os.makedirs(data_folder_path) + self.data_folder = data_folder_path + + # copy contents of app_config under executor path + self.setting_folder_path = os.path.join(executor_path, + setting_folder_name) + + all_products = get_ins502_products() + config_file_mapping = get_ins502_configuratin_file_mapping() + + for product in all_products: + product_folder = os.path.join(self.setting_folder_path, product) + if not os.path.isdir(product_folder): + os.makedirs(product_folder) + + for app_name in all_products[product]: + app_name_path = os.path.join(product_folder, app_name) + app_name_config_path = os.path.join( + app_name_path, config_file_mapping[product]) + + if not os.path.isfile(app_name_config_path): + if not os.path.isdir(app_name_path): + os.makedirs(app_name_path) + app_config_content = resource.get_content_from_bundle( + setting_folder_name, + os.path.join(product, app_name, + config_file_mapping[product])) + if app_config_content is None: + continue + + with open(app_name_config_path, "wb") as code: + code.write(app_config_content) + + def load_properties(self): + # Load config from user working path + local_config_file_path = os.path.join(os.getcwd(), 'ins502.json') + if os.path.isfile(local_config_file_path): + with open(local_config_file_path) as json_data: + self.properties = json.load(json_data) + return + + # Load the openimu.json based on its app + product_name = self.device_info['name'] + app_name = 'RTK_INS' # self.app_info['app_name'] + app_file_path = os.path.join(self.setting_folder_path, product_name, + app_name, 'ins502.json') + + with open(app_file_path) as json_data: + self.properties = json.load(json_data) + + if not self.is_app_matched: + print_yellow( + 'Failed to extract app version information from unit.' + ) + + def after_setup(self): + set_user_para = self.cli_options and self.cli_options.set_user_para + self.ntrip_client_enable = self.cli_options and self.cli_options.ntrip_client + # with_raw_log = self.cli_options and self.cli_options.with_raw_log + set_mount_angle = self.cli_options and self.cli_options.set_mount_angle + + try: + if self.data_folder: + dir_time = time.strftime("%Y%m%d_%H%M%S", time.localtime()) + file_time = time.strftime("%Y_%m_%d_%H_%M_%S", + time.localtime()) + file_name = self.data_folder + '/' + 'ins502_log_' + dir_time + os.mkdir(file_name) + self.rtk_log_file_name = file_name + + self.ins401_log_file_path = file_name + '/' + 'user_' + file_time + '.bin' + self.user_logf = open(self.ins401_log_file_path, "wb") + self.rtcm_logf = open( + file_name + '/' + 'rtcm_base_' + file_time + '.bin', "wb") + self.rtcm_rover_logf = open( + file_name + '/' + 'rtcm_rover_' + file_time + '.bin', "wb") + self.rtcm_rover2_logf = open( + file_name + '/' + 'rtcm_rover2_' + file_time + '.bin', "wb") + if set_user_para and not self.is_upgrading: + result = self.set_params( + self.properties["initial"]["userParameters"]) + ##print('set user para {0}'.format(result)) + if result['packetType'] == 'success': + self.save_config() + + # check saved result + self.check_predefined_result() + + self.set_unit_sn_message() + + if set_mount_angle: + self.set_mount_angle() + self.prepare_lib_folder() + + if self.cli_options.debug == 'true': + result = self.get_compile_message() + if result['packetType'] == 'success': + format_compile_info = self.bind_compile_info( + result['data']) + print_blue(format_compile_info) + else: + print('can\'t get get_compile_message') + self.save_device_info() + + # start ntrip client + if not self.is_upgrading and not self.with_upgrade_error: + # start ntrip client + if self.properties["initial"].__contains__("ntrip") \ + and not self.ntrip_client \ + and not self.is_in_bootloader \ + and not self.cli_options.use_cli: + + threading.Thread(target=self.ntrip_client_thread).start() + + except Exception as e: + print('Exception in after setup', e) + return False + + def on_receive_output_packet(self, packet_type, data, *args, **kwargs): + ''' + Listener for getting output packet + ''' + if packet_type == b'\x06\x0a': + if self.rtcm_rover_logf: + self.rtcm_rover_logf.write(bytes(data)) + elif packet_type == b'\x0c\x0a': + if self.rtcm_rover2_logf: + self.rtcm_rover2_logf.write(bytes(data)) + else: + raw_data = kwargs.get('raw') + if self.user_logf and raw_data: + self.user_logf.write(bytes(raw_data)) + + if self.mountangle: + payload_len = struct.unpack(' 2: + # rtk ins sdk imu each upgrade + for param in params: + if param == 'rtk': + self.rtk_upgrade_flag = True + + if param == 'ins': + self.ins_upgrade_flag = True + + if param == 'sdk': + self.sdk_upgrade_flag = True + + if param == 'sdk_2': + self.sdk_2_upgrade_flag = True + + if param == 'imu_boot': + self.imu_boot_upgrade_flag = True + + if param == 'imu': + self.imu_upgrade_flag = True + + elif len(params) == 2: + # rtk ins sdk imu upgrade, the imu boot upgrade depends on + # whether the imu boot is merged into the firmware + self.rtk_upgrade_flag = True + self.ins_upgrade_flag = True + self.sdk_upgrade_flag = True + self.sdk_2_upgrade_flag = True + self.imu_upgrade_flag = False + self.imu_boot_upgrade_flag = False + + # start a thread to do upgrade + if not self.is_upgrading: + self.is_upgrading = True + self._message_center.pause() + self.loop_upgrade_flag = True + + if self._logger is not None: + self._logger.stop_user_log() + + self.thread_do_upgrade_framework(file) + print("Upgrade INS502 firmware started at:[{0}].".format( + datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'))) + + return {'packetType': 'success'} + + def configure_algorithm(self, params, *args): + file = '' + if isinstance(params[1], str): + file = params[1] + + can_download, content = self.download_firmware(file) + if not can_download: + print_red('Cannot find configuration file') + return False + + content_size = len(content) + block_size = 1024 + block_number = math.ceil(content_size/block_size) + step_result = False + # send prepare command + step_result = self.configure_do_send_prepare( + content_size, block_number) + if not step_result: + print_red('Failed to prepare configration') + return False + + # send packet command + step_result = self.configure_do_send_packet(content, block_size) + if not step_result: + print_red('Failed to send configuration packet') + return False + + print('Configure succeed, restarting...') + # do reset + step_result = self.configure_do_reset() + if not step_result: + print_red('Restart failed') + return False + + print_green('Restart succeed') + return True + + def configure_do_send_prepare(self, content_size, block_number): + content_size_bytes = struct.pack(' timeout: + return False + + result = self.send_ping_command() + if result['packetType'] == 'success': + return True + + time.sleep(1) + + @with_device_message + def send_configure_command(self, message_bytes): + command_config = b'\xa4\x0a' + + command_line = helper.build_ethernet_packet( + self.communicator.get_dst_mac(), + self.communicator.get_src_mac(), + command_config, list(message_bytes) + ) + + result = yield self._message_center.build(command=command_line.actual_command) + + error = result['error'] + data = result['data'] + response_code = -1 + + if error: + yield {'packetType': 'error', 'data': data} + + try: + if data[0] == 0x0a: + response_code = struct.unpack(' 0: + yield {'packetType': 'error', 'data': response_code} + + yield {'packetType': 'success', 'data': data} + + @with_device_message + def send_ping_command(self): + command_ping = b'\x01\xcc' + + command_line = helper.build_ethernet_packet( + self.communicator.get_dst_mac(), + self.communicator.get_src_mac(), + command_ping + ) + # self.communicator.write(command.actual_command) + result = yield self._message_center.build(command=command_line.actual_command) + + error = result['error'] + data = result['data'] + + if error: + yield {'packetType': 'error', 'data': data} + + yield {'packetType': 'success', 'data': data} diff --git a/src/aceinna/devices/message_center.py b/src/aceinna/devices/message_center.py index 5c56b52..9b05e70 100644 --- a/src/aceinna/devices/message_center.py +++ b/src/aceinna/devices/message_center.py @@ -173,9 +173,10 @@ def timeout_check(self): if span.total_seconds() > timeout and not \ self._running_message.get_finished(): timeout_command = self._running_message.get_command() - print('command timeout', - timeout_command, - timeout, start_time, current_time) + # print('command timeout', + # timeout_command, + # timeout, start_time, current_time) + APP_CONTEXT.get_logger().error('command timeout') packet_info = self._parser.get_packet_info( timeout_command) self._last_timeout_command = packet_info diff --git a/src/aceinna/devices/parser_manager.py b/src/aceinna/devices/parser_manager.py index dd0312c..e623f64 100644 --- a/src/aceinna/devices/parser_manager.py +++ b/src/aceinna/devices/parser_manager.py @@ -1,4 +1,5 @@ from .parsers.rtk330l_message_parser import UartMessageParser as Rtk330lUartMessageParser +from .parsers.rtk350l_message_parser import UartMessageParser as Rtk350lUartMessageParser from .parsers.beidou_message_parser import UartMessageParser as beidouUartMessageParser from .parsers.ins401_message_parser import EthernetMessageParser as INS401EthernetMessageParser @@ -14,9 +15,11 @@ def build(device_type, communicator_type, properties): # pylint:disable=unused- ''' Generate matched parser ''' - if device_type == 'INS401' or device_type == 'INS402': + if device_type == 'INS401' or device_type == 'INS402' or device_type == 'INS502': return INS401EthernetMessageParser(properties) elif device_type == 'beidou': return beidouUartMessageParser(properties) + elif device_type == 'RTK350LA': + return Rtk350lUartMessageParser(properties) else: return Rtk330lUartMessageParser(properties) diff --git a/src/aceinna/devices/parsers/ins401_field_parser.py b/src/aceinna/devices/parsers/ins401_field_parser.py index dafa0dc..b4beecf 100644 --- a/src/aceinna/devices/parsers/ins401_field_parser.py +++ b/src/aceinna/devices/parsers/ins401_field_parser.py @@ -53,25 +53,25 @@ def do_decode_value(data_type, data, conf): return unpack_value elif data_type == 'uint16': try: - pack_item = struct.pack('2B', *data) + pack_item = struct.pack('2B', *data[0:2]) except: # pylint: disable=bare-except return False return struct.unpack('= PACKET_PAYLOAD_INDEX: - payload_len_byte = bytes(data_block[PACKET_PAYLOAD_LEN_INDEX:PACKET_PAYLOAD_INDEX]) - payload_len = struct.unpack('H', packet_type_byte)[0] - - if len(data_block) < PACKET_PAYLOAD_INDEX + payload_len + 2: - APP_CONTEXT.get_logger().logger.info( - "crc check error! packet_type:{0}".format(packet_type)) - - self.emit('crc_failure', packet_type=packet_type, - event_time=time.time()) - print('crc_failure', packet_type=packet_type, - event_time=time.time()) - return - - result = helper.calc_crc(data_block[PACKET_TYPE_INDEX:PACKET_PAYLOAD_INDEX+payload_len]) - - if result[0] == data_block[PACKET_PAYLOAD_INDEX + payload_len] and result[1] == data_block[PACKET_PAYLOAD_INDEX + payload_len + 1]: - self._parse_message( - struct.pack('>H', packet_type), payload_len, data_block) - else: - APP_CONTEXT.get_logger().logger.info( - "crc check error! packet_type:{0}".format(packet_type)) - - self.emit('crc_failure', packet_type=packet_type, - event_time=time.time()) - input_packet_config = next( - (x for x in self.properties['userMessages']['inputPackets'] - if x['name'] == packet_type), None) - if input_packet_config: - self.emit('command', - packet_type=packet_type, - data=[], - error=True, - raw=data_block) - - def _parse_message(self, packet_type, payload_len, frame): - payload = frame[PACKET_PAYLOAD_INDEX:payload_len+PACKET_PAYLOAD_INDEX] - # parse interactive commands - is_interactive_cmd = INPUT_PACKETS.__contains__(packet_type) - - if is_interactive_cmd: - self._parse_input_packet(packet_type, payload, frame) - else: - # consider as output packet, parse output Messages - self._parse_output_packet(packet_type, payload, frame) - - def _parse_input_packet(self, packet_type, payload, frame): - payload_parser = match_command_handler(packet_type) - - if payload_parser: - data, error = payload_parser( - payload, self.properties['userConfiguration']) - self.emit('command', - packet_type=packet_type, - data=data, - error=error, - raw=frame) - else: - print('[Warning] Unsupported command {0}'.format( - packet_type.encode())) - - def _parse_output_packet(self, packet_type, payload, frame): - # check if it is the valid out packet - payload_parser = None - is_other_output_packet = OTHER_OUTPUT_PACKETS.__contains__(packet_type) - if is_other_output_packet: - payload_parser = other_output_parser - data = payload_parser(payload) - - self.emit('continuous_message', - packet_type=packet_type, - data=payload, - event_time=time.time(), - raw=frame) - return - - payload_parser = common_continuous_parser - - output_packet_config = next( - (x for x in self.properties['userMessages']['outputPackets'] - if x['name'] == packet_type), None) - data = payload_parser(payload, output_packet_config) - - if not data: - # APP_CONTEXT.get_logger().logger.info( - # 'Cannot parse packet type {0}. It may caused by firmware upgrade'.format(packet_type)) - return - - self.emit('continuous_message', - packet_type=packet_type, - data=data, - event_time=time.time()) +import collections import operator import time import struct from ..base.message_parser_base import MessageParserBase from ...framework.utils import helper from ...framework.context import APP_CONTEXT from .ins401_packet_parser import ( match_command_handler, common_continuous_parser, other_output_parser) MSG_HEADER = [0x55, 0x55] PACKET_TYPE_INDEX = 2 PACKET_PAYLOAD_LEN_INDEX = 4 PACKET_PAYLOAD_INDEX = 8 INPUT_PACKETS = [b'\x01\xcc', b'\x02\xcc', b'\x03\xcc', b'\x04\xcc', b'\x05\xcc',b'\x06\xcc', b'\x01\x0b', b'\x02\x0b', b'\x09\x0a', b'\x09\xaa', b'\x01\xfc', b'\xa4\x0a'] OTHER_OUTPUT_PACKETS = [b'\x01\n', b'\x02\n', b'\x03\n', b'\x04\n', b'\x05\n', b'\x06\n', b'\x08\n',b'\x09\x0a', b'\x0a\x0a', b'\x0b\x0a', b'\x0c\x0a', b'\x0f\x0a', b'\x07\n', b'\x09\xaa', b'\x44\x4D', b'\x49\x67', b'\x64\x66', b'\x65\x66', b'\xa3\x0a', b'\x49\x49'] class EthernetMessageParser(MessageParserBase): def __init__(self, configuration): super(EthernetMessageParser, self).__init__(configuration) def set_run_command(self, command): pass def analyse(self, data_block): if operator.eq(list(data_block[0:2]), MSG_HEADER) and len(data_block) >= PACKET_PAYLOAD_INDEX: payload_len_byte = bytes(data_block[PACKET_PAYLOAD_LEN_INDEX:PACKET_PAYLOAD_INDEX]) payload_len = struct.unpack('H', packet_type_byte)[0] if len(data_block) < PACKET_PAYLOAD_INDEX + payload_len + 2: APP_CONTEXT.get_logger().logger.info( "crc check error! packet_type:{0}".format(packet_type)) self.emit('crc_failure', packet_type=packet_type, event_time=time.time()) print('crc_failure', packet_type=packet_type, event_time=time.time()) return result = helper.calc_crc(data_block[PACKET_TYPE_INDEX:PACKET_PAYLOAD_INDEX+payload_len]) if result[0] == data_block[PACKET_PAYLOAD_INDEX + payload_len] and result[1] == data_block[PACKET_PAYLOAD_INDEX + payload_len + 1]: self._parse_message( struct.pack('>H', packet_type), payload_len, data_block) else: APP_CONTEXT.get_logger().logger.info( "crc check error! packet_type:{0}".format(packet_type)) self.emit('crc_failure', packet_type=packet_type, event_time=time.time()) input_packet_config = next( (x for x in self.properties['userMessages']['inputPackets'] if x['name'] == packet_type), None) if input_packet_config: self.emit('command', packet_type=packet_type, data=[], error=True, raw=data_block) def _parse_message(self, packet_type, payload_len, frame): payload = frame[PACKET_PAYLOAD_INDEX:payload_len+PACKET_PAYLOAD_INDEX] # parse interactive commands is_interactive_cmd = INPUT_PACKETS.__contains__(packet_type) if is_interactive_cmd: self._parse_input_packet(packet_type, payload, frame) else: # consider as output packet, parse output Messages self._parse_output_packet(packet_type, payload, frame) def _parse_input_packet(self, packet_type, payload, frame): payload_parser = match_command_handler(packet_type) if payload_parser: data, error = payload_parser( payload, self.properties['userConfiguration']) self.emit('command', packet_type=packet_type, data=data, error=error, raw=frame) else: print('[Warning] Unsupported command {0}'.format( packet_type.encode())) def _parse_output_packet(self, packet_type, payload, frame): # check if it is the valid out packet payload_parser = None is_other_output_packet = OTHER_OUTPUT_PACKETS.__contains__(packet_type) if is_other_output_packet: payload_parser = other_output_parser data = payload_parser(payload) self.emit('continuous_message', packet_type=packet_type, data=payload, event_time=time.time(), raw=frame) return payload_parser = common_continuous_parser output_packet_config = next( (x for x in self.properties['userMessages']['outputPackets'] if x['name'] == packet_type), None) data = payload_parser(payload, output_packet_config) if not data: # APP_CONTEXT.get_logger().logger.info( # 'Cannot parse packet type {0}. It may caused by firmware upgrade'.format(packet_type)) return self.emit('continuous_message', packet_type=packet_type, data=data, event_time=time.time()) \ No newline at end of file diff --git a/src/aceinna/devices/parsers/ins401_packet_parser.py b/src/aceinna/devices/parsers/ins401_packet_parser.py index b574839..18b3472 100644 --- a/src/aceinna/devices/parsers/ins401_packet_parser.py +++ b/src/aceinna/devices/parsers/ins401_packet_parser.py @@ -36,7 +36,7 @@ def string_parser(payload, user_configuration): data_str = _format_string(payload) - if data_str and (data_str.find('INS401') > -1) \ + if data_str and (data_str.find('INS') > -1) \ and (data_str.find('RTK_INS App') > -1) \ and (data_str.find('Bootloader') > -1): data = data_str @@ -353,6 +353,7 @@ def match_command_handler(packet_type): b'\x02\x0b': common_input_parser, b'\x09\x0a': common_input_parser, b'\x09\xaa': common_input_parser, + b'\xa4\x0a': common_input_parser, b'\x01\xfc': set_serial_number_parser } return parser_dict.get(packet_type) diff --git a/src/aceinna/devices/parsers/rtk330l_field_parser.py b/src/aceinna/devices/parsers/rtk330l_field_parser.py index dafa0dc..aa88c7f 100644 --- a/src/aceinna/devices/parsers/rtk330l_field_parser.py +++ b/src/aceinna/devices/parsers/rtk330l_field_parser.py @@ -1,7 +1,7 @@ import math import struct import decimal -from . import filter_nan +from . import filter_nan def do_decode_value(data_type, data, conf): @@ -121,6 +121,15 @@ def decode_value(data_type, data, conf=None): return filter_nan(ret_value) +def get_value_len(data_type): + if data_type == 'uint64' or data_type == 'uint64' or data_type == 'double': + return 8 + elif data_type == 'uint32' or data_type == 'int32' or data_type == 'float': + return 4 + elif data_type == 'uint16' or data_type == 'int16': + return 2 + elif data_type == 'uint8' or data_type == 'int8': + return 1 def encode_value(data_type, data): payload = [] diff --git a/src/aceinna/devices/parsers/rtk330l_message_parser.py b/src/aceinna/devices/parsers/rtk330l_message_parser.py index 20e2258..27153a7 100644 --- a/src/aceinna/devices/parsers/rtk330l_message_parser.py +++ b/src/aceinna/devices/parsers/rtk330l_message_parser.py @@ -17,7 +17,7 @@ 'JI', 'JA', 'WA', 'CS', 'JS', 'JG' 'RE', 'WE', 'UE', 'LE', 'SR', 'SF', 'RF', 'WF', 'GF', 'RC', 'WC', 'PK', 'CH'] -OTHER_OUTPUT_PACKETS = ['s1', 's2', 'iN', 'd1', 'gN', 'd2', 'sT', 'o1', 'DM'] +OTHER_OUTPUT_PACKETS = ['s1', 'S2', 'iN', 'd1', 'gN', 'd2', 'sT', 'o1', 'DM'] class ANALYSIS_STATUS: @@ -75,131 +75,6 @@ def check_crc(self): crc_value = self._raw_data_bytes[-2:] return crc_calculate_value == crc_value - -# class UartMessageParser(MessageParserBase): -# _current_analysis_status = ANALYSIS_STATUS.INIT -# _current_packet = None -# _read_index = 0 -# _current_packet_type = [] - -# def __init__(self, configuration): -# super(UartMessageParser, self).__init__(configuration) -# self._current_analysis_status = ANALYSIS_STATUS.INIT -# self._sync_pattern = collections.deque(2*[0], 2) -# self._current_packet_type = [] - -# def set_run_command(self, command): -# pass - -# def analyse(self, data): -# for value in data: -# if self._current_analysis_status == ANALYSIS_STATUS.INIT: -# self._sync_pattern.append(value) - -# if self._sync_pattern[0] == MSG_HEADER[0] and self._sync_pattern[1] == MSG_HEADER[1]: -# self._current_packet = OpenDevicePacket() -# self._current_packet.accept_to_header( -# list(self._sync_pattern)) -# self._current_analysis_status = ANALYSIS_STATUS.FOUND_HEADER -# self._read_index = len(MSG_HEADER) - -# continue - -# if self._current_analysis_status == ANALYSIS_STATUS.FOUND_HEADER: -# if len(self._current_packet_type) < 2: -# self._current_packet_type.append(value) - -# if len(self._current_packet_type) == 2: -# self._current_packet.accept_to_packet_type( -# self._current_packet_type) -# self._current_analysis_status = ANALYSIS_STATUS.FOUND_PACKET_TYPE -# self._read_index += 2 - -# continue - -# if self._current_analysis_status == ANALYSIS_STATUS.FOUND_PACKET_TYPE: -# self._current_packet.accept_to_length(value) -# self._current_analysis_status = ANALYSIS_STATUS.FOUND_PAYLOAD_LENGTH -# self._read_index += 1 -# continue - -# if self._current_analysis_status == ANALYSIS_STATUS.FOUND_PAYLOAD_LENGTH: -# self._current_packet.accept_to_payload(value) -# self._read_index += 1 -# if self._read_index == self._current_packet.payload_length + 2: -# # calculate crc -# crc_result = self._current_packet.check_crc() -# if not crc_result: -# self.reset() -# continue - -# # crc valid -# self._current_analysis_status = ANALYSIS_STATUS.CRC_PASSED - -# if self._current_analysis_status == ANALYSIS_STATUS.CRC_PASSED: -# #self.crc_passed_count += 1 -# # packets.push(this._currentPacket); -# self._parse_message(self._current_packet) -# self.reset() - -# continue - -# def reset(self): -# self._current_analysis_status = ANALYSIS_STATUS.INIT -# self._sync_pattern = collections.deque(2*[0], 2) -# self._current_packet_type = [] -# self._read_index = 0 - -# def _parse_message(self, data_packet): -# # parse interactive commands -# is_interactive_cmd = INPUT_PACKETS.__contains__( -# data_packet.packet_type) -# if is_interactive_cmd: -# self._parse_input_packet(data_packet) -# else: -# # consider as output packet, parse output Messages -# self._parse_output_packet(data_packet) - -# def _parse_input_packet(self, data_packet): -# payload_parser = match_command_handler(data_packet.packet_type) -# if payload_parser: -# data, error = payload_parser( -# data_packet.payload, self.properties['userConfiguration']) - -# self.emit('command', -# packet_type=data_packet.packet_type, -# data=data, -# error=error, -# raw=data_packet.raw) -# else: -# print('[Warning] Unsupported command {0}'.format( -# data_packet.packet_type)) - -# def _parse_output_packet(self, data_packet): -# # check if it is the valid out packet -# payload_parser = None -# is_other_output_packet = OTHER_OUTPUT_PACKETS.__contains__( -# data_packet.packet_type) -# if is_other_output_packet: -# payload_parser = other_output_parser -# data = payload_parser(data_packet.payload) -# return - -# payload_parser = common_continuous_parser - -# output_packet_config = next( -# (x for x in self.properties['userMessages']['outputPackets'] -# if x['name'] == data_packet.packet_type), None) -# data = payload_parser(data_packet.payload, output_packet_config) - -# if not data: -# return -# self.emit('continuous_message', -# packet_type=data_packet.packet_type, -# data=data, -# event_time=time.time()) - - class UartMessageParser(MessageParserBase): def __init__(self, configuration): super(UartMessageParser, self).__init__(configuration) diff --git a/src/aceinna/devices/parsers/rtk350l_message_parser.py b/src/aceinna/devices/parsers/rtk350l_message_parser.py new file mode 100644 index 0000000..746b0ba --- /dev/null +++ b/src/aceinna/devices/parsers/rtk350l_message_parser.py @@ -0,0 +1,139 @@ +import collections +import operator +import time +from ..base.message_parser_base import MessageParserBase +from ...framework.utils import helper +from ...framework.context import APP_CONTEXT +from .rtk350l_packet_parser import ( + match_command_handler, common_continuous_parser, other_output_parser) + +MSG_HEADER = [0x55, 0x55] +PACKET_TYPE_INDEX = 2 + +INPUT_PACKETS = ['pG', 'uC', 'uP', 'uA', 'uB', + 'sC', 'rD', + 'gC', 'gA', 'gB', 'gP', 'gV', 'cA' + '\x15\x15', '\x00\x00', + 'JI', 'JA', 'WA', 'CS', 'JS', 'JG' + 'RE', 'WE', 'UE', 'LE', 'SR', + 'SF', 'RF', 'WF', 'GF', 'RC', 'WC', 'PK', 'CH'] +OTHER_OUTPUT_PACKETS = ['S2','SI', 'gN', 'iN', 'iS', 'o1', 'pv', 'rR', 'iB', 'sT', 'MB', 'HS' ] + + +class ANALYSIS_STATUS: + INIT = 0 + FOUND_HEADER = 1 + FOUND_PAYLOAD_LENGTH = 2 + FOUND_PACKET_TYPE = 3 + CRC_PASSED = 4 + +class UartMessageParser(MessageParserBase): + def __init__(self, configuration): + super(UartMessageParser, self).__init__(configuration) + self.frame = [] + self.payload_len_idx = 5 + self.sync_pattern = collections.deque(2*[0], 2) + self.find_header = False + self.payload_len = 0 + # command,continuous_message + + def set_run_command(self, command): + pass + + def analyse(self, data): + for data_block in data: + if self.find_header: + self.frame.append(data_block) + if self.payload_len_idx == len(self.frame): + self.payload_len = data_block + + elif 5 + self.payload_len + 2 == len(self.frame): + packet_type = ''.join( + ["%c" % x for x in self.frame[PACKET_TYPE_INDEX:4]]) + self.find_header = False + result = helper.calc_crc(self.frame[2:-2]) + if result[0] == self.frame[-2] and result[1] == self.frame[-1]: + # find a whole frame + # self._parse_frame(self.frame, self.payload_len) + self._parse_message( + packet_type, self.payload_len, self.frame) + + self.find_header = False + self.payload_len = 0 + self.sync_pattern = collections.deque(2*[0], 2) + else: + APP_CONTEXT.get_logger().logger.info( + "crc check error! packet_type:{0}".format(packet_type)) + + self.emit('crc_failure', packet_type=packet_type, + event_time=time.time()) + input_packet_config = next( + (x for x in self.properties['userMessages']['inputPackets'] + if x['name'] == packet_type), None) + if input_packet_config: + self.emit('command', + packet_type=packet_type, + data=[], + error=True, + raw=self.frame) + else: + self.sync_pattern.append(data_block) + if operator.eq(list(self.sync_pattern), MSG_HEADER): + self.frame = MSG_HEADER[:] # header_tp.copy() + self.find_header = True + + def _parse_message(self, packet_type, payload_len, frame): + payload = frame[5:payload_len+5] + # parse interactive commands + is_interactive_cmd = INPUT_PACKETS.__contains__(packet_type) + if is_interactive_cmd: + self._parse_input_packet(packet_type, payload, frame) + else: + # consider as output packet, parse output Messages + self._parse_output_packet(packet_type, payload, frame) + + def _parse_input_packet(self, packet_type, payload, frame): + payload_parser = match_command_handler(packet_type) + if payload_parser: + data, error = payload_parser( + payload, self.properties['userConfiguration']) + self.emit('command', + packet_type=packet_type, + data=data, + error=error, + raw=frame) + else: + print('[Warning] Unsupported command {0}'.format( + packet_type.encode())) + + def _parse_output_packet(self, packet_type, payload, frame): + # check if it is the valid out packet + payload_parser = None + is_other_output_packet = OTHER_OUTPUT_PACKETS.__contains__(packet_type) + if is_other_output_packet: + payload_parser = other_output_parser + data = payload_parser(payload) + + self.emit('continuous_message', + packet_type=packet_type, + data=data, + event_time=time.time(), + raw=frame) + return + + payload_parser = common_continuous_parser + + output_packet_config = next( + (x for x in self.properties['userMessages']['outputPackets'] + if x['name'] == packet_type), None) + data = payload_parser(payload, output_packet_config) + + if not data: + # APP_CONTEXT.get_logger().logger.info( + # 'Cannot parse packet type {0}. It may caused by firmware upgrade'.format(packet_type)) + return + + self.emit('continuous_message', + packet_type=packet_type, + data=data, + event_time=time.time()) diff --git a/src/aceinna/devices/parsers/rtk350l_packet_parser.py b/src/aceinna/devices/parsers/rtk350l_packet_parser.py new file mode 100644 index 0000000..337bb3c --- /dev/null +++ b/src/aceinna/devices/parsers/rtk350l_packet_parser.py @@ -0,0 +1,361 @@ +import sys +import struct +import collections +from . import filter_nan +from .rtk330l_field_parser import decode_value +from ...framework.utils.print import print_yellow +from ...framework.context import APP_CONTEXT + +# input packet +error_decode_packet = 0 + + +def string_parser(payload, user_configuration): + error = False + data = '' + try: + if sys.version_info < (3, 0): + data = str(struct.pack( + '{0}B'.format(len(payload)), *payload)) + else: + data = str(struct.pack( + '{0}B'.format(len(payload)), *payload), 'utf-8') + except UnicodeDecodeError: + data = '' + + return data, error + + +def get_all_parameters_parser(payload, user_configuration): + ''' + gA parser + ''' + error = False + data = [] + data_len = 0 + for parameter in user_configuration: + param_id = parameter['paramId'] + param_type = parameter['type'] + name = parameter['name'] + + if param_type == 'uint8' or param_type == 'int8': + value = decode_value( + param_type, payload[data_len:data_len + 1]) + data_len = data_len + 1 + elif param_type == 'uint16' or param_type == 'int16': + value = decode_value( + param_type, payload[data_len:data_len + 2]) + data_len = data_len + 2 + elif param_type == 'uint32' or param_type == 'int32' or param_type == 'float': + value = decode_value( + param_type, payload[data_len:data_len + 4]) + data_len = data_len + 4 + elif param_type == 'uint64' or param_type == 'int64' or param_type == 'double': + value = decode_value( + param_type, payload[data_len:data_len + 8]) + data_len = data_len + 8 + elif param_type == 'ip4': + value = decode_value( + param_type, payload[data_len:data_len + 4]) + data_len = data_len + 4 + elif param_type == 'ip6': + value = decode_value( + param_type, payload[data_len:data_len + 6]) + data_len = data_len + 6 + elif 'char' in param_type: + ctype_n = param_type.replace('char', '') + ctype_l = int(ctype_n) + value = decode_value( + param_type, payload[data_len:data_len + ctype_l]) + data_len = data_len + ctype_l + else: + print( + "no [{0}] when unpack_input_packet".format(param_type)) + value = False + data.append( + {"paramId": param_id, "name": name, "value": value}) + + return data, error + + +def get_parameters_by_block_parser(payload, user_configuration): + ''' + gB parser + ''' + data = [] + error = False + para_id = 0 + para_len = 0 + data_len = len(payload) + index = 0 + while index < data_len: + para_id = payload[index] + para_len = payload[index+1] + exist_param_conf = next((param_conf for param_conf in user_configuration + if param_conf['paramId'] == para_id), None) + if para_len == 1: + param_type = 'uint8' + value = decode_value( + param_type, payload[index+2: index+2+para_len]) + elif para_len == 4: + param_type = 'float' + value = decode_value( + param_type, payload[index+2: index+2+para_len], exist_param_conf) + # data_len = data_len - 2 - para_len + index+= para_len+1+1 + data.append({ + "paramId": para_id, + "name": exist_param_conf['name'], + "value": value + }) + + + # for i in range(start_param_id, end_param_id+1, 1): + # exist_param_conf = next((param_conf for param_conf in user_configuration + # if param_conf['paramId'] == i), None) + # if exist_param_conf: + # param_type = exist_param_conf['type'] + + # if param_type == 'uint8' or param_type == 'int8': + # value = decode_value( + # param_type, payload[data_len:data_len + 1]) + # data_len = data_len + 1 + # elif param_type == 'uint16' or param_type == 'int16': + # value = decode_value( + # param_type, payload[data_len:data_len + 2]) + # data_len = data_len + 2 + # elif param_type == 'uint32' or param_type == 'int32' or param_type == 'float': + # value = decode_value( + # param_type, payload[data_len:data_len + 4], exist_param_conf) + # data_len = data_len + 4 + # elif param_type == 'uint64' or param_type == 'int64' or param_type == 'double': + # value = decode_value( + # param_type, payload[data_len:data_len + 8]) + # data_len = data_len + 8 + # elif param_type == 'ip4': + # value = decode_value( + # param_type, payload[data_len:data_len + 4]) + # data_len = data_len + 4 + # elif param_type == 'ip6': + # value = decode_value( + # param_type, payload[data_len:data_len + 6]) + # data_len = data_len + 6 + # elif 'char' in param_type: + # ctype_n = param_type.replace('char', '') + # ctype_l = int(ctype_n) + # value = decode_value( + # param_type, payload[data_len:data_len + ctype_l]) + # data_len = data_len + ctype_l + # else: + # print( + # "no [{0}] when unpack_input_packet".format(param_type)) + # value = False + + # data.append({ + # "paramId": i, + # "name": exist_param_conf['name'], + # "value": value + # }) + + return data, error + + +def get_parameter_parser(payload, user_configuration): + ''' + gP Parser + ''' + data = None + error = False + param_id = decode_value('uint32', payload[0:4]) + + if param_id is not False: + param = filter(lambda item: item['paramId'] == + param_id, user_configuration) + + try: + first_item = next(iter(param), None) + param_value = decode_value( + first_item['type'], payload[4:12]) + data = {"paramId": param_id, + "name": first_item['name'], "value": param_value} + except StopIteration: + error = True + except Exception: + error = True + else: + error = True + + return data, error + + +def update_parameter_parser(payload, user_configuration): + ''' + uP parser + ''' + error = False + data = decode_value('uint32', payload[0:4]) + if data: + error = True + return data, error + + +def update_parameters_parser(payload, user_configuration): + ''' + uB parser + ''' + # print('uB response: ', payload) + error = True + data = 0 + # print('data', payload) + for i in range(0, len(payload), 2): + if payload[i+1] != 0: + error = False + data = payload[i] + break + return data, error + + +def common_input_parser(payload, user_configuration): + ''' + General input packet parser + ''' + return payload, False + + +def read_eeprom_parser(payload, user_configuration=None): + return payload[3:], False + + +# output packet + + +def common_continuous_parser(payload, configuration): + ''' + Unpack output packet + ''' + if configuration is None: + return + + data = None + is_list = 0 + length = 0 + pack_fmt = '<' + for value in configuration['payload']: + if value['type'] == 'float': + pack_fmt += 'f' + length += 4 + elif value['type'] == 'uint32': + pack_fmt += 'I' + length += 4 + elif value['type'] == 'int32': + pack_fmt += 'i' + length += 4 + elif value['type'] == 'int16': + pack_fmt += 'h' + length += 2 + elif value['type'] == 'uint16': + pack_fmt += 'H' + length += 2 + elif value['type'] == 'double': + pack_fmt += 'd' + length += 8 + elif value['type'] == 'int64': + pack_fmt += 'q' + length += 8 + elif value['type'] == 'uint64': + pack_fmt += 'Q' + length += 8 + elif value['type'] == 'char': + pack_fmt += 'c' + length += 1 + elif value['type'] == 'uchar': + pack_fmt += 'B' + length += 1 + elif value['type'] == 'uint8': + pack_fmt += 'B' + length += 1 + len_fmt = '{0}B'.format(length) + + has_list = configuration.__contains__('isList') + if has_list: + is_list = configuration['isList'] + + if is_list == 1: + packet_num = len(payload) // length + data = [] + for i in range(packet_num): + payload_c = payload[i*length:(i+1)*length] + try: + pack_item = struct.pack(len_fmt, *payload_c) + item = struct.unpack(pack_fmt, pack_item) + out = [(value['name'], item[idx]) + for idx, value in enumerate(configuration['payload'])] + item = collections.OrderedDict(out) + data.append(item) + except Exception as ex: # pylint: disable=broad-except + print( + "error happened when decode the payload, pls restart driver: {0}" + .format(ex)) + else: + try: + pack_item = struct.pack(len_fmt, *payload) + data = struct.unpack(pack_fmt, pack_item) + out = [( + value['name'], + filter_nan(data[idx]) + ) for idx, value in enumerate(configuration['payload'])] + + data = collections.OrderedDict(out) + except Exception as ex: # pylint: disable=broad-except + global error_decode_packet + error_decode_packet = error_decode_packet + 1 + if error_decode_packet == 100 or error_decode_packet == 400 or error_decode_packet == 700: + print_yellow( + "warning: your firmware may not suitable for this driver, pls update firmware or driver") + + if error_decode_packet % 300 == 0: + APP_CONTEXT.get_logger().logger.warning( + "error happened when decode the payload of packets, pls restart driver: {0}" + .format(ex)) + + return data + + +def other_output_parser(payload): + return payload + +# packet handler + + +def match_command_handler(packet_type): + ''' + Find the handler for specified packet + ''' + parser_dict = { + 'pG': string_parser, + 'uC': common_input_parser, # update_command_parser, + 'uP': update_parameter_parser, + 'uA': common_input_parser, # update_all_command_parser, + 'sC': common_input_parser, + 'rD': common_input_parser, + 'gC': common_input_parser, # get_command_parser, + 'gA': get_all_parameters_parser, + 'gP': get_parameter_parser, + 'gB': get_parameters_by_block_parser, + 'gV': string_parser, + 'uB': update_parameters_parser, + 'ma': common_input_parser, + 'RE': read_eeprom_parser, + 'WE': common_input_parser, + 'UE': common_input_parser, + 'LE': common_input_parser, + 'SR': common_input_parser, + 'JI': common_input_parser, + 'JA': common_input_parser, + 'WA': common_input_parser, + 'RF': common_input_parser, + 'GF': common_input_parser, + 'SF': common_input_parser, + 'WF': common_input_parser, + } + return parser_dict.get(packet_type) diff --git a/src/aceinna/devices/ping/ins401.py b/src/aceinna/devices/ping/ins.py similarity index 83% rename from src/aceinna/devices/ping/ins401.py rename to src/aceinna/devices/ping/ins.py index 903da15..17180d4 100644 --- a/src/aceinna/devices/ping/ins401.py +++ b/src/aceinna/devices/ping/ins.py @@ -3,6 +3,8 @@ import struct from ...framework.utils import (helper, resource) from ...framework.context import APP_CONTEXT +from ...framework.utils.print import (print_red) + pG = [0x01, 0xcc] @@ -55,10 +57,10 @@ def run_command_as_string(communicator, command): return result -def try_parse_app_mode(info_text): +def try_parse_app_mode(device_type, info_text): is_app_mode = False app_ping_info = None - + split_text = info_text.split(' SN:') if len(split_text) == 1: @@ -69,7 +71,7 @@ def try_parse_app_mode(info_text): app_info_text = 'RTK_INS' + split_text[1] app_ping_info = { - 'device_type': 'INS401', + 'device_type': device_type, 'device_info': device_info_text, 'app_info': app_info_text } @@ -77,10 +79,10 @@ def try_parse_app_mode(info_text): return is_app_mode, app_ping_info -def try_parse_bootloader_mode(info_text): +def try_parse_bootloader_mode(device_type, info_text): is_bootloader_mode = False bootloader_ping_info = None - + split_text = info_text.split('SN:') if len(split_text) == 2: is_bootloader_mode = True @@ -89,7 +91,7 @@ def try_parse_bootloader_mode(info_text): app_info_text = info_text bootloader_ping_info = { - 'device_type': 'INS401', + 'device_type': device_type, 'device_info': device_info_text, 'app_info': app_info_text } @@ -100,6 +102,8 @@ def try_parse_bootloader_mode(info_text): def ping(communicator, *args): '''OpenDevice Ping ''' + filter_device_type = args[0] + cmd_info_text = run_command_as_string(communicator, pG) if cmd_info_text.find(',') > -1: info_text = cmd_info_text.replace(',', ' ') @@ -109,16 +113,22 @@ def ping(communicator, *args): # Prevent action. Get app info again, # if cannot retrieve any info at the first time of ping. Should find the root cause. - if info_text.find('INS401') > -1: - is_app_mode, app_ping_info = try_parse_app_mode(info_text) + if info_text.find(filter_device_type) > -1: + is_app_mode, app_ping_info = try_parse_app_mode(filter_device_type, info_text) if is_app_mode: return app_ping_info is_bootloader_mode, bootloader_ping_info = try_parse_bootloader_mode( + filter_device_type, info_text) if is_bootloader_mode: return bootloader_ping_info return None + else: + cmd_info = info_text.split(' ') + if len(cmd_info) > 0: + print_red('{0} != {1}'.format(filter_device_type, cmd_info[0])) + print(info_text) return None diff --git a/src/aceinna/devices/ping/ins402.py b/src/aceinna/devices/ping/ins402.py deleted file mode 100644 index f81fb73..0000000 --- a/src/aceinna/devices/ping/ins402.py +++ /dev/null @@ -1,123 +0,0 @@ -import sys -import time -import struct -from ...framework.utils import (helper, resource) -from ...framework.context import APP_CONTEXT -pG = [0x01, 0xcc] - - -def _run_command(communicator, command): - run_command = helper.build_ethernet_packet(communicator.get_dst_mac(), - communicator.get_src_mac(), command) - communicator.reset_buffer() - communicator.write(run_command.actual_command) - - time.sleep(0.1) - data_buffer = helper.read_untils_have_data( - communicator, command, retry_times=500) - return data_buffer - - -def _format_string(data_buffer): - parsed = bytearray( - data_buffer) if data_buffer and len(data_buffer) > 0 else None - - formatted = '' - if parsed is not None: - try: - if sys.version_info < (3, 0): - formatted = str( - struct.pack('{0}B'.format(len(parsed)), *parsed)) - else: - formatted = str( - struct.pack('{0}B'.format(len(parsed)), *parsed), 'utf-8') - except UnicodeDecodeError: - APP_CONTEXT.get_logger().logger.error( - 'Parse data as string failed') - formatted = '' - - return formatted - - -def _need_check(limit_type, device_type): - if limit_type is None: - return True - - return limit_type == device_type - - -def run_command_as_string(communicator, command): - ''' Run command and parse result as string - ''' - data_buffer = _run_command(communicator, command) - result = _format_string(data_buffer) - - return result - - -def try_parse_app_mode(info_text): - is_app_mode = False - app_ping_info = None - - split_text = info_text.split(' SN:') - - if len(split_text) == 1: - split_text = info_text.split(' RTK_INS') - is_app_mode = True - - device_info_text = split_text[0] - app_info_text = 'RTK_INS' + split_text[1] - - app_ping_info = { - 'device_type': 'INS402', - 'device_info': device_info_text, - 'app_info': app_info_text - } - - return is_app_mode, app_ping_info - - -def try_parse_bootloader_mode(info_text): - is_bootloader_mode = False - bootloader_ping_info = None - - split_text = info_text.split('SN:') - if len(split_text) == 2: - is_bootloader_mode = True - - device_info_text = info_text - app_info_text = info_text - - bootloader_ping_info = { - 'device_type': 'INS402', - 'device_info': device_info_text, - 'app_info': app_info_text - } - - return is_bootloader_mode, bootloader_ping_info - - -def ping(communicator, *args): - '''OpenDevice Ping - ''' - cmd_info_text = run_command_as_string(communicator, pG) - if cmd_info_text.find(',') > -1: - info_text = cmd_info_text.replace(',', ' ') - else: - info_text = cmd_info_text - - # Prevent action. Get app info again, - # if cannot retrieve any info at the first time of ping. Should find the root cause. - if info_text.find('INS402') > -1: - is_app_mode, app_ping_info = try_parse_app_mode(info_text) - if is_app_mode: - return app_ping_info - - is_bootloader_mode, bootloader_ping_info = try_parse_bootloader_mode( - info_text) - if is_bootloader_mode: - return bootloader_ping_info - - return None - - return None diff --git a/src/aceinna/devices/ping/open.py b/src/aceinna/devices/ping/open.py new file mode 100644 index 0000000..a1ac620 --- /dev/null +++ b/src/aceinna/devices/ping/open.py @@ -0,0 +1,107 @@ +import sys +import time +import struct +from ...framework.utils import (helper, resource) +from ...framework.context import APP_CONTEXT + +pG = 'pG' +gV = 'gV' + + +def _run_command(communicator, command, size, retry): + command_line = helper.build_input_packet(command) + communicator.write(command_line) + time.sleep(0.1) + + data_buffer = helper.read_untils_have_data( + communicator, command, size, retry) + + return data_buffer + + +def _format_string(data_buffer): + parsed = bytearray(data_buffer) if data_buffer and len( + data_buffer) > 0 else None + + formatted = '' + if parsed is not None: + try: + if sys.version_info < (3, 0): + formatted = str(struct.pack( + '{0}B'.format(len(parsed)), *parsed)) + else: + formatted = str(struct.pack( + '{0}B'.format(len(parsed)), *parsed), 'utf-8') + except UnicodeDecodeError: + APP_CONTEXT.get_logger().logger.error('Parse data as string failed') + formatted = '' + + return formatted + + +def _need_check(limit_type, device_type): + if limit_type is None: + return True + + return limit_type == device_type + + +def run_command_as_string(communicator, command, size=1000, retry=10): + ''' Run command and parse result as string + ''' + data_buffer = _run_command(communicator, command, size, retry) + result = _format_string(data_buffer) + + return result + + +def ping(communicator, *args): + '''OpenDevice Ping + ''' + filter_device_type = args[0] + + device_info_text = run_command_as_string(communicator, pG) + app_info_text = run_command_as_string(communicator, gV) + + # Prevent action. Get app info again, + # if cannot retrieve any info at the first time of ping. Should find the root cause. + if app_info_text == '': + app_info_text = run_command_as_string(communicator, gV) + + if _need_check(filter_device_type, 'RTK') and device_info_text.find('OpenRTK') > -1: + return { + 'device_type': 'OpenRTK', + 'device_info': device_info_text, + 'app_info': app_info_text + } + + # a bad check, to distinguish RTK330L or OpenRTK330L + if _need_check(filter_device_type, 'RTKL') and device_info_text.find('RTK330L') > -1 and device_info_text.find('OpenRTK') == -1 : + return { + 'device_type': 'RTKL', + 'device_info': device_info_text, + 'app_info': app_info_text + } + + if _need_check(filter_device_type, 'IMU') and device_info_text.find('OpenIMU') > -1 and \ + device_info_text.find('OpenRTK') == -1: + return { + 'device_type': 'OpenIMU', + 'device_info': device_info_text, + 'app_info': app_info_text + } + if _need_check(filter_device_type, 'INS') and device_info_text.find('INS401') > -1: + return { + 'device_type': 'INS401', + 'device_info': device_info_text, + 'app_info': app_info_text + } + + if _need_check(filter_device_type, 'RTKL') and device_info_text.find('RTK350L') > -1 and device_info_text.find('OpenRTK') == -1 : + return { + 'device_type': 'RTK350LA', + 'device_info': device_info_text, + 'app_info': app_info_text + } + + return None diff --git a/src/aceinna/devices/ping/ping_tool.py b/src/aceinna/devices/ping/ping_tool.py index fc7832b..bcf7dd8 100644 --- a/src/aceinna/devices/ping/ping_tool.py +++ b/src/aceinna/devices/ping/ping_tool.py @@ -1,13 +1,14 @@ from .rtk330l import ping as ping_rtk330l -from .ins401 import ping as ping_ins401 -from .ins402 import ping as ping_ins402 +from .ins import ping as ping_ins from .beidou import ping as ping_beidou +from .open import ping as ping_opendevice from ...framework.context import APP_CONTEXT from ...framework.constants import INTERFACES def do_ping(communicator_type, device_access, filter_device_type): if communicator_type == INTERFACES.UART: - if filter_device_type is None or filter_device_type in ['RTKL', 'beidou']: + # if filter_device_type is None or filter_device_type in ['RTKL', 'beidou']: + if filter_device_type in ['RTKL', 'beidou']: APP_CONTEXT.get_logger().logger.debug( 'Checking if is RTK330L device...') ping_result = ping_rtk330l( @@ -19,14 +20,24 @@ def do_ping(communicator_type, device_access, filter_device_type): if ping_result: return ping_result + elif filter_device_type is None: + ping_result = ping_opendevice( + device_access, filter_device_type) + if ping_result: + return ping_result + if communicator_type == INTERFACES.ETH_100BASE_T1: - if device_access.filter_device_type == 'INS402': - pin_tools = ping_ins402 + if filter_device_type in ['INS401', 'INS402', 'INS502']: + ping_tools = ping_ins else: - pin_tools = ping_ins401 - APP_CONTEXT.get_logger().logger.debug('Checking if is INS401 device...') - ping_result = pin_tools(device_access, None) - if ping_result: - return ping_result + filter_device_type = 'INS401' + ping_tools = ping_ins + + APP_CONTEXT.get_logger().logger.debug('Checking if is {0} device...'.format(filter_device_type)) + + if ping_tools: + ping_result = ping_tools(device_access, filter_device_type) + if ping_result: + return ping_result return None diff --git a/src/aceinna/devices/rtk350la/__init__.py b/src/aceinna/devices/rtk350la/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/aceinna/devices/rtk350la/uart_provider.py b/src/aceinna/devices/rtk350la/uart_provider.py new file mode 100644 index 0000000..b3c9ecb --- /dev/null +++ b/src/aceinna/devices/rtk350la/uart_provider.py @@ -0,0 +1,364 @@ +import time +import serial +import struct +from ..decorator import with_device_message +from ..base.rtk_provider_base import RTKProviderBase +from ..upgrade_workers import ( + FirmwareUpgradeWorker, + SDK9100UpgradeWorker, + UPGRADE_EVENT, + UPGRADE_GROUP +) +from ...framework.utils import ( + helper +) +from ...framework.utils.print import print_red +from ..parsers.rtk330l_field_parser import encode_value, get_value_len +from ...framework.context import APP_CONTEXT +from ...framework.utils.print import (print_green, print_yellow, print_red) +import threading +import os +from ..parsers.rtk350l_message_parser import UartMessageParser as Rtk350lUartMessageParser + +class Provider(RTKProviderBase): + ''' + RTK350LA UART provider + ''' + + def __init__(self, communicator, *args): + super(Provider, self).__init__(communicator) + self.type = 'RTK350LA' + self.bootloader_baudrate = 460800 + self.config_file_name = 'RTK350LA.json' + self.device_category = 'RTK350LA' + self.port_index_define = { + 'user': 0, + 'rtcm': -2, + 'debug': 1, + } + self.user_logf = None + #self.user2_logf = None + self.rtcm_rover_logf = None + self.rtcm_rover2_logf = None + + + @with_device_message + def get_params(self, *args): # pylint: disable=unused-argument + ''' + Get all parameters + ''' + has_error = False + parameter_values = [] + + if self.app_info['app_name'] == 'RTK_INS': + conf_parameters = self.properties['userConfiguration'] + conf_parameters_len = len(conf_parameters)-1 + step = 10 + + for i in range(2, conf_parameters_len, step): + start_byte = i + end_byte = i+step-1 if i+step < conf_parameters_len else conf_parameters_len + time.sleep(0.2) + + para_num = end_byte - start_byte + 1 + message_bytes = [] + message_bytes.append(para_num) + for i in range(start_byte, end_byte+1): + message_bytes.append(i) + command_line = helper.build_packet( + 'gB', message_bytes) + result = yield self._message_center.build(command=command_line, timeout=20) + if result['error']: + has_error = True + break + + parameter_values.extend(result['data']) + else: + command_line = helper.build_input_packet('gA') + result = yield self._message_center.build(command=command_line, timeout=5) + if result['error']: + has_error = True + + parameter_values = result['data'] + + if not has_error: + self.parameters = parameter_values + yield { + 'packetType': 'inputParams', + 'data': parameter_values + } + + yield { + 'packetType': 'error', + 'data': 'No Response' + } + + + @with_device_message + def set_params(self, params, *args): # pylint: disable=unused-argument + ''' + Update paramters value + ''' + input_parameters = self.properties['userConfiguration'] + grouped_parameters = {} + + for parameter in params: + exist_parameter = next( + (x for x in input_parameters if x['paramId'] == parameter['paramId']), None) + + if exist_parameter: + has_group = grouped_parameters.__contains__( + exist_parameter['category']) + if not has_group: + grouped_parameters[exist_parameter['category']] = [] + + current_group = grouped_parameters[exist_parameter['category']] + + current_group.append( + {'paramId': parameter['paramId'], 'value': parameter['value'], 'type': exist_parameter['type']}) + for group in grouped_parameters.values(): + message_bytes = [] + for parameter in group: + message_bytes.extend( + encode_value('int8', parameter['paramId']) + ) + + message_bytes.extend( + encode_value('uint8', get_value_len(parameter['type'])) + ) + + message_bytes.extend( + encode_value(parameter['type'], parameter['value']) + ) + # print('parameter type {0}, value {1}'.format( + # parameter['type'], parameter['value'])) + + command_line = helper.build_packet( + 'uB', message_bytes) + # hex_command = [hex(ele) for ele in command_line ] + # print(hex_command) + result = yield self._message_center.build(command=command_line) + + packet_type = result['packet_type'] + data = result['data'] + + if packet_type == 'error': + yield { + 'packetType': 'error', + 'data': { + 'error': data + } + } + break + + if data > 0: + yield { + 'packetType': 'error', + 'data': { + 'error': data + } + } + break + + yield { + 'packetType': 'success', + 'data': { + 'error': 0 + } + } + + def thread_debug_port_receiver(self, formatted_file_time, *args, **kwargs): + self.rtcm_rover2_logf = open( + os.path.join(self.rtk_log_file_name, 'rtcm_rover2_{0}.bin'.format( + formatted_file_time)), "wb") + # self.user2_logf = open( + # os.path.join(self.rtk_log_file_name, 'user_slave_{0}.bin'.format( + # formatted_file_time)), "wb") + + def on_continuous_message_received(packet_type, data, event_time, raw): + if packet_type == 'rR': + self.rtcm_rover2_logf.write(bytes(data)) + # else: + # if self.user2_logf and raw: + # self.user2_logf.write(bytes(raw)) + + + # build a parser + parser = Rtk350lUartMessageParser(self.properties) + parser.on('continuous_message', on_continuous_message_received) + + # log data + while True: + if self.is_upgrading: + time.sleep(0.1) + continue + try: + data = bytearray(self.debug_serial_port.read_all()) + parser.analyse(data) + + except Exception as e: + print_red('DEBUG PORT Thread error: {0}'.format(e)) + return # exit thread receiver + + time.sleep(0.001) + + def before_write_content(self, core, content_len): + self.communicator.serial_port.baudrate = self.bootloader_baudrate + self.communicator.serial_port.reset_input_buffer() + + message_bytes = [ord('C'), ord(core)] + message_bytes.extend(struct.pack('>I', content_len)) + command_line = helper.build_packet('CS', message_bytes) + for i in range(5): + self.communicator.write(command_line, True) + time.sleep(1) + result = helper.read_untils_have_data( + self.communicator, 'CS', 200, 100) + if result: + break + + if not result: + raise Exception('Cannot run set core command') + + def firmware_write_command_generator(self, data_len, current, data): + command_WA = 'WA' + message_bytes = [] + message_bytes.extend(struct.pack('>I', current)) + message_bytes.extend(struct.pack('B', data_len)) + message_bytes.extend(data) + return helper.build_packet(command_WA, message_bytes) + + # override + def build_worker(self, rule, content): + pass + + def after_setup(self): + local_time = time.localtime() + formatted_dir_time = time.strftime("%Y%m%d_%H%M%S", local_time) + formatted_file_time = time.strftime("%Y_%m_%d_%H_%M_%S", local_time) + debug_port = '' + rtcm_port = '' + set_user_para = self.cli_options and self.cli_options.set_user_para + + # save original baudrate + if hasattr(self.communicator, 'serial_port'): + self.original_baudrate = self.communicator.serial_port.baudrate + + if self.data_folder is None: + raise Exception( + 'Data folder does not exists, please check if the application has create folder permission') + + try: + self.rtk_log_file_name = os.path.join( + self.data_folder, '{0}_log_{1}'.format(self.device_category.lower(), formatted_dir_time)) + os.mkdir(self.rtk_log_file_name) + except: + raise Exception( + 'Cannot create log folder, please check if the application has create folder permission') + + # set parameters from predefined parameters + if set_user_para: + result = self.set_params( + self.properties["initial"]["userParameters"]) + if (result['packetType'] == 'success'): + self.save_config() + + # check saved result + self.check_predefined_result() + + # start ntrip client + if self.properties["initial"].__contains__("ntrip") \ + and not self.ntrip_client \ + and not self.is_in_bootloader \ + and not self.cli_options.use_cli: + + self.ntrip_rtcm_logf = open(os.path.join(self.rtk_log_file_name, 'rtcm_base_{0}.bin'.format( + formatted_file_time)), "wb") + + thead = threading.Thread(target=self.ntrip_client_thread) + thead.start() + + try: + if (self.properties["initial"]["useDefaultUart"]): + user_port_num, port_name = self.build_connected_serial_port_info() + if not user_port_num or not port_name: + return False + debug_port = port_name + \ + str(int(user_port_num) + self.port_index_define['debug']) + + else: + for x in self.properties["initial"]["uart"]: + if x['enable'] == 1: + if x['name'] == 'DEBUG': + debug_port = x["value"] + + self.user_logf = open(os.path.join( + self.rtk_log_file_name, 'user_{0}.bin'.format(formatted_file_time)), "wb") + + self.rtcm_rover_logf = open(os.path.join( + self.rtk_log_file_name, 'rtcm_rover1_{0}.bin'.format(formatted_file_time)), "wb") + + if debug_port != '': + print_green('{0} log DEBUG UART {1}'.format( + self.device_category, debug_port)) + self.debug_serial_port = serial.Serial( + debug_port, '460800', timeout=0.1) + if self.debug_serial_port.isOpen(): + thead = threading.Thread( + target=self.thread_debug_port_receiver, args=(formatted_file_time,)) + thead.start() + + self.save_device_info() + except Exception as ex: + if self.debug_serial_port is not None: + if self.debug_serial_port.isOpen(): + self.debug_serial_port.close() + self.debug_serial_port = None + APP_CONTEXT.get_logger().logger.error(ex) + print_red( + 'Can not log GNSS UART or DEBUG UART, pls check uart driver and connection!') + return False + + def on_read_raw(self, data): + for bytedata in data: + if bytedata == 0x24: + self.nmea_buffer = [] + self.nmea_sync = 0 + self.nmea_buffer.append(chr(bytedata)) + else: + self.nmea_buffer.append(chr(bytedata)) + if self.nmea_sync == 0: + if bytedata == 0x0D: + self.nmea_sync = 1 + elif self.nmea_sync == 1: + if bytedata == 0x0A: + try: + str_nmea = ''.join(self.nmea_buffer) + cksum, calc_cksum = self.nmea_checksum( + str_nmea) + if cksum == calc_cksum: + if str_nmea.find("$GPGGA") != -1 or str_nmea.find("$GNGGA") != -1: + if self.ntrip_client: + self.ntrip_client.send(str_nmea) + APP_CONTEXT.get_print_logger().info(str_nmea.replace('\r\n', '')) + + except Exception as e: + pass + self.nmea_buffer = [] + self.nmea_sync = 0 + + + def on_receive_output_packet(self, packet_type, data, *args, **kwargs): + ''' + Listener for getting output packet + ''' + if packet_type == 'rR': + if self.rtcm_rover_logf: + self.rtcm_rover_logf.write(bytes(data)) + else: + raw_data = kwargs.get('raw') + if self.user_logf and raw_data: + self.user_logf.write(bytes(raw_data)) + + # command list + # use base methods diff --git a/src/aceinna/devices/widgets/can/interface.py b/src/aceinna/devices/widgets/can/interface.py index 0363a59..df7a09c 100644 --- a/src/aceinna/devices/widgets/can/interface.py +++ b/src/aceinna/devices/widgets/can/interface.py @@ -106,7 +106,6 @@ def __new__(cls, channel=None, *args, **kwargs): else: context = None kwargs = load_config(config=kwargs, context=context) - # print('1111111111111111111111111111') # resolve the bus class to use for that interface cls = _get_class_for_interface(kwargs['interface']) diff --git a/src/aceinna/framework/communicators/ethernet_100base_t1.py b/src/aceinna/framework/communicators/ethernet_100base_t1.py index 02d00c0..0f25473 100644 --- a/src/aceinna/framework/communicators/ethernet_100base_t1.py +++ b/src/aceinna/framework/communicators/ethernet_100base_t1.py @@ -10,7 +10,7 @@ # Add parameter configuration type to be filtered to resolve timeout issue OTHER_FILTER_PACKETS = [b'\x02\xcc', b'\x03\xcc', b'\x04\xcc', b'\x05\xcc', b'\x06\xcc'] -UPGRADE_PACKETS = [b'\x01\xcc', b'\x01\xaa', b'\x02\xaa', b'\x03\xaa', b'\x04\xaa',b'\x05\xaa', +UPGRADE_PACKETS = [b'\x01\xcc', b'\x01\xaa', b'\x02\xaa', b'\x03\xaa', b'\x04\xaa',b'\x05\xaa', b'\x06\xaa', b'\x07\xaa', b'\x08\xaa', b'\x4a\x49', b'\x4a\x41', b'\x57\x41', b'\x0a\xaa'] class Ethernet(Communicator): @@ -42,7 +42,7 @@ def __init__(self, options=None): if options: self.filter_host_mac_assigned = options.host_mac != 'auto' self.filter_host_mac = options.host_mac if self.filter_host_mac_assigned else None - + if options: self.config_unit_sn = options.unit_sn != 'auto' self.config_unit_sn = options.unit_sn if self.config_unit_sn else None @@ -119,7 +119,7 @@ def find_device(self, callback, retries=0, not_found_handler=None): # confirm device for i in range(3): - self.confirm_device(self) + self.confirm_device(self, self.filter_device_type) if self.device: # establish the packet sniff thread callback(self.device) @@ -128,6 +128,7 @@ def find_device(self, callback, retries=0, not_found_handler=None): if i == 2: print_red( 'Cannot confirm the device in ethernet 100base-t1 connection') + os._exit(1) else: time.sleep(0.1) diff --git a/src/aceinna/framework/constants.py b/src/aceinna/framework/constants.py index d04589f..5889b9b 100644 --- a/src/aceinna/framework/constants.py +++ b/src/aceinna/framework/constants.py @@ -1,5 +1,5 @@ # Device -DEVICE_TYPES = ['RTK', 'beidou', 'INS402'] +DEVICE_TYPES = ['RTK', 'beidou', 'INS402', 'INS502'] BAUDRATE_LIST = [460800, 115200, 57600, 230400, 38400] DEFAULT_PORT_RANGE = [8000, 8001, 8002, 8003] diff --git a/src/aceinna/framework/decorator.py b/src/aceinna/framework/decorator.py index d4e2525..f986ed2 100644 --- a/src/aceinna/framework/decorator.py +++ b/src/aceinna/framework/decorator.py @@ -15,9 +15,14 @@ INTERFACE_LIST = INTERFACES.list() MODES = ['default', 'cli', 'receiver'] -TYPES_OF_LOG = ['rtkl', 'ins401', 'beidou', 'ins401c', 'ins402'] +TYPES_OF_LOG = ['rtkl', 'rtk350la', 'ins401', 'beidou', 'ins401c', 'ins402', 'ins502'] KML_RATES = [1, 2, 5, 10] +def _uppercase_string(s): + return s.upper() + +def _lowercase_string(s): + return s.lower() def _build_args(): """parse input arguments @@ -27,7 +32,7 @@ def _build_args(): parser.add_argument("-i", "--interface", dest="interface", metavar='', help="Interface. Allowed one of values: {0}".format(INTERFACE_LIST), default=INTERFACES.ETH_100BASE_T1, choices=INTERFACE_LIST) - parser.add_argument("--device-type", dest="device_type", type=str, + parser.add_argument("--device-type", dest="device_type", type=_uppercase_string, help="Open Device Type. Allowed one of values: {0}".format(DEVICE_TYPES), choices=DEVICE_TYPES, metavar='') parser.add_argument("-b", "--baudrate", dest="baudrate", type=int, metavar='', help="Baudrate for uart. Allowed one of values: {0}".format(BAUDRATE_LIST), choices=BAUDRATE_LIST) @@ -55,7 +60,7 @@ def _build_args(): title='Sub commands', help='use ` -h` to get sub command help', dest="sub_command") parse_log_action = subparsers.add_parser( 'parse', help='A parse log command') - parse_log_action.add_argument("-t", metavar='', type=str, + parse_log_action.add_argument("-t", metavar='', type=_lowercase_string, help="Type of logs, Allowed one of values: {0}".format( TYPES_OF_LOG), default='ins401', dest="log_type", choices=TYPES_OF_LOG) diff --git a/src/aceinna/framework/utils/firmware_parser.py b/src/aceinna/framework/utils/firmware_parser.py index 98e7a99..660f556 100644 --- a/src/aceinna/framework/utils/firmware_parser.py +++ b/src/aceinna/framework/utils/firmware_parser.py @@ -27,6 +27,8 @@ def parser(content, parser_rules): part_data_end_pos = part_data_len_pos + part_data_len parsed_content[rule.name] = content[part_data_len_pos: part_data_end_pos] current_pos = part_data_end_pos + if current_pos == len(content): + break else: parsed_content[rule.name] = b'' diff --git a/src/aceinna/libs/UserDecoderLib.dll b/src/aceinna/libs/UserDecoderLib.dll index 71f01b3..1a7eb27 100644 Binary files a/src/aceinna/libs/UserDecoderLib.dll and b/src/aceinna/libs/UserDecoderLib.dll differ diff --git a/src/aceinna/setting/INS402/RTK_INS/ins402.json b/src/aceinna/setting/INS402/RTK_INS/ins402.json index be00153..5a80f0e 100644 --- a/src/aceinna/setting/INS402/RTK_INS/ins402.json +++ b/src/aceinna/setting/INS402/RTK_INS/ins402.json @@ -113,6 +113,26 @@ "paramId": 24, "name": "dual ant heading cali", "value": 0 + }, + { + "paramId": 25, + "name": "heading boresight", + "value": 20 + }, + { + "paramId": 35, + "name": "USER_SLIPANG_F_PARAM_BX", + "value": 0 + }, + { + "paramId": 36, + "name": "USER_SLIPANG_F_PARAM_BY", + "value": 0 + }, + { + "paramId": 37, + "name": "USER_SLIPANG_F_PARAM_BZ", + "value": 0 } ], "ntrip":[ @@ -319,7 +339,39 @@ "type": "float", "name": "dual ant heading cali", "value_accuracy": 4 - } + }, + { + "paramId": 25, + "category": "GNSS", + "paramType": "input", + "type": "float", + "name": "heading boresight", + "value_accuracy": 4 + }, + { + "paramId": 35, + "category": "INS", + "paramType": "input", + "type": "float", + "name": "USER_SLIPANG_F_PARAM_BX", + "value_accuracy": 4 + }, + { + "paramId": 36, + "category": "INS", + "paramType": "input", + "type": "float", + "name": "USER_SLIPANG_F_PARAM_BY", + "value_accuracy": 4 + }, + { + "paramId": 37, + "category": "INS", + "paramType": "input", + "type": "float", + "name": "USER_SLIPANG_F_PARAM_BZ", + "value_accuracy": 4 + } ], "userMessages": { "inputPackets": [ @@ -736,30 +788,15 @@ "description": "Save the configuration into EEPROM", "function": "save_handler" }, - { - "name": "connect", - "description": "Find OpenIMU device", - "function": "connect_handler" - }, { "name": "upgrade", "description": "Upgrade firmware", "function": "upgrade_handler" }, { - "name": "record", - "description": "Record output data of OpenIMU on local machine", - "function": "record_handler" - }, - { - "name": "stop", - "description": "stop recording outputs on local machine", - "function": "stop_handler" - }, - { - "name": "server_start", - "description": "start server thread and must use exit command to quit", - "function": "server_start_handler" + "name": "configure", + "description": "Update the configuration on algorithm", + "function": "configure_handler" }, { "name": "get", @@ -768,7 +805,7 @@ }, { "name": "set", - "description": "Write parameters to OpenIMU", + "description": "Write parameters to INS402", "function": "set_handler" } ], diff --git a/src/aceinna/setting/INS402/RTK_INS/ins402c.json b/src/aceinna/setting/INS402/RTK_INS/ins402c.json index f11f01d..a8b2c92 100644 --- a/src/aceinna/setting/INS402/RTK_INS/ins402c.json +++ b/src/aceinna/setting/INS402/RTK_INS/ins402c.json @@ -1593,7 +1593,7 @@ "is_extended_frame": false, "is_fd": false, "name": "BASE_RTCM", - "valid_len": 62, + "valid_len": 63, "signals": [ { "bit_length": 512, diff --git a/src/aceinna/setting/INS502/RTK_INS/ins502.json b/src/aceinna/setting/INS502/RTK_INS/ins502.json new file mode 100644 index 0000000..6af00b3 --- /dev/null +++ b/src/aceinna/setting/INS502/RTK_INS/ins502.json @@ -0,0 +1,2296 @@ +{ + "appVersion": "INS502 34.00.01", + "type": "INS502", + "description": "6-axis INS502 with INS application", + "initial": { + "userParameters": [ + { + "paramId": 1, + "name": "USER_PRI_LEVER_ARM_BX", + "value": 0.7 + }, + { + "paramId": 2, + "name": "USER_PRI_LEVER_ARM_BY", + "value": 0.02 + }, + { + "paramId": 3, + "name": "USER_PRI_LEVER_ARM_BZ", + "value": -1.06 + }, + { + "paramId": 4, + "name": "USER_VRP_LEVER_ARM_BX", + "value": 0.38 + }, + { + "paramId": 5, + "name": "USER_VRP_LEVER_ARM_BY", + "value": 0.01 + }, + { + "paramId": 6, + "name": "USER_VRP_LEVER_ARM_BZ", + "value": 0.21 + }, + { + "paramId": 7, + "name": "USER_USER_LEVER_ARM_BX", + "value": 0.7 + }, + { + "paramId": 8, + "name": "USER_USER_LEVER_ARM_BY", + "value": 0.02 + }, + { + "paramId": 9, + "name": "USER_USER_LEVER_ARM_BZ", + "value": -1.06 + }, + { + "paramId": 10, + "name": "USER_ROTATION_RBVX", + "value": 0.0 + }, + { + "paramId": 11, + "name": "USER_ROTATION_RBVY", + "value": 0.0 + }, + { + "paramId": 12, + "name": "USER_ROTATION_RBVZ", + "value": 180.0 + }, + { + "paramId": 13, + "name": "USER_GNSS2_LEVER_ARM_BX", + "value": 1.75 + }, + { + "paramId": 14, + "name": "USER_GNSS2_LEVER_ARM_BY", + "value": 0.02 + }, + { + "paramId": 15, + "name": "USER_GNSS2_LEVER_ARM_BZ", + "value": -1.06 + }, + { + "paramId": 16, + "name": "USER_ROTATION_ALIGN_BX", + "value": 0 + }, + { + "paramId": 17, + "name": "USER_ROTATION_ALIGN_BY", + "value": 0.0 + }, + { + "paramId": 18, + "name": "USER_ROTATION_ALIGN_BZ", + "value": 0.0 + }, + { + "paramId": 19, + "name": "USER_NHC_ENABLE", + "value": 1 + }, + { + "paramId": 20, + "name": "USER_ODOMETER_ENABLE", + "value": 1 + }, + { + "paramId": 21, + "name": "USER_COMBINE_NHC_AND_ODO", + "value": 1 + }, + { + "paramId": 22, + "name": "USER_GNSS_HEADING_UPDATE_ENABLE", + "value": 3 + }, + { + "paramId": 23, + "name": "USER_DUAL_ANT_LENGTH", + "value": 0 + }, + { + "paramId": 24, + "name": "USER_HEADING_COMPENSATION", + "value": 0 + }, + { + "paramId": 25, + "name": "USER_HEADING_BORESIGHT", + "value": 0 + }, + { + "paramId": 26, + "name": "USER_RELATIVE_LENGTH_TOL", + "value": 0 + }, + { + "paramId": 27, + "name": "USER_COG_UPDATE_ENABLE", + "value": 0 + }, + { + "paramId": 28, + "name": "USER_HEADINGCOG_SPEED_TOL", + "value": 0 + }, + { + "paramId": 29, + "name": "USER_DO_ZUPT", + "value": 0 + }, + { + "paramId": 30, + "name": "USER_ZUPT_INTERVAL", + "value": 0 + }, + { + "paramId": 31, + "name": "USER_USE_ODOMETER_FOR_ZUPT", + "value": 0 + }, + { + "paramId": 32, + "name": "USER_ODO_SPEED_TOL", + "value": 0 + }, + { + "paramId": 33, + "name": "USER_CHECK_ZUPT_WITH_ODOMETRY", + "value": 0 + }, + { + "paramId": 34, + "name": "USER_MAX_ODO_ZUPT_SPEED", + "value": 0 + }, + { + "paramId": 35, + "name": "USER_SLIPANG_F_PARAM_0", + "value": 0 + }, + { + "paramId": 36, + "name": "USER_SLIPANG_F_PARAM_1", + "value": 0 + }, + { + "paramId": 37, + "name": "USER_SLIPANG_F_PARAM_2", + "value": 0 + }, + { + "paramId": 38, + "name": "USER_SLIPANG_F_NUM", + "value": 0 + }, + { + "paramId": 39, + "name": "USER_SLIPANG_MINSPEED", + "value": 0 + }, + { + "paramId": 40, + "name": "USER_SLIPANG_MINRATE", + "value": 0 + } + ], + "ntrip": [ + { + "name": "ip", + "value": "58.215.20.43" + }, + { + "name": "port", + "value": 2201 + }, + { + "name": "mountPoint", + "value": "WX02" + }, + { + "name": "username", + "value": "daich" + }, + { + "name": "password", + "value": "888999" + } + ] + }, + "userConfiguration": [ + { + "paramId": 0, + "category": "General", + "paramType": "disabled", + "type": "uint16", + "name": "Data CRC" + }, + { + "paramId": 1, + "category": "INS", + "paramType": "input", + "type": "float", + "name": "USER_PRI_LEVER_ARM_BX", + "value_accuracy": 4 + }, + { + "paramId": 2, + "category": "INS", + "paramType": "input", + "type": "float", + "name": "USER_PRI_LEVER_ARM_BY", + "value_accuracy": 4 + }, + { + "paramId": 3, + "category": "INS", + "paramType": "input", + "type": "float", + "name": "USER_PRI_LEVER_ARM_BZ", + "value_accuracy": 4 + }, + { + "paramId": 4, + "category": "INS", + "paramType": "input", + "type": "float", + "name": "USER_VRP_LEVER_ARM_BX", + "value_accuracy": 4 + }, + { + "paramId": 5, + "category": "INS", + "paramType": "input", + "type": "float", + "name": "USER_VRP_LEVER_ARM_BY", + "value_accuracy": 4 + }, + { + "paramId": 6, + "category": "INS", + "paramType": "input", + "type": "float", + "name": "USER_VRP_LEVER_ARM_BZ", + "value_accuracy": 4 + }, + { + "paramId": 7, + "category": "INS", + "paramType": "input", + "type": "float", + "name": "USER_USER_LEVER_ARM_BX", + "value_accuracy": 4 + }, + { + "paramId": 8, + "category": "INS", + "paramType": "input", + "type": "float", + "name": "USER_USER_LEVER_ARM_BY", + "value_accuracy": 4 + }, + { + "paramId": 9, + "category": "INS", + "paramType": "input", + "type": "float", + "name": "USER_USER_LEVER_ARM_BZ", + "value_accuracy": 4 + }, + { + "paramId": 10, + "category": "INS", + "paramType": "input", + "type": "float", + "name": "USER_ROTATION_RBVX", + "value_accuracy": 4 + }, + { + "paramId": 11, + "category": "INS", + "paramType": "input", + "type": "float", + "name": "USER_ROTATION_RBVY", + "value_accuracy": 4 + }, + { + "paramId": 12, + "category": "INS", + "paramType": "input", + "type": "float", + "name": "USER_ROTATION_RBVZ", + "value_accuracy": 4 + }, + { + "paramId": 13, + "category": "INS", + "paramType": "input", + "type": "float", + "name": "USER_GNSS2_LEVER_ARM_BX", + "value_accuracy": 4 + }, + { + "paramId": 14, + "category": "INS", + "paramType": "input", + "type": "float", + "name": "USER_GNSS2_LEVER_ARM_BY", + "value_accuracy": 4 + }, + { + "paramId": 15, + "category": "INS", + "paramType": "input", + "type": "float", + "name": "USER_GNSS2_LEVER_ARM_BZ", + "value_accuracy": 4 + }, + { + "paramId": 16, + "category": "INS", + "paramType": "input", + "type": "float", + "name": "USER_ROTATION_ALIGN_BX", + "value_accuracy": 4 + }, + { + "paramId": 17, + "category": "INS", + "paramType": "input", + "type": "float", + "name": "USER_ROTATION_ALIGN_BY", + "value_accuracy": 4 + }, + { + "paramId": 18, + "category": "INS", + "paramType": "input", + "type": "float", + "name": "USER_ROTATION_ALIGN_BZ", + "value_accuracy": 4 + }, + { + "paramId": 19, + "category": "INS", + "paramType": "input", + "type": "uint8", + "name": "USER_NHC_ENABLE" + }, + { + "paramId": 20, + "category": "INS", + "paramType": "input", + "type": "uint8", + "name": "USER_ODOMETER_ENABLE" + }, + { + "paramId": 21, + "category": "INS", + "paramType": "input", + "type": "uint8", + "name": "USER_COMBINE_NHC_AND_ODO" + }, + { + "paramId": 22, + "category": "GNSS", + "paramType": "input", + "type": "int16", + "name": "USER_GNSS_HEADING_UPDATE_ENABLE" + }, + { + "paramId": 23, + "category": "GNSS", + "paramType": "input", + "type": "float", + "name": "USER_DUAL_ANT_LENGTH", + "value_accuracy": 4 + }, + { + "paramId": 24, + "category": "GNSS", + "paramType": "input", + "type": "float", + "name": "USER_HEADING_COMPENSATION", + "value_accuracy": 4 + }, + { + "paramId": 25, + "category": "GNSS", + "paramType": "input", + "type": "float", + "name": "USER_HEADING_BORESIGHT", + "value_accuracy": 4 + }, + { + "paramId": 26, + "category": "GNSS", + "paramType": "input", + "type": "float", + "name": "USER_RELATIVE_LENGTH_TOL", + "value_accuracy": 4 + }, + { + "paramId": 27, + "category": "GNSS", + "paramType": "input", + "type": "int16", + "name": "USER_COG_UPDATE_ENABLE", + "value_accuracy": 4 + }, + { + "paramId": 28, + "category": "GNSS", + "paramType": "input", + "type": "float", + "name": "USER_HEADINGCOG_SPEED_TOL", + "value_accuracy": 4 + }, + { + "paramId": 29, + "category": "GNSS", + "paramType": "input", + "type": "uint8", + "name": "USER_DO_ZUPT", + "value_accuracy": 4 + }, + { + "paramId": 30, + "category": "GNSS", + "paramType": "input", + "type": "double", + "name": "USER_ZUPT_INTERVAL", + "value_accuracy": 4 + }, + { + "paramId": 31, + "category": "GNSS", + "paramType": "input", + "type": "uint8", + "name": "USER_USE_ODOMETER_FOR_ZUPT", + "value_accuracy": 4 + }, + { + "paramId": 32, + "category": "GNSS", + "paramType": "input", + "type": "float", + "name": "USER_ODO_SPEED_TOL", + "value_accuracy": 4 + }, + { + "paramId": 33, + "category": "GNSS", + "paramType": "input", + "type": "uint8", + "name": "USER_CHECK_ZUPT_WITH_ODOMETRY", + "value_accuracy": 4 + }, + { + "paramId": 34, + "category": "GNSS", + "paramType": "input", + "type": "float", + "name": "USER_MAX_ODO_ZUPT_SPEED", + "value_accuracy": 4 + }, + { + "paramId": 35, + "category": "GNSS", + "paramType": "input", + "type": "float", + "name": "USER_SLIPANG_F_PARAM_0", + "value_accuracy": 4 + }, + { + "paramId": 36, + "category": "GNSS", + "paramType": "input", + "type": "float", + "name": "USER_SLIPANG_F_PARAM_1", + "value_accuracy": 4 + }, + { + "paramId": 37, + "category": "GNSS", + "paramType": "input", + "type": "float", + "name": "USER_SLIPANG_F_PARAM_2", + "value_accuracy": 4 + }, + { + "paramId": 38, + "category": "INS", + "paramType": "input", + "type": "int32", + "name": "USER_SLIPANG_F_NUM", + "value_accuracy": 4 + }, + { + "paramId": 39, + "category": "INS", + "paramType": "input", + "type": "float", + "name": "USER_SLIPANG_MINSPEED", + "value_accuracy": 4 + }, + { + "paramId": 40, + "category": "INS", + "paramType": "input", + "type": "float", + "name": "USER_SLIPANG_MINRATE", + "value_accuracy": 4 + } + ], + "userMessages": { + "inputPackets": [ + { + "name": "pG", + "description": "Get device serial number & factory ID", + "inputPayload": {}, + "responsePayload": { + "type": "string", + "name": "Device ID and SN" + } + }, + { + "name": "gV", + "description": "Get user app version", + "inputPayload": {}, + "responsePayload": { + "type": "string", + "name": "User Version" + } + }, + { + "name": "gA", + "description": "Get All Configuration Parameters", + "inputPayload": {}, + "responsePayload": { + "type": "userConfiguration", + "name": "Full Current Configuration" + } + }, + { + "name": "sC", + "description": "Save Conifguration Parameters to Flash", + "inputPayload": {}, + "responsePayload": {} + }, + { + "name": "uP", + "description": "Update Configuration Parameter", + "inputPayload": { + "type": "userParameter", + "name": "Parameter to be Updated" + }, + "responsePayload": { + "type": "paramId", + "name": "ID of the Updated Parameter" + } + } + ], + "outputPackets": [ + { + "name": "s1", + "isList": 0, + "payload": [ + { + "type": "uint32", + "name": "GPS_Week", + "unit": "" + }, + { + "type": "double", + "name": "GPS_TimeofWeek", + "unit": "sec" + }, + { + "type": "float", + "name": "x_accel", + "unit": "m/s^2" + }, + { + "type": "float", + "name": "y_accel", + "unit": "m/s^2" + }, + { + "type": "float", + "name": "z_accel", + "unit": "m/s^2" + }, + { + "type": "float", + "name": "x_rate", + "unit": "deg/s" + }, + { + "type": "float", + "name": "y_rate", + "unit": "deg/s" + }, + { + "type": "float", + "name": "z_rate", + "unit": "deg/s" + } + ], + "graphs": [ + { + "name": "Acceleration", + "units": "m/s^2", + "xAxis": { + "name": "GPS_TimeofWeek", + "unit": "sec" + }, + "yAxes": [ + "x_accel", + "y_accel", + "z_accel" + ], + "colors": [ + "#FF0000", + "#00FF00", + "#0000FF" + ], + "yMax": 20 + }, + { + "name": "Angular-Rate", + "units": "deg/s", + "xAxis": { + "name": "GPS_TimeofWeek", + "unit": "sec" + }, + "yAxes": [ + "x_rate", + "y_rate", + "z_rate" + ], + "colors": [ + "#FF0000", + "#00FF00", + "#0000FF" + ], + "yMax": 200 + } + ] + }, + { + "name": "iN", + "isList": 0, + "payload": [ + { + "type": "uint32", + "name": "GPS_Week", + "unit": "" + }, + { + "type": "double", + "name": "GPS_TimeofWeek", + "unit": "sec" + }, + { + "type": "uint8", + "name": "insStatus", + "unit": "" + }, + { + "type": "uint8", + "name": "insPositionType", + "unit": "" + }, + { + "type": "int32", + "name": "latitude", + "unit": "deg" + }, + { + "type": "int32", + "name": "longitude", + "unit": "deg" + }, + { + "type": "float", + "name": "height", + "unit": "m" + }, + { + "type": "int16", + "name": "velocityNorth", + "unit": "m/s" + }, + { + "type": "int16", + "name": "velocityEast", + "unit": "m/s" + }, + { + "type": "int16", + "name": "velocityUp", + "unit": "m/s" + }, + { + "type": "int16", + "name": "roll", + "unit": "m/s" + }, + { + "type": "int16", + "name": "pitch", + "unit": "m/s" + }, + { + "type": "int16", + "name": "heading", + "unit": "m/s" + } + ], + "graphs": [] + }, + { + "name": "d1", + "isList": 0, + "payload": [ + { + "type": "uint32", + "name": "GPS_Week", + "unit": "" + }, + { + "type": "double", + "name": "GPS_TimeofWeek", + "unit": "sec" + }, + { + "type": "int16", + "name": "latitude_std", + "unit": "" + }, + { + "type": "int16", + "name": "longitude_std", + "unit": "" + }, + { + "type": "int16", + "name": "height_std", + "unit": "" + }, + { + "type": "int16", + "name": "north_vel_std", + "unit": "" + }, + { + "type": "int16", + "name": "east_vel_std", + "unit": "" + }, + { + "type": "int16", + "name": "up_vel_std", + "unit": "" + }, + { + "type": "int16", + "name": "roll_std", + "unit": "" + }, + { + "type": "int16", + "name": "pitch_std", + "unit": "" + }, + { + "type": "int16", + "name": "heading_std", + "unit": "" + } + ], + "graphs": [] + }, + { + "name": "gN", + "isList": 0, + "payload": [ + { + "type": "uint32", + "name": "GPS_Week", + "unit": "" + }, + { + "type": "double", + "name": "GPS_TimeofWeek", + "unit": "sec" + }, + { + "type": "uint8", + "name": "positionMode", + "unit": "" + }, + { + "type": "int32", + "name": "latitude", + "unit": "deg" + }, + { + "type": "int32", + "name": "longitude", + "unit": "deg" + }, + { + "type": "float", + "name": "height", + "unit": "m" + }, + { + "type": "uint8", + "name": "numberOfSVs", + "unit": "" + }, + { + "type": "float", + "name": "hdop", + "unit": "" + }, + { + "type": "uint16", + "name": "diffage", + "unit": "" + }, + { + "type": "int16", + "name": "velocityNorth", + "unit": "m/s" + }, + { + "type": "int16", + "name": "velocityEast", + "unit": "m/s" + }, + { + "type": "int16", + "name": "velocityUp", + "unit": "m/s" + } + ], + "graphs": [] + }, + { + "name": "sT", + "isList": 0, + "payload": [ + { + "type": "uint32", + "name": "GPS_Week", + "unit": "" + }, + { + "type": "double", + "name": "GPS_TimeofWeek", + "unit": "sec" + }, + { + "type": "uint16", + "name": "year", + "unit": "" + }, + { + "type": "uint8", + "name": "mouth", + "unit": "" + }, + { + "type": "uint8", + "name": "day", + "unit": "" + }, + { + "type": "uint8", + "name": "hour", + "unit": "" + }, + { + "type": "uint8", + "name": "min", + "unit": "" + }, + { + "type": "uint8", + "name": "sec", + "unit": "" + }, + { + "type": "uint32", + "name": "imu_status", + "unit": "" + }, + { + "type": "float", + "name": "imu_temperature", + "unit": "sec" + }, + { + "type": "float", + "name": "mcu_temperature", + "unit": "" + } + ], + "graphs": [] + } + ] + }, + "CLICommands": [ + { + "name": "help", + "description": "CLI help menu", + "function": "help_handler" + }, + { + "name": "exit", + "description": "exit CLI", + "function": "" + }, + { + "name": "run", + "description": "Operations defined by users", + "function": "run_handler" + }, + { + "name": "save", + "description": "Save the configuration into EEPROM", + "function": "save_handler" + }, + { + "name": "upgrade", + "description": "Upgrade firmware", + "function": "upgrade_handler" + }, + { + "name": "configure", + "description": "Update the configuration on algorithm", + "function": "configure_handler" + }, + { + "name": "get", + "description": "Read the current configuration and output data", + "function": "get_handler" + }, + { + "name": "set", + "description": "Write parameters to INS502", + "function": "set_handler" + } + ], + "canfd_settings": { + "canfd_type": "canfd", + "is_parse": true, + "canfd_id": [ + 384, + 640, + 641, + 1412 + ], + "canfd_remote_id": [ + 1408, + 1409, + 1410, + 1411 + ], + "can_id": [ + 384, + 385, + 386, + 387, + 388, + 389, + 390, + 391, + 392, + 640 + ], + "can_config": { + "bus_type": "bmcan", + "channel": 0, + "bitrate": 500000, + "data_bitrate": 2000000 + }, + "imu_log_config": { + "title": "GPS_Week(),GPS_TimeofWeek(s),x_accel(m/s^2),y_accel(m/s^2),z_accel(m/s^2),x_rate(deg/s),y_rate(deg/s),z_rate(deg/s)\n", + "index": 0 + }, + "ins_log_config": { + "title": "GPS_Week(),GPS_TimeofWeek(s),insCarStatus(),insPositionType(),latitude(deg),longitude(deg),height(m),velocityNorth(m/s),velocityEast(m/s),velocityUp(m/s),roll(deg),pitch(deg),heading(deg),latitude_std(m),longitude_std(m),height_std(m)\n", + "index": 0 + }, + "can_messages": [ + { + "id": 384, + "is_extended_frame": false, + "is_fd": false, + "name": "INS_ACC", + "valid_len": 6, + "signals": [ + { + "bit_length": 16, + "factor": "0.0001220703125", + "is_big_endian": true, + "is_float": true, + "is_signed": false, + "name": "ACC_X", + "offset": "-4", + "start_bit": 8, + "type": "uint16", + "format": "11.4f", + "unit": "s" + }, + { + "bit_length": 16, + "factor": "0.0001220703125", + "is_big_endian": true, + "is_float": true, + "is_signed": false, + "name": "ACC_Y", + "offset": "-4", + "start_bit": 24, + "type": "uint16", + "format": "11.4f", + "unit": "s" + }, + { + "bit_length": 16, + "factor": "0.0001220703125", + "is_big_endian": true, + "is_float": true, + "is_signed": false, + "name": "ACC_Z", + "offset": "-4", + "start_bit": 40, + "type": "uint16", + "format": "11.4f", + "unit": "s" + } + ] + }, + { + "id": 385, + "is_extended_frame": false, + "is_fd": false, + "name": "INS_GYRO", + "valid_len": 6, + "signals": [ + { + "bit_length": 16, + "factor": "0.0076293", + "is_big_endian": true, + "is_float": true, + "is_signed": false, + "name": "GYRO_X", + "offset": "-250", + "start_bit": 8, + "type": "uint16", + "format": "11.4f", + "unit": "s" + }, + { + "bit_length": 16, + "factor": "0.0076293", + "is_big_endian": true, + "is_float": true, + "is_signed": false, + "name": "GYRO_Y", + "offset": "-250", + "start_bit": 24, + "type": "uint16", + "format": "11.4f", + "unit": "s" + }, + { + "bit_length": 16, + "factor": "0.0076293", + "is_big_endian": true, + "is_float": true, + "is_signed": false, + "name": "GYRO_Z", + "offset": "-250", + "start_bit": 40, + "type": "uint16", + "format": "11.4f", + "unit": "s" + } + ] + }, + { + "id": 386, + "is_extended_frame": false, + "is_fd": false, + "name": "INS_HeadingPitchRoll", + "valid_len": 6, + "signals": [ + { + "bit_length": 16, + "factor": "0.010986", + "is_big_endian": true, + "is_float": true, + "is_signed": false, + "name": "INS_PitchAngle", + "offset": "-250", + "start_bit": 8, + "type": "uint16", + "format": "11.4f", + "unit": "s" + }, + { + "bit_length": 16, + "factor": "0.010986", + "is_big_endian": true, + "is_float": true, + "is_signed": false, + "name": "INS_RollAngle", + "offset": "-250", + "start_bit": 24, + "type": "uint16", + "format": "11.4f", + "unit": "s" + }, + { + "bit_length": 16, + "factor": "0.010986", + "is_big_endian": true, + "is_float": true, + "is_signed": false, + "name": "INS_HeadingAngle", + "offset": "-250", + "start_bit": 40, + "type": "uint16", + "format": "11.4f", + "unit": "s" + } + ] + }, + { + "id": 387, + "is_extended_frame": false, + "is_fd": false, + "name": "INS_HeightAndIMUStatus", + "valid_len": 8, + "signals": [ + { + "bit_length": 32, + "factor": "0.001", + "is_big_endian": true, + "is_float": true, + "is_signed": false, + "name": "INS_LocatHeight", + "offset": "-10000", + "start_bit": 24, + "type": "uint32", + "format": "11.4f", + "unit": "s" + }, + { + "bit_length": 32, + "factor": "1", + "is_big_endian": true, + "is_float": false, + "is_signed": false, + "name": "IMU_Status", + "offset": "0", + "start_bit": 56, + "type": "uint32", + "format": "", + "unit": "s" + } + ] + }, + { + "id": 388, + "is_extended_frame": false, + "is_fd": false, + "name": "INS_LatitudeLongitude", + "valid_len": 8, + "signals": [ + { + "bit_length": 32, + "factor": "0.0000001", + "is_big_endian": true, + "is_float": true, + "is_signed": false, + "name": "INS_Latitude", + "offset": "-180", + "start_bit": 24, + "type": "uint32", + "format": "11.7f", + "unit": "s" + }, + { + "bit_length": 32, + "factor": "0.0000001", + "is_big_endian": true, + "is_float": true, + "is_signed": false, + "name": "INS_Longitude", + "offset": "-180", + "start_bit": 56, + "type": "uint32", + "format": "11.7f", + "unit": "s" + } + ] + }, + { + "id": 389, + "is_extended_frame": false, + "is_fd": false, + "name": "INS_Speed", + "valid_len": 6, + "signals": [ + { + "bit_length": 16, + "factor": "0.0030517", + "is_big_endian": true, + "is_float": true, + "is_signed": false, + "name": "INS_NorthSpd", + "offset": "-100", + "start_bit": 8, + "type": "uint16", + "format": "11.4f", + "unit": "s" + }, + { + "bit_length": 16, + "factor": "0.0030517", + "is_big_endian": true, + "is_float": true, + "is_signed": false, + "name": "INS_EastSpd", + "offset": "-100", + "start_bit": 24, + "type": "uint16", + "format": "11.4f", + "unit": "s" + }, + { + "bit_length": 16, + "factor": "0.0030517", + "is_big_endian": true, + "is_float": true, + "is_signed": false, + "name": "INS_ToGroundSpd", + "offset": "-100", + "start_bit": 40, + "type": "uint16", + "format": "11.4f", + "unit": "s" + } + ] + }, + { + "id": 390, + "is_extended_frame": false, + "is_fd": false, + "name": "INS_DataInfo", + "valid_len": 6, + "signals": [ + { + "bit_length": 8, + "factor": "1", + "is_big_endian": true, + "is_float": false, + "is_signed": false, + "name": "INS_GpsFlag_Pos", + "offset": "0", + "start_bit": 0, + "type": "uint8", + "format": "2", + "unit": "s" + }, + { + "bit_length": 8, + "factor": "1", + "is_big_endian": true, + "is_float": false, + "is_signed": false, + "name": "INS_NumSV", + "offset": "0", + "start_bit": 8, + "type": "uint8", + "format": "11.4f", + "unit": "s" + }, + { + "bit_length": 8, + "factor": "1", + "is_big_endian": true, + "is_float": false, + "is_signed": false, + "name": "INS_GpsFlag_Heading", + "offset": "0", + "start_bit": 16, + "type": "uint8", + "format": "2", + "unit": "s" + }, + { + "bit_length": 8, + "factor": "1", + "is_big_endian": true, + "is_float": false, + "is_signed": false, + "name": "INS_Gps_Age", + "offset": "0", + "start_bit": 24, + "type": "uint8", + "format": "3f", + "unit": "s" + }, + { + "bit_length": 8, + "factor": "1", + "is_big_endian": true, + "is_float": false, + "is_signed": false, + "name": "INS_Car_Status", + "offset": "0", + "start_bit": 32, + "type": "uint8", + "format": "2", + "unit": "s" + }, + { + "bit_length": 8, + "factor": "1", + "is_big_endian": true, + "is_float": false, + "is_signed": false, + "name": "INS_Status", + "offset": "0", + "start_bit": 40, + "type": "uint8", + "format": "2", + "unit": "s" + } + ] + }, + { + "id": 391, + "is_extended_frame": false, + "is_fd": false, + "name": "INS_Std", + "valid_len": 8, + "signals": [ + { + "bit_length": 16, + "factor": "0.001", + "is_big_endian": true, + "is_float": true, + "is_signed": false, + "name": "INS_Std_Lat", + "offset": "0", + "start_bit": 8, + "type": "uint16", + "format": "11.4f", + "unit": "s" + }, + { + "bit_length": 16, + "factor": "0.001", + "is_big_endian": true, + "is_float": true, + "is_signed": false, + "name": "INS_Std_Lon", + "offset": "0", + "start_bit": 24, + "type": "uint16", + "format": "11.4f", + "unit": "s" + }, + { + "bit_length": 16, + "factor": "0.001", + "is_big_endian": true, + "is_float": true, + "is_signed": false, + "name": "INS_Std_LocatHeight", + "offset": "0", + "start_bit": 40, + "type": "uint16", + "format": "11.4f", + "unit": "s" + }, + { + "bit_length": 16, + "factor": "0.001", + "is_big_endian": true, + "is_float": true, + "is_signed": false, + "name": "INS_Std_Heading", + "offset": "0", + "start_bit": 56, + "type": "uint16", + "format": "11.4f", + "unit": "s" + } + ] + }, + { + "id": 392, + "is_extended_frame": false, + "is_fd": false, + "name": "INS_Time", + "valid_len": 6, + "signals": [ + { + "bit_length": 16, + "factor": "1", + "is_big_endian": true, + "is_float": true, + "is_signed": false, + "name": "Week", + "offset": "0", + "start_bit": 8, + "type": "uint16", + "format": "", + "unit": "s" + }, + { + "bit_length": 32, + "factor": "1", + "is_big_endian": true, + "is_float": true, + "is_signed": false, + "name": "TimeOfWeek", + "offset": "0", + "start_bit": 24, + "type": "uint32", + "format": "11.4f", + "unit": "s" + } + ] + }, + { + "id": 640, + "is_extended_frame": false, + "is_fd": false, + "name": "BASE_RTCM", + "valid_len": 6, + "signals": [ + { + "bit_length": 8, + "factor": "0", + "is_big_endian": true, + "is_float": false, + "is_signed": false, + "name": "BASE", + "offset": "0", + "start_bit": 0, + "type": "", + "format": "", + "unit": "s" + } + ] + } + ], + "canfd_messages": [ + { + "id": 384, + "is_extended_frame": false, + "is_fd": true, + "name": "INSPVAX", + "valid_len": 60, + "signals": [ + { + "bit_length": 16, + "factor": "0.0001220703125", + "is_big_endian": true, + "is_float": true, + "is_signed": false, + "name": "ACC_X", + "offset": "-4", + "start_bit": 8, + "type": "uint16", + "format": "11.4f", + "unit": "s" + }, + { + "bit_length": 16, + "factor": "0.0001220703125", + "is_big_endian": true, + "is_float": true, + "is_signed": false, + "name": "ACC_Y", + "offset": "-4", + "start_bit": 24, + "type": "uint16", + "format": "11.4f", + "unit": "s" + }, + { + "bit_length": 16, + "factor": "0.0001220703125", + "is_big_endian": true, + "is_float": true, + "is_signed": false, + "name": "ACC_Z", + "offset": "-4", + "start_bit": 40, + "type": "uint16", + "format": "11.4f", + "unit": "s" + }, + { + "bit_length": 16, + "factor": "0.0076293", + "is_big_endian": true, + "is_float": true, + "is_signed": false, + "name": "GYRO_X", + "offset": "-250", + "start_bit": 56, + "type": "uint16", + "format": "11.4f", + "unit": "s" + }, + { + "bit_length": 16, + "factor": "0.0076293", + "is_big_endian": true, + "is_float": true, + "is_signed": false, + "name": "GYRO_Y", + "offset": "-250", + "start_bit": 72, + "type": "uint16", + "format": "11.4f", + "unit": "s" + }, + { + "bit_length": 16, + "factor": "0.0076293", + "is_big_endian": true, + "is_float": true, + "is_signed": false, + "name": "GYRO_Z", + "offset": "-250", + "start_bit": 88, + "type": "uint16", + "format": "11.4f", + "unit": "s" + }, + { + "bit_length": 16, + "factor": "0.010986", + "is_big_endian": true, + "is_float": true, + "is_signed": false, + "name": "INS_PitchAngle", + "offset": "-250", + "start_bit": 104, + "type": "uint16", + "format": "11.4f", + "unit": "s" + }, + { + "bit_length": 16, + "factor": "0.010986", + "is_big_endian": true, + "is_float": true, + "is_signed": false, + "name": "INS_RollAngle", + "offset": "-250", + "start_bit": 120, + "type": "uint16", + "format": "11.4f", + "unit": "s" + }, + { + "bit_length": 16, + "factor": "0.010986", + "is_big_endian": true, + "is_float": true, + "is_signed": false, + "name": "INS_HeadingAngle", + "offset": "-250", + "start_bit": 136, + "type": "uint16", + "format": "11.4f", + "unit": "s" + }, + { + "bit_length": 32, + "factor": "0.001", + "is_big_endian": true, + "is_float": true, + "is_signed": false, + "name": "INS_LocatHeight", + "offset": "-10000", + "start_bit": 168, + "type": "uint32", + "format": "11.4f", + "unit": "s" + }, + { + "bit_length": 32, + "factor": "1", + "is_big_endian": true, + "is_float": false, + "is_signed": false, + "name": "IMU_Status", + "offset": "0", + "start_bit": 200, + "type": "uint32", + "format": "11.4f", + "unit": "s" + }, + { + "bit_length": 32, + "factor": "0.0000001", + "is_big_endian": true, + "is_float": true, + "is_signed": false, + "name": "INS_Latitude", + "offset": "-180", + "start_bit": 232, + "type": "uint32", + "format": "11.7f", + "unit": "s" + }, + { + "bit_length": 32, + "factor": "0.0000001", + "is_big_endian": true, + "is_float": true, + "is_signed": false, + "name": "INS_Longitude", + "offset": "-180", + "start_bit": 264, + "type": "uint32", + "format": "11.7f", + "unit": "s" + }, + { + "bit_length": 16, + "factor": "0.0030517", + "is_big_endian": true, + "is_float": true, + "is_signed": false, + "name": "INS_NorthSpd", + "offset": "-100", + "start_bit": 280, + "type": "uint16", + "format": "11.4f", + "unit": "s" + }, + { + "bit_length": 16, + "factor": "0.0030517", + "is_big_endian": true, + "is_float": true, + "is_signed": false, + "name": "INS_EastSpd", + "offset": "-100", + "start_bit": 296, + "type": "uint16", + "format": "11.4f", + "unit": "s" + }, + { + "bit_length": 16, + "factor": "0.0030517", + "is_big_endian": true, + "is_float": true, + "is_signed": false, + "name": "INS_ToGroundSpd", + "offset": "-100", + "start_bit": 312, + "type": "uint16", + "format": "11.4f", + "unit": "s" + }, + { + "bit_length": 8, + "factor": "1", + "is_big_endian": true, + "is_float": false, + "is_signed": false, + "name": "INS_GpsFlag_Pos", + "offset": "0", + "start_bit": 320, + "type": "uint8", + "format": "2", + "unit": "s" + }, + { + "bit_length": 8, + "factor": "1", + "is_big_endian": true, + "is_float": false, + "is_signed": false, + "name": "INS_NumSV", + "offset": "0", + "start_bit": 328, + "type": "uint8", + "format": "11.4f", + "unit": "s" + }, + { + "bit_length": 8, + "factor": "1", + "is_big_endian": true, + "is_float": false, + "is_signed": false, + "name": "INS_GpsFlag_Heading", + "offset": "0", + "start_bit": 336, + "type": "uint8", + "format": "2", + "unit": "s" + }, + { + "bit_length": 8, + "factor": "1", + "is_big_endian": true, + "is_float": false, + "is_signed": false, + "name": "INS_Gps_Age", + "offset": "0", + "start_bit": 344, + "type": "uint8", + "format": "3f", + "unit": "s" + }, + { + "bit_length": 8, + "factor": "1", + "is_big_endian": true, + "is_float": false, + "is_signed": false, + "name": "INS_Car_Status", + "offset": "0", + "start_bit": 352, + "type": "uint8", + "format": "2", + "unit": "s" + }, + { + "bit_length": 8, + "factor": "1", + "is_big_endian": true, + "is_float": false, + "is_signed": false, + "name": "INS_Status", + "offset": "0", + "start_bit": 360, + "type": "uint8", + "format": "2", + "unit": "s" + }, + { + "bit_length": 16, + "factor": "0.001", + "is_big_endian": true, + "is_float": true, + "is_signed": false, + "name": "INS_Std_Lat", + "offset": "0", + "start_bit": 376, + "type": "uint16", + "format": "11.4f", + "unit": "s" + }, + { + "bit_length": 16, + "factor": "0.001", + "is_big_endian": true, + "is_float": true, + "is_signed": false, + "name": "INS_Std_Lon", + "offset": "0", + "start_bit": 392, + "type": "uint16", + "format": "11.4f", + "unit": "s" + }, + { + "bit_length": 16, + "factor": "0.001", + "is_big_endian": true, + "is_float": true, + "is_signed": false, + "name": "INS_Std_LocatHeight", + "offset": "0", + "start_bit": 408, + "type": "uint16", + "format": "11.4f", + "unit": "s" + }, + { + "bit_length": 16, + "factor": "0.001", + "is_big_endian": true, + "is_float": true, + "is_signed": false, + "name": "INS_Std_Heading", + "offset": "0", + "start_bit": 424, + "type": "uint16", + "format": "11.4f", + "unit": "s" + }, + { + "bit_length": 16, + "factor": "1", + "is_big_endian": true, + "is_float": false, + "is_signed": false, + "name": "Week", + "offset": "0", + "start_bit": 440, + "type": "uint16", + "format": "", + "unit": "s" + }, + { + "bit_length": 32, + "factor": "1", + "is_big_endian": true, + "is_float": false, + "is_signed": false, + "name": "TimeOfWeek", + "offset": "0", + "start_bit": 456, + "type": "uint32", + "format": "11.4f", + "unit": "s" + } + ] + }, + { + "id": 640, + "is_extended_frame": false, + "is_fd": false, + "name": "BASE_RTCM", + "valid_len": 62, + "signals": [ + { + "bit_length": 512, + "factor": "0", + "is_big_endian": true, + "is_float": false, + "is_signed": false, + "name": "BASE", + "offset": "0", + "start_bit": 0, + "type": "", + "format": "", + "unit": "s" + } + ] + }, + { + "id": 641, + "is_extended_frame": false, + "is_fd": false, + "name": "ROVER_RTCM", + "valid_len": 63, + "signals": [ + { + "bit_length": 512, + "factor": "0", + "is_big_endian": true, + "is_float": false, + "is_signed": false, + "name": "BASE", + "offset": "0", + "start_bit": 0, + "type": "", + "format": "", + "unit": "s" + } + ] + }, + { + "id": 1412, + "is_extended_frame": false, + "is_fd": true, + "name": "LEVER_ARM_SET", + "valid_len": 48, + "signals": [ + { + "bit_length": 32, + "factor": "1", + "is_big_endian": true, + "is_float": true, + "is_signed": false, + "name": "GNSS_LEVER_ARM_X", + "offset": "0", + "start_bit": 24, + "type": "float", + "format": "", + "unit": "s" + }, + { + "bit_length": 32, + "factor": "1", + "is_big_endian": true, + "is_float": true, + "is_signed": false, + "name": "GNSS_LEVER_ARM_Y", + "offset": "0", + "start_bit": 56, + "type": "float", + "format": "", + "unit": "s" + }, + { + "bit_length": 32, + "factor": "1", + "is_big_endian": true, + "is_float": true, + "is_signed": false, + "name": "GNSS_LEVER_ARM_Z", + "offset": "0", + "start_bit": 88, + "type": "float", + "format": "", + "unit": "s" + }, + { + "bit_length": 32, + "factor": "1", + "is_big_endian": true, + "is_float": true, + "is_signed": false, + "name": "VRP_LEVER_ARM_X", + "offset": "0", + "start_bit": 120, + "type": "float", + "format": "", + "unit": "s" + }, + { + "bit_length": 32, + "factor": "1", + "is_big_endian": true, + "is_float": true, + "is_signed": false, + "name": "VRP_LEVER_ARM_Y", + "offset": "0", + "start_bit": 152, + "type": "float", + "format": "", + "unit": "s" + }, + { + "bit_length": 32, + "factor": "1", + "is_big_endian": true, + "is_float": true, + "is_signed": false, + "name": "VRP_LEVER_ARM_Z", + "offset": "0", + "start_bit": 184, + "type": "float", + "format": "", + "unit": "s" + }, + { + "bit_length": 32, + "factor": "1", + "is_big_endian": true, + "is_float": true, + "is_signed": false, + "name": "USER_LEVER_ARM_X", + "offset": "0", + "start_bit": 216, + "type": "float", + "format": "", + "unit": "s" + }, + { + "bit_length": 32, + "factor": "1", + "is_big_endian": true, + "is_float": true, + "is_signed": false, + "name": "USER_LEVER_ARM_Y", + "offset": "0", + "start_bit": 248, + "type": "float", + "format": "", + "unit": "s" + }, + { + "bit_length": 32, + "factor": "1", + "is_big_endian": true, + "is_float": true, + "is_signed": false, + "name": "USER_LEVER_ARM_Z", + "offset": "0", + "start_bit": 280, + "type": "float", + "format": "", + "unit": "s" + }, + { + "bit_length": 32, + "factor": "1", + "is_big_endian": true, + "is_float": true, + "is_signed": false, + "name": "ROTATION_RBVX", + "offset": "0", + "start_bit": 312, + "type": "float", + "format": "", + "unit": "s" + }, + { + "bit_length": 32, + "factor": "1", + "is_big_endian": true, + "is_float": true, + "is_signed": false, + "name": "ROTATION_RBVY", + "offset": "0", + "start_bit": 332, + "type": "float", + "format": "", + "unit": "s" + }, + { + "bit_length": 32, + "factor": "1", + "is_big_endian": true, + "is_float": true, + "is_signed": false, + "name": "ROTATION_RBVZ", + "offset": "0", + "start_bit": 364, + "type": "float", + "format": "", + "unit": "s" + } + ] + } + ], + "canfd_remote_messages": [ + { + "id": 1408, + "is_extended_frame": false, + "is_fd": true, + "name": "INS_VERSION", + "valid_len": 0, + "signals": [ + { + "name": "INS_VERSION" + } + ] + }, + { + "id": 1409, + "is_extended_frame": false, + "is_fd": true, + "name": "SDK_VERSION", + "valid_len": 0, + "signals": [ + { + "name": "SDK_VERSION" + } + ] + }, + { + "id": 1410, + "is_extended_frame": false, + "is_fd": true, + "name": "IMU_VERSION", + "valid_len": 0, + "signals": [ + { + "name": "IMU_VERSION" + } + ] + }, + { + "id": 1411, + "is_extended_frame": false, + "is_fd": true, + "name": "LEVER_ARM_GET", + "valid_len": 48, + "signals": [ + { + "bit_length": 32, + "factor": "1", + "is_big_endian": true, + "is_float": true, + "is_signed": false, + "name": "GNSS_LEVER_ARM_X", + "offset": "0", + "start_bit": 24, + "type": "float", + "format": "", + "unit": "s" + }, + { + "bit_length": 32, + "factor": "1", + "is_big_endian": true, + "is_float": true, + "is_signed": false, + "name": "GNSS_LEVER_ARM_Y", + "offset": "0", + "start_bit": 56, + "type": "float", + "format": "", + "unit": "s" + }, + { + "bit_length": 32, + "factor": "1", + "is_big_endian": true, + "is_float": true, + "is_signed": false, + "name": "GNSS_LEVER_ARM_Z", + "offset": "0", + "start_bit": 88, + "type": "float", + "format": "", + "unit": "s" + }, + { + "bit_length": 32, + "factor": "1", + "is_big_endian": true, + "is_float": true, + "is_signed": false, + "name": "VRP_LEVER_ARM_X", + "offset": "0", + "start_bit": 120, + "type": "float", + "format": "", + "unit": "s" + }, + { + "bit_length": 32, + "factor": "1", + "is_big_endian": true, + "is_float": true, + "is_signed": false, + "name": "VRP_LEVER_ARM_Y", + "offset": "0", + "start_bit": 152, + "type": "float", + "format": "", + "unit": "s" + }, + { + "bit_length": 32, + "factor": "1", + "is_big_endian": true, + "is_float": true, + "is_signed": false, + "name": "VRP_LEVER_ARM_Z", + "offset": "0", + "start_bit": 184, + "type": "float", + "format": "", + "unit": "s" + }, + { + "bit_length": 32, + "factor": "1", + "is_big_endian": true, + "is_float": true, + "is_signed": false, + "name": "USER_LEVER_ARM_X", + "offset": "0", + "start_bit": 216, + "type": "float", + "format": "", + "unit": "s" + }, + { + "bit_length": 32, + "factor": "1", + "is_big_endian": true, + "is_float": true, + "is_signed": false, + "name": "USER_LEVER_ARM_Y", + "offset": "0", + "start_bit": 248, + "type": "float", + "format": "", + "unit": "s" + }, + { + "bit_length": 32, + "factor": "1", + "is_big_endian": true, + "is_float": true, + "is_signed": false, + "name": "USER_LEVER_ARM_Z", + "offset": "0", + "start_bit": 280, + "type": "float", + "format": "", + "unit": "s" + }, + { + "bit_length": 32, + "factor": "1", + "is_big_endian": true, + "is_float": true, + "is_signed": false, + "name": "ROTATION_RBVX", + "offset": "0", + "start_bit": 312, + "type": "float", + "format": "", + "unit": "s" + }, + { + "bit_length": 32, + "factor": "1", + "is_big_endian": true, + "is_float": true, + "is_signed": false, + "name": "ROTATION_RBVY", + "offset": "0", + "start_bit": 332, + "type": "float", + "format": "", + "unit": "s" + }, + { + "bit_length": 32, + "factor": "1", + "is_big_endian": true, + "is_float": true, + "is_signed": false, + "name": "ROTATION_RBVZ", + "offset": "0", + "start_bit": 364, + "type": "float", + "format": "", + "unit": "s" + } + ] + } + ] + } +} \ No newline at end of file diff --git a/src/aceinna/setting/RTK350L/RTK_INS/RTK350LA.json b/src/aceinna/setting/RTK350L/RTK_INS/RTK350LA.json new file mode 100644 index 0000000..4c208f8 --- /dev/null +++ b/src/aceinna/setting/RTK350L/RTK_INS/RTK350LA.json @@ -0,0 +1,1100 @@ +{ + "appVersion": "RTK330LA INS 24.00", + "type": "openrtk", + "description": "6-axis OpenRTK with INS application", + "initial":{ + "useDefaultUart": 1, + "uart":[ + { + "name": "GNSS", + "value": "com10", + "enable": 0 + }, + { + "name": "DEBUG", + "value": "com11", + "enable": 0 + }, + { + "name": "SDK", + "value": "com12", + "enable": 0 + } + ], + "userParameters": [ + { + "paramId": 2, + "name": "S2 rate", + "value": 200 + }, + { + "paramId": 3, + "name": "gN rate", + "value": 255 + }, + { + "paramId": 4, + "name": "iN rate", + "value": 100 + }, + { + "paramId": 5, + "name": "iS rate", + "value": 10 + }, + { + "paramId": 6, + "name": "sT rate", + "value": 10 + }, + { + "paramId": 7, + "name": "iB rate", + "value": 10 + }, + { + "paramId": 8, + "name": "RM rate", + "value": 100 + }, + { + "paramId": 9, + "name": "rR rate", + "value": 255 + }, + { + "paramId": 10, + "name": "pvt rate", + "value": 255 + }, + { + "paramId": 11, + "name": "nmea rate", + "value": 1 + }, + { + "paramId": 12, + "name": "odo rate", + "value": 255 + }, + { + "paramId": 13, + "name": "movbs rate", + "value": 255 + }, + { + "paramId": 14, + "name": "heading rate", + "value": 255 + }, + { + "paramId": 15, + "name": "S2 port", + "value": 1 + }, + { + "paramId": 16, + "name": "gN port", + "value": 1 + }, + { + "paramId": 17, + "name": "iN port", + "value": 1 + }, + { + "paramId": 18, + "name": "iS port", + "value": 1 + }, + { + "paramId": 19, + "name": "sT port", + "value": 1 + }, + { + "paramId": 20, + "name": "iB port", + "value": 1 + }, + { + "paramId": 21, + "name": "RM port", + "value": 1 + }, + { + "paramId": 22, + "name": "rR port", + "value": 3 + }, + { + "paramId": 23, + "name": "pvt port", + "value": 1 + }, + { + "paramId": 24, + "name": "nmea port", + "value": 1 + }, + { + "paramId": 25, + "name": "odo port", + "value": 1 + }, + { + "paramId": 26, + "name": "movbs port", + "value": 1 + }, + { + "paramId": 27, + "name": "heading port", + "value": 1 + }, + { + "paramId": 28, + "name": "pri lever arm x", + "value": 2.5 + }, + { + "paramId": 29, + "name": "pri lever arm y", + "value": -0.24 + }, + { + "paramId": 30, + "name": "pri lever arm z", + "value": -0.9 + }, + { + "paramId": 31, + "name": "vrp lever arm x", + "value": 0.0 + }, + { + "paramId": 32, + "name": "vrp lever arm y", + "value": 0.0 + }, + { + "paramId": 33, + "name": "vrp lever arm z", + "value": 0.0 + }, + { + "paramId": 34, + "name": "user lever arm x", + "value": 1.19 + }, + { + "paramId": 35, + "name": "user lever arm y", + "value": -0.24 + }, + { + "paramId": 36, + "name": "user lever arm z", + "value": -0.9 + }, + { + "paramId": 37, + "name": "rotation rbvx", + "value": 0.0 + }, + { + "paramId": 38, + "name": "rotation rbvy", + "value": 0.0 + }, + { + "paramId": 39, + "name": "rotation rbvz", + "value": 0.0 + }, + { + "paramId": 40, + "name": "second lever arm x", + "value": 0.0 + }, + { + "paramId": 41, + "name": "second lever arm y", + "value": 0.0 + }, + { + "paramId": 42, + "name": "second lever arm z", + "value": 0.0 + }, + { + "paramId": 43, + "name": "rotation align x", + "value": 0.0 + }, + { + "paramId": 44, + "name": "rotation align y", + "value": 0.0 + }, + { + "paramId": 45, + "name": "rotation align z", + "value": 0.0 + }, + { + "paramId": 46, + "name": "nhc_enable", + "value": 1 + }, + { + "paramId": 47, + "name": "odo_enable", + "value": 1 + }, + { + "paramId": 48, + "name": "cali_enable", + "value": 1 + }, + { + "paramId": 49, + "name": "baseline length", + "value": 0.8 + }, + { + "paramId": 50, + "name": "heading calibration", + "value": 0.0 + }, + { + "paramId": 51, + "name": "master_slave_type", + "value": 1 + } + ] + }, + "userConfiguration": [ + { + "paramId": 0, + "category": "General", + "paramType": "disabled", + "type": "uint16", + "name": "Data CRC" + }, + { + "paramId": 1, + "category": "General", + "paramType": "disabled", + "type": "uint16", + "name": "Data Size" + }, + { + "paramId": 2, + "category": "General", + "paramType": "input", + "type": "uint8", + "name": "RAWIMU Packet Rate", + "argument": "S2" + }, + { + "paramId": 3, + "category": "General", + "paramType": "input", + "type": "uint8", + "name": "BESTGNSS Packet Rate", + "argument": "gN" + }, + { + "paramId": 4, + "category": "General", + "paramType": "input", + "type": "uint8", + "name": "INSPVA Packet Rate", + "argument": "iN" + }, + { + "paramId": 5, + "category": "General", + "paramType": "input", + "type": "uint8", + "name": "INSSTD Packet Rate", + "argument": "iS" + }, + { + "paramId": 6, + "category": "General", + "paramType": "input", + "type": "uint8", + "name": "RUNSTATUS Packet Rate", + "argument": "sT" + }, + { + "paramId": 7, + "category": "General", + "paramType": "input", + "type": "uint8", + "name": "INSBIAS Packet Rate", + "argument": "iB" + }, + { + "paramId": 8, + "category": "General", + "paramType": "input", + "type": "uint8", + "name": "MONITOR Packet Rate", + "argument": "RM" + }, + { + "paramId": 9, + "category": "General", + "paramType": "input", + "type": "uint8", + "name": "ROVER RTCM Packet Rate", + "argument": "rR" + }, + { + "paramId": 10, + "category": "General", + "paramType": "input", + "type": "uint8", + "name": "PVT Packet Rate", + "argument": "pv" + }, + { + "paramId": 11, + "category": "General", + "paramType": "input", + "type": "uint8", + "name": "NMEA Packet Rate", + "argument": "nm" + }, + { + "paramId": 12, + "category": "General", + "paramType": "input", + "type": "uint8", + "name": "odo Packet Rate", + "argument": "odo" + }, + { + "paramId": 13, + "category": "General", + "paramType": "input", + "type": "uint8", + "name": "movbs Packet Rate", + "argument": "MB" + }, + { + "paramId": 14, + "category": "General", + "paramType": "input", + "type": "uint8", + "name": "heading Packet Rate", + "argument": "HS" + }, + { + "paramId": 15, + "category": "General", + "paramType": "input", + "type": "uint8", + "name": "RAWIMU Packet Port", + "argument": "S2" + }, + { + "paramId": 16, + "category": "General", + "paramType": "input", + "type": "uint8", + "name": "BESTGNSS Packet Port", + "argument": "gN" + }, + { + "paramId": 17, + "category": "General", + "paramType": "input", + "type": "uint8", + "name": "INSPVA Packet Port", + "argument": "iN" + }, + { + "paramId": 18, + "category": "General", + "paramType": "input", + "type": "uint8", + "name": "INSSTD Packet Port", + "argument": "iS" + }, + { + "paramId": 19, + "category": "General", + "paramType": "input", + "type": "uint8", + "name": "RUNSTATUS Packet Port", + "argument": "sT" + }, + { + "paramId": 20, + "category": "General", + "paramType": "input", + "type": "uint8", + "name": "INSBIAS Packet Port", + "argument": "iS" + }, + { + "paramId": 21, + "category": "General", + "paramType": "input", + "type": "uint8", + "name": "MONITOR Packet Port", + "argument": "RM" + }, + { + "paramId": 22, + "category": "General", + "paramType": "input", + "type": "uint8", + "name": "ROVER RTCM Packet Port", + "argument": "rR" + }, + { + "paramId": 23, + "category": "General", + "paramType": "input", + "type": "uint8", + "name": "PVT Packet Port", + "argument": "pv" + }, + { + "paramId": 24, + "category": "General", + "paramType": "input", + "type": "uint8", + "name": "NMEA Packet Port", + "argument": "nm" + }, + { + "paramId": 25, + "category": "General", + "paramType": "input", + "type": "uint8", + "name": "odo Packet Port", + "argument": "nm" + }, + { + "paramId": 26, + "category": "General", + "paramType": "input", + "type": "uint8", + "name": "movbs Packet Port", + "argument": "nm" + }, + { + "paramId": 27, + "category": "General", + "paramType": "input", + "type": "uint8", + "name": "heading Packet Port", + "argument": "nm" + }, + { + "paramId": 28, + "category": "INS", + "paramType": "input", + "type": "float", + "name": "pri lever arm x", + "value_accuracy": 4 + }, + { + "paramId": 29, + "category": "INS", + "paramType": "input", + "type": "float", + "name": "pri lever arm y", + "value_accuracy": 4 + }, + { + "paramId": 30, + "category": "INS", + "paramType": "input", + "type": "float", + "name": "pri lever arm z", + "value_accuracy": 4 + }, + { + "paramId": 31, + "category": "INS", + "paramType": "input", + "type": "float", + "name": "vrp lever arm x", + "value_accuracy": 4 + }, + { + "paramId": 32, + "category": "INS", + "paramType": "input", + "type": "float", + "name": "vrp lever arm y", + "value_accuracy": 4 + }, + { + "paramId": 33, + "category": "INS", + "paramType": "input", + "type": "float", + "name": "vrp lever arm z", + "value_accuracy": 4 + }, + { + "paramId": 34, + "category": "INS", + "paramType": "input", + "type": "float", + "name": "user lever arm x", + "value_accuracy": 4 + }, + { + "paramId": 35, + "category": "INS", + "paramType": "input", + "type": "float", + "name": "user lever arm y", + "value_accuracy": 4 + }, + { + "paramId": 36, + "category": "INS", + "paramType": "input", + "type": "float", + "name": "user lever arm z", + "value_accuracy": 4 + }, + { + "paramId": 37, + "category": "INS", + "paramType": "input", + "type": "float", + "name": "rotation rbvx", + "value_accuracy": 4 + }, + { + "paramId": 38, + "category": "INS", + "paramType": "input", + "type": "float", + "name": "rotation rbvy", + "value_accuracy": 4 + }, + { + "paramId": 39, + "category": "INS", + "paramType": "input", + "type": "float", + "name": "rotation rbvz", + "value_accuracy": 4 + }, + { + "paramId": 40, + "category": "INS", + "paramType": "input", + "type": "float", + "name": "second lever arm x", + "value_accuracy": 4 + }, + { + "paramId": 41, + "category": "INS", + "paramType": "input", + "type": "float", + "name": "second lever arm y", + "value_accuracy": 4 + }, + { + "paramId": 42, + "category": "INS", + "paramType": "input", + "type": "float", + "name": "second lever arm z", + "value_accuracy": 4 + }, + { + "paramId": 43, + "category": "INS", + "paramType": "input", + "type": "float", + "name": "rotation align x", + "value_accuracy": 4 + }, + { + "paramId": 44, + "category": "INS", + "paramType": "input", + "type": "float", + "name": "rotation align y", + "value_accuracy": 4 + }, + { + "paramId": 45, + "category": "INS", + "paramType": "input", + "type": "float", + "name": "rotation align z", + "value_accuracy": 4 + }, + { + "paramId": 46, + "category": "INS", + "paramType": "input", + "name": "nhc_enable", + "type": "uint8", + "value_accuracy": 1 + }, + { + "paramId": 47, + "category": "INS", + "paramType": "input", + "name": "odo_enable", + "type": "uint8", + "value_accuracy": 1 + }, + { + "paramId": 48, + "category": "INS", + "paramType": "input", + "name": "cali_enable", + "type": "uint8", + "value_accuracy": 1 + }, + { + "paramId": 49, + "category": "INS", + "paramType": "input", + "name": "baseline length", + "type": "float", + "value_accuracy": 4 + }, + { + "paramId": 50, + "category": "INS", + "paramType": "input", + "name": "heading calibration", + "type": "float", + "value_accuracy": 4 + }, + { + "paramId": 51, + "category": "type", + "paramType": "input", + "type": "uint8", + "name": "master_slave_type", + "value_accuracy": 1 + } + ], + "userMessages": { + "inputPackets": [ + { + "name": "pG", + "description": "Get device serial number & factory ID", + "inputPayload": {}, + "responsePayload": { + "type": "string", + "name": "Device ID and SN" + } + }, + { + "name": "gV", + "description": "Get user app version", + "inputPayload": {}, + "responsePayload": { + "type": "string", + "name": "User Version" + } + }, + { + "name": "gA", + "description": "Get All Configuration Parameters", + "inputPayload": {}, + "responsePayload": { + "type": "userConfiguration", + "name": "Full Current Configuration" + } + }, + { + "name": "sC", + "description": "Save Conifguration Parameters to Flash", + "inputPayload": {}, + "responsePayload": {} + }, + { + "name": "uP", + "description": "Update Configuration Parameter", + "inputPayload": { + "type": "userParameter", + "name": "Parameter to be Updated" + }, + "responsePayload": { + "type": "paramId", + "name": "ID of the Updated Parameter" + } + } + ], + "outputPackets": [ + { + "name": "S2", + "isList": 0, + "payload": [ + { + "type": "uint32", + "name": "GPS_Week", + "unit": "" + }, + { + "type": "double", + "name": "GPS_TimeofWeek", + "unit": "sec" + }, + { + "type": "float", + "name": "x_accel", + "unit": "m/s^2" + }, + { + "type": "float", + "name": "y_accel", + "unit": "m/s^2" + }, + { + "type": "float", + "name": "z_accel", + "unit": "m/s^2" + }, + { + "type": "float", + "name": "x_rate", + "unit": "deg/s" + }, + { + "type": "float", + "name": "y_rate", + "unit": "deg/s" + }, + { + "type": "float", + "name": "z_rate", + "unit": "deg/s" + } + ], + "graphs": [ + { + "name": "Acceleration", + "units": "m/s^2", + "xAxis": {"name":"GPS_TimeofWeek", "unit":"sec"}, + "yAxes": [ + "x_accel", + "y_accel", + "z_accel" + ], + "colors": [ + "#FF0000", + "#00FF00", + "#0000FF" + ], + "yMax": 20 + }, + { + "name": "Angular-Rate", + "units": "deg/s", + "xAxis": {"name":"GPS_TimeofWeek", "unit":"sec"}, + "yAxes": [ + "x_rate", + "y_rate", + "z_rate" + ], + "colors": [ + "#FF0000", + "#00FF00", + "#0000FF" + ], + "yMax": 200 + } + ] + }, + { + "name": "iN", + "isList": 0, + "payload": [ + { + "type": "uint32", + "name": "GPS_Week", + "unit": "" + }, + { + "type": "double", + "name": "GPS_TimeofWeek", + "unit": "sec" + }, + { + "type": "uint8", + "name": "insStatus", + "unit": "" + }, + { + "type": "uint8", + "name": "insPositionType", + "unit": "" + }, + { + "type": "int32", + "name": "latitude", + "unit": "deg" + }, + { + "type": "int32", + "name": "longitude", + "unit": "deg" + }, + { + "type": "float", + "name": "height", + "unit": "m" + }, + { + "type": "int16", + "name": "velocityNorth", + "unit": "m/s" + }, + { + "type": "int16", + "name": "velocityEast", + "unit": "m/s" + }, + { + "type": "int16", + "name": "velocityUp", + "unit": "m/s" + }, + { + "type": "int16", + "name": "roll", + "unit": "m/s" + }, + { + "type": "int16", + "name": "pitch", + "unit": "m/s" + }, + { + "type": "int16", + "name": "heading", + "unit": "m/s" + } + ], + "graphs": [] + }, + { + "name": "d1", + "isList": 0, + "payload": [ + { + "type": "uint32", + "name": "GPS_Week", + "unit": "" + }, + { + "type": "double", + "name": "GPS_TimeofWeek", + "unit": "sec" + }, + { + "type": "int16", + "name": "latitude_std", + "unit": "" + }, + { + "type": "int16", + "name": "longitude_std", + "unit": "" + }, + { + "type": "int16", + "name": "height_std", + "unit": "" + }, + { + "type": "int16", + "name": "north_vel_std", + "unit": "" + }, + { + "type": "int16", + "name": "east_vel_std", + "unit": "" + }, + { + "type": "int16", + "name": "up_vel_std", + "unit": "" + }, + { + "type": "int16", + "name": "roll_std", + "unit": "" + }, + { + "type": "int16", + "name": "pitch_std", + "unit": "" + }, + { + "type": "int16", + "name": "heading_std", + "unit": "" + } + ], + "graphs": [] + }, + { + "name": "gN", + "isList": 0, + "payload": [ + { + "type": "uint32", + "name": "GPS_Week", + "unit": "" + }, + { + "type": "double", + "name": "GPS_TimeofWeek", + "unit": "sec" + }, + { + "type": "uint8", + "name": "positionMode", + "unit": "" + }, + { + "type": "int32", + "name": "latitude", + "unit": "deg" + }, + { + "type": "int32", + "name": "longitude", + "unit": "deg" + }, + { + "type": "float", + "name": "height", + "unit": "m" + }, + { + "type": "uint8", + "name": "numberOfSVs", + "unit": "" + }, + { + "type": "float", + "name": "hdop", + "unit": "" + }, + { + "type": "uint16", + "name": "diffage", + "unit": "" + }, + { + "type": "int16", + "name": "velocityNorth", + "unit": "m/s" + }, + { + "type": "int16", + "name": "velocityEast", + "unit": "m/s" + }, + { + "type": "int16", + "name": "velocityUp", + "unit": "m/s" + } + ], + "graphs": [] + }, + { + "name": "sT", + "isList": 0, + "payload": [ + { + "type": "uint32", + "name": "GPS_Week", + "unit": "" + }, + { + "type": "double", + "name": "GPS_TimeofWeek", + "unit": "sec" + }, + { + "type": "uint16", + "name": "year", + "unit": "" + }, + { + "type": "uint8", + "name": "mouth", + "unit": "" + }, + { + "type": "uint8", + "name": "day", + "unit": "" + }, + { + "type": "uint8", + "name": "hour", + "unit": "" + }, + { + "type": "uint8", + "name": "min", + "unit": "" + }, + { + "type": "uint8", + "name": "sec", + "unit": "" + }, + + { + "type": "uint32", + "name": "imu_status", + "unit": "" + }, + { + "type": "float", + "name": "imu_temperature", + "unit": "sec" + }, + { + "type": "float", + "name": "mcu_temperature", + "unit": "" + } + ], + "graphs": [] + } + ] + }, + "CLICommands": [ + { + "name": "help", + "description": "CLI help menu", + "function": "help_handler" + }, + { + "name": "exit", + "description": "exit CLI", + "function": "" + } + ] +} diff --git a/src/aceinna/setting/RTK350L/log-parser.json b/src/aceinna/setting/RTK350L/log-parser.json new file mode 100644 index 0000000..2d90f2d --- /dev/null +++ b/src/aceinna/setting/RTK350L/log-parser.json @@ -0,0 +1,721 @@ +{ + "version": "2.0.5", + "userNMEAList": ["$GPGGA", "$GPRMC", "$GPGSV", "$GLGSV", "$GAGSV", "$BDGSV", "$GPGSA", "$GLGSA", "$GAGSA", "$BDGSA"], + "userPacketsTypeList": ["S2", "gN", "iN", "d1", "sT", "fM", "o1", "rt"], + "userOutputPackets": [ + { + "name": "o1", + "isList": 0, + "payload": [ + { + "type": "uint16", + "name": "GPS_Week", + "unit": "", + "format": "" + }, + { + "type": "uint32", + "name": "GPS_TimeOfWeek", + "unit": "s", + "format": "11.4f" + }, + { + "type": "uint8", + "name": "mode", + "unit": "", + "format": "3" + }, + { + "type": "double", + "name": "speed", + "unit": "m/s", + "format": "10.4f" + }, + { + "type": "uint8", + "name": "fwd", + "unit": "", + "format": "3" + }, + { + "type": "uint64", + "name": "wheel_tick", + "unit": "", + "format": "16" + } + ] + }, + { + "name": "fM", + "isList": 0, + "payload": [ + { + "type": "uint32", + "name": "GPS_Week", + "unit": "", + "format": "" + }, + { + "type": "double", + "name": "GPS_TimeofWeek", + "unit": "s", + "format": "11.4f" + }, + { + "type": "int32", + "name": "xAccelCounts1", + "unit": "", + "format": "8" + }, + { + "type": "int32", + "name": "yAccelCounts1", + "unit": "", + "format": "8" + }, + { + "type": "int32", + "name": "zAccelCounts1", + "unit": "", + "format": "8" + }, + { + "type": "int32", + "name": "xRateCounts1", + "unit": "", + "format": "8" + }, + { + "type": "int32", + "name": "yRateCounts1", + "unit": "", + "format": "8" + }, + { + "type": "int32", + "name": "zRateCounts1", + "unit": "", + "format": "8" + }, + { + "type": "int32", + "name": "TempCounts1", + "unit": "", + "format": "8" + }, + { + "type": "int32", + "name": "xAccelCounts2", + "unit": "", + "format": "8" + }, + { + "type": "int32", + "name": "yAccelCounts2", + "unit": "", + "format": "8" + }, + { + "type": "int32", + "name": "zAccelCounts2", + "unit": "", + "format": "8" + }, + { + "type": "int32", + "name": "xRateCounts2", + "unit": "", + "format": "8" + }, + { + "type": "int32", + "name": "yRateCounts2", + "unit": "", + "format": "8" + }, + { + "type": "int32", + "name": "zRateCounts2", + "unit": "", + "format": "8" + }, + { + "type": "int32", + "name": "TempCounts2", + "unit": "", + "format": "8" + }, + { + "type": "int32", + "name": "xAccelCounts3", + "unit": "", + "format": "8" + }, + { + "type": "int32", + "name": "yAccelCounts3", + "unit": "", + "format": "8" + }, + { + "type": "int32", + "name": "zAccelCounts3", + "unit": "", + "format": "8" + }, + { + "type": "int32", + "name": "xRateCounts3", + "unit": "", + "format": "8" + }, + { + "type": "int32", + "name": "yRateCounts3", + "unit": "", + "format": "8" + }, + { + "type": "int32", + "name": "zRateCounts3", + "unit": "", + "format": "8" + }, + { + "type": "int32", + "name": "TempCounts3", + "unit": "", + "format": "8" + }, + { + "type": "uint16", + "name": "index", + "unit": "", + "format": "" + } + ] + }, + { + "name": "rt", + "isList": 0, + "payload": [ + { + "type": "uint32", + "name": "GPS_Week", + "unit": "", + "format": "" + }, + { + "type": "double", + "name": "GPS_TimeofWeek", + "unit": "s", + "format": "11.4f" + }, + { + "type": "float", + "name": "xAccelCounts1", + "unit": "", + "format": "14.6f" + }, + { + "type": "float", + "name": "yAccelCounts1", + "unit": "", + "format": "14.6f" + }, + { + "type": "float", + "name": "zAccelCounts1", + "unit": "", + "format": "14.6f" + }, + { + "type": "float", + "name": "xRateCounts1", + "unit": "", + "format": "14.6f" + }, + { + "type": "float", + "name": "yRateCounts1", + "unit": "", + "format": "14.6f" + }, + { + "type": "float", + "name": "zRateCounts1", + "unit": "", + "format": "14.6f" + }, + { + "type": "float", + "name": "TempCounts1", + "unit": "", + "format": "14.6f" + }, + { + "type": "float", + "name": "xAccelCounts2", + "unit": "", + "format": "14.6f" + }, + { + "type": "float", + "name": "yAccelCounts2", + "unit": "", + "format": "14.6f" + }, + { + "type": "float", + "name": "zAccelCounts2", + "unit": "", + "format": "14.6f" + }, + { + "type": "float", + "name": "xRateCounts2", + "unit": "", + "format": "14.6f" + }, + { + "type": "float", + "name": "yRateCounts2", + "unit": "", + "format": "14.6f" + }, + { + "type": "float", + "name": "zRateCounts2", + "unit": "", + "format": "14.6f" + }, + { + "type": "float", + "name": "TempCounts2", + "unit": "", + "format": "14.6f" + }, + { + "type": "float", + "name": "xAccelCounts3", + "unit": "", + "format": "14.6f" + }, + { + "type": "float", + "name": "yAccelCounts3", + "unit": "", + "format": "14.6f" + }, + { + "type": "float", + "name": "zAccelCounts3", + "unit": "", + "format": "14.6f" + }, + { + "type": "float", + "name": "xRateCounts3", + "unit": "", + "format": "14.6f" + }, + { + "type": "float", + "name": "yRateCounts3", + "unit": "", + "format": "14.6f" + }, + { + "type": "float", + "name": "zRateCounts3", + "unit": "", + "format": "14.6f" + }, + { + "type": "float", + "name": "TempCounts3", + "unit": "", + "format": "14.6f" + } + ] + }, + { + "name": "s1", + "isList": 0, + "payload": [ + { + "type": "uint32", + "name": "GPS_Week", + "unit": "", + "format": "" + }, + { + "type": "double", + "name": "GPS_TimeofWeek", + "unit": "s", + "format": "11.4f" + }, + { + "type": "float", + "name": "x_accel", + "unit": "m/s^2", + "format": "14.10f" + }, + { + "type": "float", + "name": "y_accel", + "unit": "m/s^2", + "format": "14.10f" + }, + { + "type": "float", + "name": "z_accel", + "unit": "m/s^2", + "format": "14.10f" + }, + { + "type": "float", + "name": "x_rate", + "unit": "deg/s", + "format": "14.10f" + }, + { + "type": "float", + "name": "y_rate", + "unit": "deg/s", + "format": "14.10f" + }, + { + "type": "float", + "name": "z_rate", + "unit": "deg/s", + "format": "14.10f" + } + ] + }, + { + "name": "gN", + "isList": 0, + "payload": [ + { + "type": "uint32", + "name": "GPS_Week", + "unit": "", + "format": "" + }, + { + "type": "double", + "name": "GPS_TimeofWeek", + "unit": "s", + "format": "11.4f" + }, + { + "type": "uint8", + "name": "positionMode", + "unit": "", + "format": "3" + }, + { + "type": "int32", + "name": "latitude", + "unit": "deg", + "format": "14.9f" + }, + { + "type": "int32", + "name": "longitude", + "unit": "deg", + "format": "14.9f" + }, + { + "type": "float", + "name": "height", + "unit": "m", + "format": "10.4f" + }, + { + "type": "uint8", + "name": "numberOfSVs", + "unit": "", + "format": "3" + }, + { + "type": "float", + "name": "hdop", + "unit": "", + "format": "5.1f" + }, + { + "type": "uint16", + "name": "diffage", + "unit": "", + "format": "5.1f" + }, + { + "type": "int16", + "name": "velocityNorth", + "unit": "m/s", + "format": "10.4f" + }, + { + "type": "int16", + "name": "velocityEast", + "unit": "m/s", + "format": "10.4f" + }, + { + "type": "int16", + "name": "velocityUp", + "unit": "m/s", + "format": "10.4f" + }, + { + "type": "int16", + "name": "latitude_std", + "unit": "m", + "format": "10.4f" + }, + { + "type": "int16", + "name": "longitude_std", + "unit": "m", + "format": "10.4f" + }, + { + "type": "int16", + "name": "height_std", + "unit": "m", + "format": "10.4f" + } + ] + }, + { + "name": "iN", + "isList": 0, + "payload": [ + { + "type": "uint32", + "name": "GPS_Week", + "unit": "", + "format": "" + }, + { + "type": "double", + "name": "GPS_TimeofWeek", + "unit": "s", + "format": "11.4f" + }, + { + "type": "uint8", + "name": "insStatus", + "unit": "", + "format": "3" + }, + { + "type": "uint8", + "name": "insPositionType", + "unit": "", + "format": "3" + }, + { + "type": "int32", + "name": "latitude", + "unit": "deg", + "format": "14.9f" + }, + { + "type": "int32", + "name": "longitude", + "unit": "deg", + "format": "14.9f" + }, + { + "type": "float", + "name": "height", + "unit": "m", + "format": "10.4f" + }, + { + "type": "int16", + "name": "velocityNorth", + "unit": "m/s", + "format": "10.4f" + }, + { + "type": "int16", + "name": "velocityEast", + "unit": "m/s", + "format": "10.4f" + }, + { + "type": "int16", + "name": "velocityUp", + "unit": "m/s", + "format": "10.4f" + }, + { + "type": "int16", + "name": "roll", + "unit": "deg", + "format": "14.9f" + }, + { + "type": "int16", + "name": "pitch", + "unit": "deg", + "format": "14.9f" + }, + { + "type": "int16", + "name": "heading", + "unit": "deg", + "format": "14.9f" + } + ] + }, + { + "name": "d1", + "isList": 0, + "payload": [ + { + "type": "uint32", + "name": "GPS_Week", + "unit": "", + "format": "" + }, + { + "type": "double", + "name": "GPS_TimeofWeek", + "unit": "s", + "format": "11.4f" + }, + { + "type": "int16", + "name": "latitude_std", + "unit": "", + "format": "8.3f" + }, + { + "type": "int16", + "name": "longitude_std", + "unit": "", + "format": "8.3f" + }, + { + "type": "int16", + "name": "height_std", + "unit": "", + "format": "8.3f" + }, + { + "type": "int16", + "name": "north_vel_std", + "unit": "", + "format": "8.3f" + }, + { + "type": "int16", + "name": "east_vel_std", + "unit": "", + "format": "8.3f" + }, + { + "type": "int16", + "name": "up_vel_std", + "unit": "", + "format": "8.3f" + }, + { + "type": "int16", + "name": "roll_std", + "unit": "", + "format": "8.3f" + }, + { + "type": "int16", + "name": "pitch_std", + "unit": "", + "format": "8.3f" + }, + { + "type": "int16", + "name": "heading_std", + "unit": "", + "format": "8.3f" + } + ] + }, + { + "name": "sT", + "isList": 0, + "payload": [ + { + "type": "uint32", + "name": "GPS_Week", + "unit": "", + "format": "" + }, + { + "type": "double", + "name": "GPS_TimeofWeek", + "unit": "s", + "format": "11.4f" + }, + { + "type": "uint16", + "name": "year", + "unit": "", + "format": "5" + }, + { + "type": "uint8", + "name": "mouth", + "unit": "", + "format": "5" + }, + { + "type": "uint8", + "name": "day", + "unit": "", + "format": "5" + }, + { + "type": "uint8", + "name": "hour", + "unit": "", + "format": "5" + }, + { + "type": "uint8", + "name": "min", + "unit": "", + "format": "5" + }, + { + "type": "uint8", + "name": "sec", + "unit": "", + "format": "5" + }, + { + "type": "uint32", + "name": "imu_status", + "unit": "", + "format": "5" + }, + { + "type": "float", + "name": "imu_temperature", + "unit": "", + "format": "8.3" + }, + { + "type": "float", + "name": "mcu_temperature", + "unit": "", + "format": "8.3" + } + ] + } + ] +} \ No newline at end of file diff --git a/tests/test_ins402_config_algorithm.py b/tests/test_ins402_config_algorithm.py new file mode 100644 index 0000000..b433e4c --- /dev/null +++ b/tests/test_ins402_config_algorithm.py @@ -0,0 +1,146 @@ +import math +import re +import sys +import time +import os +import signal +import struct + +try: + from aceinna.core.driver import (Driver, DriverEvents) + from aceinna.models.args import WebserverArgs + from aceinna.framework.utils.print import (print_green, print_red) + from aceinna.framework.decorator import handle_application_exception + from aceinna.devices.ins401.ethernet_provider_ins402 import Provider as EhternetProvider + from aceinna.framework.constants import INTERFACES +except: # pylint: disable=bare-except + print('load package from local') + sys.path.append('./src') + from aceinna.core.driver import (Driver, DriverEvents) + from aceinna.models.args import WebserverArgs + from aceinna.framework.utils.print import (print_green, print_red) + from aceinna.framework.decorator import handle_application_exception + from aceinna.devices.ins401.ethernet_provider_ins402 import Provider as EhternetProvider + from aceinna.framework.constants import INTERFACES + +FILE_NAME = './toro_rlx.bin' + +class FileContent: + content: bytes = None + content_size: int = 0 + block_size: int = 1024 + block_number: int = 0 + + def __init__(self, file_path) -> None: + self.content = self.read_file(file_path) + self.content_size = len(self.content) + self.block_number = math.ceil(self.content_size / self.block_size) + + def read_file(self, file_path): + with open(file_path, 'rb') as file: + return file.read() + +def test_fail_configuration_algorithm_command(configuration: FileContent, device_provider: EhternetProvider): + result = device_provider.configure_do_send_packet( + configuration.content, configuration.block_size) + if not result: + print_green('send packet command before prepare command. Should be failed: Yes') + else: + print_red('send packet command before prepare command. Should be failed: No') + return False + + wrong_block_size = 512 + device_provider.configure_do_send_prepare( + configuration.content_size, configuration.block_number) + result = device_provider.configure_do_send_packet( + configuration.content, wrong_block_size) + if not result: + print_green('send packet command in wrong size. Should be failed: Yes') + else: + print_red('send packet command in wrong size. Should be failed: No') + return False + +def test_configuration_algorithm_command(configuration: FileContent, device_provider: EhternetProvider): + # test send prepare command + result = device_provider.configure_do_send_prepare( + configuration.content_size, configuration.block_number) + if result: + print_green('send prepare command ok.') + else: + print_red('send prepare command error.') + return False + + # test send packet command + result = device_provider.configure_do_send_packet( + configuration.content, configuration.block_size) + if result: + print_green('send packet command ok.') + else: + print_red('send packet command error.') + return False + + # test reset command + result = device_provider.configure_do_reset() + if result: + print_green('device reset and ping ok.') + else: + print_red('device reset and ping error.') + return False + + return True + +def test_configuration_algorithm_process(device_provider: EhternetProvider): + cmd_str = 'configure {0}'.format(FILE_NAME) + cmd_list = re.split(r'\s+', cmd_str) + + return device_provider.configure_algorithm(cmd_list) + +def handle_discovered(device_provider): + configuration = FileContent(FILE_NAME) + + result = test_fail_configuration_algorithm_command(configuration, device_provider) + if result: + print_green('test fail config algorithm command ok.') + else: + print_red('test fail config algorithm command error.') + return + + result = test_configuration_algorithm_command( + configuration, device_provider) + if result: + print_green('test config algorithm command ok.') + else: + print_red('test config algorithm command error.') + return + + result = test_configuration_algorithm_process(device_provider) + if result: + print_green('test config algorithm process ok.') + else: + print_red('test config algorithm process error.') + return + + +def kill_app(signal_int, call_back): + '''Kill main thread + ''' + os.kill(os.getpid(), signal.SIGTERM) + sys.exit() + + +@handle_application_exception +def simple_start(): + driver = Driver(WebserverArgs( + interface=INTERFACES.ETH_100BASE_T1, + device_type='INS402', + use_cli=True + )) + driver.on(DriverEvents.Discovered, handle_discovered) + driver.detect() + + +if __name__ == '__main__': + simple_start() + + while True: + signal.signal(signal.SIGINT, kill_app) diff --git a/tests/test_rtk350la_command.py b/tests/test_rtk350la_command.py new file mode 100644 index 0000000..6701172 --- /dev/null +++ b/tests/test_rtk350la_command.py @@ -0,0 +1,104 @@ +import sys +import time +import os +import signal +import struct + +try: + from aceinna.core.driver import (Driver, DriverEvents) + from aceinna.models.args import WebserverArgs + from aceinna.framework.utils import (helper) + from aceinna.framework.decorator import handle_application_exception + from aceinna.devices.ins401.ethernet_provider_ins401 import Provider as EhternetProvider + from aceinna.framework.constants import INTERFACES +except: # pylint: disable=bare-except + print('load package from local') + sys.path.append('./src') + from aceinna.core.driver import (Driver, DriverEvents) + from aceinna.models.args import WebserverArgs + from aceinna.framework.utils import (helper) + from aceinna.framework.decorator import handle_application_exception + from aceinna.devices.rtk350la.uart_provider import Provider as UartProvider + from aceinna.framework.constants import INTERFACES + +def set_user_configuration(command, message_bytes): + + command_line = helper.build_packet(command, message_bytes) + return command_line + +def get_user_configuration_parameters(command, field_id): + message_bytes = [] + + field_id_bytes = struct.pack('