diff --git a/docs/Application_guide/en/README.md b/docs/Application_guide/en/README.md
index f669890cff0709df5f45804d62b5f9593695cf7d..82aa5ce5b4520664b922b534cfa32d707a2060eb 100644
--- a/docs/Application_guide/en/README.md
+++ b/docs/Application_guide/en/README.md
@@ -102,7 +102,7 @@ QuecPython Application Guide is a guide on how to use the commonly used function
- [Wearable Solution](solutions/Wear/readme.md)
- [Electricity Meter](solutions/electricity-meter/README.md)
- [Tracker Solution](solutions/tracker/README.md)
-
+- [Smart Tracker Solution Based on BG95M3](solutions/tracker_box(BG95M3)/README.md)
Helios SDK
diff --git a/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/3b5b2ebd-e154-459d-8992-1d4615834b8e.png b/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/3b5b2ebd-e154-459d-8992-1d4615834b8e.png
new file mode 100644
index 0000000000000000000000000000000000000000..0eeac776f428f7cf2e43d4c5d874e45e121655fa
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/3b5b2ebd-e154-459d-8992-1d4615834b8e.png differ
diff --git a/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/60eb6249-67ea-40d3-a59b-0612dbc9f308.png b/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/60eb6249-67ea-40d3-a59b-0612dbc9f308.png
new file mode 100644
index 0000000000000000000000000000000000000000..1dc97ed9cb91109dfee0dd3359fd16b9153521be
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/60eb6249-67ea-40d3-a59b-0612dbc9f308.png differ
diff --git a/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/860ce14a-e915-4207-9f29-36ac5b1a7a64.png b/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/860ce14a-e915-4207-9f29-36ac5b1a7a64.png
new file mode 100644
index 0000000000000000000000000000000000000000..c084009280e911c36d4c6f5644c13eb04323d7c5
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/860ce14a-e915-4207-9f29-36ac5b1a7a64.png differ
diff --git a/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/Qpycom.png b/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/Qpycom.png
new file mode 100644
index 0000000000000000000000000000000000000000..4f6ab07b08ff44df9c62ce85ae8b6d529309739b
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/Qpycom.png differ
diff --git a/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/USB.png b/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/USB.png
new file mode 100644
index 0000000000000000000000000000000000000000..575a02096cca25723bdc02123f4fe85bc7f352a8
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/USB.png differ
diff --git a/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/add_device.png b/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/add_device.png
new file mode 100644
index 0000000000000000000000000000000000000000..85a199774230e6726fda6c60578e5767e0dde9e1
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/add_device.png differ
diff --git a/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/bg95-m3-back.png b/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/bg95-m3-back.png
new file mode 100644
index 0000000000000000000000000000000000000000..91923ff379f400753ab484f371c360f3d847b872
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/bg95-m3-back.png differ
diff --git a/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/bg95-m3.png b/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/bg95-m3.png
new file mode 100644
index 0000000000000000000000000000000000000000..f10f68194295775ac18fed29d4af41f847ddb196
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/bg95-m3.png differ
diff --git a/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/bg95_clear.png b/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/bg95_clear.png
new file mode 100644
index 0000000000000000000000000000000000000000..4ee7b07e8263a1492530638bbf2437e86f2f3f22
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/bg95_clear.png differ
diff --git a/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/box.jpg b/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/box.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..342f04693869f1cfe94e9454550a412eaa1988dc
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/box.jpg differ
diff --git a/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/box.png b/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/box.png
new file mode 100644
index 0000000000000000000000000000000000000000..404ef07820124a596e7fe8c334116010491032bb
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/box.png differ
diff --git a/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/device_control_panel.jpg b/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/device_control_panel.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..d7a9a4317794f7e8580f32e118f227ac7d0af651
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/device_control_panel.jpg differ
diff --git a/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/device_qr_code.png b/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/device_qr_code.png
new file mode 100644
index 0000000000000000000000000000000000000000..8c0c815ec17cb0d4c97b01cf48bfcc6c436fe354
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/device_qr_code.png differ
diff --git a/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/ebb64f59-a7ec-4742-b2f3-40d6e58a0bdf.png b/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/ebb64f59-a7ec-4742-b2f3-40d6e58a0bdf.png
new file mode 100644
index 0000000000000000000000000000000000000000..a4775f003e5b6b7ae0b8666bb412aa7cb5375588
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/ebb64f59-a7ec-4742-b2f3-40d6e58a0bdf.png differ
diff --git a/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/f735bcd9b0c85d0aaad96173b315ca73.png b/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/f735bcd9b0c85d0aaad96173b315ca73.png
new file mode 100644
index 0000000000000000000000000000000000000000..cc9bf76734ff4e370391c3d8590b0ab8f80e1984
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/f735bcd9b0c85d0aaad96173b315ca73.png differ
diff --git a/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/gnss_antenna.png b/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/gnss_antenna.png
new file mode 100644
index 0000000000000000000000000000000000000000..2de0a5c5f3cc788e7e13c7b241041c78eefeeb4b
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/gnss_antenna.png differ
diff --git a/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/lte_antenna.png b/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/lte_antenna.png
new file mode 100644
index 0000000000000000000000000000000000000000..93c162d804cc63e652af347e676389f1c1ebbba8
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/lte_antenna.png differ
diff --git a/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/power_button.PNG b/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/power_button.PNG
new file mode 100644
index 0000000000000000000000000000000000000000..6d3edf9428a32b3f44e25b7a6065cd54294a3a47
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/power_button.PNG differ
diff --git a/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/raspberry_pi_sensor_hat_b_board.png b/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/raspberry_pi_sensor_hat_b_board.png
new file mode 100644
index 0000000000000000000000000000000000000000..9a5667c7435a898e3b22699066d7473681811354
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/raspberry_pi_sensor_hat_b_board.png differ
diff --git a/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/saas_location.png b/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/saas_location.png
new file mode 100644
index 0000000000000000000000000000000000000000..d65c4712f7ccf3e7734df53c950afa15d8a84590
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/saas_location.png differ
diff --git a/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/saas_login.png b/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/saas_login.png
new file mode 100644
index 0000000000000000000000000000000000000000..f6cefcaf569164ed4f11d9ce56806f29fb03db90
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/saas_login.png differ
diff --git a/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/search_device_imei.png b/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/search_device_imei.png
new file mode 100644
index 0000000000000000000000000000000000000000..0c170ca8ffd1df38c7e29db8090a9e3f1a29b559
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/search_device_imei.png differ
diff --git a/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/sensor.png b/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/sensor.png
new file mode 100644
index 0000000000000000000000000000000000000000..86608b7c993723d848b8a252001aabac330754c2
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/sensor.png differ
diff --git a/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/usb-c_sim.jpg b/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/usb-c_sim.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..dd28eabadd315ca3f9b98a95a051d715c9e20b30
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/usb-c_sim.jpg differ
diff --git a/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/wonderfree.png b/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/wonderfree.png
new file mode 100644
index 0000000000000000000000000000000000000000..22d335e319d40d96ce5cd28937cc49170575058b
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/wonderfree.png differ
diff --git a/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/wonderfree0.png b/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/wonderfree0.png
new file mode 100644
index 0000000000000000000000000000000000000000..04f81ae01a6128c950c48debe2f148e47e23118b
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/wonderfree0.png differ
diff --git a/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/wonderfree3.png b/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/wonderfree3.png
new file mode 100644
index 0000000000000000000000000000000000000000..d22cd8ad80c96f51be963c2e4b346f47c10be341
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/wonderfree3.png differ
diff --git a/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/wonderfree4.png b/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/wonderfree4.png
new file mode 100644
index 0000000000000000000000000000000000000000..4b5125fed2d20735a3eb3ed8fa160a2b7879f46e
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/wonderfree4.png differ
diff --git a/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/wonderfree5.png b/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/wonderfree5.png
new file mode 100644
index 0000000000000000000000000000000000000000..6453e8edbfd01604eb1dc6ab408699b39b8b6c27
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/tracker_box(BG95M3)/wonderfree5.png differ
diff --git a/docs/Application_guide/en/sidebar.yaml b/docs/Application_guide/en/sidebar.yaml
index b03850bc7690a91829d5e3f09928fc2292211691..e42650b0442604e3ace4957696511c43f2688972 100644
--- a/docs/Application_guide/en/sidebar.yaml
+++ b/docs/Application_guide/en/sidebar.yaml
@@ -346,6 +346,15 @@ items:
file: solutions/tracker/quick_start.md
- label: software design
file: solutions/tracker/software_design.md
+ label: Smart Tracker Solution Based on BG95M3
+ file: solutions/tracker_box(BG95M3)/README.md
+ items:
+ - label: development resources
+ file: solutions/tracker_box(BG95M3)/dev_resources.md
+ - label: quick start
+ file: solutions/tracker_box(BG95M3)/quick_start.md
+ - label: software design
+ file: solutions/tracker_box(BG95M3)/software_design.md
- label: SensorHub
file: solutions/SensorHub/README.md
items:
diff --git a/docs/Application_guide/en/solutions/README.md b/docs/Application_guide/en/solutions/README.md
index 13186def85e552a4322e2f1060659f12db85cf27..657fc0789269665983976d3e42327e5a968a76ba 100644
--- a/docs/Application_guide/en/solutions/README.md
+++ b/docs/Application_guide/en/solutions/README.md
@@ -11,6 +11,7 @@ To facilitate your application development and accelerate your project implement
- [Wearable Solution](./Wear/readme.md)
- [Electricity-Meter solution](./electricity-meter/README.md)
- [Tracker Solution](./tracker/README.md)
+- [Smart Tracker Solution Based on BG95M3](solutions/tracker_box(BG95M3)/README.md)
- [SensorHub solution](./SensorHub/README.md)
- [DTU based on EG912U](./DTU-EG912U/README.md)
- [Poc](./poc/README.md)
diff --git a/docs/Application_guide/en/solutions/tracker_box(BG95M3)/README.md b/docs/Application_guide/en/solutions/tracker_box(BG95M3)/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..27b64c536c2159d1525e9e0c5834710003f41ee2
--- /dev/null
+++ b/docs/Application_guide/en/solutions/tracker_box(BG95M3)/README.md
@@ -0,0 +1,18 @@
+# Acceleronix Intelligent Tracker Solution
+
+The Acceleronix solution is implemented based on the QuecPython **BG95-M3** standard development board and has the following features:
+
+• Provides accurate high-precision GNSS positioning.
+
+ • Powerful and rich interfaces.
+
+• Uses Python language, facilitating secondary development.
+
+\box.png)
+
+------
+
+- [Summary of Development Resources](./dev_resources.md)
+- [Quick Start](quick_start.md)
+- [Software Design Explanation](./software_design.md)
+
diff --git a/docs/Application_guide/en/solutions/tracker_box(BG95M3)/dev_resources.md b/docs/Application_guide/en/solutions/tracker_box(BG95M3)/dev_resources.md
new file mode 100644
index 0000000000000000000000000000000000000000..dd80536c3c81534c8c6cb68ccf2da0e4420d2b04
--- /dev/null
+++ b/docs/Application_guide/en/solutions/tracker_box(BG95M3)/dev_resources.md
@@ -0,0 +1,35 @@
+# Development resources summary
+
+## Development board documentation
+
+- model:QuecPython BG95M3
+- Purchase link:[click](https://www.waveshare.com/bg95-m3-zero.htm)
+- docs:
+ - [specification](https://developer.quectel.com/wp-content/uploads/2024/11/BG95%E6%A0%B8%E5%BF%83%E6%9D%BF%E4%BA%A7%E5%93%81%E8%A7%84%E6%A0%BC%E5%8F%8A%E7%94%A8%E6%88%B7%E6%8C%87%E5%AF%BC.pdf)
+ - [schematic](https://developer.quectel.com/wp-content/uploads/2024/11/BG95%E6%A0%B8%E5%BF%83%E6%9D%BF%E5%8E%9F%E7%90%86%E5%9B%BE.pdf)
+ - [Screen printing](https://developer.quectel.com/wp-content/uploads/2024/11/BG95%E6%A0%B8%E5%BF%83%E6%9D%BF%E4%B8%9D%E5%8D%B0.pdf)
+ - [User guidance](https://developer.quectel.com/doc/quecpython/Getting_started/zh/evb/ec200x-evb.html)
+
+## Development tool
+
+- QuecPython debug tool - QPYcom
+ - version:V3.6.0
+ - download [QPYcom](https://python.quectel.com/wp-content/uploads/2024/09/QPYcom_V3.6.0.zip)
+ - [User Guidance](https://developer.quectel.com/doc/quecpython/Application_guide/en/dev-tools/QPYcom/index.html)
+- Editor - VSCode
+ - download [VSCode](https://code.visualstudio.com/)
+
+## Firmware
+
+- version:QPY_OCPU_V0003_BG95M3_FW-V0003
+- download [Firmware](https://developer.quectel.com/wp-content/uploads/2024/09/QPY_OCPU_V0003_BG95M3_FW.zip)
+
+## Source code
+
+- Version: v2.0.1
+
+- The steps for downloading source code from the Github repository are as follows:
+
+ ```bash
+ git clone https://github.com/QuecPython/tracker-box
+ ```
\ No newline at end of file
diff --git a/docs/Application_guide/en/solutions/tracker_box(BG95M3)/quick_start.md b/docs/Application_guide/en/solutions/tracker_box(BG95M3)/quick_start.md
new file mode 100644
index 0000000000000000000000000000000000000000..151e5f0ac70e6f723c9fc137622f7591c4fddea0
--- /dev/null
+++ b/docs/Application_guide/en/solutions/tracker_box(BG95M3)/quick_start.md
@@ -0,0 +1,92 @@
+# Quick Start
+
+## Hardware preparation
+
+- A Windows computer, recommended for the 'Win10' system
+- A set of [BG95M3 QuecPython standard development board ](https://developer.quectel.com/doc/quecpython/Dev_board_guide/zh/bg95-evb.html)
+- A functional Nano SIM card
+
+## Environment construction
+
+- Download and install BG95M3 series module driver: [QuecPython_USB_Driver_Win10_U_G]( https://developer.quectel.com/wp-content/uploads/2024/09/Quectel_Windows_USB_DriverQ_NDIS_V2.7.14.zip)
+- Download and install [VSCode](https://code.visualstudio.com/ )
+- Download and unzip [QPYcom](https://python.quectel.com/wp-content/uploads/2024/09/QPYcom_V3.6.0.zip) Tool to the appropriate location on the computer
+- Use QPYcom to burn [firmware package](https://developer.quectel.com/wp-content/uploads/2024/09/QPY_OCPU_V0003_BG95M3_FW.zip )
+- Download [Experimental Source Code](https://github.com/QuecPython/tracker-box)
+
+## Set up your smart tracker
+
+Power on the smart tracker by following these steps:
+
+1. Before turning on the device, insert the nano SIM card (data service must be activated) into the SIM card slot. If the SIM card is inserted after the device is turned on, the device needs to be restarted.
+
+2. Turn on the device by any of the following methods:
+
+ Method 1: Press the power button on the side of the device.
+
+
+
+ Method 2: Connect the smart tracker to a laptop or power bank using the included USB-C cable, and the device will automatically turn on.
+
+
+
+## Connect to the Asset Management SaaS Platform
+
+The asset management SaaS platform developed by Acceleronix provides comprehensive solutions for specific industries. It covers the entire business process from TSL model function definition to SaaS platform management and mobile application device control.
+
+This asset management SaaS platform supports users in operating devices and can dynamically analyze hardware data based on the TSL model. It integrates multiple sensors such as water quality, temperature, humidity, light, and carbon dioxide to adapt to different scenarios. Functions include real-time data viewing, historical operation curves, data aggregation, as well as device maps and trajectory playback for location-based devices.
+
+### Device development
+
+### Power on
+
+After completing the hardware connection work, when PWR and SCK1 are lit up or a COM port containing the words "Quectel USB" appears in the port list of the computer's Device Manager, it indicates that the device has been successfully powered on.
+
+\USB.png)
+
+### Burn firmware package
+
+Refer to [this chapter](https://developer.quectel.com/doc/quecpython/Getting_started/zh/4G/flash_firmware.html) to flash the [firmware package](https://developer.quectel.com/wp-content/uploads/2024/09/QPY_OCPU_V0003_BG95M3_FW.zip ) to the development board.
+
+## Script import and run
+
+1.Refer to [this section](https://developer.quectel.com/doc/quecpython/Getting_started/zh/4G/first_python.html#PC与模组间的文件传输) to import all files in the code folder under the source code directory into the module file system according to the original directory structure, as shown in the figure below.
+
+\Qpycom.png)
+
+2.Refer to [this chapter ](https://developer.quectel.com/doc/quecpython/Getting_started/zh/4G/first_python.html#执行脚本文件)and execute the main program file _main.py.
+
+3.Refer to [this section](https://developer.quectel.com/doc/quecpython/Getting_started/zh/4G/first_python.html#停止程序运行) to stop the program.
+
+### Business debugging
+
+### Program launch
+
+ After executing the _main.py script, the program starts running and prints dialing information, including dialing status, IP Address, DNS server address, device number, etc.
+
+\860ce14a-e915-4207-9f29-36ac5b1a7a64.png)
+
+### Data detection
+
+After starting to run, startup information will be printed.
+
+\60eb6249-67ea-40d3-a59b-0612dbc9f308.png)
+
+### View device location (LBS)
+
+1. Click "Details" in the device list to open the device details page.
+2. Go to the Location tab to view LBS location data.
+
+\saas_location.png)
+
+**Note**: The location is updated every 30 minutes. If you need to manually refresh it, please click the refresh button in the application control panel, then reload the page to view the updated location.
+
+### View and manage sensor data
+
+1. When the device is online, click on the device in the Wonderfree app to enter the control panel.
+2. View the real-time sensor data and LBS location data of the smart tracker.
+3. If you need to update the sensor data or LBS location, click the refresh button in the upper right corner of the control panel.
+
+
+
+
\ No newline at end of file
diff --git a/docs/Application_guide/en/solutions/tracker_box(BG95M3)/software_design.md b/docs/Application_guide/en/solutions/tracker_box(BG95M3)/software_design.md
new file mode 100644
index 0000000000000000000000000000000000000000..e3f36b202eb023c030fdc0f07791f98036e3a89c
--- /dev/null
+++ b/docs/Application_guide/en/solutions/tracker_box(BG95M3)/software_design.md
@@ -0,0 +1,423 @@
+# Software Design
+
+## Introduction
+
+The Smart Tracker by Acceleronix lets you connect effortlessly to the Acceleronix Asset Management SaaS, enabling quick cloud service demos with zero setup hassle. This guide will walk you through using the Smart Tracker to explore platform features seamlessly.
+
+## Software framework
+
+### Software Design Diagram
+
+\f735bcd9b0c85d0aaad96173b315ca73.png)
+
+## Code Explanation
+
+### Wait for the network to be ready
+
+The wait_network_ready class in main.py calculates the maximum number of waiting times (WAIT_NETWORK_READY_S seconds divided by a 5-second interval). It returns True if the network is ready, and False if it times out.
+
+```python
+def wait_network_ready():
+ wait_cnt = WAIT_NETWORK_READY_S / 5
+ is_ready = False
+
+ while wait_cnt:
+ lte = dataCall.getInfo(1, 0)
+ if lte[2][0] == 1:
+ is_ready = True
+ break
+
+ utime.sleep(5)
+ wait_cnt -= 1
+
+ return is_ready
+```
+
+### Create an application instance
+
+The `create_app` function creates an application instance. Its main functions include: creating an Application object, setting the name and version, initializing application configuration, loading configuration files from specified paths, initializing various service modules (such as QTH Client, GNSS Service, Battery Service, etc.), and returning the configured application instance.
+
+```python
+def create_app(name="SimpliKit", version="1.0.0", config_path="/usr/config.json"):
+ _app = Application(name, version)
+ _app.config.init(config_path)
+
+ qth_client.init_app(_app)
+ #lbs_service.init_app(_app)
+ gnss_service.init_app(_app)
+ battery_service.init_app(_app)
+ #sensor_service.init_app(_app)
+
+ return _app
+```
+
+### GNSS
+
+This is a Python service module used to process GNSS (Global Navigation Satellite System) positioning data, mainly used for positioning and tracking of IoT devices.
+
+### NMEA Data Parsing Class - NmeaDict
+
+NMEA is the standard data format used by GPS devices:
+
+• The load() method: Parses raw NMEA data and performs CRC checks.
+
+• The checksum() method: Verifies the integrity of NMEA sentences.
+
+```python
+class NmeaDict(dict):
+
+ @classmethod
+ def load(cls, raw):
+ items = {}
+ for line in raw.split('\r\n'):
+ try:
+ tail_index = line.rfind('*')
+ if tail_index == -1:
+ continue
+ head_index = line.rfind('$', 0, tail_index)
+ if head_index == -1:
+ continue
+ crc = int(line[tail_index + 1:tail_index + 3], 16)
+ if cls.checksum(line[head_index + 1:tail_index]) != crc:
+ raise ValueError('CRC check failed')
+ cmdlist = line[head_index:tail_index].split(',')
+ # print(line[head_index:])
+ if cmdlist[0] not in items:
+ items[cmdlist[0]] = []
+ items[cmdlist[0]].append(line)
+ except Exception as e:
+ # logger.debug('parse nmea line error: {}; pass it: {}'.format(e, line))
+ continue
+ return cls(items)
+
+ @staticmethod
+ def checksum(data):
+ crc = ord(data[0])
+ for one in (ord(_) for _ in data[1:]):
+ crc ^= one
+ return crc
+```
+
+### Core Service Class - GnssService
+
+### Initialization and Configuration
+
+• Manage the initialization and state control of GNSS modules
+
+• Integrate with applications (init_app)
+
+• Set the positioning update interval (update_interval)
+
+```python
+class GnssService(object):
+
+ def __init__(self, app=None):
+ self.interval = 300
+ self.__gnss = quecgnss
+
+ if app is not None:
+ self.init_app(app)
+
+ def __str__(self):
+ return '{}'.format(type(self).__name__)
+ def init_app(self, app):
+ self.event = app.event
+ self.gnss_sleep_event = app.gnss_sleep_event
+ self.interval = app.config["SLEEP_INTERVAL_SECONDS"]
+ app.register('gnss_service', self)
+ def load(self):
+ logger.info('loading {} extension, init quecgnss will take some seconds'.format(self))
+ result = self.init()
+ logger.info('{} init gnss res: {}'.format(self, result))
+ if result:
+ Thread(target=self.start_update).start()
+
+ def init(self):
+ if self.__gnss.init() != 0:
+ logger.warn('{} gnss init FAILED'.format(self))
+ return False
+ return True
+ def status(self):
+ # 0 int GNSS模块处于关闭状态
+ # 1 int GNSS模块固件升级中
+ # 2 int GNSS模块定位中,这种模式下即可开始读取GNSS定位数据,定位数据是否有效需要用户获取到定位数据后,解析对应语句来判断,比如判断GNRMC语句的status是 A 还是 V,A 表示定位有效,V表示定位无效。
+ return self.__gnss.get_state()
+
+ def enable(self, flag=True):
+ return self.__gnss.gnssEnable(bool(flag)) == 0
+ def read(self, size=4096):
+ raw = self.__gnss.read(size)
+ if raw != -1:
+ size, data = raw
+ # KHK
+ #logger.debug('gnss read raw {} bytes data:\n{}'.format(size, data))
+ return NmeaDict.load(data)
+ def check_gnss_signal(self, nmea_dict):
+
+ snr_threshold = 15
+ min_sats = 3
+ has_3d_fix = False
+ if "$GNGSA" in nmea_dict:
+ for line in nmea_dict["$GNGSA"]:
+ parts = line.split(",")
+ if len(parts) > 2 and (parts[2] == "3" or parts[2] == "2"):
+ has_3d_fix = True
+ break
+ if not has_3d_fix:
+ return False
+
+ snrs = []
+
+ def extract_snrs(lines):
+ for line in lines:
+ parts = line.split(",")
+ i = 4
+ while i + 3 < len(parts):
+ snr_str = parts[i + 3]
+ if snr_str.isdigit():
+ snrs.append(int(snr_str))
+ i += 4
+ if "$GPGSV" in nmea_dict:
+ extract_snrs(nmea_dict["$GPGSV"])
+
+ if "$GBGSV" in nmea_dict:
+ extract_snrs(nmea_dict["$GBGSV"])
+
+ if "$GAGSV" in nmea_dict:
+ extract_snrs(nmea_dict["$GAGSV"])
+
+ # count satelites with SNR > 15
+ count = 0
+ for snr in snrs:
+ if snr > snr_threshold:
+ count += 1
+ if count >= min_sats:
+ return True
+ return False
+
+ def update_interval(self,interval):
+ self.interval = interval
+```
+
+### QTH Platform Client
+
+The `QthClient` class is a client class used for communicating with the QTH (Quantum Technology Hub) platform. It is responsible for initializing, starting, and managing the connection to the QTH platform, as well as handling various events and callbacks from the platform.
+
+```python
+logger = getLogger(__name__)
+
+
+class QthClient(object):
+
+ def __init__(self, app=None):
+ self.opt_lock = Lock()
+ if app:
+ self.init_app(app)
+ def __enter__(self):
+ self.opt_lock.acquire()
+ return self
+
+ def __exit__(self, *args, **kwargs):
+ self.opt_lock.release()
+
+ def init_app(self, app):
+ app.register("qth_client", self)
+ Qth.init()
+ Qth.setProductInfo(app.config["QTH_PRODUCT_KEY"], app.config["QTH_PRODUCT_SECRET"])
+ Qth.setServer(app.config["QTH_SERVER"])
+ Qth.setEventCb(
+ {
+ "devEvent": self.eventCallback,
+ "recvTrans": self.recvTransCallback,
+ "recvTsl": self.recvTslCallback,
+ "readTsl": self.readTslCallback,
+ "readTslServer": self.recvTslServerCallback,
+ "ota": {
+ "otaPlan":self.otaPlanCallback,
+ "fotaResult":self.fotaResultCallback
+ }
+ }
+ )
+
+def load(self):
+ self.start()
+
+ def start(self):
+ Qth.start()
+ while not self.isStatusOk():
+ utime.sleep(3)
+
+ def stop(self):
+ Qth.stop()
+
+ def sendTsl(self, mode, value):
+ return Qth.sendTsl(mode, value)
+
+ def isStatusOk(self):
+ return Qth.state()
+
+ def sendLbs(self, lbs_data):
+ return Qth.sendOutsideLocation(lbs_data)
+
+ def sendGnss(self, nmea_data):
+ return Qth.sendOutsideLocation(nmea_data)
+
+ def eventCallback(self, event, result):
+ logger.info("dev event:{} result:{}".format(event, result))
+ if(2== event and 0 == result):
+ Qth.otaRequest()
+def recvTransCallback(self, value):
+ ret =Qth.sendTrans(1, value)
+ logger.info("recvTrans value:{} ret:{}".format(value, ret))
+
+ def recvTslCallback(self, value):
+ logger.info("recvTsl:{}".format(value))
+ for cmdId, val in value.items():
+ logger.info("recvTsl {}:{}".format(cmdId, val))
+
+ if cmdId == 8:
+ CurrentApp().gnss_service.update_interval(val)
+ CurrentApp().lbs_service.update_interval(val)
+
+ def readTslCallback(self, ids, pkgId):
+ logger.info("readTsl ids:{} pkgId:{}".format(ids, pkgId))
+ value=dict()
+ temp1, humi =CurrentApp().sensor_service.get_temp1_and_humi()
+ press, temp2 = CurrentApp().sensor_service.get_press_and_temp2()
+ r,g,b = CurrentApp().sensor_service.get_rgb888()
+
+
+ for id in ids:
+ if 3 == id:
+ value[3]=temp1
+ elif 4 == id:
+ value[4]=humi
+ elif 5 == id:
+ value[5]=temp2
+ elif 6 == id:
+ value[6]=press
+ elif 7 == id:
+ value[7]={1:r, 2:g, 3:b}
+ Qth.ackTsl(1, value, pkgId)
+
+
+ def recvTslServerCallback(self, serverId, value, pkgId):
+ logger.info("recvTslServer serverId:{} value:{} pkgId:{}".format(serverId, value, pkgId))
+ Qth.ackTslServer(1, serverId, value, pkgId)
+def otaPlanCallback(self, plans):
+ logger.info("otaPlan:{}".format(plans))
+ Qth.otaAction(1)
+
+ def fotaResultCallback(self, comp_no, result):
+ logger.info("fotaResult comp_no:{} result:{}".format(comp_no, result))
+
+ def sotaInfoCallback(self, comp_no, version, url, md5, crc):
+ logger.info("sotaInfo comp_no:{} version:{} url:{} md5:{} crc:{}".format(comp_no, version, url, md5, crc))
+ # 当使用url下载固件完成,且MCU更新完毕后,需要获取MCU最新的版本信息,并通过setMcuVer进行更新
+ Qth.setMcuVer("MCU1", "V1.0.0", self.sotaInfoCallback, self.sotaResultCallback)
+
+ def sotaResultCallback(comp_no, result):
+ logger.info("sotaResult comp_no:{} result:{}".format(comp_no, result))
+```
+
+### Battery Service
+
+battery_service.init_app initializes the battery service module.
+
+```python
+logger = getLogger(__name__)
+
+BATTERY_OCV_TABLE = {
+ "nix_coy_mnzo2": {
+ 55: {
+ 4152: 100, 4083: 95, 4023: 90, 3967: 85, 3915: 80, 3864: 75, 3816: 70, 3773: 65, 3737: 60, 3685: 55,
+ 3656: 50, 3638: 45, 3625: 40, 3612: 35, 3596: 30, 3564: 25, 3534: 20, 3492: 15, 3457: 10, 3410: 5, 3380: 0,
+ },
+ 20: {
+ 4143: 100, 4079: 95, 4023: 90, 3972: 85, 3923: 80, 3876: 75, 3831: 70, 3790: 65, 3754: 60, 3720: 55,
+ 3680: 50, 3652: 45, 3634: 40, 3621: 35, 3608: 30, 3595: 25, 3579: 20, 3548: 15, 3511: 10, 3468: 5, 3430: 0,
+ },
+ 0: {
+ 4147: 100, 4089: 95, 4038: 90, 3990: 85, 3944: 80, 3899: 75, 3853: 70, 3811: 65, 3774: 60, 3741: 55,
+ 3708: 50, 3675: 45, 3651: 40, 3633: 35, 3620: 30, 3608: 25, 3597: 20, 3585: 15, 3571: 10, 3550: 5, 3500: 0,
+ },
+ },
+}
+class BatteryService(object):
+ def __init__(self, app=None):
+ self.interval = 30
+ self.__net = net
+ if app is not None:
+ self.init_app(app, battery_ocv="nix_coy_mnzo2")
+
+ def __str__(self):
+ return '{}'.format(type(self).__name__)
+
+ def init_app(self, app, battery_ocv="nix_coy_mnzo2"):
+ self.gnss_sleep_event = app.gnss_sleep_event
+ self.interval = app.config["SLEEP_INTERVAL_SECONDS"]
+ self.__energy = 100
+ self.__temp = 30
+ self.__vbatt_count = 100
+ if not BATTERY_OCV_TABLE.get(battery_ocv):
+ raise TypeError("Battery OCV %s is not support." % battery_ocv)
+ self.__battery_ocv = battery_ocv
+ app.register('battery_service', self)
+def load(self):
+ logger.info('loading {} extension, init battery will take some seconds'.format(self))
+ Thread(target=self.start_update).start()
+
+ def __get_soc_from_dict(self, key, volt_arg):
+ """Get battery energy from map"""
+ if BATTERY_OCV_TABLE[self.__battery_ocv].get(key):
+ volts = sorted(BATTERY_OCV_TABLE[self.__battery_ocv][key].keys(), reverse=True)
+ pre_volt = 0
+ volt_not_under = 0 # Determine whether the voltage is lower than the minimum voltage value of soc.
+ for volt in volts:
+ if volt_arg > volt:
+ volt_not_under = 1
+ soc1 = BATTERY_OCV_TABLE[self.__battery_ocv][key].get(volt, 0)
+ soc2 = BATTERY_OCV_TABLE[self.__battery_ocv][key].get(pre_volt, 0)
+ break
+ else:
+ pre_volt = volt
+ if pre_volt == 0: # Input Voltarg > Highest Voltarg
+ return soc1
+ elif volt_not_under == 0:
+ return 0
+ else:
+ return soc2 - (soc2 - soc1) * (pre_volt - volt_arg) // (pre_volt - volt)
+def __get_soc(self, temp, volt_arg):
+ """Get battery energy by temperature and voltage"""
+ if temp > 30:
+ return self.__get_soc_from_dict(55, volt_arg)
+ elif temp < 10:
+ return self.__get_soc_from_dict(0, volt_arg)
+ else:
+ return self.__get_soc_from_dict(20, volt_arg)
+
+ def __get_power_vbatt(self):
+ """Get vbatt from power"""
+ return int(sum([Power.getVbatt() for i in range(self.__vbatt_count)]) / self.__vbatt_count)
+def set_temp(self, temp):
+ """Set now temperature."""
+ if isinstance(temp, int) or isinstance(temp, float):
+ self.__temp = temp
+ return True
+ return False
+ def start_update(self):
+ while True:
+ if quecgnss.getPriority():
+ self.__energy = self.__get_soc(self.__temp, self.__get_power_vbatt())
+ data = {4: self.__energy}
+ if data:
+ with CurrentApp().qth_client:
+ for _ in range(3):
+ if CurrentApp().qth_client.sendTsl(1, data):
+ logger.debug("send battery data to qth server success")
+ break
+ #self.gnss_sleep_event.set() # Notify GNSS service to wake up
+ utime.sleep(self.interval)
+ else:
+ utime.sleep(0.1)
+```
\ No newline at end of file
diff --git a/docs/Application_guide/zh/README.md b/docs/Application_guide/zh/README.md
index eaf29976b0c61db2c154cd88d341b23b77a30d5c..ab2cbc7d15545b47521bc0f8bccc0a53dc8c4ee3 100644
--- a/docs/Application_guide/zh/README.md
+++ b/docs/Application_guide/zh/README.md
@@ -92,6 +92,7 @@ QuecPython 开发指南,是对QuecPython常用功能模块如何使用的指
- [可穿戴解决方案](solutions/Wear/readme.md)
- [电表](solutions/electricity-meter/README.md)
- [智能定位器](solutions/tracker/README.md)
+- [基于BG95M3的Smart Tracker解决方案](solutions/tracker_box(BG95M3)/README.md)
- [公网对讲机](solutions/poc/README.md)
diff --git a/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/3b5b2ebd-e154-459d-8992-1d4615834b8e.png b/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/3b5b2ebd-e154-459d-8992-1d4615834b8e.png
new file mode 100644
index 0000000000000000000000000000000000000000..0eeac776f428f7cf2e43d4c5d874e45e121655fa
Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/3b5b2ebd-e154-459d-8992-1d4615834b8e.png differ
diff --git a/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/60eb6249-67ea-40d3-a59b-0612dbc9f308.png b/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/60eb6249-67ea-40d3-a59b-0612dbc9f308.png
new file mode 100644
index 0000000000000000000000000000000000000000..1dc97ed9cb91109dfee0dd3359fd16b9153521be
Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/60eb6249-67ea-40d3-a59b-0612dbc9f308.png differ
diff --git a/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/860ce14a-e915-4207-9f29-36ac5b1a7a64.png b/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/860ce14a-e915-4207-9f29-36ac5b1a7a64.png
new file mode 100644
index 0000000000000000000000000000000000000000..c084009280e911c36d4c6f5644c13eb04323d7c5
Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/860ce14a-e915-4207-9f29-36ac5b1a7a64.png differ
diff --git a/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/Qpycom.png b/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/Qpycom.png
new file mode 100644
index 0000000000000000000000000000000000000000..4f6ab07b08ff44df9c62ce85ae8b6d529309739b
Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/Qpycom.png differ
diff --git a/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/USB.png b/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/USB.png
new file mode 100644
index 0000000000000000000000000000000000000000..575a02096cca25723bdc02123f4fe85bc7f352a8
Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/USB.png differ
diff --git a/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/add_device.png b/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/add_device.png
new file mode 100644
index 0000000000000000000000000000000000000000..85a199774230e6726fda6c60578e5767e0dde9e1
Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/add_device.png differ
diff --git a/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/bg95-m3-back.png b/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/bg95-m3-back.png
new file mode 100644
index 0000000000000000000000000000000000000000..91923ff379f400753ab484f371c360f3d847b872
Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/bg95-m3-back.png differ
diff --git a/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/bg95-m3.png b/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/bg95-m3.png
new file mode 100644
index 0000000000000000000000000000000000000000..f10f68194295775ac18fed29d4af41f847ddb196
Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/bg95-m3.png differ
diff --git a/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/bg95_clear.png b/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/bg95_clear.png
new file mode 100644
index 0000000000000000000000000000000000000000..4ee7b07e8263a1492530638bbf2437e86f2f3f22
Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/bg95_clear.png differ
diff --git a/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/box.jpg b/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/box.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..342f04693869f1cfe94e9454550a412eaa1988dc
Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/box.jpg differ
diff --git a/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/box.png b/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/box.png
new file mode 100644
index 0000000000000000000000000000000000000000..404ef07820124a596e7fe8c334116010491032bb
Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/box.png differ
diff --git a/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/device_control_panel.jpg b/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/device_control_panel.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..d7a9a4317794f7e8580f32e118f227ac7d0af651
Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/device_control_panel.jpg differ
diff --git a/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/device_qr_code.png b/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/device_qr_code.png
new file mode 100644
index 0000000000000000000000000000000000000000..8c0c815ec17cb0d4c97b01cf48bfcc6c436fe354
Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/device_qr_code.png differ
diff --git a/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/ebb64f59-a7ec-4742-b2f3-40d6e58a0bdf.png b/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/ebb64f59-a7ec-4742-b2f3-40d6e58a0bdf.png
new file mode 100644
index 0000000000000000000000000000000000000000..a4775f003e5b6b7ae0b8666bb412aa7cb5375588
Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/ebb64f59-a7ec-4742-b2f3-40d6e58a0bdf.png differ
diff --git a/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/f735bcd9b0c85d0aaad96173b315ca73.png b/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/f735bcd9b0c85d0aaad96173b315ca73.png
new file mode 100644
index 0000000000000000000000000000000000000000..cc9bf76734ff4e370391c3d8590b0ab8f80e1984
Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/f735bcd9b0c85d0aaad96173b315ca73.png differ
diff --git a/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/gnss_antenna.png b/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/gnss_antenna.png
new file mode 100644
index 0000000000000000000000000000000000000000..2de0a5c5f3cc788e7e13c7b241041c78eefeeb4b
Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/gnss_antenna.png differ
diff --git a/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/lte_antenna.png b/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/lte_antenna.png
new file mode 100644
index 0000000000000000000000000000000000000000..93c162d804cc63e652af347e676389f1c1ebbba8
Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/lte_antenna.png differ
diff --git a/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/power_button.PNG b/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/power_button.PNG
new file mode 100644
index 0000000000000000000000000000000000000000..6d3edf9428a32b3f44e25b7a6065cd54294a3a47
Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/power_button.PNG differ
diff --git a/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/raspberry_pi_sensor_hat_b_board.png b/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/raspberry_pi_sensor_hat_b_board.png
new file mode 100644
index 0000000000000000000000000000000000000000..9a5667c7435a898e3b22699066d7473681811354
Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/raspberry_pi_sensor_hat_b_board.png differ
diff --git a/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/saas_location.png b/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/saas_location.png
new file mode 100644
index 0000000000000000000000000000000000000000..d65c4712f7ccf3e7734df53c950afa15d8a84590
Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/saas_location.png differ
diff --git a/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/saas_login.png b/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/saas_login.png
new file mode 100644
index 0000000000000000000000000000000000000000..f6cefcaf569164ed4f11d9ce56806f29fb03db90
Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/saas_login.png differ
diff --git a/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/search_device_imei.png b/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/search_device_imei.png
new file mode 100644
index 0000000000000000000000000000000000000000..0c170ca8ffd1df38c7e29db8090a9e3f1a29b559
Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/search_device_imei.png differ
diff --git a/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/sensor.png b/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/sensor.png
new file mode 100644
index 0000000000000000000000000000000000000000..86608b7c993723d848b8a252001aabac330754c2
Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/sensor.png differ
diff --git a/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/usb-c_sim.jpg b/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/usb-c_sim.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..dd28eabadd315ca3f9b98a95a051d715c9e20b30
Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/usb-c_sim.jpg differ
diff --git a/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/wonderfree.png b/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/wonderfree.png
new file mode 100644
index 0000000000000000000000000000000000000000..22d335e319d40d96ce5cd28937cc49170575058b
Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/wonderfree.png differ
diff --git a/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/wonderfree0.png b/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/wonderfree0.png
new file mode 100644
index 0000000000000000000000000000000000000000..04f81ae01a6128c950c48debe2f148e47e23118b
Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/wonderfree0.png differ
diff --git a/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/wonderfree3.png b/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/wonderfree3.png
new file mode 100644
index 0000000000000000000000000000000000000000..d22cd8ad80c96f51be963c2e4b346f47c10be341
Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/wonderfree3.png differ
diff --git a/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/wonderfree4.png b/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/wonderfree4.png
new file mode 100644
index 0000000000000000000000000000000000000000..4b5125fed2d20735a3eb3ed8fa160a2b7879f46e
Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/wonderfree4.png differ
diff --git a/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/wonderfree5.png b/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/wonderfree5.png
new file mode 100644
index 0000000000000000000000000000000000000000..6453e8edbfd01604eb1dc6ab408699b39b8b6c27
Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/tracker_box(BG95M3)/wonderfree5.png differ
diff --git a/docs/Application_guide/zh/sidebar.yaml b/docs/Application_guide/zh/sidebar.yaml
index 9b2d2d19339ace5c1d983b9bbbdae2f88526a09a..5f42cb26310923ec9f99c8204dd8b40dcce4f243 100644
--- a/docs/Application_guide/zh/sidebar.yaml
+++ b/docs/Application_guide/zh/sidebar.yaml
@@ -349,6 +349,15 @@ items:
file: solutions/tracker/quick_start.md
- label: 软件设计讲解
file: solutions/tracker/software_design.md
+ label: 基于BG95M3的Smart Tracker解决方案
+ file: solutions/tracker_box(BG95M3)/README.md
+ items:
+ - label: 开发资源汇总
+ file: solutions/tracker_box(BG95M3)/dev_resources.md
+ - label: 快速上手
+ file: solutions/tracker_box(BG95M3)/quick_start.md
+ - label: 软件设计讲解
+ file: solutions/tracker_box(BG95M3)/software_design.md
- label: SensorHub
file: solutions/SensorHub/README.md
items:
diff --git a/docs/Application_guide/zh/solutions/README.md b/docs/Application_guide/zh/solutions/README.md
index afd35410caf6bc3e1f056dfaaac3e6b54087e87b..5942248712e4619de20d7025aceb2c611f7123fb 100644
--- a/docs/Application_guide/zh/solutions/README.md
+++ b/docs/Application_guide/zh/solutions/README.md
@@ -11,6 +11,7 @@
- [可穿戴解决方案](./Wear/readme.md)
- [电表解决方案](./electricity-meter/README.md)
- [智能定位器](./tracker/README.md)
+- [基于BG95M3的Smart Tracker解决方案](./tracker_box(BG95M3)/README.md)
- [SensorHub](./SensorHub/README.md)
- [基于 EG912U 核心版 DTU](./DTU-EG912U/README.md)
- [公网对讲机](./poc/README.md)
diff --git a/docs/Application_guide/zh/solutions/tracker_box(BG95M3)/README.md b/docs/Application_guide/zh/solutions/tracker_box(BG95M3)/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..dc3b78234d1a000bcd180d15f3e7b8734d14c703
--- /dev/null
+++ b/docs/Application_guide/zh/solutions/tracker_box(BG95M3)/README.md
@@ -0,0 +1,15 @@
+# 基于BG95M3的Smart Tracker解决方案
+
+该Acceleronix方案基于QuecPython **BG95-M3** 标准开发板实现,具有以下特性:
+
+- 提供准确的高精度GNSS定位。
+- 强大丰富的接口。
+- 使用python语言,便于二次开发
+
+
+
+------
+
+- [开发资源汇总](./dev_resources.md)
+- [快速上手](quick_start.md)
+- [软件设计讲解](./software_design.md)
\ No newline at end of file
diff --git a/docs/Application_guide/zh/solutions/tracker_box(BG95M3)/dev_resources.md b/docs/Application_guide/zh/solutions/tracker_box(BG95M3)/dev_resources.md
new file mode 100644
index 0000000000000000000000000000000000000000..2999937cba08fcc7cce29eff8c96fac91f291f87
--- /dev/null
+++ b/docs/Application_guide/zh/solutions/tracker_box(BG95M3)/dev_resources.md
@@ -0,0 +1,46 @@
+# 开发资源汇总
+
+## 开发板资料
+
+- 型号:[QuecPython BG95M3](https://developer.quectel.com/doc/quecpython/Dev_board_guide/zh/bg-eg-core-evb.html)
+- 购买链接:[点击购买](https://www.waveshare.com/bg95-m3-zero.htm)
+
+**·** 开发板文档
+
+ ° [规格书](https://developer.quectel.com/wp-content/uploads/2024/11/BG95%E6%A0%B8%E5%BF%83%E6%9D%BF%E4%BA%A7%E5%93%81%E8%A7%84%E6%A0%BC%E5%8F%8A%E7%94%A8%E6%88%B7%E6%8C%87%E5%AF%BC.pdf)
+
+ ° [原理图](https://developer.quectel.com/wp-content/uploads/2024/11/BG95%E6%A0%B8%E5%BF%83%E6%9D%BF%E5%8E%9F%E7%90%86%E5%9B%BE.pdf)
+
+ ° [丝印图](https://developer.quectel.com/wp-content/uploads/2024/11/BG95%E6%A0%B8%E5%BF%83%E6%9D%BF%E4%B8%9D%E5%8D%B0.pdf)
+
+ ° [资源介绍与使用指导](https://developer.quectel.com/doc/quecpython/Getting_started/zh/evb/ec200x-evb.html)
+
+
+
+## 开发工具
+
+- QPYcom - QuecPython 调试工具
+
+ - 版本:V3.6.0
+
+ - 下载 [QPYcom](https://python.quectel.com/wp-content/uploads/2024/09/QPYcom_V3.6.0.zip)
+
+- VSCode - 代码编辑器
+
+ - 下载 [VSCode](https://code.visualstudio.com/)
+
+## 固件包
+
+版本:QPY_OCPU_V0003_BG95M3_FW-V0003
+
+下载[资源下载](https://developer.quectel.com/wp-content/uploads/2024/09/QPY_OCPU_V0003_BG95M3_FW.zip)
+
+## 实验源码
+
+- 版本:v2.0.1
+
+- 从 Github 仓库获取源代码步骤如下:
+
+ ```shell
+ git clone https://github.com/QuecPython/tracker-box
+ ```
diff --git a/docs/Application_guide/zh/solutions/tracker_box(BG95M3)/quick_start.md b/docs/Application_guide/zh/solutions/tracker_box(BG95M3)/quick_start.md
new file mode 100644
index 0000000000000000000000000000000000000000..48d5437a1734e9e74e005fdc1596a92106fe55cd
--- /dev/null
+++ b/docs/Application_guide/zh/solutions/tracker_box(BG95M3)/quick_start.md
@@ -0,0 +1,96 @@
+# 快速上手
+
+## 硬件准备
+
+- Windows电脑一台,建议 `Win10` 系统。
+
+- 一套[BG95-M3 Quecpython 标准开发板](https://developer.quectel.com/doc/quecpython/Dev_board_guide/zh/bg95-evb.html)
+
+- 一张能够正常使用的SIM卡
+
+
+## 环境搭建
+
+- 下载并安装 BG95 系列模组驱动:[QuecPython_USB_Driver_Win10_ASR](https://developer.quectel.com/wp-content/uploads/2024/09/Quectel_Windows_USB_DriverQ_NDIS_V2.7.14.zip)。
+
+
+- 下载并安装 [VSCode](https://code.visualstudio.com/)。
+- 下载并解压 [QPYCom](https://images.quectel.com/python/2022/12/QPYcom_V3.6.0.zip) 工具到电脑的合适位置。
+- 下载[固件包](https://developer.quectel.com/wp-content/uploads/2024/09/QPY_OCPU_V0003_BG95M3_FW.zip )。
+- 下载[实验源码](https://github.com/QuecPython/tracker-box)
+
+## 设置您的智能追踪器
+
+按照以下步骤为智能追踪器供电:
+
+1. 开机前,将 nano SIM 卡(需开通数据服务)插入 SIM 卡槽。若开机后插入 SIM 卡,需重启设备。
+2. 通过以下任一方式开机:
+
+
+- 方式 1:按下设备侧面的电源按钮。
+
+
+
+
+
+- 方式 2:使用随附的 USB-C 线缆将智能追踪器连接至笔记本电脑或充电宝,设备将自动开机。
+
+3.开机后,智能追踪器将连接至蜂窝网络并链接到 Acceleronix 资产管理 SaaS 平台。
+
+## 连接至资产管理 SaaS 平台
+
+Acceleronix 开发的资产管理 SaaS 平台为特定行业提供全面解决方案。它涵盖从 TSL 模型功能定义到 SaaS 平台管理及移动应用设备控制的全业务流程。
+
+该资产管理 SaaS 平台支持用户对设备进行操作,可基于 TSL 模型对硬件数据进行动态分析。它集成了水质、温度、湿度、光线、二氧化碳等多种传感器,以适应不同场景。功能包括实时数据查看、历史运行曲线、数据聚合,以及基于位置设备的设备地图与轨迹回放。
+
+## 设备开发
+
+- ### 开机
+
+完成硬件连接工作后,当PWR,SCK1亮起或电脑设备管理器的端口列表出现包含Quectel USB字样的COM口,表示开机成功
+
+
+
+- ### 烧录固件包
+
+参考[此章节](https://developer.quectel.com/doc/quecpython/Getting_started/zh/4G/flash_firmware.html),烧录[固件包](https://developer.quectel.com/wp-content/uploads/2024/09/QPY_OCPU_V0003_BG95M3_FW.zip )至开发板。
+
+- ### 脚本导入与运行
+
+1.参考[此章节](https://developer.quectel.com/doc/quecpython/Getting_started/zh/4G/first_python.html#PC与模组间的文件传输),将源码目录下的code文件夹中的所有文件按原目录结构导入到模组文件系统中,如下图所示
+
+
+
+2.参考[此章节](https://developer.quectel.com/doc/quecpython/Getting_started/zh/4G/first_python.html#执行脚本文件),执行主程序文件_main.py
+
+3.参考[此章节](https://developer.quectel.com/doc/quecpython/Getting_started/zh/4G/first_python.html#停止程序运行),停止程序运行。
+
+## 业务调试
+
+### 程序启动
+
+执行_main.py脚本后,程序开始运行,会打印拨号信息,包括拨号状态、IP地址、DNS服务器地址,设备号等
+
+
+
+### 数据检测
+
+开始运行后会打印启动信息
+
+
+
+### 查看设备位置(LBS)
+
+1. 在设备列表中点击 **详情**,打开设备详情页。
+2. 进入 **位置** 标签页查看 LBS 位置数据。
+
+> **注意**:位置每 30 分钟更新一次。如需手动刷新,请点击应用控制面板中的刷新按钮,然后重新加载页面即可查看更新后的位置。
+
+### 查看和管理传感器数据
+
+1. 当设备在线时,在 Wonderfree 应用中点击设备进入控制面板。
+2. 查看智能追踪器的实时传感器数据和 LBS 位置数据。
+3. 如需更新传感器数据或 LBS 位置,点击控制面板右上角的刷新按钮
+4.
+
+
\ No newline at end of file
diff --git a/docs/Application_guide/zh/solutions/tracker_box(BG95M3)/software_design.md b/docs/Application_guide/zh/solutions/tracker_box(BG95M3)/software_design.md
new file mode 100644
index 0000000000000000000000000000000000000000..2727d521c32a8d005fdffb8438df514c343d54a5
--- /dev/null
+++ b/docs/Application_guide/zh/solutions/tracker_box(BG95M3)/software_design.md
@@ -0,0 +1,420 @@
+# 软件设计讲解
+
+## 软件框架
+
+### 软件设计图
+
+
+
+## 代码讲解
+
+### 等待网络就绪
+
+main.py的`wait_network_ready`类是计算最大等待次数(WAIT_NETWORK_READY_S秒除以5秒间隔。如果网络就绪则返回True,超时则返回False。
+
+```python
+def wait_network_ready():
+ wait_cnt = WAIT_NETWORK_READY_S / 5
+ is_ready = False
+
+ while wait_cnt:
+ lte = dataCall.getInfo(1, 0)
+ if lte[2][0] == 1:
+ is_ready = True
+ break
+
+ utime.sleep(5)
+ wait_cnt -= 1
+
+ return is_ready
+
+```
+
+### 创建应用实例
+
+create_app创建应用实例的函数。主要功能包括:创建Application应用对象,设置名称和版本初始化应用配置,加载指定路径的配置文件初始化各种服务模块(QTH客户端、GNSS服务、电池服务等),返回配置好的应用实例。
+
+```python
+def create_app(name="SimpliKit", version="1.0.0", config_path="/usr/config.json"):
+ _app = Application(name, version)
+ _app.config.init(config_path)
+
+ qth_client.init_app(_app)
+ #lbs_service.init_app(_app)
+ gnss_service.init_app(_app)
+ battery_service.init_app(_app)
+ #sensor_service.init_app(_app)
+
+ return _app
+```
+
+## GNSS
+
+这是一个用于处理GNSS(全球导航卫星系统)定位数据的Python服务模块,主要用于物联网设备的定位追踪。
+
+### NMEA数据解析类 - NmeaDict
+
+NMEA是GPS设备使用的标准数据格式:
+
+- load() 方法:解析原始NMEA数据,进行CRC校验
+- checksum()方法:验证NMEA语句的完整性
+
+```python
+class NmeaDict(dict):
+
+ @classmethod
+ def load(cls, raw):
+ items = {}
+ for line in raw.split('\r\n'):
+ try:
+ tail_index = line.rfind('*')
+ if tail_index == -1:
+ continue
+ head_index = line.rfind('$', 0, tail_index)
+ if head_index == -1:
+ continue
+ crc = int(line[tail_index + 1:tail_index + 3], 16)
+ if cls.checksum(line[head_index + 1:tail_index]) != crc:
+ raise ValueError('CRC check failed')
+ cmdlist = line[head_index:tail_index].split(',')
+ # print(line[head_index:])
+ if cmdlist[0] not in items:
+ items[cmdlist[0]] = []
+ items[cmdlist[0]].append(line)
+ except Exception as e:
+ # logger.debug('parse nmea line error: {}; pass it: {}'.format(e, line))
+ continue
+ return cls(items)
+
+ @staticmethod
+ def checksum(data):
+ crc = ord(data[0])
+ for one in (ord(_) for _ in data[1:]):
+ crc ^= one
+ return crc
+```
+### 核心服务类 - GnssService
+
+#### 初始化和配置
+
+- 管理GNSS模块的初始化和状态控制
+
+- 与应用程序集成 (init_app)
+
+- 设置定位更新间隔 (update_interval)
+
+ ```python
+ class GnssService(object):
+
+ def __init__(self, app=None):
+ self.interval = 300
+ self.__gnss = quecgnss
+
+ if app is not None:
+ self.init_app(app)
+
+ def __str__(self):
+ return '{}'.format(type(self).__name__)
+ def init_app(self, app):
+ self.event = app.event
+ self.gnss_sleep_event = app.gnss_sleep_event
+ self.interval = app.config["SLEEP_INTERVAL_SECONDS"]
+ app.register('gnss_service', self)
+ def load(self):
+ logger.info('loading {} extension, init quecgnss will take some seconds'.format(self))
+ result = self.init()
+ logger.info('{} init gnss res: {}'.format(self, result))
+ if result:
+ Thread(target=self.start_update).start()
+
+ def init(self):
+ if self.__gnss.init() != 0:
+ logger.warn('{} gnss init FAILED'.format(self))
+ return False
+ return True
+ def status(self):
+ # 0 int GNSS模块处于关闭状态
+ # 1 int GNSS模块固件升级中
+ # 2 int GNSS模块定位中,这种模式下即可开始读取GNSS定位数据,定位数据是否有效需要用户获取到定位数据后,解析对应语句来判断,比如判断GNRMC语句的status是 A 还是 V,A 表示定位有效,V表示定位无效。
+ return self.__gnss.get_state()
+
+ def enable(self, flag=True):
+ return self.__gnss.gnssEnable(bool(flag)) == 0
+ def read(self, size=4096):
+ raw = self.__gnss.read(size)
+ if raw != -1:
+ size, data = raw
+ # KHK
+ #logger.debug('gnss read raw {} bytes data:\n{}'.format(size, data))
+ return NmeaDict.load(data)
+ def check_gnss_signal(self, nmea_dict):
+
+ snr_threshold = 15
+ min_sats = 3
+ has_3d_fix = False
+ if "$GNGSA" in nmea_dict:
+ for line in nmea_dict["$GNGSA"]:
+ parts = line.split(",")
+ if len(parts) > 2 and (parts[2] == "3" or parts[2] == "2"):
+ has_3d_fix = True
+ break
+ if not has_3d_fix:
+ return False
+
+ snrs = []
+
+ def extract_snrs(lines):
+ for line in lines:
+ parts = line.split(",")
+ i = 4
+ while i + 3 < len(parts):
+ snr_str = parts[i + 3]
+ if snr_str.isdigit():
+ snrs.append(int(snr_str))
+ i += 4
+ if "$GPGSV" in nmea_dict:
+ extract_snrs(nmea_dict["$GPGSV"])
+
+ if "$GBGSV" in nmea_dict:
+ extract_snrs(nmea_dict["$GBGSV"])
+
+ if "$GAGSV" in nmea_dict:
+ extract_snrs(nmea_dict["$GAGSV"])
+
+ # count satelites with SNR > 15
+ count = 0
+ for snr in snrs:
+ if snr > snr_threshold:
+ count += 1
+ if count >= min_sats:
+ return True
+ return False
+
+ def update_interval(self,interval):
+ self.interval = interval
+ ```
+
+### QTH平台客户端
+
+`QthClient` 类是一个用于与 QTH(Quantum Technology Hub)平台进行通信的客户端类。它负责初始化、启动和管理与 QTH 平台的连接,并处理来自平台的各种事件和回调。
+
+```python
+logger = getLogger(__name__)
+
+
+class QthClient(object):
+
+ def __init__(self, app=None):
+ self.opt_lock = Lock()
+ if app:
+ self.init_app(app)
+ def __enter__(self):
+ self.opt_lock.acquire()
+ return self
+
+ def __exit__(self, *args, **kwargs):
+ self.opt_lock.release()
+
+ def init_app(self, app):
+ app.register("qth_client", self)
+ Qth.init()
+ Qth.setProductInfo(app.config["QTH_PRODUCT_KEY"], app.config["QTH_PRODUCT_SECRET"])
+ Qth.setServer(app.config["QTH_SERVER"])
+ Qth.setEventCb(
+ {
+ "devEvent": self.eventCallback,
+ "recvTrans": self.recvTransCallback,
+ "recvTsl": self.recvTslCallback,
+ "readTsl": self.readTslCallback,
+ "readTslServer": self.recvTslServerCallback,
+ "ota": {
+ "otaPlan":self.otaPlanCallback,
+ "fotaResult":self.fotaResultCallback
+ }
+ }
+ )
+
+def load(self):
+ self.start()
+
+ def start(self):
+ Qth.start()
+ while not self.isStatusOk():
+ utime.sleep(3)
+
+ def stop(self):
+ Qth.stop()
+
+ def sendTsl(self, mode, value):
+ return Qth.sendTsl(mode, value)
+
+ def isStatusOk(self):
+ return Qth.state()
+
+ def sendLbs(self, lbs_data):
+ return Qth.sendOutsideLocation(lbs_data)
+
+ def sendGnss(self, nmea_data):
+ return Qth.sendOutsideLocation(nmea_data)
+
+ def eventCallback(self, event, result):
+ logger.info("dev event:{} result:{}".format(event, result))
+ if(2== event and 0 == result):
+ Qth.otaRequest()
+def recvTransCallback(self, value):
+ ret =Qth.sendTrans(1, value)
+ logger.info("recvTrans value:{} ret:{}".format(value, ret))
+
+ def recvTslCallback(self, value):
+ logger.info("recvTsl:{}".format(value))
+ for cmdId, val in value.items():
+ logger.info("recvTsl {}:{}".format(cmdId, val))
+
+ if cmdId == 8:
+ CurrentApp().gnss_service.update_interval(val)
+ CurrentApp().lbs_service.update_interval(val)
+
+ def readTslCallback(self, ids, pkgId):
+ logger.info("readTsl ids:{} pkgId:{}".format(ids, pkgId))
+ value=dict()
+ temp1, humi =CurrentApp().sensor_service.get_temp1_and_humi()
+ press, temp2 = CurrentApp().sensor_service.get_press_and_temp2()
+ r,g,b = CurrentApp().sensor_service.get_rgb888()
+
+
+ for id in ids:
+ if 3 == id:
+ value[3]=temp1
+ elif 4 == id:
+ value[4]=humi
+ elif 5 == id:
+ value[5]=temp2
+ elif 6 == id:
+ value[6]=press
+ elif 7 == id:
+ value[7]={1:r, 2:g, 3:b}
+ Qth.ackTsl(1, value, pkgId)
+
+
+ def recvTslServerCallback(self, serverId, value, pkgId):
+ logger.info("recvTslServer serverId:{} value:{} pkgId:{}".format(serverId, value, pkgId))
+ Qth.ackTslServer(1, serverId, value, pkgId)
+def otaPlanCallback(self, plans):
+ logger.info("otaPlan:{}".format(plans))
+ Qth.otaAction(1)
+
+ def fotaResultCallback(self, comp_no, result):
+ logger.info("fotaResult comp_no:{} result:{}".format(comp_no, result))
+
+ def sotaInfoCallback(self, comp_no, version, url, md5, crc):
+ logger.info("sotaInfo comp_no:{} version:{} url:{} md5:{} crc:{}".format(comp_no, version, url, md5, crc))
+ # 当使用url下载固件完成,且MCU更新完毕后,需要获取MCU最新的版本信息,并通过setMcuVer进行更新
+ Qth.setMcuVer("MCU1", "V1.0.0", self.sotaInfoCallback, self.sotaResultCallback)
+
+ def sotaResultCallback(comp_no, result):
+ logger.info("sotaResult comp_no:{} result:{}".format(comp_no, result))
+
+```
+
+### 电池服务
+
+ battery_service.init_app初始化电池服务模块。
+
+```python
+logger = getLogger(__name__)
+
+BATTERY_OCV_TABLE = {
+ "nix_coy_mnzo2": {
+ 55: {
+ 4152: 100, 4083: 95, 4023: 90, 3967: 85, 3915: 80, 3864: 75, 3816: 70, 3773: 65, 3737: 60, 3685: 55,
+ 3656: 50, 3638: 45, 3625: 40, 3612: 35, 3596: 30, 3564: 25, 3534: 20, 3492: 15, 3457: 10, 3410: 5, 3380: 0,
+ },
+ 20: {
+ 4143: 100, 4079: 95, 4023: 90, 3972: 85, 3923: 80, 3876: 75, 3831: 70, 3790: 65, 3754: 60, 3720: 55,
+ 3680: 50, 3652: 45, 3634: 40, 3621: 35, 3608: 30, 3595: 25, 3579: 20, 3548: 15, 3511: 10, 3468: 5, 3430: 0,
+ },
+ 0: {
+ 4147: 100, 4089: 95, 4038: 90, 3990: 85, 3944: 80, 3899: 75, 3853: 70, 3811: 65, 3774: 60, 3741: 55,
+ 3708: 50, 3675: 45, 3651: 40, 3633: 35, 3620: 30, 3608: 25, 3597: 20, 3585: 15, 3571: 10, 3550: 5, 3500: 0,
+ },
+ },
+}
+class BatteryService(object):
+ def __init__(self, app=None):
+ self.interval = 30
+ self.__net = net
+ if app is not None:
+ self.init_app(app, battery_ocv="nix_coy_mnzo2")
+
+ def __str__(self):
+ return '{}'.format(type(self).__name__)
+
+ def init_app(self, app, battery_ocv="nix_coy_mnzo2"):
+ self.gnss_sleep_event = app.gnss_sleep_event
+ self.interval = app.config["SLEEP_INTERVAL_SECONDS"]
+ self.__energy = 100
+ self.__temp = 30
+ self.__vbatt_count = 100
+ if not BATTERY_OCV_TABLE.get(battery_ocv):
+ raise TypeError("Battery OCV %s is not support." % battery_ocv)
+ self.__battery_ocv = battery_ocv
+ app.register('battery_service', self)
+def load(self):
+ logger.info('loading {} extension, init battery will take some seconds'.format(self))
+ Thread(target=self.start_update).start()
+
+ def __get_soc_from_dict(self, key, volt_arg):
+ """Get battery energy from map"""
+ if BATTERY_OCV_TABLE[self.__battery_ocv].get(key):
+ volts = sorted(BATTERY_OCV_TABLE[self.__battery_ocv][key].keys(), reverse=True)
+ pre_volt = 0
+ volt_not_under = 0 # Determine whether the voltage is lower than the minimum voltage value of soc.
+ for volt in volts:
+ if volt_arg > volt:
+ volt_not_under = 1
+ soc1 = BATTERY_OCV_TABLE[self.__battery_ocv][key].get(volt, 0)
+ soc2 = BATTERY_OCV_TABLE[self.__battery_ocv][key].get(pre_volt, 0)
+ break
+ else:
+ pre_volt = volt
+ if pre_volt == 0: # Input Voltarg > Highest Voltarg
+ return soc1
+ elif volt_not_under == 0:
+ return 0
+ else:
+ return soc2 - (soc2 - soc1) * (pre_volt - volt_arg) // (pre_volt - volt)
+def __get_soc(self, temp, volt_arg):
+ """Get battery energy by temperature and voltage"""
+ if temp > 30:
+ return self.__get_soc_from_dict(55, volt_arg)
+ elif temp < 10:
+ return self.__get_soc_from_dict(0, volt_arg)
+ else:
+ return self.__get_soc_from_dict(20, volt_arg)
+
+ def __get_power_vbatt(self):
+ """Get vbatt from power"""
+ return int(sum([Power.getVbatt() for i in range(self.__vbatt_count)]) / self.__vbatt_count)
+def set_temp(self, temp):
+ """Set now temperature."""
+ if isinstance(temp, int) or isinstance(temp, float):
+ self.__temp = temp
+ return True
+ return False
+ def start_update(self):
+ while True:
+ if quecgnss.getPriority():
+ self.__energy = self.__get_soc(self.__temp, self.__get_power_vbatt())
+ data = {4: self.__energy}
+ if data:
+ with CurrentApp().qth_client:
+ for _ in range(3):
+ if CurrentApp().qth_client.sendTsl(1, data):
+ logger.debug("send battery data to qth server success")
+ break
+ #self.gnss_sleep_event.set() # Notify GNSS service to wake up
+ utime.sleep(self.interval)
+ else:
+ utime.sleep(0.1)
+```
+