diff --git a/docs/Application_guide/en/media/solutions/AIChatBot-Volcengine-webRTC/code_ai.png b/docs/Application_guide/en/media/solutions/AIChatBot-Volcengine-webRTC/code_ai.png
new file mode 100644
index 0000000000000000000000000000000000000000..97a524333a7faf16a1cb32fffa1c4cc2a949f8cf
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/AIChatBot-Volcengine-webRTC/code_ai.png differ
diff --git a/docs/Application_guide/en/media/solutions/AIChatBot-Volcengine-webRTC/code_ai_audio.png b/docs/Application_guide/en/media/solutions/AIChatBot-Volcengine-webRTC/code_ai_audio.png
new file mode 100644
index 0000000000000000000000000000000000000000..d382d867591bd7fb35e70baeb9af402187b98cd9
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/AIChatBot-Volcengine-webRTC/code_ai_audio.png differ
diff --git a/docs/Application_guide/en/media/solutions/AIChatBot-Volcengine-webRTC/code_ai_frame.png b/docs/Application_guide/en/media/solutions/AIChatBot-Volcengine-webRTC/code_ai_frame.png
new file mode 100644
index 0000000000000000000000000000000000000000..582eb33246df500434fd1d0c1da4c1894cec9982
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/AIChatBot-Volcengine-webRTC/code_ai_frame.png differ
diff --git a/docs/Application_guide/en/media/solutions/AIChatBot-Volcengine-webRTC/code_ai_process.png b/docs/Application_guide/en/media/solutions/AIChatBot-Volcengine-webRTC/code_ai_process.png
new file mode 100644
index 0000000000000000000000000000000000000000..4c3d37035829413693232a22f12e14f50ad53ea0
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/AIChatBot-Volcengine-webRTC/code_ai_process.png differ
diff --git a/docs/Application_guide/en/media/solutions/AIChatBot-Volcengine-webRTC/comport.png b/docs/Application_guide/en/media/solutions/AIChatBot-Volcengine-webRTC/comport.png
new file mode 100644
index 0000000000000000000000000000000000000000..270017b82e7cae2e731cfa8deb67bd6530ed6485
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/AIChatBot-Volcengine-webRTC/comport.png differ
diff --git a/docs/Application_guide/en/media/solutions/AIChatBot-Volcengine-webRTC/wire_connection.jpg b/docs/Application_guide/en/media/solutions/AIChatBot-Volcengine-webRTC/wire_connection.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..2b52b10530b01dd2b5c052eafb413ef409967ca4
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/AIChatBot-Volcengine-webRTC/wire_connection.jpg differ
diff --git a/docs/Application_guide/en/media/solutions/Agriculture-Control-Panel/Downloadfile.png b/docs/Application_guide/en/media/solutions/Agriculture-Control-Panel/Downloadfile.png
new file mode 100644
index 0000000000000000000000000000000000000000..c09d1a2d85666b9a04d09c17e4060ebf1d3ec199
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/Agriculture-Control-Panel/Downloadfile.png differ
diff --git a/docs/Application_guide/en/media/solutions/Agriculture-Control-Panel/UI_Alarm_Information_Bar.png b/docs/Application_guide/en/media/solutions/Agriculture-Control-Panel/UI_Alarm_Information_Bar.png
index 4ab8aa54c877549f330c784e5d4c61e0d105ca36..35861b0a7d26fc79354766cf80cd3f7c41ec0374 100644
Binary files a/docs/Application_guide/en/media/solutions/Agriculture-Control-Panel/UI_Alarm_Information_Bar.png and b/docs/Application_guide/en/media/solutions/Agriculture-Control-Panel/UI_Alarm_Information_Bar.png differ
diff --git a/docs/Application_guide/en/media/solutions/Agriculture-Control-Panel/UI_Detection_interface.png b/docs/Application_guide/en/media/solutions/Agriculture-Control-Panel/UI_Detection_interface.png
index 0621835d085a5d56cb76a5deec0c54e7e5789238..bad8572e6799d695c2570aa8ba330857aae97633 100644
Binary files a/docs/Application_guide/en/media/solutions/Agriculture-Control-Panel/UI_Detection_interface.png and b/docs/Application_guide/en/media/solutions/Agriculture-Control-Panel/UI_Detection_interface.png differ
diff --git a/docs/Application_guide/en/media/solutions/Agriculture-Control-Panel/UI_Device_Control_Interfacd.png b/docs/Application_guide/en/media/solutions/Agriculture-Control-Panel/UI_Device_Control_Interfacd.png
index e9801b8509e5a4e061b81815d605f78fc1440a97..7a8d6a8c163cb061f378071e05bc6a280be4807d 100644
Binary files a/docs/Application_guide/en/media/solutions/Agriculture-Control-Panel/UI_Device_Control_Interfacd.png and b/docs/Application_guide/en/media/solutions/Agriculture-Control-Panel/UI_Device_Control_Interfacd.png differ
diff --git a/docs/Application_guide/en/media/solutions/Agriculture-Control-Panel/UI_Device_Status_Interface.png b/docs/Application_guide/en/media/solutions/Agriculture-Control-Panel/UI_Device_Status_Interface.png
index fa04cb0426d3dded8b687c6ef47fc7c94cf4a856..fcfa476bf89d18b0437f13002d26a9b043727e50 100644
Binary files a/docs/Application_guide/en/media/solutions/Agriculture-Control-Panel/UI_Device_Status_Interface.png and b/docs/Application_guide/en/media/solutions/Agriculture-Control-Panel/UI_Device_Status_Interface.png differ
diff --git a/docs/Application_guide/en/media/solutions/Agriculture-Control-Panel/UI_History_Curve_Bar.png b/docs/Application_guide/en/media/solutions/Agriculture-Control-Panel/UI_History_Curve_Bar.png
index 19fbbc2827f0b3b2156aced748bff1358c616f1d..ac193b87a33406cb1fe1b21764f5c3aa46c62478 100644
Binary files a/docs/Application_guide/en/media/solutions/Agriculture-Control-Panel/UI_History_Curve_Bar.png and b/docs/Application_guide/en/media/solutions/Agriculture-Control-Panel/UI_History_Curve_Bar.png differ
diff --git a/docs/Application_guide/en/media/solutions/Agriculture-Control-Panel/UI_Information_Display_Bar.png b/docs/Application_guide/en/media/solutions/Agriculture-Control-Panel/UI_Information_Display_Bar.png
index 766e1bf25a59d5452d2f3864d06c805d6fda1a11..0ff8530bbc5e26d059a329499b0b594188b54d9c 100644
Binary files a/docs/Application_guide/en/media/solutions/Agriculture-Control-Panel/UI_Information_Display_Bar.png and b/docs/Application_guide/en/media/solutions/Agriculture-Control-Panel/UI_Information_Display_Bar.png differ
diff --git a/docs/Application_guide/en/media/solutions/Agriculture-Control-Panel/UI_Local _Settings_Interface.png b/docs/Application_guide/en/media/solutions/Agriculture-Control-Panel/UI_Local _Settings_Interface.png
index 4fe4ae5869c50742d916bf9509989891f3fe4aa7..f7eb2d4e1c95993e04f200a9fd9ce0262375f2ff 100644
Binary files a/docs/Application_guide/en/media/solutions/Agriculture-Control-Panel/UI_Local _Settings_Interface.png and b/docs/Application_guide/en/media/solutions/Agriculture-Control-Panel/UI_Local _Settings_Interface.png differ
diff --git a/docs/Application_guide/en/media/solutions/Agriculture-Control-Panel/UI_Main_interface.png b/docs/Application_guide/en/media/solutions/Agriculture-Control-Panel/UI_Main_interface.png
index dbf6ce87086ac261423cda1a3e38c2fa8c1a468f..1fa183628a867b9f5fedac55abfa4f1a9b5a0f88 100644
Binary files a/docs/Application_guide/en/media/solutions/Agriculture-Control-Panel/UI_Main_interface.png and b/docs/Application_guide/en/media/solutions/Agriculture-Control-Panel/UI_Main_interface.png differ
diff --git a/docs/Application_guide/en/media/solutions/Agriculture-Control-Panel/UI_Parameter_Display_Bar.png b/docs/Application_guide/en/media/solutions/Agriculture-Control-Panel/UI_Parameter_Display_Bar.png
index b05c214d60c1b4d33a56136fe34b8b8f7913f1ff..f1a9d4fdb89b56a8d608700598a7a2f209880fe9 100644
Binary files a/docs/Application_guide/en/media/solutions/Agriculture-Control-Panel/UI_Parameter_Display_Bar.png and b/docs/Application_guide/en/media/solutions/Agriculture-Control-Panel/UI_Parameter_Display_Bar.png differ
diff --git a/docs/Application_guide/en/media/solutions/Agriculture-Control-Panel/UI_Parameter_Setting_Interface.png b/docs/Application_guide/en/media/solutions/Agriculture-Control-Panel/UI_Parameter_Setting_Interface.png
index 820d357bc0b918dfeb41366bcd0d1f0351d74eea..0853a8350e1816a1854eb8a28de050c4cf0dfbeb 100644
Binary files a/docs/Application_guide/en/media/solutions/Agriculture-Control-Panel/UI_Parameter_Setting_Interface.png and b/docs/Application_guide/en/media/solutions/Agriculture-Control-Panel/UI_Parameter_Setting_Interface.png differ
diff --git a/docs/Application_guide/en/media/solutions/Agriculture-Control-Panel/UI_Shortcut_Bar.png b/docs/Application_guide/en/media/solutions/Agriculture-Control-Panel/UI_Shortcut_Bar.png
index bc49860d9d7b56622e9166b0d4824d6c88d8b42a..d5e35b9d0833e712f01a99956ed33955b0f1226e 100644
Binary files a/docs/Application_guide/en/media/solutions/Agriculture-Control-Panel/UI_Shortcut_Bar.png and b/docs/Application_guide/en/media/solutions/Agriculture-Control-Panel/UI_Shortcut_Bar.png differ
diff --git a/docs/Application_guide/en/media/solutions/Agriculture-Control-Panel/UI_Weather.png b/docs/Application_guide/en/media/solutions/Agriculture-Control-Panel/UI_Weather.png
new file mode 100644
index 0000000000000000000000000000000000000000..86013fc596cce3a4043e380e6f36ed6f9bf350d8
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/Agriculture-Control-Panel/UI_Weather.png differ
diff --git a/docs/Application_guide/en/media/solutions/Agriculture-Control-Panel/UI_Weather_Column.png b/docs/Application_guide/en/media/solutions/Agriculture-Control-Panel/UI_Weather_Column.png
index 00d193d61908a7e0f124490698e0c3525df26550..d81f4604dad869e9e509b9b8cd1645d57ee83d19 100644
Binary files a/docs/Application_guide/en/media/solutions/Agriculture-Control-Panel/UI_Weather_Column.png and b/docs/Application_guide/en/media/solutions/Agriculture-Control-Panel/UI_Weather_Column.png differ
diff --git a/docs/Application_guide/en/media/solutions/Agriculture-Control-Panel/UI_Welcomescreen.png b/docs/Application_guide/en/media/solutions/Agriculture-Control-Panel/UI_Welcomescreen.png
new file mode 100644
index 0000000000000000000000000000000000000000..ad8333fe556db0167eed9a1203a075d1113866ee
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/Agriculture-Control-Panel/UI_Welcomescreen.png differ
diff --git a/docs/Application_guide/en/media/solutions/Agriculture-Control-Panel/comport.png b/docs/Application_guide/en/media/solutions/Agriculture-Control-Panel/comport.png
new file mode 100644
index 0000000000000000000000000000000000000000..66728782024289081ab7266b74cbe612acaa0233
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/Agriculture-Control-Panel/comport.png differ
diff --git a/docs/Application_guide/en/media/solutions/Agriculture-Control-Panel/connection.png b/docs/Application_guide/en/media/solutions/Agriculture-Control-Panel/connection.png
new file mode 100644
index 0000000000000000000000000000000000000000..401825cf0f6f8336271375d1b47aacd0390a2b24
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/Agriculture-Control-Panel/connection.png differ
diff --git a/docs/Application_guide/en/media/solutions/Agriculture-Control-Panel/software.png b/docs/Application_guide/en/media/solutions/Agriculture-Control-Panel/software.png
new file mode 100644
index 0000000000000000000000000000000000000000..109eb429c64e49cf1a7e8abfad2ee9fd05dfc247
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/Agriculture-Control-Panel/software.png differ
diff --git a/docs/Application_guide/en/media/solutions/Agriculture-Control-Panel/start.png b/docs/Application_guide/en/media/solutions/Agriculture-Control-Panel/start.png
new file mode 100644
index 0000000000000000000000000000000000000000..0dbee652969dfdcd0dbfb3e9f0e818fafe5fb6a0
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/Agriculture-Control-Panel/start.png differ
diff --git "a/docs/Application_guide/en/media/solutions/DTU/4G\350\203\266\346\243\222\345\244\251\347\272\277.jpg" "b/docs/Application_guide/en/media/solutions/DTU/4G\350\203\266\346\243\222\345\244\251\347\272\277.jpg"
new file mode 100644
index 0000000000000000000000000000000000000000..66650e405222f9a0b82509fa5424ea2b672bcd7f
Binary files /dev/null and "b/docs/Application_guide/en/media/solutions/DTU/4G\350\203\266\346\243\222\345\244\251\347\272\277.jpg" differ
diff --git a/docs/Application_guide/en/media/solutions/DTU/DP-DTU-Q600.png b/docs/Application_guide/en/media/solutions/DTU/DP-DTU-Q600.png
index 32494a2818f0bc55f234214655ede74d955ed987..2a65bb7039e012e999057f27cb011b5866f42ca7 100644
Binary files a/docs/Application_guide/en/media/solutions/DTU/DP-DTU-Q600.png and b/docs/Application_guide/en/media/solutions/DTU/DP-DTU-Q600.png differ
diff --git "a/docs/Application_guide/en/media/solutions/DTU/DP-DTU-Q600\347\241\254\344\273\266\346\216\245\345\217\243\345\233\276\347\244\2722.png" "b/docs/Application_guide/en/media/solutions/DTU/DP-DTU-Q600\347\241\254\344\273\266\346\216\245\345\217\243\345\233\276\347\244\2722.png"
new file mode 100644
index 0000000000000000000000000000000000000000..d41e62c2bb1092503465545511c8fd38dd349829
Binary files /dev/null and "b/docs/Application_guide/en/media/solutions/DTU/DP-DTU-Q600\347\241\254\344\273\266\346\216\245\345\217\243\345\233\276\347\244\2722.png" differ
diff --git a/docs/Application_guide/en/media/solutions/DTU/DTU_BOARD_003.jpg b/docs/Application_guide/en/media/solutions/DTU/DTU_BOARD_003.jpg
index 01aae53e7f34477e6df5e3e9de667fc6aa7975ed..e588bf95747fa9357c99465a5b553c9d5a4ed8f3 100644
Binary files a/docs/Application_guide/en/media/solutions/DTU/DTU_BOARD_003.jpg and b/docs/Application_guide/en/media/solutions/DTU/DTU_BOARD_003.jpg differ
diff --git a/docs/Application_guide/en/media/solutions/DTU/DTU_wires_connection.png b/docs/Application_guide/en/media/solutions/DTU/DTU_wires_connection.png
new file mode 100644
index 0000000000000000000000000000000000000000..2a1a5497716fd2ed4ffc8f5a71a67e8a7f2f4652
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/DTU/DTU_wires_connection.png differ
diff --git "a/docs/Application_guide/en/media/solutions/DTU/DTU\345\272\224\347\224\250\351\242\206\345\237\237.jpg" "b/docs/Application_guide/en/media/solutions/DTU/DTU\345\272\224\347\224\250\351\242\206\345\237\237.jpg"
new file mode 100644
index 0000000000000000000000000000000000000000..6a089140e5a14c89b8aa6204396376da97849ef3
Binary files /dev/null and "b/docs/Application_guide/en/media/solutions/DTU/DTU\345\272\224\347\224\250\351\242\206\345\237\237.jpg" differ
diff --git "a/docs/Application_guide/en/media/solutions/DTU/DTU\347\273\204\344\273\266\345\233\276\347\244\2724.png" "b/docs/Application_guide/en/media/solutions/DTU/DTU\347\273\204\344\273\266\345\233\276\347\244\2724.png"
new file mode 100644
index 0000000000000000000000000000000000000000..bd8a07483c3e7862c43f95abce942fe546f330ef
Binary files /dev/null and "b/docs/Application_guide/en/media/solutions/DTU/DTU\347\273\204\344\273\266\345\233\276\347\244\2724.png" differ
diff --git a/docs/Application_guide/en/media/solutions/DTU/EC800GCN.png b/docs/Application_guide/en/media/solutions/DTU/EC800GCN.png
new file mode 100644
index 0000000000000000000000000000000000000000..6c57b10d315acb2eed67fe9c992f62b614763aec
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/DTU/EC800GCN.png differ
diff --git a/docs/Application_guide/en/media/solutions/DTU/HuaDTU.jpg b/docs/Application_guide/en/media/solutions/DTU/HuaDTU.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..59f79e566d9b94b02f722ead1cdaad1252a51e6b
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/DTU/HuaDTU.jpg differ
diff --git a/docs/Application_guide/en/media/solutions/DTU/UML.png b/docs/Application_guide/en/media/solutions/DTU/UML.png
new file mode 100644
index 0000000000000000000000000000000000000000..ad7cd0c464d62cde72d699ffbfcc0c7c7ada8c31
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/DTU/UML.png differ
diff --git a/docs/Application_guide/en/media/solutions/DTU/cloud_down.png b/docs/Application_guide/en/media/solutions/DTU/cloud_down.png
new file mode 100644
index 0000000000000000000000000000000000000000..0feebf83cab55858bcc9ec36b1954f283e8e66d8
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/DTU/cloud_down.png differ
diff --git a/docs/Application_guide/en/media/solutions/DTU/cloud_up.png b/docs/Application_guide/en/media/solutions/DTU/cloud_up.png
new file mode 100644
index 0000000000000000000000000000000000000000..6a93ab866a6e9148e17bce5541286d75a7729fda
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/DTU/cloud_up.png differ
diff --git a/docs/Application_guide/en/media/solutions/DTU/debug_log.png b/docs/Application_guide/en/media/solutions/DTU/debug_log.png
new file mode 100644
index 0000000000000000000000000000000000000000..f56e908927718dacf402095c07180bc33d70651c
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/DTU/debug_log.png differ
diff --git a/docs/Application_guide/en/media/solutions/DTU/debug_log_down_data.png b/docs/Application_guide/en/media/solutions/DTU/debug_log_down_data.png
new file mode 100644
index 0000000000000000000000000000000000000000..b020bdacebfc014c0b76610e9d7e1d712e196a33
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/DTU/debug_log_down_data.png differ
diff --git a/docs/Application_guide/en/media/solutions/DTU/debugview.png b/docs/Application_guide/en/media/solutions/DTU/debugview.png
new file mode 100644
index 0000000000000000000000000000000000000000..ceb61c02b8301368c4c8c8d36229797cc8f9248e
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/DTU/debugview.png differ
diff --git a/docs/Application_guide/en/media/solutions/DTU/download_scripts.png b/docs/Application_guide/en/media/solutions/DTU/download_scripts.png
new file mode 100644
index 0000000000000000000000000000000000000000..034704cb7628bc86bbeedc9b21aba6705b0ee163
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/DTU/download_scripts.png differ
diff --git a/docs/Application_guide/en/media/solutions/DTU/dtu_graph.png b/docs/Application_guide/en/media/solutions/DTU/dtu_graph.png
new file mode 100644
index 0000000000000000000000000000000000000000..e4a29ee2c7464a9dfd39a4d3e6afd85c556d9340
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/DTU/dtu_graph.png differ
diff --git a/docs/Application_guide/en/media/solutions/DTU/dupont.png b/docs/Application_guide/en/media/solutions/DTU/dupont.png
new file mode 100644
index 0000000000000000000000000000000000000000..d04543958240f2e29e82f2dcfca4a754a6cee8ac
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/DTU/dupont.png differ
diff --git a/docs/Application_guide/en/media/solutions/DTU/flowchart.png b/docs/Application_guide/en/media/solutions/DTU/flowchart.png
new file mode 100644
index 0000000000000000000000000000000000000000..00cb771a230a7035fc9ae1a4be30d955c092ba3a
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/DTU/flowchart.png differ
diff --git a/docs/Application_guide/en/media/solutions/DTU/gitbash.png b/docs/Application_guide/en/media/solutions/DTU/gitbash.png
new file mode 100644
index 0000000000000000000000000000000000000000..45d0f79ff5b0466097693d3bc91505f503a4a723
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/DTU/gitbash.png differ
diff --git a/docs/Application_guide/en/media/solutions/DTU/mini_usb.png b/docs/Application_guide/en/media/solutions/DTU/mini_usb.png
new file mode 100644
index 0000000000000000000000000000000000000000..ec4361fd79f4bdd719630867ca2a0df58016996d
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/DTU/mini_usb.png differ
diff --git a/docs/Application_guide/en/media/solutions/DTU/qcom_down.png b/docs/Application_guide/en/media/solutions/DTU/qcom_down.png
new file mode 100644
index 0000000000000000000000000000000000000000..e5e661ad34343b1496497e97630d0e7ca78eb4e4
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/DTU/qcom_down.png differ
diff --git a/docs/Application_guide/en/media/solutions/DTU/qcom_test.png b/docs/Application_guide/en/media/solutions/DTU/qcom_test.png
new file mode 100644
index 0000000000000000000000000000000000000000..69f9bc5177a6a1c31ad03be86802bb6e83802b43
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/DTU/qcom_test.png differ
diff --git a/docs/Application_guide/en/media/solutions/DTU/qpycom_select_port2.png b/docs/Application_guide/en/media/solutions/DTU/qpycom_select_port2.png
index 0fc246f5eaa4f1e3dbce3641750e6b624b75b2e8..69aff02827bc13c2c3744ad7c199de9e8e763631 100644
Binary files a/docs/Application_guide/en/media/solutions/DTU/qpycom_select_port2.png and b/docs/Application_guide/en/media/solutions/DTU/qpycom_select_port2.png differ
diff --git a/docs/Application_guide/en/media/solutions/DTU/repl_logs.png b/docs/Application_guide/en/media/solutions/DTU/repl_logs.png
new file mode 100644
index 0000000000000000000000000000000000000000..785382aef1fe3cea174d9108d1807edef2dbb84a
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/DTU/repl_logs.png differ
diff --git a/docs/Application_guide/en/media/solutions/DTU/run_scripts.png b/docs/Application_guide/en/media/solutions/DTU/run_scripts.png
new file mode 100644
index 0000000000000000000000000000000000000000..ccd49d4a8a6711bd0674297709cdfe733f2668da
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/DTU/run_scripts.png differ
diff --git a/docs/Application_guide/en/media/solutions/DTU/sim_card.png b/docs/Application_guide/en/media/solutions/DTU/sim_card.png
new file mode 100644
index 0000000000000000000000000000000000000000..4d49057b4f9179495c1c946403273af14d20e7db
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/DTU/sim_card.png differ
diff --git a/docs/Application_guide/en/media/solutions/DTU/usb_ttl.png b/docs/Application_guide/en/media/solutions/DTU/usb_ttl.png
new file mode 100644
index 0000000000000000000000000000000000000000..cc0e9fd13517673a255ca1b31a33dd975fdc46ea
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/DTU/usb_ttl.png differ
diff --git a/docs/Application_guide/en/media/solutions/SensorHub/1.png b/docs/Application_guide/en/media/solutions/SensorHub/1.png
new file mode 100644
index 0000000000000000000000000000000000000000..19576594120f54c40e624ccb3da652e96053822e
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/SensorHub/1.png differ
diff --git a/docs/Application_guide/en/media/solutions/SensorHub/EVB_link1.png b/docs/Application_guide/en/media/solutions/SensorHub/EVB_link1.png
new file mode 100644
index 0000000000000000000000000000000000000000..675da5455eda468dd72bd7266b813e2cb4968115
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/SensorHub/EVB_link1.png differ
diff --git a/docs/Application_guide/en/media/solutions/SensorHub/EVB_link2.png b/docs/Application_guide/en/media/solutions/SensorHub/EVB_link2.png
new file mode 100644
index 0000000000000000000000000000000000000000..08601ad8f98fd31ba0639ba332b037bbfbafdf32
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/SensorHub/EVB_link2.png differ
diff --git a/docs/Application_guide/en/media/solutions/SensorHub/Qpycom.png b/docs/Application_guide/en/media/solutions/SensorHub/Qpycom.png
new file mode 100644
index 0000000000000000000000000000000000000000..4f6ab07b08ff44df9c62ce85ae8b6d529309739b
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/SensorHub/Qpycom.png differ
diff --git a/docs/Application_guide/en/media/solutions/SensorHub/USB.png b/docs/Application_guide/en/media/solutions/SensorHub/USB.png
new file mode 100644
index 0000000000000000000000000000000000000000..575a02096cca25723bdc02123f4fe85bc7f352a8
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/SensorHub/USB.png differ
diff --git a/docs/Application_guide/en/media/solutions/SensorHub/app.png b/docs/Application_guide/en/media/solutions/SensorHub/app.png
new file mode 100644
index 0000000000000000000000000000000000000000..c0ef5a4073b4e8e80f694db614e027aa0d78d9a0
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/SensorHub/app.png differ
diff --git a/docs/Application_guide/en/media/solutions/SensorHub/app_ui.png b/docs/Application_guide/en/media/solutions/SensorHub/app_ui.png
new file mode 100644
index 0000000000000000000000000000000000000000..4f86efa6623e0732a7f06ee16db375e0072607a3
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/SensorHub/app_ui.png differ
diff --git a/docs/Application_guide/en/media/solutions/SensorHub/data.png b/docs/Application_guide/en/media/solutions/SensorHub/data.png
new file mode 100644
index 0000000000000000000000000000000000000000..21a2671d3ccd60a33d8c967f4bbda5803946c6bc
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/SensorHub/data.png differ
diff --git a/docs/Application_guide/en/media/solutions/SensorHub/data1.png b/docs/Application_guide/en/media/solutions/SensorHub/data1.png
new file mode 100644
index 0000000000000000000000000000000000000000..24ba2a95ca10c44cbfe054f9f6f6055547792543
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/SensorHub/data1.png differ
diff --git a/docs/Application_guide/en/media/solutions/SensorHub/data_get.png b/docs/Application_guide/en/media/solutions/SensorHub/data_get.png
new file mode 100644
index 0000000000000000000000000000000000000000..97a77a9d8cfc343c34b1d940071dbbc8cd115b66
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/SensorHub/data_get.png differ
diff --git a/docs/Application_guide/en/media/solutions/SensorHub/data_up.png b/docs/Application_guide/en/media/solutions/SensorHub/data_up.png
new file mode 100644
index 0000000000000000000000000000000000000000..e0b98d9a8c268afc6aafbeffd7cddfaf760913f3
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/SensorHub/data_up.png differ
diff --git a/docs/Application_guide/en/media/solutions/SensorHub/drivers_data.png b/docs/Application_guide/en/media/solutions/SensorHub/drivers_data.png
new file mode 100644
index 0000000000000000000000000000000000000000..2e396463456805792e430bd00875565353c333c9
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/SensorHub/drivers_data.png differ
diff --git a/docs/Application_guide/en/media/solutions/SensorHub/gnss.png b/docs/Application_guide/en/media/solutions/SensorHub/gnss.png
new file mode 100644
index 0000000000000000000000000000000000000000..e356ec1267cdd0a798169cb70cfbd74433d21f18
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/SensorHub/gnss.png differ
diff --git a/docs/Application_guide/en/media/solutions/SensorHub/service_model.png b/docs/Application_guide/en/media/solutions/SensorHub/service_model.png
new file mode 100644
index 0000000000000000000000000000000000000000..8dbe2784e9df725e742a3b48f711bb218ad87640
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/SensorHub/service_model.png differ
diff --git a/docs/Application_guide/en/media/solutions/SensorHub/sim_erro.png b/docs/Application_guide/en/media/solutions/SensorHub/sim_erro.png
new file mode 100644
index 0000000000000000000000000000000000000000..609d9a7ce0d98eabae38b1d70105923e61f9b7c1
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/SensorHub/sim_erro.png differ
diff --git a/docs/Application_guide/en/media/solutions/SensorHub/software1.png b/docs/Application_guide/en/media/solutions/SensorHub/software1.png
new file mode 100644
index 0000000000000000000000000000000000000000..a3e6e48899859fdc4e63339ae7e2d0fbaf14f8de
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/SensorHub/software1.png differ
diff --git a/docs/Application_guide/en/media/solutions/SensorHub/software2.png b/docs/Application_guide/en/media/solutions/SensorHub/software2.png
new file mode 100644
index 0000000000000000000000000000000000000000..5ceccb68d4dc2c94a06ec26599c5487569b4fef8
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/SensorHub/software2.png differ
diff --git a/docs/Application_guide/en/media/solutions/SensorHub/yun.png b/docs/Application_guide/en/media/solutions/SensorHub/yun.png
new file mode 100644
index 0000000000000000000000000000000000000000..78359c14e78e567f99d425ff79fbfb35878c9c93
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/SensorHub/yun.png differ
diff --git a/docs/Application_guide/en/media/solutions/Wear/Downloadfile.png b/docs/Application_guide/en/media/solutions/Wear/Downloadfile.png
new file mode 100644
index 0000000000000000000000000000000000000000..5e7502fd3d97e8b8b1865daabbb6379d9c825158
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/Wear/Downloadfile.png differ
diff --git a/docs/Application_guide/en/media/solutions/Wear/comport.png b/docs/Application_guide/en/media/solutions/Wear/comport.png
new file mode 100644
index 0000000000000000000000000000000000000000..66728782024289081ab7266b74cbe612acaa0233
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/Wear/comport.png differ
diff --git a/docs/Application_guide/en/media/solutions/Wear/connection.png b/docs/Application_guide/en/media/solutions/Wear/connection.png
new file mode 100644
index 0000000000000000000000000000000000000000..1b289053f405ed6361a3386fef850634485e20f0
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/Wear/connection.png differ
diff --git a/docs/Application_guide/en/media/solutions/electricity-meter/EG915U_EVB.png b/docs/Application_guide/en/media/solutions/electricity-meter/EG915U_EVB.png
new file mode 100644
index 0000000000000000000000000000000000000000..b5b94ac840b684df700142c5571ce9ebde743fdd
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/electricity-meter/EG915U_EVB.png differ
diff --git a/docs/Application_guide/en/media/solutions/electricity-meter/TCPandUART.png b/docs/Application_guide/en/media/solutions/electricity-meter/TCPandUART.png
new file mode 100644
index 0000000000000000000000000000000000000000..ce0ee5836427b45f630574e4f24b6efb0ea753d4
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/electricity-meter/TCPandUART.png differ
diff --git a/docs/Application_guide/en/media/solutions/electricity-meter/comport.png b/docs/Application_guide/en/media/solutions/electricity-meter/comport.png
new file mode 100644
index 0000000000000000000000000000000000000000..66728782024289081ab7266b74cbe612acaa0233
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/electricity-meter/comport.png differ
diff --git a/docs/Application_guide/en/media/solutions/electricity-meter/connection1.png b/docs/Application_guide/en/media/solutions/electricity-meter/connection1.png
new file mode 100644
index 0000000000000000000000000000000000000000..b3c37e3a2a03fef040885929683797a8ed47081d
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/electricity-meter/connection1.png differ
diff --git a/docs/Application_guide/en/media/solutions/electricity-meter/connection2.png b/docs/Application_guide/en/media/solutions/electricity-meter/connection2.png
new file mode 100644
index 0000000000000000000000000000000000000000..34990c3bcfa655715ec859d10afd9c9b068a665f
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/electricity-meter/connection2.png differ
diff --git a/docs/Application_guide/en/media/solutions/electricity-meter/downloadfile.png b/docs/Application_guide/en/media/solutions/electricity-meter/downloadfile.png
new file mode 100644
index 0000000000000000000000000000000000000000..363abe8d74c9eb689832b91ab32b7ed566868e97
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/electricity-meter/downloadfile.png differ
diff --git a/docs/Application_guide/en/media/solutions/electricity-meter/eletricity_to_tcp.png b/docs/Application_guide/en/media/solutions/electricity-meter/eletricity_to_tcp.png
new file mode 100644
index 0000000000000000000000000000000000000000..aa9db61c972066543749f37adde60b9fe1610ab6
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/electricity-meter/eletricity_to_tcp.png differ
diff --git a/docs/Application_guide/en/media/solutions/electricity-meter/module_rfc.png b/docs/Application_guide/en/media/solutions/electricity-meter/module_rfc.png
new file mode 100644
index 0000000000000000000000000000000000000000..43f4d1c43b67061a41e4b1a99166ec63ba70d105
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/electricity-meter/module_rfc.png differ
diff --git a/docs/Application_guide/en/media/solutions/electricity-meter/start.png b/docs/Application_guide/en/media/solutions/electricity-meter/start.png
new file mode 100644
index 0000000000000000000000000000000000000000..5711720a57f5e200b7b3ed60333c130718cf194a
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/electricity-meter/start.png differ
diff --git a/docs/Application_guide/en/media/solutions/electricity-meter/uart_recv.png b/docs/Application_guide/en/media/solutions/electricity-meter/uart_recv.png
new file mode 100644
index 0000000000000000000000000000000000000000..e77c13fa573d3675168b93c33de0caab305a3385
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/electricity-meter/uart_recv.png differ
diff --git a/docs/Application_guide/en/media/solutions/electricity-meter/uart_send.png b/docs/Application_guide/en/media/solutions/electricity-meter/uart_send.png
new file mode 100644
index 0000000000000000000000000000000000000000..49464ea9cf522b855d170e65fc5c58a4524938ab
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/electricity-meter/uart_send.png differ
diff --git a/docs/Application_guide/en/media/solutions/poc/Logging.png b/docs/Application_guide/en/media/solutions/poc/Logging.png
new file mode 100644
index 0000000000000000000000000000000000000000..a6a99a652c09fe7812adc3f66a9df1c0677b88f5
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/poc/Logging.png differ
diff --git a/docs/Application_guide/en/media/solutions/poc/MainScreen.png b/docs/Application_guide/en/media/solutions/poc/MainScreen.png
new file mode 100644
index 0000000000000000000000000000000000000000..94fcf10980f06853cf1b95a8e550c5ea8df1ba54
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/poc/MainScreen.png differ
diff --git a/docs/Application_guide/en/media/solutions/poc/bord.png b/docs/Application_guide/en/media/solutions/poc/bord.png
new file mode 100644
index 0000000000000000000000000000000000000000..a656e40d5b7d0fe3e279959c45cec925c5230f64
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/poc/bord.png differ
diff --git a/docs/Application_guide/en/media/solutions/poc/comport.png b/docs/Application_guide/en/media/solutions/poc/comport.png
new file mode 100644
index 0000000000000000000000000000000000000000..270017b82e7cae2e731cfa8deb67bd6530ed6485
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/poc/comport.png differ
diff --git a/docs/Application_guide/en/media/solutions/poc/files.png b/docs/Application_guide/en/media/solutions/poc/files.png
new file mode 100644
index 0000000000000000000000000000000000000000..a8a328c5a79dd8e476ff73b21f3e1238a176aee8
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/poc/files.png differ
diff --git a/docs/Application_guide/en/media/solutions/poc/get_imei.png b/docs/Application_guide/en/media/solutions/poc/get_imei.png
new file mode 100644
index 0000000000000000000000000000000000000000..26db7f5e97cc0b759cbe5eea95b4744d0b7b409c
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/poc/get_imei.png differ
diff --git a/docs/Application_guide/en/media/solutions/poc/group.png b/docs/Application_guide/en/media/solutions/poc/group.png
new file mode 100644
index 0000000000000000000000000000000000000000..46f8714bccd99e53af37d323b1c77665111c0ad9
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/poc/group.png differ
diff --git a/docs/Application_guide/en/media/solutions/poc/listen.png b/docs/Application_guide/en/media/solutions/poc/listen.png
new file mode 100644
index 0000000000000000000000000000000000000000..a5dd2c60b9fe5ae51eccedd4f1ac2108afe8df45
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/poc/listen.png differ
diff --git a/docs/Application_guide/en/media/solutions/poc/member.png b/docs/Application_guide/en/media/solutions/poc/member.png
new file mode 100644
index 0000000000000000000000000000000000000000..66d97359f43f759e5b63a9bd1ad62f97570db383
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/poc/member.png differ
diff --git a/docs/Application_guide/en/media/solutions/poc/no_sim_card.png b/docs/Application_guide/en/media/solutions/poc/no_sim_card.png
new file mode 100644
index 0000000000000000000000000000000000000000..5bed31217449da5468b76c41573cab4daa4fba45
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/poc/no_sim_card.png differ
diff --git a/docs/Application_guide/en/media/solutions/poc/services.png b/docs/Application_guide/en/media/solutions/poc/services.png
new file mode 100644
index 0000000000000000000000000000000000000000..ddb0a5a59cfd3adeef44dbf642ffe6454ee184e0
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/poc/services.png differ
diff --git a/docs/Application_guide/en/media/solutions/poc/software_design.png b/docs/Application_guide/en/media/solutions/poc/software_design.png
new file mode 100644
index 0000000000000000000000000000000000000000..51149392a2221d2d042215cee3efbf813461568f
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/poc/software_design.png differ
diff --git a/docs/Application_guide/en/media/solutions/poc/speak.png b/docs/Application_guide/en/media/solutions/poc/speak.png
new file mode 100644
index 0000000000000000000000000000000000000000..a656e40d5b7d0fe3e279959c45cec925c5230f64
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/poc/speak.png differ
diff --git a/docs/Application_guide/en/media/solutions/poc/start.png b/docs/Application_guide/en/media/solutions/poc/start.png
new file mode 100644
index 0000000000000000000000000000000000000000..39125f7dda5b5983084c6b1ab50b9e43510387ed
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/poc/start.png differ
diff --git a/docs/Application_guide/en/media/solutions/poc/ui_uml.png b/docs/Application_guide/en/media/solutions/poc/ui_uml.png
new file mode 100644
index 0000000000000000000000000000000000000000..68d018a603e89b5a41d6d6f02d2b2f7c5c919d9d
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/poc/ui_uml.png differ
diff --git a/docs/Application_guide/en/media/solutions/poc/wire_connection.png b/docs/Application_guide/en/media/solutions/poc/wire_connection.png
new file mode 100644
index 0000000000000000000000000000000000000000..741718128fc846f99c6196a2215da17092f002c5
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/poc/wire_connection.png differ
diff --git a/docs/Application_guide/en/media/solutions/tracker/after_ota.png b/docs/Application_guide/en/media/solutions/tracker/after_ota.png
new file mode 100644
index 0000000000000000000000000000000000000000..0971e55240dbc61c8cd38a6300f1acdde36c9dbf
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/tracker/after_ota.png differ
diff --git a/docs/Application_guide/en/media/solutions/tracker/aliyun_create_device.png b/docs/Application_guide/en/media/solutions/tracker/aliyun_create_device.png
new file mode 100644
index 0000000000000000000000000000000000000000..254620b218d5db68b65cef66db3d95467b600b68
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/tracker/aliyun_create_device.png differ
diff --git a/docs/Application_guide/en/media/solutions/tracker/aliyun_create_product.png b/docs/Application_guide/en/media/solutions/tracker/aliyun_create_product.png
new file mode 100644
index 0000000000000000000000000000000000000000..acc99a0e64b8f0ce7b33da07f0cb0b3b5b32621c
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/tracker/aliyun_create_product.png differ
diff --git a/docs/Application_guide/en/media/solutions/tracker/aliyun_export_lite_mode_object_model.png b/docs/Application_guide/en/media/solutions/tracker/aliyun_export_lite_mode_object_model.png
new file mode 100644
index 0000000000000000000000000000000000000000..073cd76edc588bfd814da0052be6eb1e606aeb96
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/tracker/aliyun_export_lite_mode_object_model.png differ
diff --git a/docs/Application_guide/en/media/solutions/tracker/aliyun_import_object_model.png b/docs/Application_guide/en/media/solutions/tracker/aliyun_import_object_model.png
new file mode 100644
index 0000000000000000000000000000000000000000..6123be724b45d3aef7fbebd8647cf465aafdd849
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/tracker/aliyun_import_object_model.png differ
diff --git a/docs/Application_guide/en/media/solutions/tracker/aliyun_mqtt_param.png b/docs/Application_guide/en/media/solutions/tracker/aliyun_mqtt_param.png
new file mode 100644
index 0000000000000000000000000000000000000000..9e1be0a22cac6b5283f60af107577954408e8e7e
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/tracker/aliyun_mqtt_param.png differ
diff --git a/docs/Application_guide/en/media/solutions/tracker/aliyun_online_send_message.png b/docs/Application_guide/en/media/solutions/tracker/aliyun_online_send_message.png
new file mode 100644
index 0000000000000000000000000000000000000000..8382eac354f1e739db594d001c82c4228aecbcfd
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/tracker/aliyun_online_send_message.png differ
diff --git a/docs/Application_guide/en/media/solutions/tracker/aliyun_ota_fota_module.png b/docs/Application_guide/en/media/solutions/tracker/aliyun_ota_fota_module.png
new file mode 100644
index 0000000000000000000000000000000000000000..3db28b17724abf60317c180846a51931eafb2f35
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/tracker/aliyun_ota_fota_module.png differ
diff --git a/docs/Application_guide/en/media/solutions/tracker/aliyun_ota_fota_plain.png b/docs/Application_guide/en/media/solutions/tracker/aliyun_ota_fota_plain.png
new file mode 100644
index 0000000000000000000000000000000000000000..fed62ed39efda028b150fbe2c556b235e08ca4be
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/tracker/aliyun_ota_fota_plain.png differ
diff --git a/docs/Application_guide/en/media/solutions/tracker/aliyun_ota_fota_plain_2.png b/docs/Application_guide/en/media/solutions/tracker/aliyun_ota_fota_plain_2.png
new file mode 100644
index 0000000000000000000000000000000000000000..875f7f83ff18c275ca6122120a1a3c7664d7d1c5
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/tracker/aliyun_ota_fota_plain_2.png differ
diff --git a/docs/Application_guide/en/media/solutions/tracker/aliyun_ota_fota_upgrade_package.png b/docs/Application_guide/en/media/solutions/tracker/aliyun_ota_fota_upgrade_package.png
new file mode 100644
index 0000000000000000000000000000000000000000..e04822b5b266ac82be012e76e863a5f5a866b0d9
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/tracker/aliyun_ota_fota_upgrade_package.png differ
diff --git a/docs/Application_guide/en/media/solutions/tracker/aliyun_ota_fota_upgrade_process.png b/docs/Application_guide/en/media/solutions/tracker/aliyun_ota_fota_upgrade_process.png
new file mode 100644
index 0000000000000000000000000000000000000000..dc14cc23d57f2b59f984c13e59e6242192eb8d7c
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/tracker/aliyun_ota_fota_upgrade_process.png differ
diff --git a/docs/Application_guide/en/media/solutions/tracker/aliyun_ota_sota_module.png b/docs/Application_guide/en/media/solutions/tracker/aliyun_ota_sota_module.png
new file mode 100644
index 0000000000000000000000000000000000000000..2237541f41600f0a6a75adc04141ae1280879b41
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/tracker/aliyun_ota_sota_module.png differ
diff --git a/docs/Application_guide/en/media/solutions/tracker/aliyun_ota_sota_plain.png b/docs/Application_guide/en/media/solutions/tracker/aliyun_ota_sota_plain.png
new file mode 100644
index 0000000000000000000000000000000000000000..3820e75154432405a0b91ef5f11453c307fe4456
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/tracker/aliyun_ota_sota_plain.png differ
diff --git a/docs/Application_guide/en/media/solutions/tracker/aliyun_ota_sota_upgrade_package.png b/docs/Application_guide/en/media/solutions/tracker/aliyun_ota_sota_upgrade_package.png
new file mode 100644
index 0000000000000000000000000000000000000000..e7090edc0770ca4ad47d8d90506f3324cd3d9f3c
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/tracker/aliyun_ota_sota_upgrade_package.png differ
diff --git a/docs/Application_guide/en/media/solutions/tracker/aliyun_ota_sota_upgrade_process.png b/docs/Application_guide/en/media/solutions/tracker/aliyun_ota_sota_upgrade_process.png
new file mode 100644
index 0000000000000000000000000000000000000000..431771964d72414dd67d73f0266e7e2807c0b85c
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/tracker/aliyun_ota_sota_upgrade_process.png differ
diff --git a/docs/Application_guide/en/media/solutions/tracker/aliyun_tracker_running_saas_view.png b/docs/Application_guide/en/media/solutions/tracker/aliyun_tracker_running_saas_view.png
new file mode 100644
index 0000000000000000000000000000000000000000..f3b81d75155ab2309e0203f9e43dd5b41f868cb8
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/tracker/aliyun_tracker_running_saas_view.png differ
diff --git a/docs/Application_guide/en/media/solutions/tracker/bord.png b/docs/Application_guide/en/media/solutions/tracker/bord.png
new file mode 100644
index 0000000000000000000000000000000000000000..c30c2bb9575f1f72b1fa25f12c737d1e6657ce74
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/tracker/bord.png differ
diff --git a/docs/Application_guide/en/media/solutions/tracker/code.png b/docs/Application_guide/en/media/solutions/tracker/code.png
new file mode 100644
index 0000000000000000000000000000000000000000..aaa4455ea14310ba72e2b72d0596c5e3db0c5867
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/tracker/code.png differ
diff --git a/docs/Application_guide/en/media/solutions/tracker/comport.png b/docs/Application_guide/en/media/solutions/tracker/comport.png
new file mode 100644
index 0000000000000000000000000000000000000000..ab550004d688a6a71ec28feec2804959275a2800
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/tracker/comport.png differ
diff --git a/docs/Application_guide/en/media/solutions/tracker/tracker_running.png b/docs/Application_guide/en/media/solutions/tracker/tracker_running.png
new file mode 100644
index 0000000000000000000000000000000000000000..113f36d657f15ca6359856a136d791b7daadef6e
Binary files /dev/null and b/docs/Application_guide/en/media/solutions/tracker/tracker_running.png differ
diff --git "a/docs/Application_guide/en/media/solutions/tracker/\350\277\236\347\272\277.png" "b/docs/Application_guide/en/media/solutions/tracker/\350\277\236\347\272\277.png"
new file mode 100644
index 0000000000000000000000000000000000000000..d41ac896f92c7033834f4bbd695ffbb8d69d44a2
Binary files /dev/null and "b/docs/Application_guide/en/media/solutions/tracker/\350\277\236\347\272\277.png" differ
diff --git a/docs/Application_guide/en/sidebar.yaml b/docs/Application_guide/en/sidebar.yaml
index 98072dc5ed0016686d78eb6278e2389e71c92544..e63c10b3b6628d89f3e88ecbee050a8b88e07a74 100644
--- a/docs/Application_guide/en/sidebar.yaml
+++ b/docs/Application_guide/en/sidebar.yaml
@@ -262,10 +262,69 @@ items:
- label: Product Solution
file: solutions/README.md
items:
+ - label: Doubao RTC AI chatbot
+ file: solutions/AIChatBot-Volcengine-webRTC/README.md
+ items:
+ - label: development resources
+ file: solutions/AIChatBot-Volcengine-webRTC/dev_resources.md
+ - label: quick start
+ file: solutions/AIChatBot-Volcengine-webRTC/quick_start.md
+ - label: software design
+ file: solutions/AIChatBot-Volcengine-webRTC/software_design.md
+ - label: EP-D200 Hua Series DTU
+ file: solutions/DTU/README.md
+ items:
+ - label: development resources
+ file: solutions/DTU/dev_resources.md
+ - label: quick start
+ file: solutions/DTU/quick_start.md
+ items:
+ - label: TCP development
+ file: solutions/DTU/tcp_demo.md
+ - label: MQTT development
+ file: solutions/DTU/mqtt_demo.md
+ - label: software design
+ file: solutions/DTU/software_design.md
+ - label: Smart Agriculture Central Control Panel
+ file: solutions/Agriculture-Control-Panel/README.md
+ items:
+ - label: development resources
+ file: solutions/Agriculture-Control-Panel/dev_resources.md
+ - label: quick start
+ file: solutions/Agriculture-Control-Panel/quick_start.md
+ - label: software design
+ file: solutions/Agriculture-Control-Panel/software_design.md
+ - label: Wearable Solution
+ file: solutions/Wear/readme.md
+ items:
+ - label: development resources
+ file: solutions/Wear/dev_resources.md
+ - label: quick start
+ file: solutions/Wear/quick_start.md
+ - label: software design
+ file: solutions/Wear/software_design.md
+ - label: Electricity Meter
+ file: solutions/electricity-meter/README.md
+ items:
+ - label: development resources
+ file: solutions/electricity-meter/dev_resources.md
+ - label: quick start
+ file: solutions/electricity-meter/quick_start.md
+ - label: software design
+ file: solutions/electricity-meter/software_design.md
+ label: SensorHub
+ file: solutions/SensorHub/README.md
+ items:
+ - label: development resources
+ file: solutions/SensorHub/dev_resources.md
+ - label: quick start
+ file: solutions/SensorHub/quick_start.md
+ - label: software design
+ file: solutions/SensorHub/software_design.md
- label: DTU based on EG912U Solution
file: solutions/DTU-EG912U/README.md
items:
- - label: Development resources summary
+ - label: development resources
file: solutions/DTU-EG912U/dev_resources.md
- label: quick start
file: solutions/DTU-EG912U/quick_start.md
@@ -276,16 +335,24 @@ items:
file: solutions/DTU-EG912U/mqtt_demo.md
- label: software design
file: solutions/DTU-EG912U/software_design.md
- - label: DTU Solution
- file: solutions/DTU/README.md
- - label: Smart Agriculture Central Control Panel
- file: solutions/Agriculture-Control-Panel/README.md
- - label: Wearable Solution
- file: solutions/Wear/readme.md
- - label: Electricity Meter
- file: solutions/electricity-meter/README.md
- label: Tracker Solution
file: solutions/tracker/README.md
+ items:
+ - label: development resources
+ file: solutions/tracker/dev_resources.md
+ - label: quick start
+ file: solutions/tracker/quick_start.md
+ - label: software design
+ file: solutions/tracker/software_design.md
+ - label: Poc
+ file: solutions/poc/README.md
+ items:
+ - label: development resources
+ file: solutions/poc/dev_resources.md
+ - label: quick start
+ file: solutions/poc/quick_start.md
+ - label: software design
+ file: solutions/poc/software_design.md
- label: HeliosSDK
file: helios-sdk/README.md
items:
diff --git a/docs/Application_guide/en/solutions/AIChatBot-Volcengine-webRTC/README.md b/docs/Application_guide/en/solutions/AIChatBot-Volcengine-webRTC/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..0cb35eacc7813208a8f9605c631fd016d71311d9
--- /dev/null
+++ b/docs/Application_guide/en/solutions/AIChatBot-Volcengine-webRTC/README.md
@@ -0,0 +1,21 @@
+# Doubao RTC AI chatbot
+
+This AI chatbot solution is developed based on the Doubao Volcano RTC engine and has the following characteristics:
+
+- Support intelligent agent switching
+- Support tone switching
+- Support ASR subtitles
+- Support TTS subtitles
+- Support voice interruption/interruption
+- Support server address switching
+- Support voice wake-up
+- Using Python language for easy secondary development
+
+
+
+---
+
+- [development_resources](./dev_resources.md)
+- [quick start](./quick_start.md)
+- [software design](./software_design.md)
+
diff --git a/docs/Application_guide/en/solutions/AIChatBot-Volcengine-webRTC/dev_resources.md b/docs/Application_guide/en/solutions/AIChatBot-Volcengine-webRTC/dev_resources.md
new file mode 100644
index 0000000000000000000000000000000000000000..e1274864a942e4dee3ead2bc3343b8a4bcd95dd0
--- /dev/null
+++ b/docs/Application_guide/en/solutions/AIChatBot-Volcengine-webRTC/dev_resources.md
@@ -0,0 +1,36 @@
+# Development resources summary
+
+## Development board
+
+ - EC800MCNTE/EC800MCNGB QuecDuino development board (including antenna, Type-C data cable, etc.)
+ - [Click here to purchase the development board kit](https://www.quecmall.com/goods-detail/2c90800c94028da20194824724370127)
+ - Windows PC(Windows 7、Windows 10 or Windows 11)
+ - speaker
+ - Any 2-5W power speaker is sufficient
+ - [Mall Purchase Link](https://www.quecmall.com/goods-detail/2c90800c94028da201948249e9f4012d)
+
+## Software documentation
+
+ - QuecPython USB Driver:[QuecPython_USB_Driver_Win10_ASR](https://images.quectel.com/python/2023/04/Quectel_Windows_USB_DriverA_Customer_V1.1.13.zip)
+ - QuecPython Firmware
+ - [EC800MCNLE](https://github.com/QuecPython/AIChatBot-Volcengine-webRTC/releases/download/v1.0.1/EC800MCNLER06A08M08_OCPU_QPY_TEST0219.zip)
+ - [EC800MCNGB](https://github.com/QuecPython/AIChatBot-Volcengine-webRTC/releases/download/v1.0.1/EC800MCNGBR06A01M08_OCPU_QPY_TEST0303.zip)
+
+## Development tools
+
+- QPYcom - QuecPython debug tool
+ - version: V3.6.0
+ - Download: [QPYcom](https://python.quectel.com/wp-content/uploads/2024/09/QPYcom_V3.6.0.zip)
+- VSCode
+ - Download: [VSCode](https://code.visualstudio.com/)
+
+## Source Code
+
+- branch:ec800m-quecduino
+- github repo:[AIChatBot-Volcengine-webRTC](https://github.com/QuecPython/AIChatBot-Volcengine-webRTC/tree/ec800m-quecduino)
+ ```bash
+ git clone https://github.com/QuecPython/AIChatBot-Volcengine-webRTC.git
+ cd AIChatBot-Volcengine-webRTC
+ git checkout ec800m-quecduino
+ ```
+- [Github Download](https://codeload.github.com/QuecPython/AIChatBot-Volcengine-webRTC/zip/refs/heads/ec800m-quecduino)
\ No newline at end of file
diff --git a/docs/Application_guide/en/solutions/AIChatBot-Volcengine-webRTC/quick_start.md b/docs/Application_guide/en/solutions/AIChatBot-Volcengine-webRTC/quick_start.md
new file mode 100644
index 0000000000000000000000000000000000000000..768ddd98d51cf940b0a8775334a613b7c0db65e2
--- /dev/null
+++ b/docs/Application_guide/en/solutions/AIChatBot-Volcengine-webRTC/quick_start.md
@@ -0,0 +1,107 @@
+# Quick Start
+
+## Hardware preparation
+
+- A Windows computer, recommended for the Win10 system.
+- a set [EC800MCNLE / EC800MCNGB QuecDuino EVB](https://www.quecmall.com/goods-detail/2c90800c94028da20194824724370127) (Including antenna, Type-C data cable, etc).
+
+- A Nano SIM card.
+- A speaker with a power of 2-5W.
+
+## Environment construction
+
+- Download and install EC800M series module driver: [QuecPython_USB_Driver_Win10_ASR](https://images.quectel.com/python/2023/04/Quectel_Windows_USB_DriverA_Customer_V1.1.13.zip).
+
+- Download and install [VSCode](https://code.visualstudio.com/).
+
+- Download and unzip [QPYCom](https://images.quectel.com/python/2022/12/QPYcom_V3.6.0.zip)。
+
+- Download Firmware
+ - [EC800MCNLE](https://github.com/QuecPython/AIChatBot-Volcengine-webRTC/releases/download/v1.0.1/EC800MCNLER06A08M08_OCPU_QPY_TEST0219.zip)
+ - [EC800MCNGB](https://github.com/QuecPython/AIChatBot-Volcengine-webRTC/releases/download/v1.0.1/EC800MCNGBR06A01M08_OCPU_QPY_TEST0303.zip)
+
+- Download [Source code](https://codeload.github.com/QuecPython/AIChatBot-Volcengine-webRTC/zip/refs/heads/ec800m-quecduino)。
+
+ > 💡 **Tips**
+ > - The volcano dialogue token in the firmware is temporarily being tested and may be cancelled at any time. If you encounter difficulties in joining the room conversation, please contact the remote Fae personnel for support.
+ > - Please follow the business process for commercial applications.
+
+## Hardware connection
+
+Connect the hardware according to the following diagram:
+
+
+
+1. Connect the horn to the pins labeled 'SPK+' and 'SPK -' in the diagram.
+2. Insert an available Nano SIM card into the position shown in the diagram.
+3. Connect the antenna to the antenna connector marked with the word 'LTE'.
+4. Connect the development board and computer using a Type-C data cable.
+
+## Equipment development
+
+### Power on
+
+After completing the hardware connection work, long press the button labeled 'PWK' on the development board until the network light flashes or a COM port containing the words' Quectel USB 'appears in the port list of the computer device manager, indicating successful boot.
+
+
+
+### Burn firmware package
+
+Refer to [this chapter]( https://python.quectel.com/doc/Application_guide/en/dev-tools/QPYcom/qpycom-dw.html#%E4%B8%8B%E8%BD%BD%E5%9B%BA%E4%BB%B6 )Burn the corresponding firmware package to the development board.
+
+### Script import and execution
+
+1. Refer to [this chapter]( https://python.quectel.com/doc/Getting_started/en/first_python.html#PC%E4%B8%8E%E6%A8%A1%E7%BB%84%E9%97%B4%E7%9A%84%E6%96%87%E4%BB%B6%E4%BC%A0%E8%BE%93 )Import all files from the 'code' folder in the source code directory into the module file system, as shown in the following figure:
+
+
+
+
+2. Refer to [this chapter]( https://python.quectel.com/doc/Getting_started/en/first_python.html#%E6%89%A7%E8%A1%8C%E8%84%9A%E6%9C%AC%E6%96%87%E4%BB%B6 )Execute the main program file 'ai_main. py'.
+3. Refer to [this chapter]( https://python.quectel.com/doc/Getting_started/en/first_python.html#%E5%81%9C%E6%AD%A2%E7%A8%8B%E5%BA%8F%E8%BF%90%E8%A1%8C )Stop the program from running.
+
+## Debugging
+
+### Program startup
+
+After executing the 'ai_main. py' script, the program starts running.
+
+### Get into the room
+
+Press the KEY S3 key to enter the room. Upon receiving the TIKTOK_STC_SVENT-START event, it indicates successful entry into the room and begins a voice conversation.
+
+### Exit the room
+
+Press the KEY S2 key to exit the room, and receiving the TIKTOK_STC_SVENT-STOP event indicates that the exit from the room is successful.
+
+**Reference operation log:**
+
+```python
+import example
+>>> example.exec('/usr/ai_main.py')
+volume: 11
+>>> lte network normal
+ai task running
+
+# push down KEY S3 enter
+rtc_queue key event 1
+start rtc
+TIKTOK_RTC_EVENT_START
+TIKTOK_RTC_EVENT_TTS_TEXT 你
+TIKTOK_RTC_EVENT_TTS_TEXT 你好
+TIKTOK_RTC_EVENT_TTS_TEXT 你好有
+TIKTOK_RTC_EVENT_TTS_TEXT 你好有什
+TIKTOK_RTC_EVENT_TTS_TEXT 你好有什么
+TIKTOK_RTC_EVENT_TTS_TEXT 你好有什么可
+TIKTOK_RTC_EVENT_TTS_TEXT 你好有什么可以
+TIKTOK_RTC_EVENT_TTS_TEXT 你好有什么可以帮
+TIKTOK_RTC_EVENT_TTS_TEXT 你好有什么可以帮到
+TIKTOK_RTC_EVENT_TTS_TEXT 你好有什么可以帮到你
+TIKTOK_RTC_EVENT_TTS_TEXT 你好有什么可以帮到你的
+TIKTOK_RTC_EVENT_TTS_TEXT 你好有什么可以帮到你的吗
+
+# push down KEY S2 to exit
+rtc_queue key event 2
+stop rtc
+TIKTOK_RTC_EVENT_STOP
+```
+
diff --git a/docs/Application_guide/en/solutions/AIChatBot-Volcengine-webRTC/software_design.md b/docs/Application_guide/en/solutions/AIChatBot-Volcengine-webRTC/software_design.md
new file mode 100644
index 0000000000000000000000000000000000000000..f4edb4a104f2dfdd50e9271cb40add6be758e38d
--- /dev/null
+++ b/docs/Application_guide/en/solutions/AIChatBot-Volcengine-webRTC/software_design.md
@@ -0,0 +1,107 @@
+# Software Design
+
+## Software Framework
+
+### Framework design diagram
+
+
+
+### Business system startup process
+
+
+
+## Code Explanation
+
+### AI event management
+
+Handling AI events
+
+```python
+def ai_callback(args):
+ global GPIO39 # audio PA GPIO
+ event = args[0]
+ msg = args[1]
+ if event == 1:
+ print('TIKTOK_RTC_EVENT_START') # enter room
+ GPIO39.write(1)
+ elif event == 2:
+ print('TIKTOK_RTC_EVENT_STOP') # exit room
+ GPIO39.write(0)
+ elif event == 3:
+ print('TIKTOK_RTC_EVENT_TTS_TEXT {}'.format(msg)) # TTS
+ elif event == 4:
+ print('TIKTOK_RTC_EVENT_ASR_TEXT {}'.format(msg)) # ASR
+ elif event == 5:
+ print('TIKTOK_RTC_EVENT_ERROR {}'.format(msg)) # Error
+ else:
+ print('TIKTOK_RTC_EVENT UNKNOWN {}'.format(event)) # Unknow
+
+```
+
+### AI Init
+
+Initialize AI objects, register callback interfaces, and configure AI conversation times.
+
+```python
+tiktok = TiktokRTC(300000, ai_callback)
+```
+
+**Reference operation log**
+
+```python
+
+import example
+>>> example.exec('/usr/ai_main.py')
+volume: 11
+>>> lte network normal
+ai task running
+
+```
+
+### AI enter room
+
+push down KEY S3 to enter room, start communicate, call `tiktok.active(True)` to active.
+
+```python
+tiktok.active(True)
+```
+
+**Reference operation log**
+
+```python
+# push KEY S3 to enter
+rtc_queue key event 1
+start rtc
+TIKTOK_RTC_EVENT_START
+TIKTOK_RTC_EVENT_TTS_TEXT 你
+TIKTOK_RTC_EVENT_TTS_TEXT 你好
+TIKTOK_RTC_EVENT_TTS_TEXT 你好有
+TIKTOK_RTC_EVENT_TTS_TEXT 你好有什
+TIKTOK_RTC_EVENT_TTS_TEXT 你好有什么
+TIKTOK_RTC_EVENT_TTS_TEXT 你好有什么可
+TIKTOK_RTC_EVENT_TTS_TEXT 你好有什么可以
+TIKTOK_RTC_EVENT_TTS_TEXT 你好有什么可以帮
+TIKTOK_RTC_EVENT_TTS_TEXT 你好有什么可以帮到
+TIKTOK_RTC_EVENT_TTS_TEXT 你好有什么可以帮到你
+TIKTOK_RTC_EVENT_TTS_TEXT 你好有什么可以帮到你的
+TIKTOK_RTC_EVENT_TTS_TEXT 你好有什么可以帮到你的吗
+
+```
+
+### AI exit room
+
+push down KEY S2 to exit room, stop communicate, call `tiktok.active(False) to deactive。
+
+```python
+tiktok.active(False)
+```
+
+**Reference operation log**
+
+```python
+# push KEY S2 to exit
+rtc_queue key event 2
+stop rtc
+TIKTOK_RTC_EVENT_STOP
+```
+
diff --git a/docs/Application_guide/en/solutions/Agriculture-Control-Panel/README.md b/docs/Application_guide/en/solutions/Agriculture-Control-Panel/README.md
index 62b44157687a906eac2eb8d7a5e365fbbde0dc32..3bc80cee46d9f9ed22bee45a6a1ec8a0e099ec36 100644
--- a/docs/Application_guide/en/solutions/Agriculture-Control-Panel/README.md
+++ b/docs/Application_guide/en/solutions/Agriculture-Control-Panel/README.md
@@ -1,468 +1,19 @@
# Smart Agriculture Central Control Panel
-[QuecPython](https://python.quectel.com/en) has introduced a GUI solution for a [Smart Agriculture Central Control Panel](https://github.com/QuecPython/solution-Agriculture-Control-Panel.git) based on the [U-235 Development Board](https://python.quectel.com/en/wp-content/uploads/sites/2/2024/12/EC600U_U-235_EVB_Specification_and_User_Guide.pdf). The features include weather forecast, agricultural environmental data monitoring, real-time data display, historical data curves, agricultural equipment control, alarm and fault event notifications, system settings, and more.
+The smart agriculture control panel solution is based on the U-235 standard development board and has the following characteristics:
-
+- Provide real-time display of weather forecasts, agricultural environmental data monitoring, real-time data display, historical data curves, agricultural equipment control, and other functions.
+- Highly customizable, users can finely adjust various aspects of agricultural operations according to specific situations and needs
+- Having rich peripheral interfaces, supporting the connection of most commonly used sensors, such as temperature and humidity sensors, gas sensors, etc
+- Using Python language for easy secondary development.
-The U-235 development board comes with the default onboard EC600U module and an externally connected 5-inch screen with a MIPI interface and a resolution of 854*480. Additionally, it features a variety of sensors and peripheral interfaces onboard. For more details, you can refer to the [U-235 EVB User Guide](https://python.quectel.com/en/wp-content/uploads/sites/2/2024/12/EC600U_U-235_EVB_Specification_and_User_Guide.pdf).
+
-
+------
-The Smart Agriculture Central Control Panel uses [LVGL](https://lvgl.io/) to draw the graphical interface. LVGL is a lightweight, open-source embedded graphics library. QuecPython integrates LVGL and utilizes NXP's [GUI Guider](https://www.nxp.com/design/software/development-software/gui-guider:GUI-GUIDER) as a graphical interface design tool. It can automatically generate QuecPython code, significantly improving the efficiency of graphical interface design on embedded platforms.
-
-## Interface Introduction
+- [development resources](./dev_resources.md)
+- [quick start](./quick_start.md)
+- [software design](./software_design.md)
-The Smart Agriculture Central Control Panel offers multiple interfaces, including Home, Environmental Data Display, System Settings, Device Control, and Parameter Settings. These interfaces are designed for centralized monitoring and management of agricultural activities.
-
-### Home Screen
-
-The Home Screen serves as the information center for agricultural management. It is designed with an intuitive and user-friendly approach, integrating various functions to support effective agricultural management.
-
-
-
-**Components:**
-
-1. **Weather Information**:
-
- - Current Weather Conditions: Includes temperature, weather conditions (clear, rainy, cloudy, etc.), wind speed, and direction.
- - Future Weather Forecast: Provides forecasts for the coming days or week, including temperature changes, precipitation probability, and more.
-
- Clicking on it leads to a detailed weather screen.
-
-2. **Temperature and Humidity History Curve**:
-
- - Real-time updated temperature and humidity data presented in a curve graph, facilitating the observation of short-term and long-term trends.
- - May include data comparisons for day, week, month, or even year.
-
-3. **Common Environmental Parameters**:
-
- - Soil Moisture: Displays the moisture levels of different soil areas.
- - Soil pH Value: Monitors the acidity and alkalinity of the soil.
- - O2 Concentration: Shows the current oxygen concentration in the environment.
- - CO2 Concentration: Critical for the growth of greenhouse crops.
-
-4. **Alarm Information**:
-
- - The system monitors and alerts for any abnormal conditions, such as a sudden deviation of temperature or humidity from the normal range, unauthorized intrusion, equipment malfunctions, etc.
- - Alarm history records for easy retracing and analysis of past events.
-
-### Environmental Data Display Screen
-
-The Environmental Data Display Screen provides real-time data for various environmental parameters in agriculture. It allows agricultural managers to quickly access and analyze key data, enabling them to make timely decisions to optimize the growing conditions for crops.
-
-
-
-This screen includes real-time data display for temperature, humidity, illumination, soil temperature, oxygen concentration, carbon dioxide concentration, soil pH, and soil EC values.
-
-### Device Status Display Screen
-
-The Device Status Display Screen is used to monitor and display the operational status of various devices and sensors. This enables the quick identification of any potential issues, allowing for timely measures to ensure the smooth operation and efficiency of agricultural activities. Through such a central control panel, agricultural managers can effectively monitor and maintain critical equipment and sensors on the farm, enhancing overall productivity and reliability.
-
-
-
-This screen includes the status of common environmental sensors in agriculture. It covers temperature and humidity, illumination, soil pH, soil EC, carbon dioxide concentration, oxygen concentration, wind speed and direction, and soil temperature and humidity.
-
-### System Settings Screen
-
-The System Settings Screen is a crucial part of user configuration and personalization for their agricultural management system. It allows users to adjust various system parameters to meet specific requirements and preferences. Through these settings, users can ensure the efficient operation of the system while aligning with their individual preferences and operational habits.
-
-
-
-**Interface Functions:**
-
-1. **About This Device**:
- - Provides basic information about the system, such as manufacturer, model, and operating system version.
- - Displays hardware configurations like processor type, memory size, and storage space.
-2. **Volume Settings**:
- - Allows users to adjust the system's volume, including alert and notification sounds.
- - Offers a mute option, especially useful in environments where minimizing disturbance is necessary.
-3. **Check for Updates**:
- - Used to check for updates to the system software, ensuring all features are up-to-date.
- - May include an option for automatic updates, allowing the system to download and install new versions automatically.
-4. **Low Power Mode**:
- - This option can reduce the system's energy consumption, particularly useful in environments with limited power.
- - Low Power Mode may limit certain functions or decrease system performance.
-5. **Screen Timeout Settings**:
- - Allows users to set the time for the screen to automatically turn off during inactivity, promoting energy efficiency.
- - Users can customize different time intervals as needed.
-6. **Mode Selection**:
- - Users can choose different operation modes such as daily mode, energy-saving mode, night mode, etc.
- - Each mode may adjust settings like screen brightness, volume, and power usage.
-
-### Device Control Screen
-
-The Device Control Screen is a crucial component for managing and operating various farm equipment. It provides intuitive control options and real-time feedback, ensuring users can effortlessly and efficiently manage key farm devices. Through this intelligent device control, farm managers can optimize production conditions, enhance efficiency, and reduce resource wastage.
-
-
-
-This screen includes controls for common agricultural equipment, including ventilation devices, irrigation equipment, humidification devices, pest control devices, heating equipment, and alarm systems.
-
-### Parameter Settings Screen
-
-The Parameter Settings Screen allows users to customize and adjust various environmental and equipment operation parameters. These settings help ensure that the agricultural production environment aligns with the needs of crops, optimizing growth conditions and enhancing production efficiency.
-
-
-
-Users can set thresholds for various environmental parameters such as temperature, humidity, light intensity, soil moisture, carbon dioxide concentration, etc. When these parameters reach or exceed the set thresholds, the system can automatically adjust device operations or send alerts.
-
-Through this screen, users can finely tune various aspects of agricultural operations based on specific situations and requirements, ensuring the system operates efficiently and provides optimal growth conditions for crops. This high level of customization is a key advantage of smart agriculture systems, allowing agricultural producers to flexibly adjust operational strategies according to changing environmental and market demands.
-
-## Introduction to Application Code
-
-Code GitHub Repository:
-
-### Code Directory Structure
-
-The code directory structure is as follows:
-
-```plainText
-.
-|-- Agri_ui.py
-|-- EventMesh.py
-|-- about_screen.py
-|-- alarm_screen.py
-|-- dev1_screen.py
-|-- dev2_screen.py
-|-- img
-| |-- mp-1092957702.png
-| |-- mp-1113916345.png
-| |-- mp-1120889833.png
-| |-- (Some pictures are omitted here)
-| |-- mp807599128.png
-| |-- mp910426373.png
-| `-- mp996516799.png
-|-- main.py
-|-- main_screen.py
-|-- monitor_screen.py
-|-- screen.py
-|-- setting1_screen.py
-|-- setting2_screen.py
-|-- weather_screen.py
-`-- welcome_screen.py
-
-```
-
-- `Agri_ui.py`: This file handles all the initialization tasks for the smart agriculture control panel, including vlgl initialization and MIPI LCD initialization. It provides a screen object adder for the graphical interface and a GUI launcher. The screen object adder is used to add all possible screen objects that may need to be displayed in the application, and the GUI launcher is used to start the graphical interface functionality.
-- `screen.py`: This file provides the base class `class Screen()` for screen objects. It includes common methods required by all screen objects, such as creating screens and displaying status bar information (operator name, signal strength, system time, battery level, etc.).
-- All script files ending with `_screen.py` implement a class that inherits from `class Screen()`. These classes represent the code implementation of the screens that need to be displayed. The main content of the interface code is generated by the GUI Guider tool and then slightly modified, primarily in the object initialization method `__init__()` and control event handling callback functions (`__xxx_event_cb()`).
-- `EventMesh.py`: This module is an event manager. When an event on a screen control is triggered, users only need to call the relevant interface to send the event. [EventMesh](https://github.com/QuecPython/EventMesh) will automatically handle the screen content switching.
-- The `img` folder provides all the image resources required for the graphical interface.
-- `main.py`: This script file serves as the application entry point. It calls the class `class AgriUi()` provided by `Agri_ui.py` to create the GUI object for the smart agriculture control panel. It then calls the screen object adder of this GUI object to add the necessary screen objects and finally calls the GUI launcher to start the graphical interface.
-
-### Application Startup Process
-
-The application startup process is illustrated in the following diagram:
-
-
-
-
-
-## Software Design
-
-### Software Framework Design
-
-#### Application Design
-
-The block diagram for the smart agriculture control panel software is as follows:
-
-
-
-#### Interface Switching Mechanism
-
-##### EventMesh Event Management Framework
-
-As mentioned earlier, the interface switching is driven by the EventMesh event management framework.
-
-- EventMesh is an application framework based on the publish-subscribe mechanism. Users can subscribe to any topic, which represents an event.
-- Along with subscribing to the topic, users need to register a callback function to handle the generated event.
-- Users can publish the event from anywhere it is generated and can carry message content. At this point, the subscribed callback function is invoked, and the event is processed.
-
-The design framework of EventMesh is illustrated in the following diagram:
-
-
-
-##### Interface Switching Implementation Principle
-
-In each screen interface script code that generates touch events with controls, the `add_event_cb()` method is called to register a callback function for the corresponding event. When lvgl detects an event, it will invoke the corresponding callback function. Here is an example code snippet:
-
-```python
-class MainScreen(Screen):
- def __init__(self):
- # Some code is omitted here
- self.name = "MainScreen"
- super().create_style()
-
- # Some code is omitted here
-
- def create(self):
-
- # Some code is omitted here
-
- self.weather_btn.add_event_cb(lambda e: self.__weather_btn_event_cb(e), lv.EVENT.PRESSED, None)
- self.alarm_btn.add_event_cb(lambda e: self.__alarm_btn_event_cb(e), lv.EVENT.PRESSED, None)
- self.monitor_btn.add_event_cb(lambda e: self.__monitor_btn_event_cb(e), lv.EVENT.PRESSED, None)
- self.monitor_btn_2.add_event_cb(lambda e: self.__monitor_btn_event_cb(e), lv.EVENT.PRESSED, None)
- self.dev_btn.add_event_cb(lambda e: self.__dev_btn_event_cb(e), lv.EVENT.PRESSED, None)
- self.setting_btn.add_event_cb(lambda e: self.__setting_btn_event_cb(e), lv.EVENT.PRESSED, None)
-
- def __weather_btn_event_cb(self,e):
- src = e.get_target()
- code = e.get_code()
- print("Click event occurs")
- EventMesh.publish("load_screen", "WeatherScreen")
-
- def __monitor_btn_event_cb(self,e):
- src = e.get_target()
- code = e.get_code()
- print("Click event occurs")
- EventMesh.publish("load_screen", "MonitorScreen")
-
- def __alarm_btn_event_cb(self,e):
- src = e.get_target()
- code = e.get_code()
- print("Click event occurs")
- EventMesh.publish("load_screen", "AlarmScreen")
-
- def __dev_btn_event_cb(self,e):
- src = e.get_target()
- code = e.get_code()
- print("Click event occurs")
- EventMesh.publish("load_screen", "Dev1Screen")
-
- def __setting_btn_event_cb(self,e):
- src = e.get_target()
- code = e.get_code()
- print("Click event occurs")
- EventMesh.publish("load_screen", "SettingScreen")
-```
-
-From the above code, it can be seen that the implementation approach for each touch event's callback function is similar.
-
-Taking the example of the weather widget's touch event, the code is as follows:
-
-```python
- def __weather_btn_event_cb(self,e):
- src = e.get_target()
- code = e.get_code()
- print("Click event occurs")
- EventMesh.publish("load_screen", "WeatherScreen")
-```
-
-The core statement in this code segment is `EventMesh.publish("load_screen", "WeatherScreen")`. This statement sends an event named `"load_screen"`, indicating the loading of a new screen interface. The carried message is `"WeatherScreen"`, which is the name of the screen interface, signifying the loading of the weather display screen.
-
-##### GUI Startup
-
-The `"load_screen"` event is subscribed to in the `start()` method of the `class AgriUi(object)` in the `Agri_ui.py` script file.
-
-The code is as follows:
-
-```python
-class AgriUi(object):
-
- # Some code is omitted here
-
- def __create(self):
- for screen in self.screens:
- screen.create()
-
- def start(self):
- self.__create()
- EventMesh.subscribe("load_screen", self.__route)
- EventMesh.publish("load_screen", "WelcomeScreen")
- utime.sleep(2)
- EventMesh.publish("load_screen", "MainScreen")
-
- def __route(self, topic, meta):
- for screen in self.screens:
- if screen.name == meta:
- lv.scr_load(screen.screen)
-```
-
-The `start()` method in the above code is used to launch the graphical interface of the smart agriculture control panel, and its workflow is as follows:
-
-- Call the `__create()` method to create metadata for each screen interface.
-
-- Call the `EventMesh.subscribe()` method to subscribe to the event named `"load_screen"`. When this event occurs, call the `__route()` method to handle the event.
-
- > The `__route()` method matches the corresponding interface object based on the message carried when the event is published, i.e., the name of the screen interface. It then calls the `lv.scr_load()` method from lvgl to load the new interface.
- >
- > Observant readers will notice that in the `__init__()` method of each class implemented in the screen interface script files, there is a statement similar to `self.name = "MainScreen"`. This statement records the name of the screen interface.
-
-- The statement `EventMesh.publish("load_screen", "WelcomeScreen")` is used to trigger the display of the first interface, the welcome screen. Then, wait for the welcome screen to display for 2 seconds, creating a pleasant visual experience.
-
-- After the welcome screen, use the `EventMesh.publish("load_screen", "MainScreen")` statement to trigger the display of the main interface.
-
-With this, the graphical interface of the smart agriculture control panel is launched, and the subsequent interface switches are controlled by user touch interactions.
-
-### Graphical Interface Design
-
-As mentioned earlier, QuecPython uses NXP's [GUI Guider](https://www.nxp.com/design/software/development-software/gui-guider:GUI-GUIDER) as a graphical interface design tool. This tool not only facilitates interface layout design but also automatically generates QuecPython code. You can refer to the [GUI Guider tutorial](https://python.quectel.com/doc/Application_guide/en/multi-media/lvgl/lvgl_ui_tool.html) for more information.
-
-The following section uses the example of the [Home Screen](#Home-Screen) of the smart agriculture control panel to illustrate the graphical interface design process.
-
-#### Layout and Background Setting
-
-Create a smart agriculture project, selecting a suitable layout template, and background design. In this stage, design will start from a blank layout by choosing a blank template with a resolution of 854*480.
-
-
-
-#### Interface Drawing
-
-This section will start drawing various modules on the home screen.
-
-1. **Left Dock Bar**
-
- 
-
- - **Component**: imgbtn.
- - **Icons**: Use easily recognizable icons as shortcuts for functions such as accessing the homepage, displaying data, settings, and controls.
- - **Layout**: Vertically align icons, place them on the left side of the interface for easy access.
- - **Interactivity**: Add a selected effect to icons to enhance the interactive experience.
-
- When using the `imgbtn` component in the GUI Guider software to create the left shortcut bar in the graphical interface of smart agriculture, you need to pay attention to several key design elements:
-
- 1. **Icon Selection**:
- - Each `imgbtn` should have an intuitive icon representing its function, such as a house-shaped icon for the homepage or a gear-shaped icon for settings.
- - Icon design should be clear and straightforward for easy recognition by users.
- 2. **Size and Spacing**:
- - The size of each `imgbtn` should be large enough for users to easily click, especially on touchscreen devices.
- - There should be appropriate spacing between shortcuts to prevent accidental touches and make the interface look tidy.
- 3. **Icon States**:
- - Design icons for different states, such as default, hover, and click states. This provides visual feedback and enhances the user interaction experience.
- - The `imgbtn` component should support state switching so that users can see the response of the interface to their actions.
- 4. **Functionality**:
- - Each `imgbtn` should be configured with the correct event handlers to ensure that the correct action is triggered when users click, navigating to the corresponding screen.
- - If the function represented by the `imgbtn` is currently active or on the current screen, it should be displayed in a different visual style to indicate its active status.
-
-
-
-2. **Top Information Display Bar**
-
- 
-
- - **Components**: label, image.
- - **Operator Information**: Display mobile operator or network status on the top left of the interface.
- - **Time Display**: Show the current time in the center of the top of the interface.
- - **Signal Strength and Battery Indicators**: Display icons for Wi-Fi or network signal strength and current battery level on the top right of the interface.
-
- When designing the top information display bar of the smart agriculture control panel using GUI Guider software, combine the `label` and `image` components to create an information-rich and visually recognizable status bar. Here are detailed steps on how to use these components to design the top information display bar:
-
- 1. **Operator Information (Label Component)**:
- - Use the `label` component to display operator information. Choose a clear and readable font and size to ensure easy readability on different devices.
- - Place the `label` component on the left side of the top information bar and set the appropriate alignment, usually left-aligned.
- 2. **Time Display (Label Component)**:
- - Another `label` component is used to display the time. You can set up a timer to ensure that the time is always updated.
- - The time `label` is typically positioned on the right side of the information bar and should be easily distinguishable, which can be achieved by increasing the font size and bolding.
- 3. **Signal Strength (Image Component)**:
- - Signal strength can be represented by a series of predefined signal icons. These icons can display different images based on varying signal strengths.
- - Use the `image` component to place the signal strength icons, positioning them on the right side of the top information bar.
- 4. **Battery Indication (Image Component)**:
- - Battery indication also uses the `image` component for display. You can prepare a set of battery icons to reflect different battery states.
- - Place the battery icons on the far right of the top information bar, adjacent to the signal strength icons.
-
-3. **Weather Module**
-
- 
-
- - **Components**: label, container, image.
- - **Current Weather**: Display the current weather condition and temperature.
- - **Future Weather Forecast**: Provide a horizontal scroll or small grid next to or below the current weather, displaying the weather forecast for the upcoming days.
-
- When designing the weather information module in the top left corner using GUI Guider, you can create an intuitive and information-rich weather display area by combining `label`, `image`, and `container` components. Here are the steps on how to use these components to design the weather information module:
-
- 1. **Basic Container Setup (Container Component)**:
- - Place a `container` component in the top-left corner of the interface as the foundation for the weather module. This container will contain all the weather-related sub-components.
- - Adjust the size of the `container` to ensure it can accommodate all sub-components without appearing crowded.
- 2. **Location Display (Label Component)**:
- - Use a `label` component at the top of the container to display the current geographic location or farm name.
- - This `label` can use a larger font size and bold effect for clear identification of location information.
- 3. **Current Temperature and Weather (Label Component)**:
- - Use two `label` components for the current temperature and weather description. These should use a clear, readable font and an appropriate size for easy understanding.
- - The `label` for the current temperature should be the most prominent, possibly using a larger font size and distinctive color.
- 4. **Weather Icons (Image Component)**:
- - Use the `image` component to display an icon representing the current weather condition, such as sunny, cloudy, rainy, etc.
- - The weather icon should be adjacent to the `label` for the current temperature, providing an intuitive visual representation of the weather.
- 5. **Daily Weather Forecast (Label and Image Components)**:
- - Below or next to the `container`, use multiple `label` and `image` components to display the weather forecast for the next 5 days.
- - Each day's forecast can use a small `image` component to show a weather icon, accompanied by a `label` component displaying the date.
- 6. **Adaptive Design**:
- - Ensure that the weather information area can adapt to different screen sizes and resolutions, especially in responsive interfaces.
- - Sub-components should automatically adjust their size and position when the `container` size changes.
-
-4. **Temperature and Humidity Historical Line Chart**
-
- 
-
- - **Components**: container, chart, label.
- - **Chart Style**: Use a line chart to display the historical data trends of temperature and humidity.
- - **Time Selection**: Provide options to view data for different time periods, such as day, week, and month.
- - **Interactivity**: Allow users to hover or click on points on the chart to view specific data points.
-
- When using GUI Guider to design the temperature historical line chart in the bottom left corner of the smart agriculture graphical interface, layout the `label`, `chart`, and `container` components. These components will together form an area displaying the trend of temperature changes. Here are specific design instructions:
-
- 1. **Container Layout (Container Component)**:
- - Place a `container` component in the bottom left corner of the interface to serve as the background and framework for the temperature historical line chart. This container will contain the chart and relevant labels.
- - Set the width and height of the `container` to fit the display requirements of the line chart while maintaining coordination with other interface elements.
- 2. **Line Chart (Chart Component)**:
- - Inside the `container`, add a `chart` component to draw the historical data line chart for temperature.
- - Configure the `chart` component to display the time series of temperature data, such as setting the x-axis as the time axis and the y-axis as the temperature values, ensuring clear visibility of data points.
- - Define the style of the line, such as color, thickness, and whether to show markers for data points.
- 3. **Title Label (Label Component)**:
- - Above the line chart or at the top of the container, use a `label` component to display the title, such as "Historical Line."
- - Choose an appropriate font size and style to ensure the title is clear and consistent with the overall design style.
- 4. **Responsive Design**:
- - For responsive interfaces, ensure that the `container` and its components, including `chart` and `label`, can scale appropriately based on different screen sizes.
- - Test the display of the chart on different resolutions and devices, ensuring that the data remains clear and visible.
-
-5. **Display of Common Environmental Parameters**
-
- 
-
- - **Components**: container, label.
- - **Data Display Blocks**: Display key parameters, such as soil pH value, soil temperature, oxygen, and carbon dioxide concentrations, as current readings in separate "blocks" or "cards."
-
- When designing the display of environmental parameters in the top right corner of the smart agriculture graphical interface using GUI Guider software, you can use `label` and `container` components to clearly show key information such as soil pH value, oxygen concentration, soil humidity, and carbon dioxide concentration. Here are detailed design steps:
-
- 1. **Environmental Parameters Container (Container Component)**:
- - Place a `container` component in the top right corner of the interface as a wrapping element for all environmental parameters. This container will help organize and separate different parameter displays.
- - Set the width and height of the container to accommodate the arrangement of internal `label` components, ensuring an aesthetically pleasing and coordinated overall layout.
- 2. **Parameter Labels (Label Components)**:
- - For each environmental parameter, use a separate `label` component to display the parameter name and value. For example, one `label` displays "Soil pH Value: 7.1," while another `label` displays "Oxygen Concentration: 50%" and so on.
- - The `label` for the parameter name can use a smaller font, while the `label` for the value can use a larger or bold font to highlight the numerical information.
- 3. **Parameter Update Mechanism**:
- - If possible, design a data update mechanism to periodically refresh the displayed values of environmental parameters. This can be achieved by binding `label` components to a data source and setting up a timer to update the values.
-
-6. **Alarm Information Area**
-
- 
-
- - **Components**: container, label, table.
- - **List View**: Display recent alarms and warnings in the form of a list or log.
- - **Priority Indication**: Use color coding or icons to indicate the priority or severity of alarms.
- - **Interactivity**: Allow users to click on alarms to get more details or confirm and clear notifications.
-
- When designing the alarm information area in the bottom right corner of the smart agriculture graphical interface using GUI Guider software, you can use `label`, `container`, and `table` components to effectively display alarm titles and specific alarm information. This area will provide users with critical safety and system status updates. Here is the detailed design process:
-
- 1. **Alarm Information Container (Container Component)**:
- - Place a `container` component in the bottom right corner of the interface as the main framework for the alarm information area. This container will contain the title and specific content of alarm information.
- - Set the size of the container, ensuring enough space to display alarm information while maintaining coordination with other elements of the interface.
- 2. **Alarm Information Title (Label Component)**:
- - Use a `label` component to display the title at the top of the container, such as "Alarm Information."
- - Choose a prominent and easily readable font and size to ensure users can clearly identify the functionality of this area.
- 3. **Alarm Information Table (Table Component)**:
- - Below the `container`, use the `table` component to list specific alarm information. This can include columns for alarm time, type, status, and more.
- - Adjust the column width and row height of the `table` to ensure all information is clear and visible.
- 4. **Alarm Information Style**:
- - Set appropriate background color, border color, and font color for the `table` component to align with the overall interface style.
- - Consider using different colors or icons to represent different levels of alarms, such as red for urgent alarms and yellow for warnings.
- 5. **Alarm Information Update Mechanism**:
- - Design a data update mechanism to allow the `table` component to dynamically display the latest alarm information. This may involve binding the `table` component to a backend data source and setting up a timed refresh.
- 6. **Responsive Design**:
- - Ensure that the `container` and its `table` and `label` components can scale appropriately on different screen sizes and resolutions.
- - On smaller screens, adjustments to the layout of the `table` may be necessary to ensure readability of information.
-
-When placing these elements in GUI Guider, ensure that each component is positioned based on a grid or flexible layout system to adapt to different screen sizes and resolutions. The interface design should be clean, maintaining enough white space to avoid crowding. The color scheme used should highlight important information without being too glaring, and interactive elements should provide immediate feedback, such as changing appearance on hover or click. Additionally, it's important to test the design on different devices to ensure usability and performance.
-
-If the system will be used in various lighting conditions, such as direct sunlight, adjustments to contrast and brightness should be possible to enhance visibility. Lastly, the interface design should be intuitive, allowing new users to navigate without extensive training, reflecting good User Experience (UX) design principles.
\ No newline at end of file
diff --git a/docs/Application_guide/en/solutions/Agriculture-Control-Panel/dev_resources.md b/docs/Application_guide/en/solutions/Agriculture-Control-Panel/dev_resources.md
new file mode 100644
index 0000000000000000000000000000000000000000..5590ff5f0c59f2252a391933fb1f839e5300acf6
--- /dev/null
+++ b/docs/Application_guide/en/solutions/Agriculture-Control-Panel/dev_resources.md
@@ -0,0 +1,67 @@
+# Development resources summary
+
+
+
+## Development board
+
+- model:[QuecPython U-235 EVB](https://python.quectel.com/doc/Getting_started/en/evb/ec600u-235.html)
+
+- [Purchase link](https://detail.tmall.com/item.htm?abbucket=8&id=676710608367&pisk=gUaZxiwjTNQwcl4NnX02YOhqIW3trVX7IrMjiSVm1ADMfl_Do-wBGmM1Dkl0d-ujlSXT3rk3Ml1tcOd4YRFof-PA6jD0n-kbfM_7653xoT_VPaN9kRvQOR8DjpfmwfxcOc0MonwjoT65uHOnXOg0CuF6pHxnwvciifmcTXcsaqciiFfEKjl-nF2mo65EwjJDof0mtDcosqxDSjvn-jhSnKDiipfEMvDmoqckF5VD8biGgYh9Msd9nqMusv8DzQhZjCN6cE8qcfmaoWDEOXaE_ckovdBTpP2QiPatvMxEkWZz3o2ldhMg4byEVlWy78ytiSl0QadrKPP48cEBwEVE0Ar3SDRDo20I30q4QO-tIlwE2XmHgahQFvVTSk5vK52SQVcnAafztmqQW0U1KFuu25g_m8XBfAqrigkyHXVm9rEwnnoi9Xk5T6rc31Ew7XN5nnKxx4hEF1G6Dnni9Xk5T6-vDDDKTY1s1&rn=42a4e96745c13cd9400765e39c24c67e&spm=a1z10.3-b-s.w4011-23773493585.71.221c5886KuaZIg&skuId=4865603973616)
+
+- EVB docs
+
+ - [specification](https://python.quectel.com/wp-content/uploads/2024/10/%E9%93%80235%E5%BC%80%E5%8F%91%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://python.quectel.com/wp-content/uploads/2024/10/%E9%93%80235%E5%BC%80%E5%8F%91%E6%9D%BF%E5%8E%9F%E7%90%86%E5%9B%BE.pdf)
+ - [screen printing](https://python.quectel.com/wp-content/uploads/2024/10/%E9%93%80235%E5%BC%80%E5%8F%91%E6%9D%BF%E4%B8%9D%E5%8D%B0.pdf)
+ - [user guidance](https://python.quectel.com/doc/Getting_started/zh/evb/ec600u-235.html)
+
+
+
+## Module
+
+- model:[EC600UCN_LB](https://python.quectel.com/modules-cat/ec600u-series)
+- [specification](https://python.quectel.com/wp-content/uploads/2024/09/Quectel_EC600U%E7%B3%BB%E5%88%97_LTE_Standard_%E6%A8%A1%E5%9D%97%E4%BA%A7%E5%93%81%E8%A7%84%E6%A0%BC%E4%B9%A6_V1.5.pdf)
+- [download drivers](https://python.quectel.com/wp-content/uploads/2024/09/Quectel_Windows_USB_DriverU_V1.0.19.zip)
+
+
+
+## Dev tools
+
+- QPYcom - QuecPython debug tool
+
+ - version: V3.6.0
+
+
+ - download [QPYcom](https://python.quectel.com/wp-content/uploads/2024/09/QPYcom_V3.6.0.zip)
+
+
+
+
+
+- VSCode - code editor
+
+ - download [VSCode](https://code.visualstudio.com/)
+
+
+
+
+## Firmware
+
+- version:EC600UEUAB_R03A01M8_OCPU_QPY_BETA1107
+- download [firmware](https://objects.githubusercontent.com/github-production-release-asset-2e65be/718904250/839d5c8d-81fb-49d5-982f-73c45ceb5f9b?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=releaseassetproduction%2F20250220%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20250220T034410Z&X-Amz-Expires=300&X-Amz-Signature=ba55b3e1f47a0e7b842d315dc04b1e20b975a9f6a2fe76239989ffbbf24e42d5&X-Amz-SignedHeaders=host&response-content-disposition=attachment%3B%20filename%3D8915DM_cat1_open_EC600UEUAB_R03A01M8_OCPU_QPY_BETA1107_merge_20241108-1415_20250205-1611.zip&response-content-type=application%2Foctet-stream)
+
+
+
+## Source code
+
+- version: v1.0.1
+
+- github repo:
+
+```bash
+git clone https://github.com/QuecPython/solution-Agriculture-Control-Panel
+cd solution-Agriculture-Control-Panel
+git checkout v1.0.1
+```
+
+- [Github Zip file download link](https://codeload.github.com/QuecPython/solution-Agriculture-Control-Panel/zip/refs/tags/v1.0.1)
diff --git a/docs/Application_guide/en/solutions/Agriculture-Control-Panel/quick_start.md b/docs/Application_guide/en/solutions/Agriculture-Control-Panel/quick_start.md
new file mode 100644
index 0000000000000000000000000000000000000000..c56fa70b7f6b26fb059d57266282df183c7f8e28
--- /dev/null
+++ b/docs/Application_guide/en/solutions/Agriculture-Control-Panel/quick_start.md
@@ -0,0 +1,200 @@
+# Quick Start
+
+
+
+## Hardware preparation
+
+- A Windows computer, recommended for the `Win10` system.
+
+- A [QuecPython U-235 development board](https://python.quectel.com/doc/Getting_started/en/evb/ec600u-235.html)
+
+- A TypeC data cable
+
+
+
+
+## Environment construction
+
+- Download and install EC600U series module driver: [QuecPython_USB_DriverU_V1.0.19](https://python.quectel.com/wp-content/uploads/2024/09/Quectel_Windows_USB_DriverU_V1.0.19.zip)
+- Download and install [VSCode](https://code.visualstudio.com/)
+- Download and install [QPYCom](https://python.quectel.com/wp-content/uploads/2024/09/QPYcom_V3.6.0.zip)
+- Download [Firmware](https://objects.githubusercontent.com/github-production-release-asset-2e65be/718904250/839d5c8d-81fb-49d5-982f-73c45ceb5f9b?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=releaseassetproduction%2F20250220%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20250220T034410Z&X-Amz-Expires=300&X-Amz-Signature=ba55b3e1f47a0e7b842d315dc04b1e20b975a9f6a2fe76239989ffbbf24e42d5&X-Amz-SignedHeaders=host&response-content-disposition=attachment%3B%20filename%3D8915DM_cat1_open_EC600UEUAB_R03A01M8_OCPU_QPY_BETA1107_merge_20241108-1415_20250205-1611.zip&response-content-type=application%2Foctet-stream)
+- Download [Source Code](https://codeload.github.com/QuecPython/solution-Agriculture-Control-Panel/zip/refs/tags/v1.0.1)
+
+
+
+## Hardware connection
+
+Connect the hardware according to the following diagram:
+
+
+
+Connect the development board and computer using a Type-C data cable.
+
+
+
+## Equipment development
+
+
+
+### Power on
+
+
+After completing the hardware connection, long press the button labeled 'PWR' on the development board until the network light 'net' flashes or a COM port containing the words' Quectel USB 'appears in the port list of the computer device manager, indicating successful boot.
+
+
+
+
+
+### Download firmware
+
+Refer to [this chapter](https://python.quectel.com/doc/Application_guide/en/dev-tools/QPYcom/qpycom-dw.html# Download firmware), burn firmware package [EC600UEUAB_R03A01M8_SCPU_QPYBETA10107. zip](https://objects.githubusercontent.com/github-production-release-asset-2e65be/718904250/839d5c8d-81fb-49d5-982f-73c45ceb5f9b?X -Amz Algorithm=AWS4-HMAC-SHA256&X-Amz Credentia=releaseassetproduction% 2F0250220% 2Fus-est-1% 2Fs3% Faws4-request&X-Amz Date=20250220T034410Z&X-Amz Expires=300&X-Amz Signature=ba55b3e1f47a0e7b842d315dc04b1e20b975a9f6a2fe76239988fbbf24e42d5&X-Amz SignedHeaders=host&response content distribution=attachment% 3B% 20filename% 3D8915DM_cat1_open_CC600UEUAB_R00 3A01M8_SCPU_QPYBETA10107_marge_20241108-1415_20250205-1611. zip&response content type=application% 2Flocet stream) to the development board.
+
+
+
+### Script import and execution
+
+
+1. Refer to [this chapter](https://python.quectel.com/doc/Getting_started/en/first_python.html#PC) To transfer files between modules, import all files from the `code` folder in the source code directory into the module file system, as shown in the following figure:
+
+
·
+
+2. Refer to [this chapter](https://python.quectel.com/doc/Getting_started/en/first_python.html#) Execute the script file and execute the main program file `main. py`. (During normal startup, the module will automatically execute the `main.py` file)
+
+3. Refer to [this chapter](https://python.quectel.com/doc/Getting_started/en/first_python.html# Stop program running), stop program running.
+
+
+
+## Screens
+
+
+
+### Program startup
+
+After executing `main. py`, if the program starts successfully, it will enter the `welcomescreen` interface. After waiting for 2 seconds, it will enter the `main_screen` screen.
+
+
+
+
+
+### Main Screen
+
+The main screenis the information center for agricultural management. Its design philosophy is intuitive and user-friendly, integrating multiple functions to support effective agricultural management.
+
+
+
+components:
+1. **Weather information **:
+
+ - Current weather conditions: including temperature, weather conditions (sunny, rainy, cloudy, etc.), wind speed and direction.
+
+ - Future weather forecast: provides weather forecasts for the next few days or a week, including temperature changes, precipitation probabilities, etc.
+
+ After clicking, you can enter the complete weather interface
+
+2. **Historical curves of temperature and humidity **:
+
+ * Real time updated temperature and humidity data, presented in the form of a curve graph, for easy observation of short-term and long-term trends.
+ * This may include comparisons of data on a daily, weekly, monthly, or even yearly basis.
+
+3. **Common environmental parameters **:
+
+ - Soil moisture: Real time display of soil moisture level
+ - Soil pH value: Monitor soil pH value.
+ - O2 concentration: Display the current ambient oxygen concentration.
+ - Temperature: Real time display of current room temperature, particularly crucial for greenhouse crop growth.
+
+4. **Alarm Information **:
+
+ - The system monitors and alerts in real-time for any abnormal situations, such as sudden deviation of temperature or humidity from normal range, unauthorized intrusion, equipment failure, etc.
+
+ - Alarm history record, convenient for tracing and analyzing past events.
+
+
+
+### Weather Screen
+
+Click on `weather` on the main interface to enter the detailed weather Screen
+
+
+
+Intuitively display the current temperature, highest temperature, lowest temperature, wind speed and direction of the city, as well as detailed information on the weather for the next five days
+
+
+
+### Environmental data display screen
+
+The device status display interface is used to monitor and display the operating status of various devices and sensors, in order to quickly identify any potential problems and take corresponding measures to ensure smooth and efficient agricultural operations. Through such a central control panel, agricultural managers can effectively monitor and maintain key equipment and sensors on the farm, improving overall productivity and reliability.
+
+
+
+This interface includes the status of common environmental sensors in agriculture. Including temperature and humidity, care, soil pH value, soil EC, carbon dioxide concentration, oxygen concentration, wind speed and direction, and soil temperature and humidity.
+
+### Threshold setting screen
+
+The threshold setting screen allows users to customize and adjust various environmental and device operating parameters. These settings help ensure that the agricultural production environment matches the needs of crops, thereby optimizing growth conditions and improving production efficiency.
+
+
+
+Users can set thresholds for various environmental parameters, such as temperature, humidity, light intensity, soil moisture, carbon dioxide concentration, etc. When these parameters reach or exceed the set thresholds, the system can automatically adjust device operation or send alerts.
+
+Through this screen, users can finely adjust various aspects of agricultural operations according to specific situations and needs, ensuring efficient system operation and optimal crop growth conditions. This high degree of customizability is a major advantage of smart agriculture systems, allowing agricultural producers to flexibly adjust their operational strategies based on changing environments and market demands.
+
+
+
+### Equipment control screen
+
+The device control interface is a critical component used for managing and operating various equipment on the farm. It provides intuitive control options and real-time feedback, ensuring that users can easily and effectively manage key equipment on the farm. Through this intelligent device control, farm managers can optimize production conditions, improve efficiency, and reduce resource waste.
+
+
+
+This screen includes common equipment controls in agriculture. Including ventilation equipment, irrigation equipment, humidification equipment, deworming equipment, heating equipment, and alarm equipment.
+
+
+
+### System settings screen
+
+The system settings screen is a key component for users to configure and personalize their agricultural management system, allowing them to adjust various system parameters to meet specific needs and preferences. Through these settings, users can ensure the efficient operation of the system while meeting their personal preferences and operating habits.
+
+
+
+This screen includes the following functions:
+1. About this machine
+
+ - Provide basic information about the system, such as manufacturer, model, and operating system version.
+ - Display the hardware configuration of the system, such as processor type, memory size, storage space, etc.
+
+2. Volume setting
+
+ - Allow users to adjust the volume of the system, including alarm sounds, notification sounds, etc.
+ - Silent mode can be set, especially in environments that require reduced interference.
+
+3. Check for updates
+
+ - Used to check system software updates and ensure that all features are at the latest version.
+ - This may include an option for automatic updates, allowing the system to automatically download and install new versions when they become available.
+
+4. Low power mode
+
+ - This option can reduce the energy consumption of the system, especially useful in environments with limited power sources.
+ - Low power mode may limit certain functions or reduce system performance.
+
+5. Screen rest time setting
+
+ - Allowing users to set the time for the screen to automatically turn off when there is no operation helps save energy.
+ - Users can set different time intervals as needed.
+
+6. Mode selection
+
+ - Users can choose different operating modes, such as daily mode, energy-saving mode, night mode, etc.
+ - Each mode may adjust settings such as screen brightness, volume, energy usage, etc.
+
+
+
+### Equipment status screen
+
+The device status display screen is used to monitor and display the operating status of various devices and sensors, in order to quickly identify any potential problems and take corresponding measures to ensure smooth and efficient agricultural operations. Through such a central control panel, agricultural managers can effectively monitor and maintain key equipment and sensors on the farm, improving overall productivity and reliability.
+
+
+
+This screen includes the status of common environmental sensors in agriculture. Including temperature and humidity, care, soil pH value, soil EC, carbon dioxide concentration, oxygen concentration, wind speed and direction, and soil temperature and humidity.
\ No newline at end of file
diff --git a/docs/Application_guide/en/solutions/Agriculture-Control-Panel/software_design.md b/docs/Application_guide/en/solutions/Agriculture-Control-Panel/software_design.md
new file mode 100644
index 0000000000000000000000000000000000000000..0c5c41000b42a23582c494f8a0cce274d20c2227
--- /dev/null
+++ b/docs/Application_guide/en/solutions/Agriculture-Control-Panel/software_design.md
@@ -0,0 +1,430 @@
+# Software Designt
+
+
+
+## Software framework
+
+
+
+### Software Design Diagram
+
+
+
+### Business system startup process
+
+
+
+
+
+
+
+## Code Explanation
+
+
+
+### Event management
+
+Collaboration between various modules is achieved through the EventMet event management class `EventMeth` event management class provides publishing and subscribing of events, as well as synchronous and asynchronous sending of messages. The framework is shown in the figure:
+
+
+
+The definition of event management class is as follows:
+
+```python
+class EventStore(object):
+def __init__(self):
+ self.map = dict()
+ self.log = None
+
+ def append(self, event, cb):
+ self.map[event] = cb
+
+ def fire_async(self, event, msg):
+ if event in self.map:
+ _thread.start_new_thread(self.map[event], (event, msg))
+ if self.log:
+ self.log.info("ASYNC executed (event) -> {} (params) -> {} (result) -> {}".format(event, msg, None))
+
+ def fire_sync(self, event, msg):
+ res = None
+ try:
+ if event in self.map:
+ res = self.map[event](event, msg)
+ except Exception as e:
+ usys.print_exception(e)
+ if self.log:
+ self.log.info("SYNC executed (event) -> {} (params) -> {} (result) -> {}".format(event, msg, res))
+ return res
+
+event_store = EventStore()
+
+def subscribe(event, cb):
+ """
+ subscribe event and cb
+ """
+ return event_store.append(event, cb)
+
+def publish(event, msg=None):
+ """
+ publish event and msg
+ """
+ return publish_sync(event, msg)
+
+def publish_async(event, msg=None):
+ """
+ 异步发送
+ """
+ return event_store.fire_async(event, msg)
+
+def publish_sync(event, msg=None):
+ """
+ 同步发送
+ """
+ return event_store.fire_sync(event, msg)
+```
+
+1. EventMesh is an application framework based on subscription and publish mechanisms, where users can subscribe to any topic of interest, which represents an event.
+2. At the same time as subscribing to the topic, it is also necessary to register a callback (event_cb) function to handle the generated events.
+3. Users can post the event anywhere it occurs and carry the message content. At this point, the callback function registered by the subscriber will be called and the event will be processed.
+
+
+
+### Principle of screen switching implementation
+
+In every screen interface script code generated by a touch event with a control, the`add_event_cb()`method of the control is called to register a callback function for the corresponding event. The interface switching implementation is relatively simple. When the lvgl thread detects a touch event, it will issue the required operation to `EventMeth` through the callback function corresponding to the control.
+
+example:
+
+```python
+class MainScreen(Screen):
+ # Some code is omitted here
+ def create(self):
+ # Some code is omitted here
+ self.weather_btn.add_event_cb(lambda e: self.__weather_btn_event_cb(e), lv.EVENT.PRESSED, None)
+ self.alarm_btn.add_event_cb(lambda e: self.__alarm_btn_event_cb(e), lv.EVENT.PRESSED, None)
+ self.monitor_btn.add_event_cb(lambda e: self.__monitor_btn_event_cb(e), lv.EVENT.PRESSED, None)
+ self.monitor_btn_2.add_event_cb(lambda e: self.__monitor_btn_event_cb(e), lv.EVENT.PRESSED, None)
+ self.dev_btn.add_event_cb(lambda e: self.__dev_btn_event_cb(e), lv.EVENT.PRESSED, None)
+ self.setting_btn.add_event_cb(lambda e: self.__setting_btn_event_cb(e), lv.EVENT.PRESSED, None)
+
+ def __weather_btn_event_cb(self,e):
+ src = e.get_target()
+ code = e.get_code()
+ print("The click event occurs")
+ EventMesh.publish("load_screen", "WeatherScreen")
+
+ def __monitor_btn_event_cb(self,e):
+ src = e.get_target()
+ code = e.get_code()
+ print("The click event occurs")
+ EventMesh.publish("load_screen", "MonitorScreen")
+
+ def __alarm_btn_event_cb(self,e):
+ src = e.get_target()
+ code = e.get_code()
+ print("The click event occurs")
+ EventMesh.publish("load_screen", "AlarmScreen")
+
+ def __dev_btn_event_cb(self,e):
+ src = e.get_target()
+ code = e.get_code()
+ print("The click event occurs")
+ EventMesh.publish("load_screen", "Dev1Screen")
+
+ def __setting_btn_event_cb(self,e):
+ src = e.get_target()
+ code = e.get_code()
+ print("The click event occurs")
+ EventMesh.publish("load_screen", "SettingScreen")
+```
+
+Taking the switching weather screen in the above example code as an example:
+
+```Python
+self.weather_btn.add_event_cb(lambda e: self.__weather_btn_event_cb(e), lv.EVENT.PRESSED, None)
+```
+
+Bind callback function ` __weather_btn_event_cb()` for weather control
+
+```Python
+ def __weather_btn_event_cb(self,e):
+ src = e.get_target()
+ code = e.get_code()
+ print("The click event occurs")
+ EventMesh.publish("load_screen", "WeatherScreen")
+```
+
+Execute`EventMesh.publish("load_screen", "WeatherScreen")` in the callback function, and publish the`load_streen` event to `EventMeth`, meaning to load the screen, carrying the message `WeatherScreen`, indicating to load the `WeatherScreen` interface.
+
+
+
+### Screen module
+
+`screen.py` defines a `Screen` class as the base class for all interfaces, which is defined as follows:
+
+```Python
+class Screen(object):
+ """Abstract class of screen"""
+
+ def __init__(self):
+ super().__init__()
+ self.style_siyuan_14_red = None
+ self.style_siyuan_16_blue = None
+ self.style_opa_btn = None
+ self.style_siyuan_26 = None
+ # Some code is omitted here
+ def create_style(self):
+ """
+ create style
+ """
+ # Interface style, background color: 3a5283
+ style_screen = lv.style_t()
+ style_screen.init()
+ style_screen.set_bg_color(lv.color_make(0x3a, 0x52, 0x83))
+ style_screen.set_bg_opa(255)
+ self.style_screen = style_screen
+
+ # The style of the left menu bar
+ style_cont_menu = lv.style_t()
+ style_cont_menu.init()
+ style_cont_menu.set_radius(0)
+ style_cont_menu.set_bg_color(lv.color_make(0x28, 0x39, 0x5c))
+ style_cont_menu.set_bg_grad_color(lv.color_make(0x28, 0x39, 0x5c))
+ style_cont_menu.set_bg_grad_dir(lv.GRAD_DIR.VER)
+ style_cont_menu.set_bg_opa(255)
+ style_cont_menu.set_border_color(lv.color_make(0x21, 0x95, 0xf6))
+ style_cont_menu.set_border_width(0)
+ style_cont_menu.set_border_opa(0)
+ style_cont_menu.set_pad_left(0)
+ style_cont_menu.set_pad_right(0)
+ style_cont_menu.set_pad_top(0)
+ style_cont_menu.set_pad_bottom(0)
+ self.style_cont_menu = style_cont_menu
+ # Some code is omitted here
+```
+
+The `Screen` class provides common methods required for all screen objects, such as creating screens and displaying status bar information (operator name, signal strength, system time, battery level, etc.). QuecPython uses NXP's [GUI Guider](https://www.nxp.com/design/design-center/software/development-software/gui-guider:GUI-GUIDER) as a graphical interface design tool, generates the style code for this section.
+All script files ending with `_screen. py` implement a class inherited from `class Screen()`, which is the code implementation corresponding to the screen that needs to be displayed. The main content of the interface code is provided by the GUI Guider tool is automatically generated and then slightly modified, mainly by modifying the object initialization method ` __init__() ` and the control event handling callback function ` __xxx_event_cb() `.
+
+
+
+### GUI startup
+
+The `load_screen` event is subscribed to in the `start()` method of the `class AgriUi (object)` class in the `Agri_ui.py` script file.
+
+example:
+
+```python
+class AgriUi(object):
+
+ # Some code is omitted here
+
+ def __create(self):
+ for screen in self.screens:
+ screen.create()
+
+ def start(self):
+ self.__create()
+ EventMesh.subscribe("load_screen", self.__route)
+ EventMesh.publish("load_screen", "WelcomeScreen")
+ utime.sleep(2)
+ EventMesh.publish("load_screen", "MainScreen")
+
+ def __route(self, topic, meta):
+ for screen in self.screens:
+ if screen.name == meta:
+ lv.scr_load(screen.screen)
+```
+
+The`start()` method in the above code is used to launch the graphical interface of the smart agriculture control panel, and its workflow is as follows:
+
+- Call the ` __create() ` method to create metadata for each screen interface.
+
+- Call the `EventMesh. subscribe()` method to subscribe to an event named `load_screen`. When the event occurs, call the `__route()` method to process it.
+
+ > The `route()` method matches the corresponding interface object based on the message carried when publishing the event, that is, the name of the screen interface, and calls lvgl's `lv. scr_load() `method to load the new interface.
+ > Observant readers will notice that in every class implemented in the screen interface script file, there will be statements similar to `self. name=" MainScreen"` in its object initialization method `__init__()`. This statement records the name of the screen interface.
+
+- The `EventMesh.publish("load_screen", "WelcomeScreen")` statement is used to trigger the first interface display, which is the welcome interface. Then wait for the welcome interface to display for 2 seconds, creating a good visual experience.
+
+- After the welcome interface ends, use the ` EventMesh.publish("load_screen", "MainScreen")` statement to trigger the display of the main interface.
+
+At this point, the graphical interface of the smart agriculture control panel has been launched, and the subsequent interface switching is controlled by the user's touch.
+
+In summary`Agri_ui.py` performs all initialization work for the smart agriculture control panel, including lvgl initialization and MIPI LCD initialization; At the same time, it provides a graphical interface for adding screen objects and a GUI launcher. The screen object adder is used to add all possible screen objects that may need to be displayed in the application, and the GUI launcher is used to launch graphical interface functionality.
+
+
+
+## Graphic interface design
+
+As mentioned earlier, QuecPython uses NXP's GUI Guider as a graphical interface design tool, GUIDER not only enables interface layout design, but also automatically generates QuecPython code. [Click here](https://python.quectel.com/doc/Application_guide/en/multi-media/lvgl/lvgl_ui_tool.html) to view the tutorial on using the GUI Guider tool.
+
+### Layout and background settings
+
+Create a smart agriculture project and choose a suitable layout template and background design. This stage will start with a blank layout design, selecting a blank template and setting the resolution to 854 * 480.
+
+ 
+
+
+
+### Draw screen
+
+This section will start drawing the various modules in the homepage.
+
+1.**Left navigation bar**:
+
+
+
+- **component**: imgbtn。
+- **icon**: Use easily recognizable icons as shortcuts to access homepage, display data, settings, controls, and other functions.
+- **layout**: The icon is vertically aligned and placed on the left side of the interface for easy use.
+- **interactivity**: Add a selection effect to the icon to enhance the interactive experience.
+
+When using the `imgbtn` component in GUI Guider software to create the left shortcut bar in the graphical interface of smart agriculture, you will need to pay attention to several key design elements:
+
+1. Icon selection:
+ - Each `imgbtn` should select an intuitive icon representing its function, such as a home shaped icon representing the homepage and a gear shaped icon representing the settings.
+ - Icon design should be concise and clear, so that users can recognize its function at a glance.
+2. Size and spacing:
+ - The size of each `imgbtn` should be large enough for users to easily click, especially on touchscreen devices.
+ - There should be appropriate spacing between shortcut keys to prevent accidental touches and make the interface look neater.
+3. Icon status:
+ - Design icons in different states, such as default state, floating state, and click state, to provide visual feedback and enhance user interaction experience.
+ - The 'imgbtn' component should support state switching so that users can see the interface response caused by their cross cloud actions.
+4. Functionality:
+ - Each `imgbtn` should be configured with the correct event handler to ensure that the user can trigger the correct action or navigate to the corresponding interface when clicking.
+ - If the function represented by `imgbtn` is currently activated or located on the current page, it should be displayed in different visual styles to indicate its activity status.
+
+2.**Top Information Display Bar**:
+
+
+
+- **component**: label、image.
+- **Operator information**: Display the mobile operator or network status on the top left side of the interface.
+- **Time display**: Display the current time in the middle position at the top of the interface.
+- **Signal strength and battery level indication**: Display icons for Wi Fi or network signal strength and current battery level on the top right side of the interface.
+
+When using GUI Guider software to design the top information display bar of the smart agriculture control panel, combine the `label` and `image` components to create an informative and visually recognizable status bar. Here are the detailed steps on how to use these components to design the top information display bar:
+
+1. Operator information:
+ - Use the `label` component to display operator information. Choose clear and easy to read fonts and sizes to ensure easy reading on different devices.
+ - Place the `label` component on the left side of the top information bar and set an appropriate alignment, usually left aligned.
+2. Time display:
+ - Another `label` component is used to display time. You can set a timer to ensure that the time is always updated.
+ - The time label is usually located on the right side of the information bar and should have sufficient recognition, which can be achieved by increasing the font size and bolding.
+3. Signal strength:
+ - Signal strength can be represented by a series of predefined signal icons. These icons can display different images based on the strength of the signal.
+ - Use the `image` component to place the signal strength icon and place it on the right side of the top information bar.
+4. Battery Indicator:
+ - The battery level indicator is also displayed using the `image` component, and you can prepare a set of battery level icons to reflect different battery levels.
+ - Place the battery icon on the far right side of the top information bar, adjacent to the signal strength icon.
+
+3.**Weather module**:
+
+
+
+- **component**: label、container、image。
+- **Current Weather**: Display the current weather conditions and temperature.
+- **Future weather forecast**: Provide horizontal scrolling or small grids next to or below the current weather to display the weather forecast for the next few days.
+
+1. When designing the weather information module on the upper left side in GUI Guider, you can combine `label` , `image` and `container` components to create an intuitive and informative weather display area. Here are the steps on how to use these components to design a weather information module:
+
+ - Basic container settings:
+
+ - Place a `container` component in the upper left corner of the interface as the basis for the weather module. This container will contain all weather related subcomponents.
+ - Adjust the size of the `container` to ensure it can accommodate all sub components without appearing crowded.
+
+2. Position display:
+ - Use a `label` component to display the current geographic location or farm name at the top of the container.
+ - This label can use larger fonts and bold effects so that users can clearly identify location information.
+
+3. Current temperature and weather:
+ - Use two `label` components to describe the current temperature and weather. These should use clear and easy to read fonts, and be appropriately sized for clarity at a glance.
+ - The label for the current temperature should be the most prominent and may require larger font size and prominent colors.
+
+4. Weather icon:
+ - Use the `image` component to display icons of current weather conditions, such as sunny, cloudy, rainy, etc.
+ - The weather icon should be adjacent to the `label` of the current temperature, providing a visual representation of the weather.
+
+5. Weather forecast:
+ - Use multiple label and image components below or next to the container to display the weather forecast for the next 5 days.
+ - The daily forecast can be displayed using a small `image` component to show the weather icon, followed by a `label` component to show the date.
+
+6. Adaptive Design
+ - When designing, it is important to ensure that the weather information area can adapt to different screen sizes and resolutions, especially on responsive interfaces.
+ - The sub component should be able to automatically adjust its size and position when the size of the container changes.
+
+4.**Historical curve of temperature and humidity**:
+
+
+
+- **component**: container,chart ,label。
+- **Chart Style**: Use a line graph to display historical data trends of temperature and humidity.
+- **Timing**: Provide options to view data from different time periods, such as day, week, and month.
+- **Interactivity **: Allow users to hover or click on points on the chart to view specific data points.
+
+When using GUI Guider to design the temperature history curve on the lower left side of the smart agriculture graphical interface, layout the label` Chart and container components. These components will collectively form a chart area displaying temperature trends. The following are specific design instructions:
+
+1. Container Layout:
+ - Place a `container` component on the lower left side of the interface to serve as the background and framework for the temperature history curve. This container will contain charts and related labels.
+ - Set the width and height of the container to meet the display requirements of the curve graph, while maintaining coordination with other interface elements.
+2. Curve chart:
+ - Add a `chart` component inside the`container` to draw a historical temperature data curve.
+ - Configure the `chart` component to display temperature data of time series, such as setting the x-axis as the time axis and the y-axis as the temperature values, to ensure that the data points are clear and visible.
+ - Define curve styles, such as curve color, thickness, and whether to display markers for data points.
+3. Title tag
+ - Use the `label` component above the graph or at the top of the container to display the title, such as Historical Curve.
+ - Choose the appropriate font size and style to ensure that the title is clear and consistent with the overall design style.
+4. Responsive design
+ - For responsive interfaces, ensure that the `container` and its `chart` and `label` components can be appropriately scaled according to different screen sizes.
+ - Test the display effect of charts on different resolutions and devices to ensure that the data is always clear and visible.
+
+5.**Common environmental parameters display**:
+
+
+
+- **component**: container,label。
+- **Data display block**: Display key parameters in the form of independent "blocks" or "cards", such as current readings of soil pH, soil temperature, oxygen and carbon dioxide concentrations, etc.
+
+When designing the environmental parameter display on the upper right side of the smart agriculture graphical interface in GUI Guider software, the 'label' and 'container' components can be used to clearly display key information such as soil pH value, oxygen concentration, soil moisture, and carbon dioxide concentration. The following are detailed design steps:
+
+1. Environment parameter container:
+ - Place a `container` component on the upper right side of the interface as a wrapping element for all environment parameters. This container will help organize and separate different parameter displays.
+2. Parameter label:
+ - For each environmental parameter, use a separate `label` component to display the parameter name and value. For example, one label displays "Soil pH value: 7.1", another label displays "Oxygen concentration: 50%", and so on.
+ - The `label` of parameter names can use smaller fonts, while the `label` of numerical values can use larger or bolded fonts to highlight numerical information.
+3. Parameter update mechanism:
+ - If possible, design a data update mechanism to periodically refresh the displayed environmental parameter values. This can be done by binding the 'label' component to the data source and setting a timer to update the values.
+
+6.**Alarm Information Area**:
+
+
+
+- **component**: container,label,table。
+- **list view**: Display recent alerts and warnings in the form of a list or log.
+- **priority indication**: Use color coding or icons to indicate the priority or severity of alarms.
+- **interactivity **: Allow users to click on the alarm to obtain more details or confirm and clear notifications.
+
+When using GUI Guider software to design the lower right alarm information area of the smart agriculture graphical interface, you can use `label` `container` and `table` components are used to effectively display alarm titles and specific alarm information. This area will provide users with critical security and system status updates. The following is a detailed design process:
+
+1. Alarm information container:
+ - Place a `container` component on the bottom right side of the interface as the main framework for the alarm information area. This container will contain the title and specific content of the alarm information.
+ - Set the size of the container to ensure sufficient space to display alarm information while maintaining coordination with other elements on the interface.
+2. Alarm Information Title:
+ - Use a `label` component to display a title at the top of the container, such as Alarm Information.
+ - Choose eye-catching and easy to read fonts and sizes to ensure that users can clearly identify the functionality of this area.
+3. Alarm Information Table:
+ - Use the `table` component below the `container` to list specific alarm information. This can include columns such as alarm time, type, status, etc.
+ - Adjust the column width and row height of the `table` to ensure that all information is clearly visible.
+4. Alarm information style:
+ - Set appropriate background, border, and font colors for the `table` component to maintain consistency with the overall interface style.
+ - Consider using different colors or icons to represent different levels of alerts, such as red for emergency alerts and yellow for warnings.
+5. Alarm information update mechanism:
+ - Design a data update mechanism that allows the`table` component to dynamically display the latest alarm information. This may require binding the `table` component to the backend data source and setting a scheduled refresh.
+6. Responsive design:
+ - Ensure that the `container` and its `table` and `label` components can be appropriately scaled at different screen sizes and resolutions.
+ - On a small screen, it may be necessary to adjust the layout of the `table` to ensure the readability of information.
+
+When placing these elements in the GUI Guider, ensure that each component is placed according to a grid or flexible layout system to accommodate different screen sizes and resolutions. The interface design should be concise, with sufficient blank space to avoid crowding. The color scheme used should highlight important information but not be glaring. Interactive elements should provide instant feedback, such as floating or changing appearance when clicked. In addition, the design should be tested on different devices to ensure its availability and performance.
+
+If the system is to be used under various lighting conditions, such as direct sunlight, it should be able to adjust contrast and brightness to enhance visibility. Finally, interface design should be intuitive, allowing new users to navigate without extensive training, reflecting good user experience (UX) design principles.
diff --git a/docs/Application_guide/en/solutions/DTU-EG912U/README.md b/docs/Application_guide/en/solutions/DTU-EG912U/README.md
index 4684663f172f67d0acbc6cd2cb22abb65bcb6ac2..6ace0d164c643205b2bf17b33ec6e178c6fe7dde 100644
--- a/docs/Application_guide/en/solutions/DTU-EG912U/README.md
+++ b/docs/Application_guide/en/solutions/DTU-EG912U/README.md
@@ -1,24 +1,21 @@
# DTU based on EG912U
-DTU products are equipped with EG912U module, support 4G Cat1 full network, can achieve serial port and 4G (CAT1) data transmission, compared with the traditional 2G/3G network, wider coverage, faster speed, lower delay. 3.3V power supply. Provides TTL interfaces. Easy and fast development, support transparent transmission, support Python secondary development. This product solution supports 4G full netcom, uses 3.3V power supply, TTL interface, so that this product can be applied to various industries and complex scenarios to meet the needs of communication data transmission, such as power grid, traffic, fire protection, industrial production, meteorological environment, agriculture, minerals and so on.
+Based on EG912U core version DTU, it supports 4G and can achieve data exchange between serial port and 4G (CAT1). Compared with traditional 2G/3G networks, it has wider coverage, faster speed, and lower latency. Easy and fast development, supports transparent transmission, and supports Python secondary development. Small in size and easy to install, this product can be applied to various industries and complex scenarios to meet the needs of communication and data transmission, such as power grid, transportation, fire protection, industrial production, meteorological environment, agriculture, mining, and so on.
-**Feature Lis**:
+**Feature List**:
- Mqtt transparent transmission is supported
- Supports TCP/UDP transparent transmission
- Support 4G full Netcom
- Support Python language secondary development
-- POWER/DATA/WORK indicators
**Product icon**:
-## Developer Guide
+------
-[dev_resources](./dev_resources.md)
-
-[quick_start](./quick_start.md)
-
-[software_design](./software_design.md)
+- [development resources](./dev_resources.md)
+- [quick start](./quick_start.md)
+- [software design](./software_design.md)
diff --git a/docs/Application_guide/en/solutions/DTU-EG912U/dev_resources.md b/docs/Application_guide/en/solutions/DTU-EG912U/dev_resources.md
index 13a2af1580fa7598c7580717ff71b4e17fb63dcc..9d16c65a1dfc2d082609c629350b659de79af5cc 100644
--- a/docs/Application_guide/en/solutions/DTU-EG912U/dev_resources.md
+++ b/docs/Application_guide/en/solutions/DTU-EG912U/dev_resources.md
@@ -35,8 +35,8 @@ Mode:[EG912U Core Board](https://python.quectel.com/doc/Getting_started/zh/evb
- flash zip from sd card
-- versions: QPY_OCPU_BETA0002_EG912U_GLAA_FW
-- Download link:[Click to jump](https://python.quectel.com/wp-content/uploads/2024/09/QPY_OCPU_BETA0002_EG912U_GLAA_FW.zip)
+- firmware versions: QPY_OCPU_BETA0002_EG912U_GLAA_FW
+ - Download link:[Click to jump](https://python.quectel.com/wp-content/uploads/2024/09/QPY_OCPU_BETA0002_EG912U_GLAA_FW.zip)
## Experimental source code
diff --git a/docs/Application_guide/en/solutions/DTU-EG912U/software_design.md b/docs/Application_guide/en/solutions/DTU-EG912U/software_design.md
index 483b20514f9ecbd4f9be90b9f31a65580f4320e5..902370936247cd3104405437bf3dff3fb42da59b 100644
--- a/docs/Application_guide/en/solutions/DTU-EG912U/software_design.md
+++ b/docs/Application_guide/en/solutions/DTU-EG912U/software_design.md
@@ -42,23 +42,7 @@ In this scheme, multiple object models are defined, among which the main ones ar
The DTU class is defined in the `dtu.py`module, which is mainly used to initialize serial port, cloud, and upstream and downstream data services.
-Support for storing relevant configurations in a JSON file is provided. The operation method is similar to that of the built-in dictionary type. The following way can be adopted to read and write the configurations (taking the reading of `system_config` configuration item as an example).
-
-- Import the configuration from the specified json file:`Serial(**config.get('uart_config'))`
-- Use the `get` method to read the configuration item:`config.get('system_config.cloud')`
-
-```python
-from usr.dtu import DTU
-
- self.queue = Queue() # DTU application interacts with MQTT and TCP client downlink data through the data exchange queue for the client side.
- self.serial = Serial(**config.get('uart_config'))
-
- cloud_type = config.get('system_config.cloud')
-```
-
-
-
-Implement the cloud communication function of MQTT protocol, providing connection, subscription, publication and monitoring functions.
+Implement the cloud communication function of MQTT protocol, providing connection, subscription, publication and monitoring functions. Mqtt cloud object init as below:
```python
self.cloud = MqttIot(
@@ -75,12 +59,9 @@ self.cloud = MqttIot(
queue=self.queue,
error_trans=True
)
-
```
-
-
-- It implements the cloud communication function of TCP/UDP protocol, providing connection, sending, receiving and listening functions.
+Implements the cloud communication function of TCP/UDP protocol, providing connection, sending, receiving and listening functions. Socket object init as below:
```python
self.cloud = SocketIot(
@@ -93,32 +74,27 @@ self.cloud = SocketIot(
)
```
-
-
`up_transaction_handler` method: This is the entry function for the uplink data transmission business thread.
`down_transaction_handler` method: It is the entry function for the downlink data transmission business thread.
-```
- def down_transaction_handler(self):
- while True:
- topic, data = self.cloud.recv()
- logger.info('down transfer msg: {}'.format(data))
- self.serial.write(data)
+```python
+def down_transaction_handler(self):
+ while True:
+ topic, data = self.cloud.recv()
+ logger.info('down transfer msg: {}'.format(data))
+ self.serial.write(data)
- def up_transaction_handler(self):
+def up_transaction_handler(self):
while True:
data = self.serial.read(1024, timeout=100)
if data:
logger.info('up transfer msg: {}'.format(data))
self.cloud.send(data)
-
```
`run` method: Initiates business operations, including creating serial ports and cloud objects based on configuration files, as well as creating business data processing threads for the upper and lower industries.
-
-
#### Serial object model
- In the `serial.py` module, the serial port model class `Serial` is defined. This class is mainly used to implement the read and write operations of the serial port. The main interfaces include:`Serial`
diff --git a/docs/Application_guide/en/solutions/DTU/README.md b/docs/Application_guide/en/solutions/DTU/README.md
index fb95e70b17797b87a8dcbc80c43f937735f2d959..78685e034301b79cda5c784a0791d9193d5d3534 100644
--- a/docs/Application_guide/en/solutions/DTU/README.md
+++ b/docs/Application_guide/en/solutions/DTU/README.md
@@ -1,547 +1,26 @@
-# DTU Introduction
+# EP-D200 Hua Series DTU
-## Solution Overview
+The Hua series DTU products are equipped with the Mobile EC800G-CN module, which supports 4G Cat1 full network communication and can achieve data exchange between serial ports and 4G (CAT1). Compared with traditional 2G/3G networks, it has wider coverage, faster speed, and lower latency. Using wide voltage (9-36V) power supply. Rich interfaces are available, with RS232, RS485, and TTL interfaces to choose from. Easy and fast development, supports transparent transmission, and supports Python secondary development. Safe and reliable, supporting software and hardware watchdog protection. Compact and easy to install (22.6 * 74.6 mm). This product solution supports 4G full network connection, uses wide voltage (9-36V) power supply, and provides three interfaces: RS232, RS485, and TTL. It can be applied to various industries and complex scenarios to meet the needs of communication and data transmission, such as power grid, transportation, fire protection, industrial production, meteorological environment, agriculture, mining, etc.
-### DTU Introduction
+**Function List **:
-DTU (Data Transfer Unit) is a **wireless terminal device** specially used to **convert** serial port **data** into network data or convert network data into serial port data for wireless **communication** through **networks**. It has many advantages such as flexible networking, wide network coverage, short construction cycle, and low cost. It is widely used in meteorology, hydrology, geology and other industries.
+- Support Mqtt transparent transmission
+- Support TCP/UDP transparent transmission
+- Supports RS485 to 4G conversion
+- Support 4G full network connectivity
+- Support secondary development of Python language
+- Support 9-36V wide power supply
+- POWER/DATA/WORK indicator lights
-### Basic Principles
+**Product Diagram**
-The main function of DTU is to transmit the device data wirelessly back to the cloud (backend service), as shown in `Figure 1: DTU Introduction`. To complete the data transmission, a complete data transmission system needs to be established. This system includes: DTU device, customer device (MCU), mobile network, backend center (cloud). Insert a SIM card into the DTU device. After the device is powered on, it will first **dial and register the network**; then **establish a connection** with the cloud center service through the network; After that, the DTU device can **communicate bidirectionally** with the cloud backend service —— receive MCU data through the serial port, process it and report it to the cloud (**uplink data**), and process the data received from the cloud and send it to the MCU through the serial port (**downlink data**).
+
-
+------
-Figure 1: DTU Introduction
-> The sensor (temperature, humidity sensor, etc.) collects data and sends it to the MCU device end. The MCU device end sends the collected data to the cloud end server through the serial port of DTU. After receiving the data, the server can analyze, process, display, save, etc.
+- [development resources](./dev_resources.md)
-### Application Areas
+- [quick start](./quick_start.md)
-
+- [software design](./software_design.md)
-Figure 2: DTU Application Areas
-## Hardware Selection
-
-This solution supports multiple QuecPython hardware devices. The following introduces the `QuecPython EVB development board` and `DP-DTU-Q600`.
-
-#### QuecPython_EVB Development Board Introduction
-
-Take the `QuecPython_EC2X_EVB_V2.0` development board (EC2X development board introduction: ) equipped with the `EC200U` module as an example. As shown in the figure below, the device supplies power to the module through type-c, and connects UART to the PC via the TTL to USB module for easy debugging.
-
-
-
-Figure 3: QuecPython_EC2X_EVB_V2.0 connects to PC via UART and TTL to USB
-
-
-
-| Pin on development board | TTL to USB module | Color of wire in picture |
-| ------------------------ | ----------------- | ------------------------ |
-| Pin 13 (TX) of J7 | RX | Red |
-| Pin 14 (RX) of J7 | TX | Orange |
-| Pin 3 (GND) of J7 | GND | Yellow |
-
-For more development boards, please refer to: .
-
-#### DP-DTU-Q600 Product Introduction
-
-DP-DTU-Q600 is a DTU with LTE CAT1 network, which is convenient to be integrated into industrial computers, industrial equipment, sensing devices, etc. Its physical size is 72mm x 40.5mm x 20mm. The product has the characteristics of wide network coverage and low transmission latency. It supports access of three major operators; The product has three indicator lights for customers to easily confirm the device status.
-
-
-
-Figure 4: DP-DTU-Q600
-Product Specifications:
-
-| Specification | Parameter |
-| ----------------------- | ------------------------- |
-| Power supply range | DC5-24V |
-| DC5-24V | 2PIN terminal |
-| Antenna interface | SMA external thread holes |
-| SIM card interface | Pop-up NANO SIM card slot |
-| Network system | 4G CAT1 full Netcom |
-| Communication interface | 2PIN terminal RS485 |
-
-Product Features:
-
-- Built-in TCP/IP protocol stack, and embedded operating system, with dial-up Internet access and TCP/IP data communication functions
-- Provides serial data bidirectional conversion function
-- Support heartbeat to keep always online
-- Support parameter configuration, permanently saved
-- Support user serial port parameter settings
-- Support user secondary development
-- IoT card, no special card required, general IoT cards can be used
-- NANO SIM card slot
-- RS485 interface for easy integration
-
-Device Debugging:
-
-- Insert the SIM card into the NANO SIM card slot
-- Connect the antenna
-- Connect the power supply
-
-
-
-Figure 5: DP-DTU-Q600 Hardware Interface
-Connect the device to the development machine (this article uses `CP2102 USB to TTL module` for connection and debugging).
-
-Use 2 DuPont lines to connect the `485A` and `485B` pins, and connect the `CP2102` to the `USB` port of the development machine (as shown in Figure 6).
-
-
-
-Figure 6: Connect DP600R to development machine
-> After successful connection, when the device is powered on and connected to the network, the `power` and `net` indicator lights will light up.
-
-#### Debug with QPYcom
-
-Refer to the document for installing QPYCom and building the QuecPython development environment: .
-
-##### Open repl serial port
-
-
-
-Figure 7: QPYCom open repl serial port
-##### Download Script
-
-Create download project - Switch to the Download tab, click Create Project, and enter any project name.
-
-> Here we create a project named `dtu`.
-
-
-
-Figure 8: QPYCom create new project
-Select import file - Right-click the `usr` directory, click **Import All** in the pop-up dialog box, and then select the **code** folder in our DTU code repository - import all code in code into the module in one click. As shown below:
-
-
-
-Figure 9: QPYCom one-click import script
-Import script - Click the `Download Script` button in the lower right corner to start importing the script.
-
-##### Run DTU Application
-
-Switch to the "Files" tab, select "dtu.py" on the right, and click the Run button to start dtu debugging and running. To run automatically after power-on, just rename "dtu.py" to "main.py".
-
-
-
-Figure 10: QPYCom run script
-DTU runs successfully. In the "REPL" window of QPYcom, you can observe the following printout.
-
-> The application relies on specific user parameter configurations, such as configuring MQTT connection parameters. Refer to the subsequent DTU scheme introduction section.
-
-
-
-Figure 11: QPYCom script output log
-## Software Design of the Solution
-
-### System Diagram
-
-
-
-Figure 12: DTU Solution System Diagram
-Component Description:
-
-- Various cloud objects: Inherit `modules.CloudObservable` and override corresponding methods, mainly to implement cloud initialization, connection and data sending and receiving functions.
-- Subscriber: Inherit `modules.CloudObserver` and override corresponding methods, mainly to subscribe and receive message notifications from cloud objects, and call different executors according to message types for processing.
-- Executor: Mainly used for specific business processing, called by the subscriber. The default includes downlink executor (processing downlink data forwarding serial port), OTA upgrade executor (processing upgrade messages and triggering upgrades), and uplink executor (mainly used to process uplink data).
-- Publisher: Mainly associated with cloud objects, used to publish data to the cloud.
-
-Component Collaboration Process:
-
-- Build serial port object - At least one serial port is usually used as a communication channel, and multiple or one serial port is selected according to the actual situation.
-- Build downlink data executor and OTA upgrade executor - The executor is mainly used for business processing. Users need to implement specific business processing logic methods in the executor.
- - The downlink data executor needs to add a serial port object to process downlink messages - forwarded through the serial port.
- - OTA upgrade executor needs to implement specific upgrade business process.
-- Create cloud object - Support Alibaba Cloud, Tencent Cloud, MQTT, etc., import and use according to actual business needs.
-- Create subscriber.
- - The cloud object adds the subscriber as its observer.
- - Subscribers can have multiple, corresponding to multi-channel downlink message processing.
-- Create publisher.
- - Add cloud object as the target object for the publisher to publish messages.
-- Create uplink data executor.
- - The uplink data executor is mainly used to receive serial port data processing.
- - Add a publisher for the executor to publish messages. How the message is published is determined by the publisher.
-
-> Downlink data supports multiple channels. The **subscriber** can have multiple as an observer. Once a message is downlinked after a cloud adds multiple subscribers, it will notify all subscribers. Different subscribers may handle the data through different **downlink executors** or **OTA upgrade executors**.
->
-> Uplink data supports multiple channels. When multiple serial port data need to be monitored, there can be multiple **uplink executors** to forward multiple serial port data to the cloud.
-
-### Observer Pattern
-
-- **Concept:** When there is a one-to-many relationship between objects, the observer pattern (Observer Pattern) is used. For example, when an object is modified, it will automatically notify dependent objects. The observer pattern belongs to the behavioral pattern.
-
-- **Intent:** Define a one-to-many dependency relationship between objects. When the state of an object changes, all dependent objects are notified and updated automatically.
-
-- **Mainly solve:** The problem of notifying other objects when the state of an object changes, while considering ease of use and loose coupling to ensure a high degree of collaboration.
-
-- **When to use:** When the state of an object (target object) changes, all dependent objects (observer objects) will be notified to broadcast notification.
-
-- **Key Code:** There is a list in the abstract class to hold observers.
-
-In the design of the DTU solution, a cloud class object (`Socket` and `MqttIot`) is an **observable**, which will **notify** `RemoteSubscribe` (subscriber, **an observer**) when there is downlink data. , and `RemoteSubscribe` will call different **executors** for processing according to different businesses.
-
-### Component Class Design and Interaction
-
-#### Class Inheritance
-
-##### Cloud Class Inheritance Diagram
-
-```mermaid
-graph TD;
-CloudObservable[CloudObservable]
-CloudObservable --> MqttIot[MqttIot]
-CloudObservable --> AliYunIot[AliYunIot]
-CloudObservable --> HuaweiIot[HuaweiIot]
-CloudObservable --> Socket[Socket]
-CloudObservable --> TXYunIot[TXYunIot]
-```
-
-**CloudObservable**: Observable class, mainly used to inherit and override when defining various cloud object classes. The main user interfaces are:
-
-- init: cloud initialization
-
-- addObserver: Add an observer object
-- delObserver: Remove an observer object
-- notifyObservers: Notify all observers
-- through_post_data: transparent data publishing
-- post_data: cloud message publishing
-- ota_request: publish OTA upgrade request on cloud
-- ota_action: execute upgrade action
-
-##### Subscriber Class Inheritance Diagram
-
-```mermaid
-graph TD;
-CloudObserver[CloudObserver] --> RemoteSubscribe[RemoteSubscribe]
-```
-
-**CloudObserver**: Observer object class, mainly used for passive notification reception. The main methods are:
-
-- `execute`: This method will be called to perform specific actions after being notified by the observable.
-
-**RemoteSubscribe**: Subscriber, is an observer, used to receive cloud downlink data notifications. The main methods are:
-
-- `execute`: When notified, this method is called to perform specific business processing procedures. (Use different executors to handle different businesses, define 2 types of executors in this class object: `__executor` (ordinary executor), `__ota_executor` (dedicated to executing OTA upgrade executor))
-- `add_executor`: Add executor.
-
-#### Downlink Data Processing
-
-Downlink data processing sequence diagram:
-
-```mermaid
-sequenceDiagram
-Title: Device downlink data processing timing
-
-participant cloud as Cloud[mqtt]
-participant mqtt as MqttIot
-participant rs as RemoteSubscribe
-participant executor as Executor
-
-mqtt -->> cloud: connect cloud & subscribe
-rs -->> executor: add executor
-mqtt -->> rs: add observer
-rs -->> rs: Waiting for notification
-
-cloud ->> mqtt: downlink data
-mqtt ->> rs: notify observer(carrying downlink data)
-rs ->> executor: call executor
-```
-
-This solution defines two types of executors for processing downlink data:
-
-- `DownlinkTransaction`: Downlink data executor, responsible for forwarding cloud data through serial port.
-- `OtaTransaction`: OTA upgrade executor, responsible for processing upgrade related operations.
-
-For example, when there is downlink data, if it is transparent data, the `DownlinkTransaction` executor will be called to forward the data to the MCU through the serial port; if it is an OTA upgrade message, the `OtaTransaction` executor will be called. Perform upgrade operations.
-
-#### Uplink Data Processing
-
-Uplink data processing sequence diagram:
-
-```mermaid
-sequenceDiagram
-Title: Device uplink data processing timing
-
-
-participant cloud as Cloud[mqtt]
-participant mqtt as MqttIot
-participant rp as RemotePublish
-participant executor as UplinkTransaction
-
-
-mqtt -->> cloud: connect cloud & subscribe
-rp -->> mqtt: add cloud
-executor -->> rp: add publisher
-executor -->> executor: read serial data
-
-executor ->> rp: uplink data
-rp ->> mqtt: check connect status
-mqtt ->> rp: report connect status
-rp ->> mqtt: reconnect according to status
-
-rp ->> mqtt: uplink data
-mqtt ->> cloud: uplink data
-```
-
-This solution defines one type of uplink data executor:
-
-- `UplinkTransaction`: Uplink data executor, used to receive serial port data and upload it to the cloud.
- - Main attributes:
- - `__remote_pub`: Remote publisher, used to upload data to the cloud. It is an object of class `modules.remote.RemotePublish`.
- - `__serial`: Serial port object, used for serial port data sending and receiving. Defined in `modules.serial.Serial`.
- - Main methods:
- - `uplink_main`: Used to receive serial port data and upload it to the cloud.
-
-## User Guide
-
-### Write Configuration File
-
-DTU configuration file path: `code/dtu_config.json`.
-
-Make the following configurations based on private mqtt cloud:
-
-- System configuration
-
-
-
-- Private mqtt cloud configuration
-
-
-
-Device interface call flow (interface call logic, parameter configuration), upper computer tool configuration parameters, cloud configuration
-
-### DTU Initialization Process and Interface Description
-
-The application class `Dtu` is defined in `code/dtu.py`. Its instance is the application object. Calling the `start` method starts the application service.
-
-```python
-from usr.dtu import Dtu
-
-if __name__ == "__main__":
- dtu = Dtu()
- dtu.start()
-```
-
-#### `Dtu` Class Interface Description
-
-The following methods are defined in the `Dtu` class, as described below (see comments in code for full description, complete code refer to `dtu.py` usage example):
-
-```python
-class Dtu(Singleton):
-
- def __init__(self):
- # Define a timer to periodically check OTA upgrade plan
- self.__ota_timer = osTimer()
- # OTA upgrade executor, used to perform OTA upgrade related operations
- self.__ota_transaction = None
-
- def __cloud_init(self, protocol):
- # Initialize cloud object and connect to cloud according to protocol
- # This parameter corresponds to config item `system_config.cloud`
- pass
-
- def __periodic_ota_check(self, args):
- # Periodically check OTA upgrade plan
- pass
-
- def start(self):
- # Initialize DTU and start services
- pass
-```
-
-#### Application Service Initialization Process Description
-
-After the `start` function is called, the DTU application service is initialized and various services are started.
-
-Initialization process:
-
-- Load system configuration
-- Create serial communication object (`usr.modules.serial.Serial`)
-
-- Create cloud object (`usr.modules.mqttIot.MqttIot` or other cloud objects)
-- Create GUI tool communication object (`usr.modules.dtu_transaction.GuiToolsInteraction`)
-- Create uplink data executor (`usr.modules.dtu_transaction.UplinkTransaction`)
-- Create downlink data executor (`usr.modules.dtu_transaction.DownlinkTransaction`)
-- Create OTA upgrade executor (`usr.modules.dtu_transaction.OtaTransaction`)
-- Create subscriber (`usr.modules.remote.RemoteSubscribe`)
-- Create publisher (`usr.modules.remote.RemotePublish`)
-- Start timer to periodically check OTA upgrade plan
-- Create service thread to continuously read serial port data, parse and upload to cloud
-
-Detailed description of process steps:
-
-(1) Load system configuration
-
-```python
-from usr.settings import settings
-```
-
-`settings` is a global configuration file (`Settings`) object, corresponding to the `/usr/dtu_config.json` configuration file parameters, persisted in json format.
-
-Methods:
-
-- `get`: Get all current configuration parameters (i.e. dict type data imported from json file)
-- `set(opt, val)`: Set configuration item `opt` to parameter `val`.
-- `save`: Persistently save configuration.
-- `remove`: Delete configuration file.
-- `reset`: Restore default configuration.
-- `set_multi(**kwargs)`: Set parameters in batches.
-
-(2) Create serial communication object
-
-```python
-from usr.modules.serial import Serial
-
-# Serial initialization
-serial = Serial(int(uart_setting.get("port")),
- int(uart_setting.get("baudrate")),
- int(uart_setting.get("databits")),
- int(uart_setting.get("parity")),
- int(uart_setting.get("stopbits")),
- int(uart_setting.get("flowctl")),
- uart_setting.get("rs485_direction_pin"))
-```
-
-`serial` is a serial communication object (`Serial`).
-
-Methods:
-
-- `write(data)`: Pass in written data bytes.
-- `read(n, timeout)`: Read n bytes from serial port, timeout is timeout.
-
-(3) Create cloud object
-
-The `Dtu.__init_cloud` method is used to create a cloud object (create different cloud objects according to the system configuration file).
-
-```python
-class Dtu(object):
-
- def __init_cloud(self, protocol):
- if protocol == 'mqtt':
- cloud_config = settings.current_settings.get("mqtt_private_cloud_config")
- client_id = cloud_config["client_id"] if cloud_config.get("client_id") else modem.getDevImei()
- cloud = MqttIot(cloud_config.get("server", None),
- int(cloud_config.get("qos", 0)),
- int(cloud_config.get("port", 1883)),
- cloud_config.get("clean_session"),
- client_id,
- cloud_config.get("username"),
- cloud_config.get("password"),
- cloud_config.get("publish"),
- cloud_config.get("subscribe"),
- cloud_config.get("keep_alive")
- )
- cloud.init(enforce=True)
- return cloud
- else:
- # Omitted, refer to `code/dtu.py` for other cloud object initialization
- pass
-
- def start(self):
- # ...
- cloud = self.__cloud_init(settings.current_settings["system_config"]["cloud"])
- # ...
-```
-
-Take MQTT as an example, read mqtt configuration parameters from the system configuration file, instantiate the `MqttIot` object with passed parameters, and call the `MqttIot.init` method to complete the cloud object initialization operation.
-
-Methods:
-
-- `addObserver`: Add observer object, used by the cloud to handle it after receiving downlink data.
- - Subscriber: When receiving cloud notification (carrying downlink data), call executor to process.
-
-(4) Create GUI tool communication object
-
-```python
-gui_tool_inter = GuiToolsInteraction()
-```
-
-GUI communication object `GuiToolsInteraction`, used to parse upper computer instructions issued from serial port, and process specific instruction operations.
-
-Methods:
-
-- `parse_serial_data`: Parse serial data.
-
-(5) Create uplink data executor
-
-```python
-up_transaction = UplinkTransaction()
-up_transaction.add_module(serial)
-up_transaction.add_module(gui_tool_inter)
-```
-
-Methods:
-
-- `add_module`: Add module object.
- - Serial port object: Uplink executor reads serial port data through serial port object.
- - GUI communication object, parse the read serial port data through GUI object.
- - Publisher object, publish data to cloud through this object.
-- `uplink_main`: Read serial port data, and use GUI object to parse (if it is instruction data, process instruction operation, if it is uplink data, forward it to cloud).
-
-(6) Create downlink data executor
-
-```python
-down_transaction = DownlinkTransaction()
-down_transaction.add_module(serial)
-```
-
-Methods:
-
-- `add_module`: Add module object
- - Serial port object: Downlink executor forwards downlink data through serial port object.
-- `downlink_main`: Used to process downlink data.
-
-(7) Create OTA upgrade executor
-
-```python
-ota_transaction = OtaTransaction()
-```
-
-Methods:
-
-- `ota_check`: Check OTA upgrade plan
-- `event_ota_plain`: Respond to upgrade plan (verify parameters and start upgrade process after receiving issued upgrade plan)
-- `add_module`: Add module object
- - Publisher object: Report upgrade status or actively request upgrade plan through the publisher object.
-
-(8) Create subscriber
-
-```python
-remote_sub = RemoteSubscribe()
-remote_sub.add_executor(down_transaction, 1)
-remote_sub.add_executor(ota_transaction, 2)
-cloud.addObserver(remote_sub)
-```
-
-Methods:
-
-- `add_executor`: Add executor.
- - Downlink executor: Forward data through serial port.
- - OTA upgrade executor: Parse downlink upgrade message and process upgrade request.
-
-
-(9) Create publisher
-
-```python
-remote_pub = RemotePublish()
-remote_pub.add_cloud(cloud)
-up_transaction.add_module(remote_pub)
-ota_transaction.add_module(remote_pub)
-```
-
-Methods:
-
-- `add_cloud`: Add cloud object, use this cloud object to publish messages.
-
-(10) Start timer to periodically check OTA upgrade plan
-
-```python
-# Check upgrade plan every 600 seconds
-self.__ota_timer.start(1000 * 600, 1, self.__periodic_ota_check)
-```
-
-(11) Create service thread to continuously read serial port data, parse and upload to cloud
-
-```python
-# Start uplink transaction
-_thread.start_new_thread(up_transaction.uplink_main, ())
-```
-
-Start a separate thread to execute `up_transaction.uplink_main`. The `uplink_main` method continuously reads serial port data, uses `GuiToolsInteraction` to parse serial port data to process upper computer instructions, or uses `RemotePublish` to forward data to the cloud.
\ No newline at end of file
diff --git a/docs/Application_guide/en/solutions/DTU/dev_resources.md b/docs/Application_guide/en/solutions/DTU/dev_resources.md
new file mode 100644
index 0000000000000000000000000000000000000000..d732d27ae7f99326e409d73407175f64342f44b7
--- /dev/null
+++ b/docs/Application_guide/en/solutions/DTU/dev_resources.md
@@ -0,0 +1,58 @@
+# Development resources summary
+
+This document collects and lists the required hardware resource list and related supporting materials for the Hua series QuecPython 4G DTU.
+
+## Development board
+
+- model:[EC800GCN Hua serial DTU EVB](https://python.quectel.com/doc/Getting_started/zh/evb/ec800g_hua_dtu.html)
+- Purchase link:[click](https://www.quecmall.com/goods-detail/2c9080168ef07110018f1853d4050002)
+- EVB docs
+ - [user guidance](https://python.quectel.com/wp-content/uploads/2024/09/EC800G_华-DTU系列开发板产品规格及用户指导.pdf)
+
+## Module information
+
+- model: [EC800GCN](https://python.quectel.com/modules-cat/ec800g-series)
+- specification: [Quectel_EC800G-CN_LTE_Standard_specification](https://python.quectel.com/wp-content/uploads/2024/09/Quectel_EC800G-CN_LTE_Standard_%E6%A8%A1%E5%9D%97%E4%BA%A7%E5%93%81%E8%A7%84%E6%A0%BC%E4%B9%A6_V1.3.pdf)
+- download driver:[QuecPython_USB_Driver_Win10_U_G](https://python.quectel.com/wp-content/uploads/2024/09/Quectel_Windows_USB_DriverU_V1.0.19.zip)
+
+## Accessories Information
+
+- 4G antenna
+ - model: YECT012W1A
+ - Purchase link:[click](https://www.quecmall.com/goods-detail/2c90800c92239d5401923be899bc002c)
+- Nano Sim card
+- Mini USB
+- USB to TTL
+ - model: QTMU0085DP
+ - Purchase link:[click](https://www.quecmall.com/goods-detail/2c90800b8eec5c8e018f659f669c0043)
+
+## Development tool
+
+- QPYcom - QuecPython debug tool
+ - version:V3.6.0
+ - download [QPYcom](https://images.quectel.com/python/2022/12/QPYcom_V3.6.0.zip)
+- QCOM - serial debug tool
+ - version:V1.6
+ - download link:[click](https://python.quectel.com/wp-content/uploads/2024/09/QCOM_V1.6.zip)
+- VSCode
+ - download link:[click](https://code.visualstudio.com/)
+
+## Firmware
+
+- version: QPY_OCPU_BETA0002_EC800G_CNLD_FW
+- download link:[click](https://python.quectel.com/wp-content/uploads/2024/09/QPY_OCPU_BETA0002_EC800G_CNLD_FW.zip)
+
+## Source Code
+
+- version:v1.0.0
+
+- Github repo
+
+ ```shell
+ git clone https://github.com/QuecPython/solution-HuaDTU.git
+ cd solution-HuaDTU
+ git checkout v1.0.0
+ ```
+
+- [Github Zip download](https://github.com/QuecPython/solution-HuaDTU/archive/refs/heads/main.zip)
+
diff --git a/docs/Application_guide/en/solutions/DTU/mqtt_demo.md b/docs/Application_guide/en/solutions/DTU/mqtt_demo.md
new file mode 100644
index 0000000000000000000000000000000000000000..bf38200f50b1bcfb67635cbaaec5b58b8367947d
--- /dev/null
+++ b/docs/Application_guide/en/solutions/DTU/mqtt_demo.md
@@ -0,0 +1,155 @@
+# Device development based on MQTT protocol
+
+## Modify configuration file
+
+Configuration file path: `code/dtu_config.json`。
+
+Based on TCP private server data transparent transmission, configure as follows:
+
+- set `systemconfig.cloud` configuration item as `mqtt`, which means MQTT transparent mode.
+
+ ```python
+ {
+ "system_config": {
+ "cloud": "mqtt"
+ }
+ }
+ ```
+
+- This experiment adopts the MQTT transparent transmission mode, and users need to set the MQTT server domain name, port, client ID, and subscription and publishing topics parameters in the `mqtt_pivate_cloud_config` configuration item according to the actual situation, as follows.
+
+ ```python
+ {
+ "mqtt_private_cloud_config": {
+ "server": "mq.tongxinmao.com",
+ "port": 18830,
+ "client_id": "txm_1682300809",
+ "user": "",
+ "password": "",
+ "clean_session": true,
+ "qos": 0,
+ "keepalive": 60,
+ "subscribe": {"down": "/public/TEST/down"},
+ "publish": {"up": "/public/TEST/up"}
+ }
+ }
+ ```
+
+- The configuration item `uart_config` is a serial port configuration parameter, which defaults to the configuration made based on the current experimental development board and cannot be changed. If users use other development boards, they need to configure according to the actual hardware.
+
+```python
+{
+ "uart_config": {
+ "port": 2,
+ "baudrate": 115200,
+ "bytesize": 8,
+ "parity": 0,
+ "stopbits": 1,
+ "flowctl": 0,
+ "rs485_config": {
+ "gpio_num": 28,
+ "direction": 0
+ }
+ }
+}
+```
+
+The complete configuration file template is as follows:
+
+```json
+{
+ "system_config": {
+ "cloud": "tcp"
+ },
+ "mqtt_private_cloud_config": {
+ "server": "mq.tongxinmao.com",
+ "port": 18830,
+ "client_id": "txm_1682300809",
+ "user": "",
+ "password": "",
+ "clean_session": true,
+ "qos": 0,
+ "keepalive": 60,
+ "subscribe": {"down": "/public/TEST/down"},
+ "publish": {"up": "/public/TEST/up"}
+ },
+ "socket_private_cloud_config": {
+ "domain": "112.31.84.164",
+ "port": 8305,
+ "timeout": 5,
+ "keep_alive": 5
+ },
+ "uart_config": {
+ "port": 2,
+ "baudrate": 115200,
+ "bytesize": 8,
+ "parity": 0,
+ "stopbits": 1,
+ "flowctl": 0,
+ "rs485_config": {
+ "gpio_num": 28,
+ "direction": 0
+ }
+ }
+}
+```
+
+Parameter description:
+
+- ` systemconfig. config `: Specify the type of private cloud currently in use. Currently supports TCP and MQTT.
+
+- `mqtt_private_cloud_config`: MQTT private cloud configuration.
+- `socket_private_cloud_config`: TCP private cloud configuration.
+- `uart_config`: Serial port parameter configuration.
+
+## Script import and run
+
+After downloading and installing the QPYCom tool, use the tool to download the script to the QuecPython module.
+
+> 💡 **Tips**
+>
+> QPYCom Installation and usage tutorial: https://python.quectel.com/doc/Application_guide/en/dev-tools/QPYcom/index.html
+
+## Debugging
+
+**View REPL interaction port logs**
+
+After the program runs, the log output can be seen on the REPL interaction page as shown in the following figure. There are two threads in the DTU service that process data: one is used to detect and read serial port data and forward it to the cloud, and the other is used to detect the transmission of downstream data from the cloud to the serial port, as shown in the following figure.
+
+
+
+**Upstream data transparent transmission**
+
+Simulate MCU sending upstream data to the module using serial debugging tools.
+
+- Enter "hello world!" in the `Input String` input box character string.
+- Click the `Send Command` button to send data through the serial port.
+
+
+
+DTU receives serial data and directly transmits it to MQTT cloud.
+
+
+
+Cloud based reception of upstream data logs
+
+
+
+**Downstream data transparent transmission**
+
+Send downstream data from the cloud.
+
+- Set the theme for cloud downlink data (consistent with the subscription theme configured for DTU applications).
+- Enter downstream data.
+- Publish.
+
+
+
+DTU downlink data log.
+
+
+
+Observe the serial port debugging tool through QCOM to simulate the downstream data of the MCU receiving module.
+
+
+
diff --git a/docs/Application_guide/en/solutions/DTU/quick_start.md b/docs/Application_guide/en/solutions/DTU/quick_start.md
new file mode 100644
index 0000000000000000000000000000000000000000..8dfac701cc11d02cda6a8ab5df3ee27bc3325a94
--- /dev/null
+++ b/docs/Application_guide/en/solutions/DTU/quick_start.md
@@ -0,0 +1,36 @@
+# Quick Start
+
+## Hardware preparation
+
+- One Windows computer, recommended Win10 system.
+- A set of [EC800GCN Hua series DTU development board](https://python.quectel.com/doc/Getting_started/zh/evb/ec800g_hua_dtu.html).
+- A usable Nano Sim card.
+- A rubber stick antenna.
+- A Mini USB data cable.
+- A USB to TTL module.
+
+## Environment construction
+
+- Download and install EC800G series module driver: [QuecPython_USB_Driver_Win10_U_G](https://python.quectel.com/wp-content/uploads/2024/09/Quectel_Windows_USB_DriverU_V1.0.19.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.
+- Download and install the firmware package [QPy_OCPU_SETA0002-EC800G_CNLD_SW](https://python.quectel.com/wp-content/uploads/2024/09/QPY_OCPU_BETA0002_EC800G_CNLD_FW.zip). Please refer to [Using QPYcom to Burn Firmware](https://python.quectel.com/doc/Application_guide/zh/dev-tools/QPYcom/qpycom-dw.html ) for firmware package burning
+- Download the experimental source code.
+
+## Hardware connection
+
+Connect the hardware according to the following diagram:
+
+
+
+1. Connect the rubber rod antenna.
+2. Insert the Nano Sim card.
+3. Connect to the computer using a mini USB cable.
+4. Connect to the computer using a USB to TTL module. TX (DTU development board) connected to RX (USB to TTL module); RX (DTU development board) connected to TX (USB to TTL module); GND (DTU development board) is connected to GND (USB to TTL module) for common ground. If an RS485 interface is used, the A line at both ends is connected to the A line, and the B line is connected to the B
+5. The development board adopts a 9-36V wide power supply.
+
+## Equipment development
+
+- [Device development based on TCP protocol](./tcp_demo.md)
+- [Device development based on MQTT protocol](./mqtt_demo.md)
+
diff --git a/docs/Application_guide/en/solutions/DTU/software_design.md b/docs/Application_guide/en/solutions/DTU/software_design.md
new file mode 100644
index 0000000000000000000000000000000000000000..e32447707fba6b96d84d0450d093f18f83c70d01
--- /dev/null
+++ b/docs/Application_guide/en/solutions/DTU/software_design.md
@@ -0,0 +1,327 @@
+# Software Design Explanation
+
+## Application flowchart
+
+Generally speaking, understanding a program code mostly starts from the startup part, and this approach is also adopted here by first searching for the source of the program's startup. The general program startup sequence for this routine is shown in the following figure:
+
+
+
+Overall, the business can be summarized as follows:
+1. Start the dog feeding thread (the Huawei series 4G DTU is equipped with a hardware dog)
+2. After initializing the DTU object, read the system configuration
+3. Initialize serial peripherals
+4. Check the network status
+5. Initialize cloud configuration and message queue
+6. Start data up and down business threads
+
+> 💡 Basic principle: This DTU adopts **multi-threading + message queue** to achieve upstream and downstream forwarding of serial port and cloud data. Among them, the Uplink data thread is used to read serial data and send it to the cloud; The downlink data thread reads cloud data from the message queue and forwards it through the serial port; The message queue is used to cache downstream data in the cloud.
+
+## directory structure
+
+- `usr`:
+ - `_main.py`:main script
+ - `dtu_config.json`:configure file
+ - `dtu.py`:DTU module
+ - `logging.py`:logging module
+ - `cloud_abc.py`:cloud asb module
+ - `mqttIot.py`:Mqtt cloud module
+ - `network.py`:net
+ - `serial.py`:serial module
+ - `socketIot.py`:Socket module
+ - `threading.py`:thread, mutex, queue, etc.
+ - `utils.py`:tools
+
+## API Reference
+
+### Manager Class
+
+In the main script ` _main. py ` of the example program, we define a ` Manager ` class to manage various associated objects initialized.
+
+Main methods:
+
+- `__init__`: Management class initialization method
+ - Watchdog: Due to the hardware watchdog (GPO12) configuration of the Hua series 4G DTU, the main script program needs to initialize a 'self. dog_pin' object and feed the watchdog periodically using 'osTimer'.
+ - DTU model object: `Self. dtu` is a DTU object that reads relevant configurations from a file using the object method `self.dtu.config. read_from.json("/var/dtuconfig.json")` The start method is the main entry of the program. Start the dog feeding timer every 3s, check the sim card and network status, and finally call `self.dtu.run()` to start the DTU routine.
+- `start`: Start method
+ - Activate the dog feeding timer
+ - Check the status of the SIM card
+ - Check the network status
+ - Start the dtu routine
+- `__feed`: The callback function for the dog feeding timer
+
+The implementation is as follows:
+
+```python
+import sim
+import osTimer
+from machine import Pin
+from usr import network
+from usr.dtu import DTU
+
+
+class Manager(object):
+
+ def __init__(self, dog_gpio=Pin.GPIO12):
+ self.dog_pin = Pin(dog_gpio, Pin.OUT, Pin.PULL_DISABLE, 1)
+ self.dog_feed_timer = osTimer()
+
+ self.dtu = DTU('Quectel')
+ self.dtu.config.read_from_json('/usr/dtu_config.json')
+
+ def start(self):
+ # start timer to feed dog
+ self.dog_feed_timer.start(3000, 1, self.__feed)
+ # check sim card
+ if sim.getStatus() != 1:
+ raise ValueError("sim card not ready")
+ # check network
+ network.wait_network_ready()
+ # start dtu business
+ self.dtu.run()
+
+ def __feed(self, args):
+ if self.dog_pin.read():
+ self.dog_pin.write(0)
+ else:
+ self.dog_pin.write(1)
+
+
+if __name__ == "__main__":
+ manager = Manager()
+ manager.start()
+```
+
+### Object model
+
+Multiple object models are defined in this scheme, including the DTU object model, CloudABS object model, and Serial object model. The basic definition is as follows:
+
+
+
+#### DTU Object model
+
+Define the DTU class in the `dtu.py` module, which is mainly used to manage the upstream and downstream business of serial ports, cloud, and data.
+
+`config` property:
+
+There is a property `config` in the DTU object, which is a class `Configure` object used to manage application configuration. As follows:
+
+```python
+from usr.dtu import DTU
+
+dtu = DTU('Quectel')
+dtu.config.read_from_json('/usr/dtu_config.json')
+```
+
+Among them, it supports storing relevant configurations from JSON files, and the operation method is similar to the built-in dictionary type. The following methods can be used to read and write configurations (taking the example of reading the `system_comfig` configuration item).
+
+- Import configuration from specified JSON file: ` dtu.config.read_from_json('/usr/dtu_config.json')`
+- Use the 'get' method to read configuration items: ` dtu.config.get("system_config")`
+- Use the operator ` [] ` to read configuration items: ` dtu.config["system_config"]`
+- Save and update configuration: ` dtu.config.save()`
+
+`serial` property:
+
+This property is used to construct serial port objects, and users generally do not need to modify it. They only need to define configuration parameters according to the actual situation.
+
+```python
+@property
+def serial(self):
+ """create&get serial object according configure"""
+ __serial__ = getattr(self, '__serial__', None)
+ if __serial__ is None:
+ __serial__ = Serial(**self.config.get('uart_config')) # init serial
+ __serial__.open() # open serial
+ setattr(self, '__serial__', __serial__)
+ return __serial__
+```
+
+`cloud` property:
+
+This attribute is a property attribute used to retrieve cloud objects, and the method uses `__create_cloud` to actually build the cloud object.
+
+```python
+@property
+def cloud(self):
+ """get cloud object"""
+ cloud = getattr(self, '__cloud__', None)
+ if cloud is None:
+ cloud = self.__create_cloud() # create cloud object
+ setattr(self, '__cloud__', cloud)
+ return cloud
+```
+
+`__create_cloud` method:
+
+This method is used to actually create cloud objects. If the user customizes cloud objects, they need to add custom object initialization in this function.
+
+```python
+def __create_cloud(self):
+ """create cloud object according configure"""
+ # read cloud type
+ cloud_type = self.config.get('system_config.cloud')
+ if cloud_type == "mqtt":
+ mqtt_config = self.config.get('mqtt_private_cloud_config') # init mqtt cloud
+ cloud = MqttIot(**mqtt_config)
+ elif cloud_type == "tcp":
+ socket_config = self.config.get('socket_private_cloud_config') # init tcp cloud
+ cloud = SocketIot(**socket_config)
+ else:
+ raise ValueError('\"{}\" not supported now!'.format(cloud_type))
+ cloud.connect() # connect to cloud
+ cloud.listen() # start listen message from cloud
+ return cloud
+```
+
+`up_transaction handle` method is used as an entry function for upstream data transmission business threads.
+`down_transaction handler ` method: used as an entry function for business threads in downlink data transmission.
+`run` method: Start the business, including creating serial ports and cloud objects based on the configuration file, as well as creating upstream and downstream business data processing threads.
+
+#### Serial object model
+
+Define the serial model class' Serial 'in the' serial. py 'module, mainly for users to implement read and write operations on the serial port. The main interfaces are:
+- `Serial`:
+ - `__init__`: Serial port initialization.
+ - `open`: Open the serial port.
+ - `close`: Close the serial port.
+ - `write`: Serial port writing.
+ - `read`: Serial port read.
+
+Example of serial port usage:
+
+```python
+from usr.serial import Serial
+
+# init Serial object
+s = Serial(port=2, baudrate=115200, bytesize=8, parity=0, stopbits=1, flowctl=0, rs485_config=None)
+# open serial
+s.open()
+
+# serial write method
+s.write(b"hello world!")
+
+# serial read method
+recv_data = s.read()
+print(recv_data)
+```
+
+#### Cloud object model
+
+**Cloud model**
+
+In order to adapt to different cloud platforms (socket private cloud, MQTT, etc.), this solution defines abstract cloud types as follows. Users can customize Cloud objects according to abstract types to adapt to different cloud platforms.
+
+> 💡 The implementation of Cloud model objects can refer to socketIot and MqttIot.
+
+```python
+class CloudABC(object):
+
+ def __init__(self, **kwargs):
+ """
+ key arguments: kwargs, used for initial params for cloud (customer used).
+ """
+ raise NotImplementedError("this method should me implemented for customer designed Cloud Object")
+
+ def connect(self):
+ """connect to Coud"""
+ raise NotImplementedError("customer should implement this method to connect cloud")
+
+ def listen(self):
+ """listen message from cloud.
+
+ usually we use this method to start a thread for receiving message from the cloud and put message input a Queue, and then use `self.recv` method to get it on app side.
+ """
+ raise NotImplementedError("customer should implement this method to listen cloud message")
+
+ def recv(self):
+ """receive a message"""
+ raise NotImplementedError("customer should implement this method to recv a message")
+
+ def send(self, *args):
+ """send message
+
+ position arguments: args, customer designed method used for send message
+ """
+ raise NotImplementedError("customer should implement this method to send a message")
+```
+
+The above are the main methods and properties of the Cloud object model, including:
+
+- `__init__`: Receive keyword parameters, usually used to configure cloud initialization parameters, which users can define themselves.
+- `connect`: Connect to a cloud server.
+- `listen`: Listen to the downlink messages in the cloud. Usually, threads are used in this method to read the downlink data in the cloud and place it in the message queue for easy access by the application side through the self. recv method.
+- `recv`: Retrieve downlink messages.
+- `send`: Send an upstream message and receive several location parameters that users can customize.
+
+## 业务代码讲解
+
+The data transmission service is mainly implemented in the DTU class (dtu.py), which is mainly used to manage the upstream and downstream services of serial ports, cloud, and data.
+The DTU object starts the entire DTU business in the main script by calling the `run` method, which is mainly used to create and run two threads, namely the upstream data processing thread (whose job function is `up_transactions_handler`) and the downstream data processing thread (whose job function is `down_transactions_handler`). Obtain the corresponding serial port object and cloud object through two property attributes in the thread function. The serial object property is `serial`, and when the thread calls this property, it immediately creates and opens the configured serial object to provide a read-write interface. The cloud object attribute is `cloud`, and when the thread calls this attribute, it immediately creates and connects with the cloud object to provide receiving and sending interfaces.
+Function call sequence diagram:
+
+```mermaid
+sequenceDiagram
+Title: Device data transmit-processing timing
+
+
+participant cloud as Cloud
+participant dtu as DTU
+participant serial as Serial
+
+loop down_transaction_handler thread
+cloud ->> dtu: CloudABC.recv
+dtu ->> serial: Serial.write
+end
+
+loop up_transaction_handler thread
+serial ->> dtu: Serial.read
+dtu ->> cloud: CloudABC.send
+end
+```
+
+The implementation of the upstream data processing thread function `DTU.up_transactions_handler` is as follows:
+
+```python
+class DTU(object):
+
+ # ...
+
+ def up_transaction_handler(self):
+ while True:
+ try:
+ data = self.serial.read(1024)
+ if data:
+ logger.info('up transfer msg: {}'.format(data))
+ if isinstance(self.cloud, SocketIot):
+ msg = [data]
+ elif isinstance(self.cloud, MqttIot):
+ msg = ['up', data]
+ else:
+ raise TypeError('unknow cloud type.')
+ self.cloud.send(*msg)
+ except Exception as e:
+ logger.error('up transfer error: {}'.format(e))
+
+ # ...
+```
+
+The `up_transactions_handler` function reads serial data from a 1KB buffer (users can adjust the buffer size themselves), formats the message, and sends the data to the cloud through the CloudABC. send interface. After inheriting 'CloudABC' and customizing cloud objects and implementing the `CloudABC.send` method, users can process and send data according to the custom message format.
+The implementation of the downlink data processing thread function `down_transaction_handler` is as follows:
+
+```python
+class DTU(object):
+
+ # ...
+
+ def down_transaction_handler(self):
+ while True:
+ try:
+ msg = self.cloud.recv()
+ logger.info('down transfer msg: {}'.format(msg['data']))
+ self.serial.write(msg['data'])
+ except Exception as e:
+ logger.error('down transfer error: {}'.format(e))
+
+ # ...
+```
+
+`down_transaction_handler` function retrieves the downstream message by calling `CloudABC.recv` and forwards the message through `Serial.write`.
\ No newline at end of file
diff --git a/docs/Application_guide/en/solutions/DTU/tcp_demo.md b/docs/Application_guide/en/solutions/DTU/tcp_demo.md
new file mode 100644
index 0000000000000000000000000000000000000000..cf2126af10ce1aedbd13af4afb4dba0b402e2336
--- /dev/null
+++ b/docs/Application_guide/en/solutions/DTU/tcp_demo.md
@@ -0,0 +1,116 @@
+# Device development based on TCP protocol
+
+## Modify configuration file
+
+configuration file path: `code/dtu_config.json`。
+
+Based on TCP private server data transparent transmission, configure as follows:
+
+- The default `systemconfig.cloud` configuration item is defined as `TCP`, which means TCP transparent mode. The system will automatically read the `socket_private_cloud_config` configuration item.
+
+ ```python
+ {
+ "system_config": {
+ "cloud": "tcp"
+ }
+ }
+ ```
+
+- This experiment adopts TCP transparent transmission mode, and users need to set the TCP server domain name (*domain*) and port (*port*) in the `socket_pivate_cloud_config` configuration item according to the actual situation.
+
+ ```python
+ {
+ "socket_private_cloud_config": {
+ "domain": "112.31.84.164",
+ "port": 8305,
+ "timeout": 5,
+ "keep_alive": 5
+ }
+ }
+ ```
+
+- The `uart_config` configuration item is a serial port configuration parameter, which defaults to the configuration made based on the current experimental development board and cannot be changed. If users use other development boards, they need to configure according to the actual hardware.
+
+```python
+{
+ "uart_config": {
+ "port": 2,
+ "baudrate": 115200,
+ "bytesize": 8,
+ "parity": 0,
+ "stopbits": 1,
+ "flowctl": 0,
+ "rs485_config": {
+ "gpio_num": 28,
+ "direction": 0
+ }
+ }
+}
+```
+
+The complete configuration file template is as follows:
+
+```json
+{
+ "system_config": {
+ "cloud": "tcp"
+ },
+ "mqtt_private_cloud_config": {
+ "server": "mq.tongxinmao.com",
+ "port": 18830,
+ "client_id": "txm_1682300809",
+ "user": "",
+ "password": "",
+ "clean_session": true,
+ "qos": 0,
+ "keepalive": 60,
+ "subscribe": {"down": "/public/TEST/down"},
+ "publish": {"up": "/public/TEST/up"}
+ },
+ "socket_private_cloud_config": {
+ "domain": "112.31.84.164",
+ "port": 8305,
+ "timeout": 5,
+ "keep_alive": 5
+ },
+ "uart_config": {
+ "port": 2,
+ "baudrate": 115200,
+ "bytesize": 8,
+ "parity": 0,
+ "stopbits": 1,
+ "flowctl": 0,
+ "rs485_config": {
+ "gpio_num": 28,
+ "direction": 0
+ }
+ }
+}
+```
+
+Parameter description:
+
+- ` systemconfig. config `: Specify the type of private cloud currently in use. Currently supports TCP and MQTT.
+- `mqtt_private_cloud_config`: MQTT private cloud configuration.
+- `socket_private_cloud_config`: TCP private cloud configuration.
+- `uart_config`: Serial port parameter configuration.
+
+## Script import and run
+
+After downloading and installing the QPYCom tool, use the tool to download the script to the QuecPython module.
+
+> 💡 **Tips**
+>
+> QPYCom Installation and Usage Tutorial: https://python.quectel.com/doc/Application_guide/en/dev-tools/QPYcom/index.html
+
+## Debugging
+
+After the program runs, the log output can be seen on the REPL interaction page as shown in the following figure.
+In the diagram on the left, we use QCOM to simulate MCU opening the module serial port for transparent transmission (i.e. the COM port corresponding to the USB to TTL module).
+The diagram on the right shows the module log output from the REPL interaction port.
+Use the serial port tool QCOM to simulate MCU serial port upstream data, transmit it transparently to the TCP echo server through DTU, and then the echo server transmits the same data transparently downstream to QCOM through DTU.
+
+
+
+In this case, a TCP echo server is used, so QCOM upstream data will be transmitted through DTU to the TCP server and immediately downstream along the original path upon receipt.
+
diff --git a/docs/Application_guide/en/solutions/SensorHub/EC200UEUAAR05A01M08_TEST0222.zip b/docs/Application_guide/en/solutions/SensorHub/EC200UEUAAR05A01M08_TEST0222.zip
new file mode 100644
index 0000000000000000000000000000000000000000..570c2ef4f8326f47cf995192a389ec884bfe2ecc
Binary files /dev/null and b/docs/Application_guide/en/solutions/SensorHub/EC200UEUAAR05A01M08_TEST0222.zip differ
diff --git a/docs/Application_guide/en/solutions/SensorHub/README.md b/docs/Application_guide/en/solutions/SensorHub/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..4027dc78ebaa5fa96f8c7bb5f0b906042e68f5ab
--- /dev/null
+++ b/docs/Application_guide/en/solutions/SensorHub/README.md
@@ -0,0 +1,15 @@
+# SensorHub Solution
+
+This solution is based on the EC200U-EU QuecPython standard development board and has the following features:
+
+- Provide accurate temperature and humidity detection function and high-precision GNSS positioning
+- Support Quectel cloud and remote data viewing through the app
+- Using Python language for easy secondary development
+
+
+
+------
+
+- [development resource](./dev_resources.md)
+- [quick start](quick_start.md)
+- [software design](./software_design)
diff --git a/docs/Application_guide/en/solutions/SensorHub/dev_resources.md b/docs/Application_guide/en/solutions/SensorHub/dev_resources.md
new file mode 100644
index 0000000000000000000000000000000000000000..9c05fcf481932b592fdfeb40b7c67235fc9b3a08
--- /dev/null
+++ b/docs/Application_guide/en/solutions/SensorHub/dev_resources.md
@@ -0,0 +1,42 @@
+# Development resources summary
+
+## Development board
+
+- model:[EC200U-EU Quecpython standard EVB](https://python.quectel.com/doc/Getting_started/en/evb/ec200x-evb.html)
+- Purchase link:[click](https://www.waveshare.com/ec200u-au-c4-p01.htm)
+- 开发板文档
+ - [specification](https://python.quectel.com/wp-content/uploads/2024/09/Quectel_EC200U%E7%B3%BB%E5%88%97_LTE_Standard_%E6%A8%A1%E5%9D%97%E4%BA%A7%E5%93%81%E8%A7%84%E6%A0%BC%E4%B9%A6_V1.4.pdf)
+ - [schematic](https://python.quectel.com/wp-content/uploads/2024/09/EC200UA_C4-P01%E7%B3%BB%E5%88%97%E5%BC%80%E5%8F%91%E6%9D%BF%E5%8E%9F%E7%90%86%E5%9B%BE.pdf)
+ - [screen printing](https://python.quectel.com/wp-content/uploads/2024/09/EC200UA_C4-P01%E7%B3%BB%E5%88%97%E5%BC%80%E5%8F%91%E6%9D%BF%E4%B8%9D%E5%8D%B0.pdf)
+ - [user guidance](https://python.quectel.com/doc/Getting_started/zh/evb/ec200x-evb.html)
+
+
+
+## Development tool
+
+- QPYcom - QuecPython debug tool
+
+ - version:V3.6.0
+
+ - download [QPYcom](https://python.quectel.com/wp-content/uploads/2024/09/QPYcom_V3.6.0.zip)
+
+- VSCode
+
+ - download [VSCode](https://code.visualstudio.com/)
+
+## Firmware
+
+version:8915DM_cat1_open_EC200UEUAAR05A01M08_TEST0222_merge
+
+download [Firmware](../../solutions/SensorHub/EC200UEUAAR05A01M08_TEST0222.zip )
+
+## Source Code
+
+- version:v2.0.1
+- github repo:
+
+```bash
+git clone https://github.com/QuecPython/solution-Sensorhub
+cd solution-sensorhub
+```
+
diff --git a/docs/Application_guide/en/solutions/SensorHub/quick_start.md b/docs/Application_guide/en/solutions/SensorHub/quick_start.md
new file mode 100644
index 0000000000000000000000000000000000000000..1dd6f427972c1a6db2ddaf7ce71168f9f3b239a8
--- /dev/null
+++ b/docs/Application_guide/en/solutions/SensorHub/quick_start.md
@@ -0,0 +1,103 @@
+# Quick Start
+
+## Hardware preparation
+
+A Windows computer, recommended for the 'Win10' system.
+
+One set [EC200U-EU Quecpython standard EVB](https://python.quectel.com/doc/Getting_started/en/evb/ec200x-evb.html)
+
+One SIM card
+
+## Environment construction
+
+- Download and install driver:[QuecPython_USB_Driver_Win10_ASR](https://images.quectel.com/python/2023/04/Quectel_Windows_USB_DriverA_Customer_V1.1.13.zip)
+
+
+- Download and install [VSCode](https://code.visualstudio.com/)
+- Download [QPYCom](https://images.quectel.com/python/2022/12/QPYcom_V3.6.0.zip)
+- Download [Firmware](../../solutions/SensorHub/EC200UEUAAR05A01M08_TEST0222.zip )
+- Download [Source Code](https://gitee.com/dustin-wei/solution-sensorhub)
+
+## Hardware connection
+
+Connect the hardware according to the following diagram:
+
+
+
+
+
+1. Connect the antenna to the antenna connector marked with the word 'LTE'.
+
+2. Insert an available Nano SIM card into the SIM1 slot as shown in the diagram.
+
+3. Connect the development board and computer using a Type-C data cable.
+
+
+
+## Equipment development
+
+- ### Power on
+
+After completing the hardware connection work, when PWR, SCK1 light up or a COM port containing the words Quectel USB appears in the port list of the computer device manager, it indicates a successful boot up.
+
+
+
+
+
+- ### Download firmware
+
+Refer to [this chapter](https://python.quectel.com/doc/Application_guide/en/dev-tools/QPYcom/qpycom-dw.html) Download the firmware and burn the firmware to the development board.
+
+- ### Script import and execution
+
+1.Refer to [this chapter](https://python.quectel.com/doc/Getting_started/en/first_python.html#PC) to transfer files between modules, import all files from the code folder in the source code directory into the module file system according to the original directory structure, as shown in the following figure
+
+
+
+2.Refer to [this chapter](https://python.quectel.com/doc/Getting_started/en/first_python.html# Execute script file), execute the main program file `_main.py`
+
+3.Refer to [this chapter](https://python.quectel.com/doc/Getting_started/en/first_python.html# Stop program running), stop program running
+
+## Debugging
+
+### Program startup
+
+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
+
+
+
+### 🚩 **Warning**
+
+When the SIM card is not inserted, the SCK1 light will not light up and device information cannot be printed. After inserting the SIM card and restarting the device, it can run normally.
+
+
+
+### Data detection
+
+After starting to run, the detected data of temperature 1, humidity, air pressure, temperature 2, and the three primary colors of color will be printed every 1 second
+
+
+
+### Data update
+
+When any of the above four types of data produces a change greater than 1 or the original color produces a change greater than 150, it will attempt to upload the updated data to the cloud. When the upload is successful, it will return "send ret: True" and prompt which data has changed. The APP will read the latest data from the cloud for data update.
+
+
+
+
+
+If there is no change greater than 1 in the data, only the currently detected data will be printed in pqcom and will not be uploaded to the cloud.
+
+
+
+Location update: When the module displacement exceeds 50 meters, the cloud will refresh the location information, and the app will read the latest location information.
+
+
+
+Proactively refresh APP data. By clicking the refresh button in the upper right corner of the APP, the APP will initiate a command to the server to actively read data for updating panel data
+
+
+
+Temperature, humidity, air pressure, color, and Lbs data have been successfully obtained
+
+
\ No newline at end of file
diff --git a/docs/Application_guide/en/solutions/SensorHub/software_design.md b/docs/Application_guide/en/solutions/SensorHub/software_design.md
new file mode 100644
index 0000000000000000000000000000000000000000..1ed2017b60ecc59c1b3fac31d860654f8f3ef820
--- /dev/null
+++ b/docs/Application_guide/en/solutions/SensorHub/software_design.md
@@ -0,0 +1,413 @@
+# Software Design
+
+
+
+## Software framework
+
+- ### Software Design Diagram
+
+
+
+
+
+- ### Business initiation process
+
+
+
+## Code Explanation
+
+### data management
+
+The `Storage` class of `common.py` is an extension based on Python's built-in `dict` class, used to provide thread safe dictionary storage and support loading and saving data from JSON files.
+
+```python
+class Storage(dict):
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+ self.__lock__ = Lock()
+ self.__storage_path__ = None
+ def __enter__(self):
+ self.__lock__.acquire()
+ return self
+
+ def __exit__(self, *args, **kwargs):
+ self.__lock__.release()
+
+ def __from_json(self, path):
+ if self.__storage_path__ is not None:
+ raise ValueError('storage already init from \"{}\"'.format(self.__storage_path__))
+ if not ql_fs.path_exists(path):
+ ql_fs.touch(path, {})
+ else:
+ self.update(ql_fs.read_json(path))
+
+ def init(self, path):
+ if path.endswith('.json'):
+ self.__from_json(path)
+ else:
+ raise ValueError('\"{}\" file type not supported'.format(path))
+ self.__storage_path__ = path
+
+ def save(self):
+ if self.__storage_path__ is None:
+ raise ValueError('storage path not existed, did you init?')
+ ql_fs.touch(self.__storage_path__, self)
+
+```
+
+### Service module
+
+1. Lbs_Service: Provides Lbs data location service
+
+2. gnss_Service: Provides gnss data location services
+
+3. Sensor_Service: Provides sensor data detection services
+
+4. Qth_client: Provides data upload and callback services
+
+The relationship diagram between each service and client is as follows:
+
+
+
+
+
+### Sensor data collection
+
+The `SensorService` class of `SensorService.py` is a service class used to manage sensor data collection and updates, mainly responsible for initializing I2C channels and multiple sensors (SHTC3, LPS22HB, and TCS34725), and continuously reading temperature, humidity, air pressure, and RGB color values from these sensors. It is also responsible for sending these data to the designated QTH client.
+
+```python
+class SensorService(object):
+
+ def __init__(self, app=None):
+ # i2c channel 0
+ self.i2c_channel0 = I2C(I2C.I2C0, I2C.STANDARD_MODE)
+ # SHTC3
+ self.shtc3 = Shtc3(self.i2c_channel0, SHTC3_SLAVE_ADDR)
+ self.shtc3.init()
+ # LPS22HB
+ self.lps22hb = Lps22hb(self.i2c_channel0, LPS22HB_SLAVE_ADDRESS)
+ self.lps22hb.init()
+ # TCS34725
+ self.tcs34725 = Tcs34725(self.i2c_channel0, TCS34725_SLAVE_ADDR)
+ self.tcs34725.init()
+
+ if app is not None:
+ self.init_app(app)
+ def __str__(self):
+ return '{}'.format(type(self).__name__)
+
+ def init_app(self, app):
+ app.register('sensor_service', self)
+
+ def load(self):
+ logger.info('loading {} extension, init sensors will take some seconds'.format(self))
+ Thread(target=self.start_update).start()
+
+ def get_temp1_and_humi(self):
+ return self.shtc3.getTempAndHumi()
+
+ def get_press_and_temp2(self):
+ return self.lps22hb.getTempAndPressure()
+ def get_rgb888(self):
+ rgb888 = self.tcs34725.getRGBValue()
+ logger.debug("R: {}, G: {}, B: {}".format((rgb888 >> 16) & 0xFF, (rgb888 >> 8) & 0xFF, rgb888 & 0xFF))
+
+ r = (rgb888 >> 16) & 0xFF
+ g = (rgb888 >> 8) & 0xFF
+ b = rgb888 & 0xFF
+ return r, g, b
+ def start_update(self):
+ prev_temp1 = None
+ prev_humi = None
+ prev_press = None
+ prev_temp2 = None
+ prev_rgb888 = None
+
+
+ while True:
+ data = {}
+
+ try:
+ temp1, humi = self.shtc3.getTempAndHumi()
+ logger.debug("temp1: {:0.2f}, humi: {:0.2f}".format(temp1, humi))
+
+ if prev_temp1 is None or abs(prev_temp1 - temp1) > 1:
+ data.update({3: round(temp1, 2)})
+ prev_temp1 = temp1
+
+ if prev_humi is None or abs(prev_humi - humi) > 1:
+ data.update({4: round(humi, 2)})
+ prev_humi = humi
+
+ except Exception as e:
+ logger.error("getTempAndHumi error:{}".format(e))
+
+ utime.sleep_ms(100)
+ try:
+ press, temp2 = self.lps22hb.getTempAndPressure()
+ logger.debug("press: {:0.2f}, temp2: {:0.2f}".format(press, temp2))
+
+ if prev_temp2 is None or abs(prev_temp2 - temp2) > 1:
+ data.update({5: round(temp2, 2)})
+ prev_temp2 = temp2
+
+ if prev_press is None or abs(prev_press - press) > 1:
+ data.update({6: round(press, 2)})
+ prev_press = press
+
+ except Exception as e:
+ logger.error("getTempAndPressure error:{}".format(e))
+
+ utime.sleep_ms(100)
+
+ utime.sleep_ms(100)
+
+ try:
+ rgb888 = self.tcs34725.getRGBValue()
+ logger.debug("R: {}, G: {}, B: {}".format((rgb888 >> 16) & 0xFF, (rgb888 >> 8) & 0xFF, rgb888 & 0xFF))
+
+ r = (rgb888 >> 16) & 0xFF
+ g = (rgb888 >> 8) & 0xFF
+ b = rgb888 & 0xFF
+
+ if prev_rgb888 is None:
+ data.update({7: {1: r, 2: g, 3: b}})
+ prev_rgb888 = rgb888
+ else:
+ prev_r = (prev_rgb888 >> 16) & 0xFF
+ dr = abs(r - prev_r)
+
+ prev_g = (prev_rgb888 >> 8) & 0xFF
+ dg = abs(g - prev_g)
+
+ prev_b = prev_rgb888 & 0xFF
+ db = abs(b - prev_b)
+
+ # 色差超过 150 即认为颜色有变化
+ if pow(sum((dr*dr, dg*dg, db*db)), 0.5) >= 150:
+ data.update({7: {1: r, 2: g, 3: b}})
+ prev_rgb888 = rgb888
+
+ except Exception as e:
+ logger.error("getRGBValue error:{}".format(e))
+
+ if data:
+ with CurrentApp().qth_client:
+ for _ in range(3):
+ if CurrentApp().qth_client.sendTsl(1, data):
+ break
+ else:
+ prev_temp1 = None
+ prev_humi = None
+ prev_press = None
+ prev_temp2 = None
+ prev_rgb888 = None
+
+ utime.sleep(1)
+```
+
+
+
+
+
+### 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, initiating, and managing connections with 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()
+
+ 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))
+
+ 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()
+
+ value={
+ 3:temp1,
+ 4:humi,
+ 5:temp2,
+ 6:press,
+ 7:{1:r, 2:g, 3:b},
+ }
+
+ #Proactively obtain lbs data and upload it to the server
+ lbs=lbs_service.LbsService()
+ lbs.put_lbs()
+
+
+ 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))
+ 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))
+
+```
+
+### APP management
+
+The `Application` of `__init__.py` is a class used to manage applications and their extensions, providing functions such as initialization, registering extensions, loading extensions, and printing device information at runtime.
+
+```python
+# Global context management class for storing and retrieving global variables
+
+@Singleton
+class Application(object):
+ """Application Class"""
+
+ def __init__(self, name, version='1.0.0'):
+ self.__name = name
+ self.config = Storage()
+ self.__version = version
+ self.__extensions = OrderedDict()
+
+ def __repr__(self):
+ return '{}(name=\"{}\", version=\"{}\")'.format(type(self).__name__, self.name, self.version)
+
+# Allows access to registered extensions through properties
+ def __getattr__(self, name):
+ return self.__extensions[name]
+
+ def register(self, name, ext):
+ if name in self.__extensions:
+ raise ValueError('extension name \"{}\" already in use'.format(name))
+ self.__extensions[name] = ext
+ def __powerOnPrintOnce(self):
+ output = '==================================================\r\n'
+ output += 'APP_NAME : {}\r\n'
+ output += 'APP_VERSION : {}\r\n'
+ output += 'FIRMWARE_VERSION : {}\r\n'
+ output += 'POWERON_REASON : {}\r\n'
+ output += 'DEVICE_IMEI : {}\r\n'
+ output += 'SIM_STATUS : {}\r\n'
+ output += 'NET_STATUS : {}\r\n'
+ output += '=================================================='
+ print(output.format(
+ self.name,
+ self.version,
+ modem.getDevFwVersion(),
+ Power.powerOnReason(),
+ modem.getDevImei(),
+ sim.getStatus(),
+ net.getState()[1][0]
+ ))
+
+# load all registered extensions and call their load method (if present)
+ def __loadExtensions(self):
+ for ext in self.__extensions.values():
+ if not hasattr(ext, 'load'):
+ continue
+ try:
+ ext.load()
+ except Exception as e:
+ sys.print_exception(e)
+
+ def run(self):
+ self.__powerOnPrintOnce()
+ self.__loadExtensions()
+
+ @property
+ def version(self):
+ return self.__version
+
+ @property
+ def name(self):
+ return self.__name
+
+# Global application instance
+CurrentApp = Application
+```
+
diff --git a/docs/Application_guide/en/solutions/Wear/dev_resources.md b/docs/Application_guide/en/solutions/Wear/dev_resources.md
new file mode 100644
index 0000000000000000000000000000000000000000..7497bec79c3cdc1d7150cfd5bf6b72eabf2074a0
--- /dev/null
+++ b/docs/Application_guide/en/solutions/Wear/dev_resources.md
@@ -0,0 +1,62 @@
+# Development resources summary
+
+
+
+## Development board
+
+- model: QuecPython_EG810X C1-P03
+
+- EVB docs
+ - [specification](https://python.quectel.com/wp-content/uploads/2024/09/EG810M_EC800Z_C1-P03%E7%B3%BB%E5%88%97%E5%BC%80%E5%8F%91%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://python.quectel.com/wp-content/uploads/2024/09/EG810M_EC800Z_C1-P03%E7%B3%BB%E5%88%97%E5%BC%80%E5%8F%91%E6%9D%BF%E5%8E%9F%E7%90%86%E5%9B%BE.pdf)
+ - [screen printing](https://python.quectel.com/wp-content/uploads/2024/09/EG810M_EC800Z_C1-P03%E7%B3%BB%E5%88%97%E5%BC%80%E5%8F%91%E6%9D%BF%E4%B8%9D%E5%8D%B0.pdf)
+
+
+
+## Module information
+
+- model: [EG810MCN_GB](https://python.quectel.com/modules-cat/eg810m-series)
+- module info
+ - [specification](https://python.quectel.com/wp-content/uploads/2024/09/Quectel_EG810M%E7%B3%BB%E5%88%97_LTE_Standard_%E6%A8%A1%E5%9D%97%E4%BA%A7%E5%93%81%E8%A7%84%E6%A0%BC%E4%B9%A6_V1.3.pdf)
+ - [download drivers](https://python.quectel.com/wp-content/uploads/2024/09/Quectel_Windows_USB_DriverA_Customer_V1.1.13.zip)
+
+
+
+
+## Development tool
+
+- QPYcom - QuecPython debug tool
+
+ - version: V3.6.0
+ - download [QPYcom](https://python.quectel.com/wp-content/uploads/2024/09/QPYcom_V3.6.0.zip)
+
+
+
+
+- VSCode
+
+ - download [VSCode](https://code.visualstudio.com/)
+
+
+
+
+## Firmware
+
+- version: EG810MCNGAR06A01M08_VOEXT_OCPU_QPY_BETA0222.zip
+- download [firmware](https://raw.githubusercontent.com/QuecPython/solution-wearable/refs/heads/master/EG810MCNGAR06A01M08_VOEXT_OCPU_QPY_BETA0222_20250317-1147_20250317-1152.zip)
+
+
+
+## Source code
+
+- version: v1.0.1
+
+- github repo:
+
+```bash
+git clone https://github.com/QuecPython/solution-wearable
+cd solution-wearable
+git checkout v1.0.1
+```
+
+- [Github Zip file download](https://github.com/QuecPython/solution-wearable/archive/refs/heads/master.zip)
diff --git a/docs/Application_guide/en/solutions/Wear/quick_start.md b/docs/Application_guide/en/solutions/Wear/quick_start.md
new file mode 100644
index 0000000000000000000000000000000000000000..9ba82cee8427fc3fdebefdedf9b98129971ee54d
--- /dev/null
+++ b/docs/Application_guide/en/solutions/Wear/quick_start.md
@@ -0,0 +1,116 @@
+# Quick Start
+
+
+
+## Hardware preparation
+
+- A Windows computer, recommended for the 'Win10' system.
+- A TypeC data cable
+- A QuecPython EG810X C1-P03 development board
+
+
+
+
+## Environment construction
+
+- Download and install EG810M module driver: [QuecPython_USB_Driver_Win10_ASR](https://python.quectel.com/wp-content/uploads/2024/09/Quectel_Windows_USB_DriverA_Customer_V1.1.13.zip)
+- Download and install [VSCode](https://code.visualstudio.com/)
+- Download and install [QPYCom](https://python.quectel.com/wp-content/uploads/2024/09/QPYcom_V3.6.0.zip)
+- Download [Firmware](https://raw.githubusercontent.com/QuecPython/solution-wearable/refs/heads/master/EG810MCNGAR06A01M08_VOEXT_OCPU_QPY_BETA0222_20250317-1147_20250317-1152.zip)
+- Download [Source Code](https://codeload.github.com/QuecPython/solution-wearable/zip/refs/tags/v1.0.1)
+
+
+
+## Hardware connection
+
+Connect the hardware according to the following diagram:
+
+
+
+
+
+Connect the development board and computer using a TypeC data cable
+
+
+
+## Equipment development
+
+
+
+### Power on
+
+After completing the hardware connection work, long press the button labeled 'PWk' on the development board until the network light 'net' flashes or a COM port containing the words' Quectel USB 'appears in the port list of the computer device manager, indicating successful boot.
+
+
+
+
+
+### Download firmware
+
+Refer to [this chapter](https://python.quectel.com/doc/Application_guide/en/dev-tools/QPYcom/qpycom-dw.html# Download firmware), burn firmware package [EG810MCNGAR06A01M08_VOEXT_SCPU_QPYBETA0222. zip](https://raw.githubusercontent.com/QuecPython/solution-wearable/refs/heads/master/EG810MCNGAR06A01M08_VOEXT_OCPU_QPY_BETA0222_20250317-1147_20250317-1152.zip) To the development board.
+
+### Script import and execution
+
+
+1. Refer to [this chapter](https://python.quectel.com/doc/Getting_started/en/first_python.html#PC) To transfer files between modules, import all files ending in '. py' from the 'code' folder in the source code directory into the module file system, as shown in the following figure:
+
+
+
+2. Refer to [this chapter](https://python.quectel.com/doc/Getting_started/en/first_python.html# Execute script file), execute the main program file ` main_t.py`
+
+3. Refer to [this chapter](https://python.quectel.com/doc/Getting_started/en/first_python.html# Stop program running), stop program running
+
+
+
+## Screen display
+
+The wearing plan provides homepage, dial screen, application screen, standby scren, dial screen, heart rate/blood oxygen/body temperature detection screen.
+
+### watch dial
+
+
+
+component:
+
+1. **Universal Headboard:**
+ - Signal display.
+ - The operator displays.
+ - Battery level display.
+ - Navigation icon display.
+2. **Dial content:**
+ - Time display: Real time refresh of time.
+ - Hour hand/minute hand/second hand: Real time linkage with time.
+ - The current time on the background disk is displayed on the clock.
+ - Date display: The date is refreshed in real-time.
+3. **Interaction Relationship**:
+ - Swipe left on the digital dial to enter the screen display interface, and swipe right to enter the schedule dial interface.
+ - Swipe left on the pointer dial to enter the digital dial interface, swipe right to enter the application list 1 page
+ - The device (entered without any operation within 30 seconds) will display an off screen interface. Right swipe to enter the dial interface
+
+### App screens
+
+
+
+1. **Heart rate monitoring:**
+ - Click to jump to the heart rate detection page.
+2. **Phone:**
+ - Click to enter the phone dialing interface.
+3. **WeChat:**
+ - Click to enter the WeChat interface for sending and receiving voice messages.
+4. **Countdown interface:**
+ - Click to enter the countdown interface.
+5. **Interaction Relationship:**
+ - Right swipe on the application list interface to enter the application list 2 interface.
+ - Swipe left on the application list 2 interface to enter the application list interface, and swipe right to enter the heart rate detection and other interfaces.
+
+### Phone screen
+
+
+
+Provides modes and displays for making phone calls, going/calling/calling, etc.
+
+### Detection screen
+
+
+
+The detection interface includes temperature/blood oxygen/heart rate detection, as well as display of detection status and historical detection.
diff --git a/docs/Application_guide/en/solutions/Wear/readme.md b/docs/Application_guide/en/solutions/Wear/readme.md
index 4c0de94cbc1770606fcbab619d29af8ae4a1b139..2560792d56e008d5f381604e9ecd913cc5e25d2b 100644
--- a/docs/Application_guide/en/solutions/Wear/readme.md
+++ b/docs/Application_guide/en/solutions/Wear/readme.md
@@ -1,517 +1,19 @@
# Wearable Solution
-[QuecPython](https://python.quectel.com/en) has launched a [GUI solution](https://github.com/QuecPython/solution-wearable.git) for the wearable industry, including clock display, call making/answering, heart rate/temperature/blood oxygen measurement, step count display, system settings and other optional functions.
-
-The wearable industry solution uses [LVGL](https://lvgl.io/) to draw graphical interfaces. LVGL is a lightweight, open source embedded graphics library. QuecPython has integrated LVGL and uses NXP's [GUI Guider](https://www.nxp.com/design/software/development-software/gui-guider:GUI-GUIDER) as a graphical interface design tool to automatically generate QuecPython code, greatly improving the efficiency of embedded platform graphical interface design.
+The wearable solution is based on the QuecPython EG810M C1-P03 development board and has the following features:
-## Interface Introduction
+- Including interfaces such as clock display, phone dialing and answering reality, heart rate/temperature/blood oxygen measurement, etc
+- Using [LVGL](https://lvgl.io/) Drawing graphical interfaces, it is a lightweight, open-source embedded graphics library.
+- Having a basic application framework, users can improve their application development based on this framework
+- Using Python language for easy secondary development.
-The wearable solution provides home page, dial page, application page, standby page, dial page, heart rate/blood oxygen/temperature detection page, settings page and other pages.
+
-### Dial Page
+------
-
+- [development resource](./dev_resources.md)
+- [quick start](./quick_start.md)
+- [software design](./software_design.md)
-Components:
-
-1. **Common Top Bar:**
- - Signal display
- - Operator display
- - Battery level display
- - Navigation icon display
-2. **Dial Content:**
- - Time display: The time is refreshed in real time
- - Hour/Minute/Second hand: Updated in real time with the current time
- - Background dial showing current time
- - Date display: The date is refreshed in real time
-3. **Interactions:**
- - Swipe left on the digital dial to enter the lock screen, swipe right to enter the analog dial
- - Swipe left on the analog dial to enter the digital dial, swipe right to enter the app list 1
- - After 30s of inactivity, the device will enter lock screen. Swipe right to unlock and enter dial
-
-### Application List Page
-
-
-
-1. Heart Rate Measurement:
- - Tap to enter heart rate measurement page
-2. Phone:
- - Tap to enter phone dial page
-3. Chat:
- - Tap to enter chat page to send/receive voice
-4. Timer:
- - Tap to enter timer page
-5. Interactions:
- - Swipe right on app list page to enter app list page 2
- - Swipe left on app list page 2 to return to app list page 1, swipe right to enter detection pages
-
-### Detection Page
-
-
-
-The detection page includes body temperature/blood oxygen/heart rate measurement, measurement status and historical measurement display.
-
-### Phone Page
-
-
-
-Provides phone dialing, incoming/outgoing call modes and displays.
-
-### Step Count Page
-
-
-
-Provides daily step count, historical step count display, and step goal setting display.
-
-### Timer Page
-
-
-
-The timer page provides time setting, countdown timer, and alert when timer ends.
-
-### Alarm Page
-
-
-
-Provides alarm setting and deletion, alarm alerts and displays.
-
-### Settings Page
-
-
-
-1. About Device
- - Provides basic system information like manufacturer, model, OS version
-2. System Upgrade
- - Used to check for system software updates to ensure all features are up-to-date
- - May include auto-update options to automatically download and install updates when available
-3. Set Watch Face
- - Allows switching and displaying different watch faces
-4. Device Ringtone
- - Set incoming call ringtone
- - Set alarm ringtone
-5. Vibration Mode
- - If device has a vibration motor, vibration mode can be set
-6. Factory Reset
- - Reset device to factory default settings
-7. Power Off
- - Send power off command to device
-
-## Code Introduction
-
-Code Github Repo: https://github.com/QuecPython/solution-wearable
-
-### Code Directory Structure
-
-```
-Copy code.
-|-- EventMesh.py
-|-- common.py
-|-- constant.py
-|-- lcd.py
-|-- css.py
-|-- ui.py
-|-- mgr.py
-|-- main_t.py
-|-- 16px.bin
-|-- 28px.bin
-|-- 56px.bin
-|-- img
- |-- point.png
- |-- gps.png
- |-- bat4.png
- |-- ...png
-```
-
-- `EventMesh.py` is an event management module. When events are triggered on screen controls, users only need to call related interfaces to send events and [EventMesh](https://github.com/QuecPython/EventMesh) will automatically switch screen contents.
-- `common.py` mainly provides common abstract base classes and common dependent classes. For example, `class Abstract` provides lifecycle abstractions.
-- `constant.py` mainly provides constant configurations.
-- `lcd.py` mainly provides LCD driver initialization, TP driver initialization, and LVGL initialization. The screen will only display after successful initialization of this file.
-- `css.py` mainly provides css functionalities, static styles, font styles etc for screen objects in `ui.py` to use.
-- `ui.py`
- - Provides base class `class Screen()` for screen objects, with public methods needed by all screens, like screen creation, status bar info display (operator name, signal strength, system time, battery level etc).
- - `class **Screen` implements a class that inherits from `class Screen()`, representing code implementation for each screen's display content. The interface code is mainly automatically generated by the GUI Guider tool, with minor modifications done afterwards, primarily in the object initialization method `__init__()` and control event handler callbacks `__xxx_event_cb()`. Modifications can also be done at various lifecycle stages.
-- `mgr.py` mainly provides background functionalities, allowing interfaces to interact with various managers at different lifecycle stages or upon event triggers.
-- `main_t.py` is the application entry script file.
- - Calls `lcd.py` to initialize screen drivers and display.
- - Initializes `APP`, the wearable app.
- - Calls `class UI()` in `ui.py` to create the GUI object for the wearable solution, and adds required screen objects to this GUI object's screen object adder, which would execute the page's initialization method during addition.
- - Adds managers to `APP` and executes managers' initialization methods.
- - Starts `APP`.
- - Jumps to main interface.
-
-### Application Startup Process
-
-The application startup process is as follows:
-
-
-
-## Software Design
-
-### Software Framework Design
-
-#### Application Design
-
-The software design framework diagram for the wearable solution is as follows:
-
-
-
-#### Interface Switching Mechanism
-
-**EventMesh Event Management Framework**
-
-As mentioned above, interface switching is driven by the EventMesh event management framework.
-
-- EventMesh is an application framework based on the publish-subscribe mechanism. Users can subscribe to any topics they are interested in, representing specific events.
-- When subscribing to a topic, a callback function needs to be registered to handle the generated event.
-- Users can publish the event from anywhere events are triggered, carrying message content. The registered callback functions of subscribers will then be invoked to process the event.
-
-The EventMesh design framework is shown below:
-
-
-
-**Interface Switching Principles**
-
-
-
-Page Template and Lifecycle Example
-
-```python
-# ui.py
-
-# Any new class **Screen must inherit from Screen. The lv_obj must be predefined.
-
-class DemoScreen(Screen):
- # NAME is required, it is used to find the screen when switching
- # For example we use EventMesh.publish("load_screen", {"screen": "demo_screen"}) to find this screen
- NAME = "demo_screen"
- def __init__(self):
- super().__init__()
- # meta is the core switching object
- self.meta = app_list_screen
- # prop contains info passed during the jump
- # if EventMesh.publish("load_screen", {"screen": "demo_screen", “test”:1}) is called
- # then prop = {"screen": "demo_screen", “test”:1}
- self.prop = None
-
- # Called only once when ui.add_screen(DemoScreen())
- # Users can implement initialization here
- def post_processor_after_instantiation(self, *args, **kwargs):
- """Called after instantiation"""
- pass
-
- # These methods will be called in sequence whenever
- # EventMesh.publish("load_screen", {"screen": "demo_screen"}) switches to this screen
- # post_processor_before_initialization
- # initialization
- # post_processor_after_initialization
- # Users can implement functionality here, called every time when switching to this screen
- def post_processor_before_initialization(self, *args, **kwargs):
- """Called before initialization"""
- pass
-
- def initialization(self, *args, **kwargs):
- """initialization"""
- pass
-
-
- def post_processor_after_initialization(self, *args, **kwargs):
- """Called after initialization"""
- pass
-
- # Called when leaving this screen, for example below will
- # first call deactivate() before calling main screen init()
- def deactivate(self, *args, **kwargs):
- """initialize load"""
- pass
-
-
-# Note: If the screen is in a tileview, the mapping must be added for switching with
-# EventMesh.publish("load_screen", {"screen": "main_screen"}) to work
-# See example mapping below in UI class
-
-class UI(Abstract):
- def __init__(self):
- self.screens = []
- self.current = None
- # display_screen maps to tile at column 0 row 0
- # main_screen maps to tile at column 0 row 1, etc
- self.tileview_map = {
- "display_screen": [0, 0, lv.ANIM.OFF],
- "main_screen": [1, 0, lv.ANIM.OFF],
- "watch_face_screen": [2, 0, lv.ANIM.OFF],
- "app_list_1_screen": [3, 0, lv.ANIM.OFF],
- #...
- }
- # Reverse mapping of above
- self.tileview_position_map = {
- (0, 0): "display_screen",
- (1, 0): "main_screen",
- (2, 0): "watch_face_screen",
- #...
- }
-
-# What is tileview? For example, tile1 is at position column 1 row 0, supports left/right slide
-tile1 = tileview.add_tile(1, 0, lv.DIR.RIGHT | lv.DIR.LEFT)
-# Put main_screen on tile1, swiping left enters tile at (0,0), swiping right enters tile at (2, 0)
-main_screen = lv_obj(
- parent=tile1,
- #...
-)
-```
-
-As can be seen from the above code, the callback implementation for each touch event is similar.
-
-Taking the application list control touch as an example, the code is:
-
-```python
-# Event handling when app icon clicked
-def btn_click(self, event, i):
- screen_info = self.profile[i][1]
- if screen_info:
- # Found click event, switch page
- EventMesh.publish("load_screen", screen_info)
-
-# Render app icons
-def post_processor_after_instantiation(self):
- for i, btn_profile in enumerate(self.profile):
- btn = lv_img(
- parent=self.container,
- #...
- )
- # Add click event to each button
- btn.add_event_cb(lambda event, cur=i: self.btn_click(event, cur), lv.EVENT.CLICKED, None)
- self.btn_list.append(btn)
-```
-
-The core statement is `EventMesh.publish("load_screen", screen_info)`, which sends a `"load_screen"` event indicating loading a new screen, carrying the message `screen_info` which contains the name of the screen to switch to, like `"blood_screen"`.
-
-**UI Startup**
-
-The `"load_screen"` event is subscribed in the `start()` method of class `AgriUi(object)` in `ui.py`:
-
-```python
-class UI(Abstract):
-
- def lv_load(self, event, msg):
- # Find screen based on name
- for screen in self.screens:
- if screen.NAME == msg["screen"]:
- # Switch logic
- pass
-
- def start(self):
- # Subscribe event
- EventMesh.subscribe("load_screen", self.lv_load)
- # Load first screen
- EventMesh.publish("load_screen", {"screen": "main_screen"})
-```
-
-The above code starts up the wearable GUI:
-
-- `add_screen` creates metadata for each screen
-
-- `EventMesh.subscribe()` subscribes to `"load_screen"`, invoking `lv_load()` when event occurs
-
- ```
- lv_load() finds the target screen based on name, loads it with lv.scr_load()
- ```
-
-- First screen loaded with `EventMesh.publish("load_screen", {"screen": "main_screen"})`
-
-This completes wearable GUI startup, subsequent screen switching is driven by user touch.
-
-### Graphical Interface Design
-
-As mentioned before, QuecPython uses NXP's [GUI Guider](https://www.nxp.com/design/software/development-software/gui-guider:GUI-GUIDER) tool for graphical interface design. This tool allows not only interface layout design, but also automatic QuecPython code generation. [Click here for a GUI Guider tutorial](https://python.quectel.com/doc/Application_guide/en/multi-media/lvgl/lvgl_ui_tool.html).
-
-The following sections demonstrate the graphical interface design process using the wearable solution app as an example.
-
-#### Layout and Background Setup
-
-Start by selecting a suitable template and background design for a watch face app. This example starts from a blank template, setting the resolution to 240*280px.
-
-
-
-#### Interface Drawing
-
-This section focuses on drawing the main dial page to demonstrate layout and quick code implementation.
-
-1. Top Bar
-
-
-
-- **Components:** obj, img, label
-
-- Operator and Signal (Box 1):
-
-
-
- An obj containing an img for signal and label for operator name, left aligned in layout, 4px gap between img and label
-
- - obj size is specific pixel width * 20px
- - img size is 20px * 20px
-
-- Navigation and Battery (Box 2):
-
-
-
- An obj containing a navigation img and battery level img, 8px gap between them, sizes:
-
- - obj size is 48px * 20px
- - img size is 20px * 20px
-
-- Overall Layout:
-
- - Flex layout, default horizontal axis
- - Size 240px * 34px
- - Main axis left-right aligned using space-between
- - Children aligned flex-end on cross axis, i.e. bottom
-
-- Layout padding: top 0px, right 12px, bottom 4px, left 12px
-
-Implementation:
-
-```python
-# Styles from css.py
-
-# Main page
-main_screen = lv_obj(
- size=(240, 280),
- style=[...]
-)
-
-# Top bar
-main_top = lv_obj(
- parent=main_screen,
- size=(240, 34),
- flex_flow=lv.FLEX_FLOW.ROW,
- flex_align=(lv.FLEX_ALIGN.SPACE_BETWEEN, lv.FLEX_ALIGN.END, lv.FLEX_ALIGN.END),
- style=[...]
-)
-
-# Box 1
-main_top_cont_1 = lv_obj(
- parent=main_top,
- size=(88, 20),
- flex_flow=lv.FLEX_FLOW.ROW,
- flex_align=(...),
- style=[
- # gap set to 4px in style
- (style_main_top_cont_1, lv.PART.MAIN | lv.STATE.DEFAULT),
- ...]
-)
-
-# Signal img parent is Box 1
-main_top_cont_1_img_signal = lv_img(
- parent=main_top_cont_1,
- size=(20, 20),
- src="U:/media/s4.png",
- style[...]
-)
-
-# Operator label parent is Box 1
-main_top_cont_1_label_operator = lv_label(
- parent=main_top_cont_1,
- size=(64, 19),
- text="Operator",
- style[...]
-)
-
-# Box 2
-main_top_cont_2 = lv_obj(
- parent=main_top,
- size=(48, 20),
- flex_flow=lv.FLEX_FLOW.ROW,
- flex_align=(...),
- style[...]
-)
-
-# Navigation img parent is Box 2
-main_top_cont_2_img_gps = lv_img(
- parent=main_top_cont_2,
- ...)
-
-# Battery img parent is Box 2
-main_top_cont_2_img_bat = lv_img(
- parent=main_top_cont_2,
- ...)
-```
-
-2. Time Section
-
-
-
-- Time Section
- - Size 116px * 200px
- - Position:
- - top: 64px
- - left: 16px
-- Hour Hand Section (Box 1)
- - Size 118px * 200px
- - 2 images
- - Each image size 58 * 100px
- - Flex layout, horizontal axis
-- Minute Hand Section (Box 2)
- - 2 images
- - Image size 58 * 100px each
- - Flex layout, horizontal axis
-- Layout:
- - Flex layout, vertical axis
-
-```python
-# ... main_screen
-
-# Create time section
-main_content_cont_1 = lv_obj(
- parent=main_screen,
- size=(116, 200),
- pos=(19, 64),
- flex_flow=lv.FLEX_FLOW.COLUMN,
- flex_align=(...),
- style[...]
-)
-
-# Create Box 1
-main_content_cont_1_hour = lv_obj(
- parent=main_content_cont_1,
- size=(116, 100),
- flex_flow=lv.FLEX_FLOW.ROW,
- flex_align=(...),
- style[...]
-)
-
-# Hour hand img 1 in Box 1
-main_content_cont_1_hour_0 = lv_img(
- parent=main_content_cont_1_hour,
- size=(58, 100),
- src="U:/media/h0.png",
- style[...]
-)
-
-# Hour hand img 2 in Box 1
-main_content_cont_1_hour_1 = lv_img(
- ...)
-
-# Create Box 2
-main_content_cont_1_m = lv_obj(
- parent=main_content_cont_1,
- # Inherits vertical flex layout from parent
- flex_flow=lv.FLEX_FLOW.ROW,
- ...)
-
-# Minute hand img 0 in Box 2
-main_content_cont_1_m_0 = lv_img(
- ...)
-
-# Minute hand img 1 in Box 2
-main_content_cont_1_m_1 = lv_img(
- ...)
-```
-
-When placing elements in GUI Guider, ensure components align to grid and layout appropriately for different screen sizes and resolutions. The design should be clean and minimalist, use appropriate color schemes to make key info prominent yet non-intrusive, interactive elements should provide instant feedback e.g. hover/click change appearance. Test on different devices to ensure usability and performance.
-
-If the system will be used under various lighting conditions like direct sunlight, adjust contrast and brightness to enhance visibility. Finally, the design should be intuitive for new users to navigate without extensive training, reflecting good user experience (UX) design principles.
-
-The code generated by GUI tools lacks flexibility and maintainability. It's recommended to refactor as shown above for better encapsulation, simplicity and maintainability.
\ No newline at end of file
diff --git a/docs/Application_guide/en/solutions/Wear/software_design.md b/docs/Application_guide/en/solutions/Wear/software_design.md
new file mode 100644
index 0000000000000000000000000000000000000000..4885d7ab84f4223304d7993d461393b772a592da
--- /dev/null
+++ b/docs/Application_guide/en/solutions/Wear/software_design.md
@@ -0,0 +1,495 @@
+# Software Design
+
+
+
+## Software framework
+
+
+
+### Software Design Diagram
+
+
+
+
+
+### Business system startup process
+
+
+
+
+
+## Implementation
+
+
+
+### Code Catalog
+
+The code for the wearable solution is hosted on [Github](https://github.com/QuecPython/solution-wearable.git)The directory structure of the code is as follows:
+
+```PlainText
+.
+|-- EventMesh.py
+|-- common.py
+|-- constant.py
+|-- lcd.py
+|-- css.py
+|-- ui.py
+|-- mgr.py
+|-- main_t.py
+|-- img
+| |-- point.png
+| |-- gps.png
+| |-- bat4.png
+| |-- ...png
+```
+
+- `EventMesh.py` is an event manager module that, when an event on a screen control is triggered, users only need to call the relevant interface to send the event, [EventMesh](https://github.com/QuecPython/EventMesh) It will automatically switch screen content.
+- `common.py` mainly provides common abstract base classes and common dependency classes, such as `class Abstract` which provides abstraction of the lifecycle.
+- `constant.py` mainly provides constant configuration.
+- `lcd.py` mainly providing driver initialization for LCD, The initialization of TP drivers and LVGL will only be displayed on the screen when this file is successfully initialized.
+- `css.py` mainly provides CSS functionality, static styles, font styles, etc. for use by screen objects in UI files.
+- `ui.py`
+ - Provides the base class `class Screen()` for screen objects, providing common methods required for all screen objects, such as creating screens and displaying status bar information (operator name, signal strength, system time, battery level, etc.).
+ - `Class **Screen` implements a class that inherits from class Screen(), which is the code implementation corresponding to the image that the screen needs to display. The main content of the interface code is automatically generated by the GUI Guider tool and then modified slightly, mainly by modifying the object initialization method ` __init__() ` and the control event handling callback function (` __xxx_event_cb() `), or modifying it during the lifecycle of the control
+- `mgr.py` mainly providing backend functions, allowing the interface to interact with various managers at different lifecycles or event triggers.
+- `main_t.py` is an application entry script file.
+ - Call `lcd.py` to initialize the screen driver and display.
+ - Initialize the `APP` and wear the app.
+ - Call the class `UI()` provided by `ui. py` to create a GUI object for the wearing scheme, and call the screen object adder of the GUI object to add the required screen objects. When adding, the instantiation method of the page will be executed.
+ - Call `APP` to add a manager and execute the instantiation method of the manager.
+ - startup `APP`.
+ - Jump to the main screen.
+
+
+
+### Screen switching mechanism
+
+
+
+#### EventMesh Management Framework
+
+As mentioned earlier, the interface switching is driven by the EventMesh event management framework.
+
+- EventMesh is an application framework based on subscription and publishing mechanisms, where users can subscribe to any topic of interest, which represents an event.
+- At the same time as subscribing to the topic, you also need to register a callback function to handle the generated events.
+- Users can post the event anywhere it occurs and carry the message content. At this point, the callback function registered by the subscriber will be called and the event will be processed.
+
+EventMesh design framework is shown in the following figure:
+
+
+
+
+
+#### **Principle of screen switching implementation**
+
+
+
+
+
+Sample lifecycle of page templates and redirects
+
+```python
+# ui.py
+
+# Any new class **Screen must inherit from Screen. The lv_obj must be predefined.
+
+class DemoScreen(Screen):
+ # NAME is required, it is used to find the screen when switching
+ # For example we use EventMesh.publish("load_screen", {"screen": "demo_screen"}) to find this screen
+ NAME = "demo_screen"
+ def __init__(self):
+ super().__init__()
+ # meta is the core switching object
+ self.meta = app_list_screen
+ # prop contains info passed during the jump
+ # if EventMesh.publish("load_screen", {"screen": "demo_screen", “test”:1}) is called
+ # then prop = {"screen": "demo_screen", “test”:1}
+ self.prop = None
+
+ # Called only once when ui.add_screen(DemoScreen())
+ # Users can implement initialization here
+ def post_processor_after_instantiation(self, *args, **kwargs):
+ """Called after instantiation"""
+ pass
+
+ # These methods will be called in sequence whenever
+ # EventMesh.publish("load_screen", {"screen": "demo_screen"}) switches to this screen
+ # post_processor_before_initialization
+ # initialization
+ # post_processor_after_initialization
+ # Users can implement functionality here, called every time when switching to this screen
+ def post_processor_before_initialization(self, *args, **kwargs):
+ """Called before initialization"""
+ pass
+
+ def initialization(self, *args, **kwargs):
+ """initialization"""
+ pass
+
+
+ def post_processor_after_initialization(self, *args, **kwargs):
+ """Called after initialization"""
+ pass
+
+ # Called when leaving this screen, for example below will
+ # first call deactivate() before calling main screen init()
+ def deactivate(self, *args, **kwargs):
+ """initialize load"""
+ pass
+
+
+# Note: If the screen is in a tileview, the mapping must be added for switching with
+# EventMesh.publish("load_screen", {"screen": "main_screen"}) to work
+# See example mapping below in UI class
+
+class UI(Abstract):
+ def __init__(self):
+ self.screens = []
+ self.current = None
+ # display_screen maps to tile at column 0 row 0
+ # main_screen maps to tile at column 0 row 1, etc
+ self.tileview_map = {
+ "display_screen": [0, 0, lv.ANIM.OFF],
+ "main_screen": [1, 0, lv.ANIM.OFF],
+ "watch_face_screen": [2, 0, lv.ANIM.OFF],
+ "app_list_1_screen": [3, 0, lv.ANIM.OFF],
+ #...
+ }
+ # Reverse mapping of above
+ self.tileview_position_map = {
+ (0, 0): "display_screen",
+ (1, 0): "main_screen",
+ (2, 0): "watch_face_screen",
+ #...
+ }
+
+# What is tileview? For example, tile1 is at position column 1 row 0, supports left/right slide
+tile1 = tileview.add_tile(1, 0, lv.DIR.RIGHT | lv.DIR.LEFT)
+# Put main_screen on tile1, swiping left enters tile at (0,0), swiping right enters tile at (2, 0)
+main_screen = lv_obj(
+ parent=tile1,
+ #...
+)
+```
+
+From the above code, it can be seen that the implementation of the callback function for each touch event is similar.
+
+Taking the touch of the application list control as an example, the code is as follows:
+
+```python
+class AppList1Screen(Screen):
+ NAME = "app_list_1_screen"
+
+ def __init__(self):
+ super().__init__()
+ self.meta = app_list_screen
+ self.container = app_list_cont
+ self.profile = [
+ ["U:/media/app_heart.png", {"screen": "blood_screen"}],
+ ["U:/media/app_phone.png", {"screen": "dail_screen"}],
+ ["U:/media/app_chat.png", None],
+ ["U:/media/app_time.png", None]
+ ]
+ self.btn_list = []
+ self.bottom = None
+ self.bottom_profile = [
+ ["U:/media/wpoint.png"],
+ ["U:/media/bpoint.png"],
+ ["U:/media/bpoint.png"],
+ ["U:/media/bpoint.png"]
+ ]
+ self.bottom_btn_list = []
+
+ def btn_click(self, event, i):
+ screen_info = self.profile[i][1]
+ if screen_info:
+ EventMesh.publish("load_screen", screen_info)
+
+ def post_processor_after_instantiation(self):
+ for i, btn_profile in enumerate(self.profile):
+ btn = lv_img(
+ parent=self.container,
+ size=(110, 110),
+ src=btn_profile[0],
+ flag=lv.obj.FLAG.CLICKABLE,
+ style=[
+ (style_cont, lv.PART.MAIN | lv.STATE.DEFAULT),
+ (style_list_scrollbar, lv.PART.SCROLLBAR | lv.STATE.DEFAULT),
+ (style_list_scrollbar, lv.PART.SCROLLBAR | lv.STATE.SCROLLED),
+ (style_gap_default, lv.PART.MAIN | lv.STATE.DEFAULT),
+ (style_pad_default, lv.PART.MAIN | lv.STATE.DEFAULT),
+ ]
+ )
+ btn.add_event_cb(lambda event, cur=i: self.btn_click(event, cur), lv.EVENT.CLICKED, None)
+ self.btn_list.append(btn)
+ self.bottom = lv_obj(
+ parent=app_list_screen,
+ pos=(88, 254),
+ size=(56, 8),
+ flex_flow=lv.FLEX_FLOW.ROW,
+ flex_align=(lv.FLEX_ALIGN.SPACE_AROUND, lv.FLEX_ALIGN.START, lv.FLEX_ALIGN.START),
+ style=[
+ (style_cont, lv.PART.MAIN | lv.STATE.DEFAULT),
+ (style_list_scrollbar, lv.PART.SCROLLBAR | lv.STATE.DEFAULT),
+ (style_list_scrollbar, lv.PART.SCROLLBAR | lv.STATE.SCROLLED),
+ (style_pad_default, lv.PART.SCROLLBAR | lv.STATE.SCROLLED),
+ (style_app_list, lv.PART.MAIN | lv.STATE.DEFAULT),
+ ]
+ )
+ for btn_profile in self.bottom_profile:
+ btn = lv_img(
+ parent=self.bottom,
+ size=(8, 8),
+ src=btn_profile[0],
+ style=[
+ (style_cont, lv.PART.MAIN | lv.STATE.DEFAULT),
+ (style_list_scrollbar, lv.PART.SCROLLBAR | lv.STATE.DEFAULT),
+ (style_list_scrollbar, lv.PART.SCROLLBAR | lv.STATE.SCROLLED),
+ (style_gap_default, lv.PART.MAIN | lv.STATE.DEFAULT),
+ (style_pad_default, lv.PART.MAIN | lv.STATE.DEFAULT),
+ ]
+ )
+ self.bottom_btn_list.append(btn)
+```
+
+The core statement of this code is ` EventMesh.publish("load_screen", screen_info)`, which sends an event called ` load_screen`, meaning to load a new screen interface; The carried message is `screen_info`, `screen_info` is the name of the interface to be redirected to by `{"screen": "blood_streen"}`, indicating that the blood oxygen display interface is being loaded.
+
+#### **UI startup**
+
+The `load_screen`event is subscribed to in the `start()` method of the `class AgriUi(object)` class in the `Agri_ui.py` script file.
+
+code:
+
+```python
+class UI(Abstract):
+
+ def __init__(self):
+ ...
+
+ def lv_load(self, event, msg):
+ for screen in self.screens:
+ if screen.NAME == msg["screen"]:
+ scr = screen
+ if self.current != scr:
+ if self.current:
+ self.current.deactivate()
+ scr.last_screen_info = {"screen": self.current.NAME}
+ scr.set_prop(msg)
+ scr.post_processor_before_initialization()
+ scr.initialization()
+ scr.post_processor_after_initialization()
+ self.current = scr
+ if msg["screen"] in self.tileview_map:
+ lv.scr_load(tileview_screen)
+ tileview.set_tile_id(*self.tileview_map[msg['screen']])
+ else:
+ lv.scr_load(self.current.meta)
+
+ def post_processor_after_instantiation(self):
+ EventMesh.subscribe("load_screen", self.lv_load)
+ EventMesh.subscribe("load_tileview", self.lv_tileview)
+
+ def add_screen(self, screen):
+ screen.post_processor_after_instantiation()
+ self.screens.append(screen)
+
+ def start(self):
+ self.post_processor_after_instantiation()
+```
+
+The `start()` method in the above code is used to launch the graphical interface of the wearable solution, and its workflow is as follows:
+
+- Call the `add_streen` method to create metadata for each screen interface.
+
+- Call the `EventMesh.subscribe()` method to subscribe to an event named `load_screen`. When the event occurs, call the `lv_load()` method to process it.
+
+ > The `lv_load()` method matches the corresponding interface object based on the message carried when publishing the event, that is, the name of the screen interface, and calls lvgl's `lv.scr_load()` method to load a new interface.
+ >Observant readers will notice that in every class implemented in the screen interface script file, there will be statements similar to `NAME=' main_streen' `under its class. This statement records the name of the screen interface.
+
+- `EventMesh.publish("load_screen", {"screen": "main_screen"})` is used to trigger the first interface display, which is the main interface.
+
+At this point, the graphical interface of the wearable solution has been launched, and the subsequent interface switching is controlled by the user's touch.
+
+
+
+### Graphic interface design
+
+The following text takes the application of wearable solutions as an example to introduce the design process of graphical interfaces.
+
+#### Layout and background settings
+
+Create a watch plan and choose a suitable layout template and background design. This stage will start with a blank layout design, selecting a blank template and setting the resolution to 240 * 280.
+
+
+
+#### Screen drawing
+
+This section mainly draws the dial homepage, explains the page layout, and how to quickly implement it using code.
+
+1. top bar
+
+
+
+- **component:** obj, img, label。
+- **Operator and Signal (Box 1):** is an obj with another img display signal inside, The label displays the operator, which is aligned to the left in the layout, with a 4px gap between the weapon img and the label.
+ - The size of obj is the specific length multiplied by 20px.
+ - The img size is 20px * 20px.
+- **Navigation and battery level (Box 2):** is an obj with another navigation img and battery level img inside, with an 8px interval in between, with a size of.
+ - obj size is 48px * 20px。
+ - img size is 20px * 20px。
+- **top layout:**
+ - flex layout, Default spindle horizontal direction.
+ - size is 240px * 34px。
+ - Layout the container with the main axis aligned left and right in the space between.
+ - All sub attributes use flex end alignment, representing bottom alignment along the vertical axis.
+ - The layout padding is 0px above, 12px to the right, 4px to the bottom, and 12px to the left.
+
+ Implementation:
+
+```python
+# Styles from css.py
+
+# Main page
+main_screen = lv_obj(
+ size=(240, 280),
+ style=[...]
+)
+
+# Top bar
+main_top = lv_obj(
+ parent=main_screen,
+ size=(240, 34),
+ flex_flow=lv.FLEX_FLOW.ROW,
+ flex_align=(lv.FLEX_ALIGN.SPACE_BETWEEN, lv.FLEX_ALIGN.END, lv.FLEX_ALIGN.END),
+ style=[...]
+)
+
+# Box 1
+main_top_cont_1 = lv_obj(
+ parent=main_top,
+ size=(88, 20),
+ flex_flow=lv.FLEX_FLOW.ROW,
+ flex_align=(...),
+ style=[
+ # gap set to 4px in style
+ (style_main_top_cont_1, lv.PART.MAIN | lv.STATE.DEFAULT),
+ ...]
+)
+
+# Signal img parent is Box 1
+main_top_cont_1_img_signal = lv_img(
+ parent=main_top_cont_1,
+ size=(20, 20),
+ src="U:/media/s4.png",
+ style[...]
+)
+
+# Operator label parent is Box 1
+main_top_cont_1_label_operator = lv_label(
+ parent=main_top_cont_1,
+ size=(64, 19),
+ text="Operator",
+ style[...]
+)
+
+# Box 2
+main_top_cont_2 = lv_obj(
+ parent=main_top,
+ size=(48, 20),
+ flex_flow=lv.FLEX_FLOW.ROW,
+ flex_align=(...),
+ style[...]
+)
+
+# Navigation img parent is Box 2
+main_top_cont_2_img_gps = lv_img(
+ parent=main_top_cont_2,
+ ...)
+
+# Battery img parent is Box 2
+main_top_cont_2_img_bat = lv_img(
+ parent=main_top_cont_2,
+ ...)
+
+```
+
+
+
+2. Time Section
+
+
+
+- Time Section
+ - Size 116px * 200px
+ - Position:
+ - top: 64px
+ - left: 16px
+- Hour Hand Section (Box 1)
+ - Size 118px * 200px
+ - 2 images
+ - Each image size 58 * 100px
+ - Flex layout, horizontal axis
+- Minute Hand Section (Box 2)
+ - 2 images
+ - Image size 58 * 100px each
+ - Flex layout, horizontal axis
+- Layout:
+ - Flex layout, vertical axis
+
+```python
+# ... main_screen
+
+# Create time section
+main_content_cont_1 = lv_obj(
+ parent=main_screen,
+ size=(116, 200),
+ pos=(19, 64),
+ flex_flow=lv.FLEX_FLOW.COLUMN,
+ flex_align=(...),
+ style[...]
+)
+
+# Create Box 1
+main_content_cont_1_hour = lv_obj(
+ parent=main_content_cont_1,
+ size=(116, 100),
+ flex_flow=lv.FLEX_FLOW.ROW,
+ flex_align=(...),
+ style[...]
+)
+
+# Hour hand img 1 in Box 1
+main_content_cont_1_hour_0 = lv_img(
+ parent=main_content_cont_1_hour,
+ size=(58, 100),
+ src="U:/media/h0.png",
+ style[...]
+)
+
+# Hour hand img 2 in Box 1
+main_content_cont_1_hour_1 = lv_img(
+ ...)
+
+# Create Box 2
+main_content_cont_1_m = lv_obj(
+ parent=main_content_cont_1,
+ # Inherits vertical flex layout from parent
+ flex_flow=lv.FLEX_FLOW.ROW,
+ ...)
+
+# Minute hand img 0 in Box 2
+main_content_cont_1_m_0 = lv_img(
+ ...)
+
+# Minute hand img 1 in Box 2
+main_content_cont_1_m_1 = lv_img(
+ ...)
+```
+
+
+
+When placing elements in GUI Guider, ensure components align to grid and layout appropriately for different screen sizes and resolutions. The design should be clean and minimalist, use appropriate color schemes to make key info prominent yet non-intrusive, interactive elements should provide instant feedback e.g. hover/click change appearance. Test on different devices to ensure usability and performance.
+
+If the system will be used under various lighting conditions like direct sunlight, adjust contrast and brightness to enhance visibility. Finally, the design should be intuitive for new users to navigate without extensive training, reflecting good user experience (UX) design principles.
+
+The code generated by GUI tools lacks flexibility and maintainability. It's recommended to refactor as shown above for better encapsulation, simplicity and maintainability.
\ No newline at end of file
diff --git a/docs/Application_guide/en/solutions/electricity-meter/README.md b/docs/Application_guide/en/solutions/electricity-meter/README.md
index 25f21d523002e15a379da3e5764bbef1d629a592..8a5ab449bf029f8472b85eaf6f3fbf50c0ab0d96 100644
--- a/docs/Application_guide/en/solutions/electricity-meter/README.md
+++ b/docs/Application_guide/en/solutions/electricity-meter/README.md
@@ -1,391 +1,18 @@
-# Smart Electricity Meter Solution
+# Electricity-Meter solution
-## Overview
-The smart electricity meter solution released by QuecPython includes serial communication modules, TCP clients, RFC1662 protocols, DLMS protocols (under development) and other common functional components in the electricity meter industry, and provides a basic application framework. Users can improve the application program development based on this framework.
-## Application Framework
+Meter solution based on QuecPython_EG91X C1-P02 EVB, Has the following characteristics:
-### Introduction
+- Contains commonly used functional components in the electricity meter industry, such as serial communication module, TCP client, RFC1662 protocol, DLMS protocol (under development), etc.
+- Having a basic application framework, users can improve their application development based on this framework.
+- Using Python language for easy secondary development.
-The smart electricity meter solution is developed based on the application framework called `QFrame`.
+
-> `QFrame` is an application framework developed by QuecPython. [Click here](https://github.com/QuecPython/QFrame) to view the design and application guidance of this framework.
+------
-An application often relies on multiple business modules, and there may be coupling between business modules.
-The **star architecture design** is adopted for communication between business modules in framework design, as shown below:
+- [development resources](./dev_resources.md)
+- [quick start](./quick_start.md)
+- [software design](./software_design.md)
-
-
-Meditor in the figure is an intermediary object (usually named `Application`), and each business module communicates through the `Application` object. This design is called the **mediator pattern**.
-
-Business modules are plugged into the application in the form of application extensions, and the interaction between business extensions is uniformly dispatched through the `Application` object.
-
-### Application Object
-
-Applications based on the `QFrame` framework must have a central object that schedules various business modules, namely the `Application` object mentioned above; application parameters are also configured through this object.
-
-Sample code is as follows:
-
-```python
-from usr.qframe import Application
-
-# init application instance
-app = Application(__name__)
-
-# read settings from json file
-app.config.from_json('/usr/dev.json')
-
-# app.config is a python dict, you can use to update settings as below:
-app.config.update(
- {
- "UART": {
- "port":2,
- "baudrate":115200,
- "bytesize":8,
- "parity":0,
- "stopbits":1,
- "flowctl":0
- }
- }
-)
-```
-
-### Application Extensions
-
-Application extensions refer to the business modules loaded by the `Application` object.
-
-In general, application extensions get their own configurations from `app.config` and pass them to the application instance during initialization.
-
-The use of application extensions includes two parts: definition and initialization.
-
-#### Definition and initialization of application extensions
-
-Application extensions provide a base class called `AppExtensionABC`, defined as follows:
-
-```python
-class AppExtensionABC(object):
- """Abstract Application Extension Class"""
-
- def __init__(self, name, app=None):
- self.name = name # extension name
- if app:
- self.init_app(app)
-
- def init_app(self, app):
- # register into app, then, you can use `app.{extesion.name}` to get current extension instance
- app.append_extesion(self)
- raise NotImplementedError
-
- def load(self):
- # loading extension functions, this method will be called in `app.mainloop`
- raise NotImplementedError
-```
-
-The specific application extension class inherits this base class to constrain the interface definition of the application extension class.
-
-- We need to pass in the `Application` application object to the initialization method `__init__`. Call `init_app` when creating the application extension object to complete the initialization operation of the extension; you can also not pass in the application object, but directly create the application extension object, and then explicitly call `init_app` later to complete the initialization.
-- The `load` method is called by the `Application` object and is used to load various application extensions.
-
-#### Using application extensions
-
-After the application extension inherits the base class `AppExtensionABC` and implements the necessary interface functions, refer to the following two code samples with different methods to load the application extension object.
-
-Method 1:
-
-```python
-app = Application(__name__)
-ext = ExtensionClass(app)
-```
-
-Method 2:
-
-```python
-ext = ExtensionClass()
-ext.init_app(app)
-```
-
-## Application Development
-
-The code for the smart meter solution is hosted on [github](https://github.com/QuecPython/solution-electricity-meter.git). The directory structure is as follows:
-
-```
-.
-|-- LICENSE
-|-- README.md
-|-- code
-| |-- business.py
-| |-- constant.py
-| |-- demo.py
-| |-- dev.json
-| |-- protocol.py
-| `-- qframe
-| |-- __init__.py
-| |-- builtins
-| | |-- __init__.py
-| | |-- clients.py
-| | |-- network.py
-| | `-- uart.py
-| |-- collections.py
-| |-- core.py
-| |-- datetime.py
-| |-- globals.py
-| |-- led.py
-| |-- logging.py
-| |-- ota.py
-| |-- qsocket.py
-| |-- serial.py
-| `-- threading.py
-`-- docs
- `-- media
- |-- UML.png
- |-- init.png
- |-- system.png
- `-- ...
-```
-
-### Software Architecture Diagram
-
-The software architecture diagram for the smart electricity meter solution is as follows:
-
-
-
-### UML Class Diagram
-
-From the software architecture diagram above, we can see that the smart electricity meter solution includes DLMS, RFC1662, TCPClient and other application extensions. The logical relationship between the various application extensions in the application is shown in the following UML class diagram:
-
-
-
-### Software Initialization Process
-
-The initialization process of the smart electricity meter solution is as follows:
-
-
-
-1. Instantiate application object
-2. Import configuration json file
-3. Initialize application extension components (in this step each application extension is registered in the master application object to facilitate interaction between them)
-4. Check network (this step will block and wait for network ready, if timeout, try cfun switch to recover network)
-5. Load application extensions and start related services (customizable implementation)
-6. The system enters the normal running state (sim card and network detection are enabled by default. If network disconnection occurs, it will try cfun switch automatically to recover network)
-
-### Main Application
-
-As the script file for application entry, `demo.py` provides a factory function `create_app` that passes in the configuration path to initialize the application and load various application extensions.
-
-`demo.py` sample code is as follows:
-
-```python
-import checkNet
-from usr.qframe import Application
-from usr.business import rfc1662resolver, client, uart
-
-PROJECT_NAME = "QuecPython_Framework_DEMO"
-PROJECT_VERSION = "1.0.0"
-
-
-def poweron_print_once():
- checknet = checkNet.CheckNetwork(
- PROJECT_NAME,
- PROJECT_VERSION,
- )
- checknet.poweron_print_once()
-
-
-def create_app(name='DTU', config_path='/code/dev.json'):
- # initialize Application
- _app = Application(name)
- # read settings from json file
- _app.config.from_json(config_path)
-
- # init rfc1662resolver extension
- rfc1662resolver.init_app(_app)
- # init uart extension
- uart.init_app(_app)
- # init tcp client extension
- client.init_app(_app)
-
- return _app
-
-
-# create app with `create_app` factory function
-app = create_app()
-
-if __name__ == '__main__':
- poweron_print_once()
- # loading all extensions
- app.mainloop()
-```
-
-### Application Extensions
-
-The main application extension functions include three main categories `rfc1662resolver` (1662 protocol resolution), `client` (tcp client) and `uart` (serial read and write), which are all registered in the application object ` Application` for ease of coordination.
-
-- `rfc1662resolver`: responsible for parsing and assembling RFC1662 protocol messages, (`RFC1662ProtocolResolver` instance object).
-- `client`: tcp client (`BusinessClient` instance object), responsible for communicating with the tcp server.
-- `uart`: serial port client (`UartBusiness` instance object), responsible for serial read and write.
-
-#### Class `RFC1662ProtocolResolver`
-
-This class is an application extension class, an RFC1662 protocol data resolver, used to process RFC1662 protocol data transmitted in the business, and pack and unpack this class data.
-
-The class provides the following methods:
-
-- `resolve(msg)`
- - **Function**: Process an RFC1662 protocol message. The behavior is to find the processing function of the message from the registry by resolving the protocol (which can be understood as the message id of the protocol message), and call the function to process if found, otherwise throw a `ValueError` exception. See the `register` decorator function on how to register the processing function.
- - **Parameters**: `msg` is an `RFC1662Protocol` object, which is an encapsulation class of the RFC1662 protocol, see the introduction below.
- - **Return value**: None
- - **Exceptions**: If the processing function cannot be found in the registry for the incoming `msg`, a `ValueError` exception will be thrown.
-- `register(protocol)`
- - **Function**: It is a decorator function used to register a processing function for a protocol.
- - **Parameters**: `protocol` can be understood as the message id of the RFC1662 protocol.
- - **Return value**: original function
-- `tcp_to_meter_packet(data)`
- - **Function**: Static method, pack the byte data `data` into a transparent RFC1662 data packet (0x2100), that is, the data frame passed to the meter by tcp transparent transmission.
- - **Parameters**: `data`, byte type.
- - **Return value**: 0x2100 protocol packet byte string
- - **Exceptions**: None
-- `module_to_meter_packet(data)`
- - **Function**: Static method, assemble RFC1662 protocol data packet (0x2200), that is, the data frame sent by the module to the meter
- - **Parameters**: data is a list, `[get/set, id, data]`, where:
- - `get/set`: `COSEM.GET/COSEM.SET`, the corresponding values are `0xC0/0xC1` respectively
- - `id`: function command word
- - `data`: byte type
- - **Return value**: 0x2200 protocol packet byte string
-
-Sample code:
-
-```python
-# we have inited a RFC1662ProtocolResolver object in `business.py` module
-# import `rfc1662resolver`
-from code.business import rfc1662resolver
-
-
-# decorate with protocol 0x2100
-@rfc1662resolver.register(0x2100)
-def handle2100(msg):
- """when get a 0x2100 message,this function will be called"""
- pass
-```
-
-#### Class `RFC1662Protocol`
-
-This class is a specific implementation of the RFC1662 protocol, including unpacking and packing. The instance object of this class is an encapsulated form of a complete RFC1662 protocol package. The main methods are:
-
-- `build_rfc_0x2100`: assemble 0x2100 protocol packet, return bytes, equivalent to `RFC1662ProtocolResolver.tcp_to_meter_packet`
-- `build_rfc_0x2200`: assemble 0x2200 protocol packet, return bytes, equivalent to `RFC1662ProtocolResolver.module_to_meter_packet`
-- `build`: class method, used to resolve a protocol packet frame, return `RFC1662Protocol` object.
-- `replay_get`: reply get command, judge success or failure
-- `replay_set`: reply set command
-- `reply_event`: reply event information
-
-#### TCP Client Component
-
-##### Base Class `TcpClient`
-
-This class exposes two interfaces to the user:
-
-- `recv_callback` method, users rewrite this method to achieve business processing of TCP server downlink data.
-- `send` method, users can call this method to send data to the server.
-
-Code is as follows:
-
-```python
-class TcpClient(object):
- # ...
- def recv_callback(self, data):
- raise NotImplementedError('you must implement this method to handle data received by tcp.')
-
- def send(self, data):
- # TODO: uplink data method
- pass
-```
-
-##### Subclass `BusinessClient`
-
-`BusinessClient` rewrites the `recv_callback` method to encapsulate the downlink data of the server into RFC1662 format messages and forwards the data to the serial port.
-
-Code is as follows:
-
-```python
-class BusinessClient(TcpClient):
-
- def recv_callback(self, data):
- # recv tcp data and send to uart
- data = RFC1662Protocol.build_rfc_0x2100(data)
- CurrentApp().uart.write(data)
-```
-
-#### Serial Communication Component
-
-##### Base Class `Uart`
-
-This class exposes two interfaces to users:
-
-- `recv_callback` method, users rewrite this method to achieve business processing of received serial data.
-- `send` method, users can call this method to send data to the serial port.
-
-Code is as follows:
-
-```python
-class Uart(object):
- # ...
- def recv_callback(self, data):
- raise NotImplementedError('you must implement this method to handle data received from device.')
-
- def write(self, data):
- # TODO: write data to uart
- pass
-```
-
-##### Subclass `UartBusiness`
-
-`UartBusiness` rewrites the `recv_callback` method to implement business processing of received serial data.
-
-```python
-class UartBusiness(Uart):
-
- def recv_callback(self, data):
- # parse 1662 protocol data
- pass
-```
-
-> In the subclass `UartBusiness`'s `recv_callback` method, after parsing the RFC1662 protocol message, constructing the message object, distribute the message processing business through the `rfc1662resolver.resolve` method.
-
-### Sequence Diagram of Component Interaction
-
-```mermaid
-sequenceDiagram
-Title: extensions communication process
-
-participant uart as Uart
-participant protocol as RFC1662Protocol
-participant resolver as RFC1662ProtocolResolver
-participant client as Client
-
-uart -->> protocol: request from meter
-protocol -->> resolver: build message
-resolver -->> resolver: handle business
-resolver -->> protocol: build response message
-protocol -->> uart: response to meter
-resolver -->> client: tcp data post through
-```
-
-### Writing Business Programs
-
-Define a global `rfc1662resolver` resolver in the script file `business.py` to register message processing functions of specified types.
-
-The following sample code registers the 0x2100 protocol transparent transfer processing function:
-
-```python
-# >>>>>>>>>> handle rfc1662 message received from uart <<<<<<<<<<
-
-@rfc1662resolver.register(0x2100)
-def handle2100(msg):
- """post data received to cloud"""
- # message body bytes
- data = msg.info().request_data()
- if data:
- # post data to tcp server by `client` extension register in Application
- CurrentApp().client.send(data)
-```
\ No newline at end of file
diff --git a/docs/Application_guide/en/solutions/electricity-meter/dev_resources.md b/docs/Application_guide/en/solutions/electricity-meter/dev_resources.md
new file mode 100644
index 0000000000000000000000000000000000000000..1f565be7a19e5ed6d5e3e6f32961c5100b62f647
--- /dev/null
+++ b/docs/Application_guide/en/solutions/electricity-meter/dev_resources.md
@@ -0,0 +1,74 @@
+# Development resources summary
+
+
+
+## Development board
+
+- model: [QuecPython_EG91X Evaluation Board](https://python.quectel.com/doc/Getting_started/en/evb/eg91x-evb.html)
+
+- EVB docs
+ - [specification](https://python.quectel.com/wp-content/uploads/2024/09/EG91X_C1-P02%E7%B3%BB%E5%88%97%E5%BC%80%E5%8F%91%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://python.quectel.com/wp-content/uploads/2024/09/EG91X_C1-P02%E7%B3%BB%E5%88%97%E5%BC%80%E5%8F%91%E6%9D%BF%E5%8E%9F%E7%90%86%E5%9B%BE.pdf)
+ - [screen priting](https://python.quectel.com/wp-content/uploads/2024/09/EG91X_C1-P02%E7%B3%BB%E5%88%97%E5%BC%80%E5%8F%91%E6%9D%BF%E4%B8%9D%E5%8D%B0.pdf)
+ - [user guidance](https://python.quectel.com/doc/Getting_started/zh/evb/eg91x-evb.html)
+
+
+
+## Module infomation
+
+- model: [EG912UGL_AA](https://python.quectel.com/modules-cat/eg912u-series)
+ - [specification](https://python.quectel.com/wp-content/uploads/2024/09/Quectel_EG912U-GL_LTE_Standard_%E6%A8%A1%E5%9D%97%E4%BA%A7%E5%93%81%E8%A7%84%E6%A0%BC%E4%B9%A6_V1.2.pdf)
+ - [download drivers](https://python.quectel.com/wp-content/uploads/2024/09/Quectel_Windows_USB_DriverU_V1.0.19.zip)
+
+
+
+## Accessories Information
+
+- model: CP2102
+ - [buy link](https://detail.tmall.com/item.htm?id=613201654382&ns=1&pisk=gw4jx8fcDKvbzpBgq-frNzTvDwu_B_7FGCGTt5L26q3vW1waUPotQi2sfRyoXru4g8MTL8Mv7GD25VN_IRy_ssctBResQoSP8SVmSVBF5w7UiLJfP0yXWAHR6fhnB_ovYkeQlVBFLNtywmXqW-khxJRJ2XD-Mfn9D_O-TX3t6j3ONYhsthpYBRFRNfhMWhLxB3K-tX39XmHx27hZTnLtHFnRNfD-BV3TB4hPbBG1cxVfMyfGM_p6z7MWWFUSwOc4G68m9yGf3vVjF9IQPemjpSHWW9b0bvksEyBPV72QD-luCw6SJk275D31lpcb2Wg-32IBVqNznygYRtTqa4krvln5MZFSlxwQrDO9cqZTnPi0cCf3wqeuxvmAqTc7uyosK09RH7PSHDZ_3TYt3kN8FDzyUeuLx8asv2IPwekB6Kt6NDYsNv55NhxgK5szWq_4mBnxZjiPN_9YjmhoNv55NhxiDbcjT_1WHlf..&priceTId=2150462d17417427652285603e1227&skuId=4871003428842&spm=a21n57.sem.item.3.cf7a3903yaHeHS&utparam=%7B%22aplus_abtest%22%3A%22c0a79115a7b91391fe1a354730d582b7%22%7D&xxc=ad_ztc)
+ - [download driver](https://www.silabs.com/documents/public/software/CP210x_Universal_Windows_Driver.zip)
+
+
+
+## Developlent tool
+
+- QPYcom - QuecPython debug tool
+
+ - version: V3.6.0
+
+
+ - download [QPYcom](https://python.quectel.com/wp-content/uploads/2024/09/QPYcom_V3.6.0.zip)
+
+
+
+
+
+- VSCode
+
+ - download [VSCode](https://code.visualstudio.com/)
+
+
+
+
+## Firmware
+
+- EG912U firmware
+ - version: QPY_OCPU_BETA0002_EG912U_GLAA_FW
+ - download [Firmware](https://python.quectel.com/wp-content/uploads/2024/09/QPY_OCPU_BETA0002_EG912U_GLAA_FW.zip)
+
+
+
+## Source code
+
+- version: v1.0.0
+
+- github repo:
+
+```bash
+git clone https://github.com/QuecPython/solution-electricity-meter
+cd solution-electricity-meter
+git checkout v1.0.0
+```
+
+- [Github Zip download](https://codeload.github.com/QuecPython/solution-electricity-meter/zip/refs/tags/v1.0.0)
+
diff --git a/docs/Application_guide/en/solutions/electricity-meter/quick_start.md b/docs/Application_guide/en/solutions/electricity-meter/quick_start.md
new file mode 100644
index 0000000000000000000000000000000000000000..3a2db79a9a85e209a56985308285c0f517f3a2ec
--- /dev/null
+++ b/docs/Application_guide/en/solutions/electricity-meter/quick_start.md
@@ -0,0 +1,120 @@
+# Quick Start
+
+
+
+## Hardware preparation
+
+- A Windows computer, recommended for the 'Win10' system.
+- A TypeC data cable
+- A SIM card
+- One [EG91X Evaluation Board](https://python.quectel.com/doc/Getting_started/en/evb/eg91x-evb.html)
+- A CP2102 module
+- One antenna
+
+
+
+
+## Environment construction
+
+- Download and install drivers:[Quectel_Windows_USB_DriverU](https://python.quectel.com/wp-content/uploads/2024/09/Quectel_Windows_USB_DriverU_V1.0.19.zip)
+- Download and install [VSCode](https://code.visualstudio.com/)
+- Download and install [QPYCom](https://python.quectel.com/wp-content/uploads/2024/09/QPYcom_V3.6.0.zip)
+- Download [EG912U firmware](https://python.quectel.com/wp-content/uploads/2024/09/QPY_OCPU_BETA0002_EG912U_GLAA_FW.zip)
+- Download [Source code](https://codeload.github.com/QuecPython/solution-electricity-meter/zip/refs/tags/v1.0.0)
+
+
+
+## 硬件连接
+
+按照下图进行硬件连接:
+
+
+
+1. Insert SIM card
+2. Connect the antenna to the antenna connector marked with the word 'LTE'.
+3. Connect the serial port of the EG912U development board to the CP2102 module.
+4. Connect the CP2102 module to the computer
+5. Connect the EG912U development board with a Type-C data cable
+
+
+
+## Equipment development
+
+
+
+### Power on
+
+完成硬件连接的工作后,长按开发板上标识为`PWk`的按键,直到网络灯`net`闪烁,或电脑设备管理器的端口列表中出现包含`Quectel USB` 字样的 COM 口,表示开机成功。(EG91X系列C1-P02开发板上电自动开机)
+
+
+
+
+
+### Download firmware
+
+Refer to [this chapter](https://python.quectel.com/doc/Application_guide/en/dev-tools/QPYcom/qpycom-dw.html# Download firmware) Burn firmware package [QPy_OCPU_SETA0002REG912U_GLAA_FW. zip](https://python.quectel.com/wp-content/uploads/2024/09/QPY_OCPU_BETA0002_EG912U_GLAA_FW.zip) To EG912U module development board.
+
+
+
+### 脚本导入与运行
+
+1. Configure the specific parameters of the TCP server and UART used in `dev.json`
+
+
+
+2. Refer to [this chapter](https://python.quectel.com/doc/Getting_started/en/first_python.html#PC) To transfer files between modules, import all files from the `code` folder in the source code directory into the module file system, as shown in the following figure:
+
+
+
+3. Refer to [this chapter](https://python.quectel.com/doc/Getting_started/en/first_python.html# Execute the script file), execute the main program file ` demo.py`
+
+4. Refer to [this chapter](https://python.quectel.com/doc/Getting_started/en/first_python.html# Stop program running), stop program running
+
+
+
+## Debugging
+
+### Program startup
+
+After executing `demo.py`, the program will start various service modules and connect to the configured TCP server
+
+
+
+
+
+### Upload data from the electricity meter
+
+Here, the serial port assistant is used to send information to simulate electricity meter uploading data. The serial port assistant sends a hexadecimal RFC1662 message with the content "Hello, I am Meter".
+
+> 🚩 **Warning**
+> The information sent needs to be in the message format specified in the RFC1662 protocol in the code!
+>
+> For example, it is necessary to send "Hello I am Meter!", assemble it into a message format, and represent it in hexadecimal as:
+>
+> 7E FF 03 00 21 00 12 BF 48 65 6C 6C 6F 20 49 20 61 6D 20 4D 65 74 65 72 21 9C 1F 7E
+>
+> Then send it to the module in hexadecimal format through the serial assistant
+
+
+
+After receiving the RFC1662 message from the electricity meter, the module will first parse it and then send it to the TCP server:
+
+
+
+The TCP server received a message from the electricity meter:
+
+
+
+
+
+### TCP downlink data
+
+The TCP server sends a message "Hello, I am TCP_Server!" to the module. After receiving the message, the module will first perform RFC1662 protocol packaging on the message and then send it to the electricity meter
+
+
+
+> 🚩 **Warning**
+>
+> The phenomenon of garbled characters appearing before and after the information in the figure is not actually garbled, but rather because the module sent a complete RFC1662 protocol packet,
+>And the serial assistant does not have the ability to unpack, so this is a normal phenomenon
+
diff --git a/docs/Application_guide/en/solutions/electricity-meter/software_design.md b/docs/Application_guide/en/solutions/electricity-meter/software_design.md
new file mode 100644
index 0000000000000000000000000000000000000000..2705ba3dcac510d8ca5214d47d940484a0bd6a5c
--- /dev/null
+++ b/docs/Application_guide/en/solutions/electricity-meter/software_design.md
@@ -0,0 +1,419 @@
+# Software Design Explanation
+
+
+
+## Software framework
+
+
+
+### Software Design Diagram
+
+
+
+
+
+### UML
+
+
+
+
+
+### System startup process
+
+
+
+1. Instantiate application objects
+2. Import configuration JSON file
+3. Initialize various application extension components (this step will register each application extension into the main application object, facilitating communication between extensions)
+4. Check the network (this step will block waiting for the network to be ready. If the wait times out, try switching to cfun to restore the network)
+5. Load application extensions and start related services (customizable by users)
+6. The system enters normal operation mode (by default, SIM card and network detection are enabled. If there is a network failure, it will attempt to switch to cfun to restore the network)
+
+
+
+## Implement
+
+
+
+### Sequence Diagram
+
+```mermaid
+sequenceDiagram
+Title: extensions communication process
+
+participant uart as Uart
+participant protocol as RFC1662Protocol
+participant resolver as RFC1662ProtocolResolver
+participant client as Client
+
+uart -->> protocol: request from meter
+protocol -->> resolver: build message
+resolver -->> resolver: handle business
+resolver -->> protocol: build response message
+protocol -->> uart: response to meter
+resolver -->> client: tcp data post through
+```
+
+
+
+### Code Catalog
+
+The code for the smart meter solution is hosted on [Github](https://github.com/QuecPython/solution-electricity-meter.git) The directory structure of the code is as follows:
+
+```PlainText
+.
+|-- LICENSE
+|-- README.md
+|-- code
+| |-- business.py
+| |-- constant.py
+| |-- demo.py
+| |-- dev.json
+| |-- protocol.py
+| `-- qframe
+| |-- __init__.py
+| |-- builtins
+| | |-- __init__.py
+| | |-- clients.py
+| | |-- network.py
+| | `-- uart.py
+| |-- collections.py
+| |-- core.py
+| |-- datetime.py
+| |-- globals.py
+| |-- led.py
+| |-- logging.py
+| |-- ota.py
+| |-- qsocket.py
+| |-- serial.py
+| `-- threading.py
+`-- docs
+ `-- media
+ |-- UML.png
+ |-- init.png
+ |-- system.png
+ `-- ...
+```
+
+
+
+### Basic framework
+
+The smart meter solution is developed based on an application framework called QFrame.
+
+> The `QFrame` application framework is a fundamental application framework developed by QuecPython. [Click here to view](https://github.com/QuecPython/QFrame) Design and application guidance for this framework.
+
+An application often relies on multiple business modules, and there may be coupling between them.
+In the framework design, the communication between business modules adopts a star shaped structure design, as shown in the following figure:
+
+
+
+The Mediator in the figure is an intermediary object (usually named 'Application') that communicates between various business modules through the `Application` object. This design is called the **intermediary pattern**.
+The business module is embedded in the application program in the form of application extensions, and the interaction between various application extensions is uniformly scheduled through the `Application` object.
+
+
+
+### Application objects and extensions
+
+Applications based on the QFrame framework must have a central object for scheduling various business modules, namely the Application object mentioned earlier; The application parameters are also configured through this object.
+
+example:
+
+```python
+def create_app(name='DTU', config_path='/usr/dev.json'):
+ # init application instance
+ _app = Application(name)
+ # read settings from json file
+ _app.config.from_json(config_path)
+ #The code is omitted here
+ return _app
+
+app = create_app()
+```
+
+`Application` class:
+
+```python
+class Application(object):
+ """Application Class"""
+
+ def __init__(self, name):
+ self.name = name
+ self.config = LocalStorage()
+ self.business_threads_pool = ThreadPoolExecutor(max_workers=4, enable_priority=True)
+ self.submit = self.business_threads_pool.submit
+ # init builtins dictionary and init common, we use OrderedDict to keep loading ordering
+ self.extensions = OrderedDict()
+ self.__append_builtin_extensions()
+ # set global context variable
+ CurrentApp.set(self)
+ G.set(_AppCtxGlobals())
+
+ #The code is omitted here
+
+ def append_extension(self, extension):
+ self.extensions[extension.name] = extension
+
+ def mainloop(self):
+ """load builtins"""
+ for extension in self.extensions.values():
+ if hasattr(extension, 'load'):
+ extension.load()
+```
+
+#### Definition and initialization of application extension
+
+Application extension refers to the business modules loaded by the `Application` object. Generally speaking, application extensions obtain their own configuration from `app.config` and pass it to the application instance during initialization.
+The use of application extension includes two parts: definition and initialization. Application extension provides a base class called `AppExtendeABC`, defined as follows:
+
+```python
+class AppExtensionABC(object):
+ """Abstract Application Extension Class"""
+
+ def __init__(self, name, app=None):
+ self.name = name # extension name
+ if app:
+ self.init_app(app)
+
+ def init_app(self, app):
+ # register into app, then, you can use `app.{extesion.name}` to get current extension instance
+ app.append_extesion(self)
+ raise NotImplementedError
+
+ def load(self):
+ # loading extension functions, this method will be called in `app.mainloop`
+ raise NotImplementedError
+```
+
+This base class is inherited by a specific application extension class to constrain the interface definition of the application extension class.
+
+- We need to pass the `Application` application object to the initialization method `__init__`. When creating an application extension object, call `init_app` to complete the initialization action of the extension; It is also possible to create an application extension object directly without passing in the application object, and then explicitly call `init_app` to complete initialization.
+- The `load` method is used to be called by the `Application` object to load various application extensions.
+
+#### The use of application expansion
+
+When the application extension inherits the base class `AppExtendeABC` and implements the necessary interface functions, you can refer to the following two different ways of code to load the application extension object.
+
+Method 1:
+
+```python
+app = Application(__name__)
+ext = ExtensionClass(app)
+```
+
+Method 2:
+
+```python
+ext = ExtensionClass()
+ext.init_app(app)
+
+ rfc1662resolver.init_app(_app)
+ uart.init_app(_app)
+ client.init_app(_app)
+```
+
+
+
+### Main Application
+
+As the script file for application entry, `demo.py` provides a factory function `create_app` that passes in the configuration path to initialize the application and load various application extensions.
+
+ `demo.py` sample code is as follows:
+
+```python
+import checkNet
+from usr.qframe import Application
+from usr.business import rfc1662resolver, client, uart
+
+PROJECT_NAME = "QuecPython_Framework_DEMO"
+PROJECT_VERSION = "1.0.0"
+
+def poweron_print_once():
+ checknet = checkNet.CheckNetwork(
+ PROJECT_NAME,
+ PROJECT_VERSION,
+ )
+ checknet.poweron_print_once()
+
+def create_app(name='DTU', config_path='/code/dev.json'):
+ # initialize Application
+ _app = Application(name)
+ # read settings from json file
+ _app.config.from_json(config_path)
+
+ # init rfc1662resolver extension
+ rfc1662resolver.init_app(_app)
+ # init uart extension
+ uart.init_app(_app)
+ # init tcp client extension
+ client.init_app(_app)
+
+ return _app
+
+# create app with `create_app` factory function
+app = create_app()
+
+if __name__ == '__main__':
+ poweron_print_once()
+ # loading all extensions
+ app.mainloop()
+```
+
+
+
+### Application Extensions
+
+The main application extension functions include three main categories `rfc1662resolver` (1662 protocol resolution), `client` (tcp client) and `uart` (serial read and write), which are all registered in the application object `Application` for ease of coordination.
+
+- `rfc1662resolver`: responsible for parsing and assembling RFC1662 protocol messages, (`RFC1662ProtocolResolver` instance object).
+- `client`: tcp client (`BusinessClient` instance object), responsible for communicating with the tcp server.
+- `uart`: serial port client (`UartBusiness` instance object), responsible for serial read and write.
+
+#### Class `RFC1662ProtocolResolver`
+
+This class is an application extension class, an RFC1662 protocol data resolver, used to process RFC1662 protocol data transmitted in the business, and pack and unpack this class data.
+
+The class provides the following methods:
+
+- resolve(msg)
+ - **Function**: Process an RFC1662 protocol message. The behavior is to find the processing function of the message from the registry by resolving the protocol (which can be understood as the message id of the protocol message), and call the function to process if found, otherwise throw a `ValueError` exception. See the `register` decorator function on how to register the processing function.
+ - **Parameters**: `msg` is an `RFC1662Protocol` object, which is an encapsulation class of the RFC1662 protocol, see the introduction below.
+ - **Return value**: None
+ - **Exceptions**: If the processing function cannot be found in the registry for the incoming `msg`, a `ValueError` exception will be thrown.
+- register(protocol)
+ - **Function**: It is a decorator function used to register a processing function for a protocol.
+ - **Parameters**: `protocol` can be understood as the message id of the RFC1662 protocol.
+ - **Return value**: original function
+- tcp_to_meter_packet(data)
+ - **Function**: Static method, pack the byte data `data` into a transparent RFC1662 data packet (0x2100), that is, the data frame passed to the meter by tcp transparent transmission.
+ - **Parameters**: `data`, byte type.
+ - **Return value**: 0x2100 protocol packet byte string
+ - **Exceptions**: None
+- module_to_meter_packet(data)
+ - **Function**: Static method, assemble RFC1662 protocol data packet (0x2200), that is, the data frame sent by the module to the meter
+ - **Parameters**: data is a list, [get/set, id, data], where:
+ - `get/set`: `COSEM.GET/COSEM.SET`, the corresponding values are `0xC0/0xC1` respectively
+ - `id`: function command word
+ - `data`: byte type
+ - **Return value**: 0x2200 protocol packet byte string
+
+ Sample code:
+
+```python
+# we have inited a RFC1662ProtocolResolver object in `business.py` module
+# import `rfc1662resolver`
+from code.business import rfc1662resolver
+
+
+# decorate with protocol 0x2100
+@rfc1662resolver.register(0x2100)
+def handle2100(msg):
+ """when get a 0x2100 message,this function will be called"""
+ pass
+```
+
+#### Class `RFC1662Protocol`
+
+This class is a specific implementation of the RFC1662 protocol, including unpacking and packing. The instance object of this class is an encapsulated form of a complete RFC1662 protocol package. The main methods are:
+
+- `build_rfc_0x2100`: assemble 0x2100 protocol packet, return bytes, equivalent to `RFC1662ProtocolResolver.tcp_to_meter_packet`
+- `build_rfc_0x2200`: assemble 0x2200 protocol packet, return bytes, equivalent to `RFC1662ProtocolResolver.module_to_meter_packet`
+- `build`: class method, used to resolve a protocol packet frame, return `RFC1662Protocol` object.
+- `replay_get`: reply get command, judge success or failure
+- `replay_set`: reply set command
+- `reply_event`: reply event information
+
+#### TCP Client Component
+
+##### Base Class `TcpClient`
+
+This class exposes two interfaces to the user:
+
+- `recv_callback` method, users rewrite this method to achieve business processing of TCP server downlink data.
+- `send` method, users can call this method to send data to the server.
+
+Code is as follows:
+
+```python
+class TcpClient(object):
+ # ...
+ def recv_callback(self, data):
+ raise NotImplementedError('you must implement this method to handle data received by tcp.')
+
+ def send(self, data):
+ # TODO: uplink data method
+ pass
+```
+
+##### Subclass `BusinessClient`
+
+`BusinessClient` rewrites the `recv_callback` method to encapsulate the downlink data of the server into RFC1662 format messages and forwards the data to the serial port.
+
+Code is as follows:
+
+```python
+class BusinessClient(TcpClient):
+
+ def recv_callback(self, data):
+ # recv tcp data and send to uart
+ data = RFC1662Protocol.build_rfc_0x2100(data)
+ CurrentApp().uart.write(data)
+```
+
+#### Serial Communication Component
+
+##### Base Class `Uart`
+
+This class exposes two interfaces to users:
+
+- `recv_callback` method, users rewrite this method to achieve business processing of received serial data.
+- `send` method, users can call this method to send data to the serial port.
+
+Code is as follows:
+
+```python
+class Uart(object):
+ # ...
+ def recv_callback(self, data):
+ raise NotImplementedError('you must implement this method to handle data received from device.')
+
+ def write(self, data):
+ # TODO: write data to uart
+ pass
+```
+
+##### Subclass `UartBusiness`
+
+ `UartBusiness` rewrites the `recv_callback` method to implement business processing of received serial data.
+
+```python
+class UartBusiness(Uart):
+
+ def recv_callback(self, data):
+ # parse 1662 protocol data
+ pass
+```
+
+> In the subclass `UartBusiness`'s `recv_callback` method, after parsing the RFC1662 protocol message, constructing the message object, distribute the message processing business through the `rfc1662resolver.resolve` method.
+
+
+
+### Writing Business Programs
+
+Define a global `rfc1662resolver` resolver in the script file `business.py` to register message processing functions of specified types.
+
+The following sample code registers the 0x2100 protocol transparent transfer processing function:
+
+```python
+# >>>>>>>>>> handle rfc1662 message received from uart <<<<<<<<<<
+
+@rfc1662resolver.register(0x2100)
+def handle2100(msg):
+ """post data received to cloud"""
+ # message body bytes
+ data = msg.info().request_data()
+ if data:
+ # post data to tcp server by `client` extension register in Application
+ CurrentApp().client.send(data)
+```
+
diff --git a/docs/Application_guide/en/solutions/poc/README.md b/docs/Application_guide/en/solutions/poc/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..1aaeddb2e97f3ac494cdc4f4427b2d34e889438c
--- /dev/null
+++ b/docs/Application_guide/en/solutions/poc/README.md
@@ -0,0 +1,17 @@
+# Poc solution
+
+This public network intercom solution is based on the EC600MCNTE QuecPython standard development board and has the following features:
+
+- Provide half duplex high-definition and secure voice intercom function.
+- Support connecting commonly used intercom platforms: Android, Shanli, Bernard and their chip platforms.
+- Ultra long standby: Supports ultra-low power consumption mode.
+- Using Python language for easy secondary development.
+
+
+
+---
+
+- [development resources](./dev_resources.md)
+- [quick start](./quick_start.md)
+- [software design](./software_design.md)
+
diff --git a/docs/Application_guide/en/solutions/poc/dev_resources.md b/docs/Application_guide/en/solutions/poc/dev_resources.md
new file mode 100644
index 0000000000000000000000000000000000000000..56a73986221f190357719ab12535ddf5d6177349
--- /dev/null
+++ b/docs/Application_guide/en/solutions/poc/dev_resources.md
@@ -0,0 +1,49 @@
+# Development resources summary
+
+## Development board
+
+- model: [EC600MCNLE QuecPython Standard EVB](https://python.quectel.com/doc/Getting_started/zh/evb/ec600x-evb.html)
+- Purchase link:[click](http://e.tb.cn/h.gAlSKya8NvMC9UY?tk=7APD3KXufyq)
+- EVB docs
+ - [specification](https://python.quectel.com/wp-content/uploads/2024/10/EC600X系列开发板产品规格及用户指导.pdf)
+ - [schematic](https://python.quectel.com/wp-content/uploads/2024/09/EC600X_EVB_V3.2-SCH.pdf)
+ - [screen priting](https://python.quectel.com/wp-content/uploads/2024/09/EC600X_EVB_V3.2-丝印.pdf)
+ - [user guidance](https://python.quectel.com/doc/Getting_started/zh/evb/ec600x-evb.html)
+
+## Module information
+
+- model: [EC600MCN_LE](https://python.quectel.com/modules-cat/ec600m-series)
+- [specification](https://images.quectel.com/python/2023/04/Quectel_EC600M-CN_LTE_Standard_模块产品规格书_V1.2.pdf)
+- [download drivers](https://python.quectel.com/wp-content/uploads/2024/09/Quectel_Windows_USB_DriverA_Customer_V1.1.13.zip)
+## Accessories Information
+
+- LCD
+ - model: ST7789
+ - resolution: 240×240
+ - Purchase link: [click](https://detail.tmall.com/item.htm?id=635553532494&spm=a21dvs.23580594.0.0.1d292c1bgEWiOc&skuId=4730254699646)
+- speaker
+ - Any speaker with a power of 2-5W is sufficient.
+
+## Development tool
+
+- QPYcom - QuecPython debug tool
+ - version: V3.6.0
+ - download [QPYcom](https://python.quectel.com/wp-content/uploads/2024/09/QPYcom_V3.6.0.zip)
+- VSCode
+ - download [VSCode](https://code.visualstudio.com/)
+
+## Firmware
+
+- version: EC600MCNLER06A01M08_POC_XBND_OCPU_QPY_BETA0117
+- download [Firmware](https://github.com/QuecPython/solution-POC/releases/download/v2.0.1/EC600MCNLER06A01M08_POC_XBND_OCPU_QPY_BETA0117.zip)
+
+## Source Code
+
+- Version: v2.0.1
+- github repo:
+ ```bash
+ git clone https://github.com/QuecPython/solution-POC
+ cd solution-POC
+ git checkout v2.0.1
+ ```
+- [Github Zip download](https://github.com/QuecPython/solution-POC/archive/refs/tags/v2.0.1.zip)
\ No newline at end of file
diff --git a/docs/Application_guide/en/solutions/poc/quick_start.md b/docs/Application_guide/en/solutions/poc/quick_start.md
new file mode 100644
index 0000000000000000000000000000000000000000..affa210d52177b5d80d31b172540a8e8ea696eaf
--- /dev/null
+++ b/docs/Application_guide/en/solutions/poc/quick_start.md
@@ -0,0 +1,111 @@
+# Quick Start
+
+## Hardware preparation
+
+- A Windows computer, recommended for the 'Win10' system.
+- Two sets of [EC600MCNTE QuecPython standard development boards](https://python.quectel.com/doc/Getting_started/zh/evb/ec600x-evb.html) (Each set includes an antenna, Type-C data cable, etc.).
+
+ > 💡 **Tips**
+ > One set is used for the demonstration of the calling device, and the other set is used for the demonstration of the called device.
+
+- Two functional Nano SIM cards.
+- Two LCD screens with a resolution of 240 * 240, model ST7789.
+- Two speakers with a power of 2-5W.
+
+## Environment construction
+
+- Download and install EC600M series module driver: [QuecPython_USB_Driver_Win10_ASR](https://images.quectel.com/python/2023/04/Quectel_Windows_USB_DriverA_Customer_V1.1.13.zip).
+- Download and install [VSCode](https://code.visualstudio.com/ ).
+- Download and unzip [QPYCom](https://images.quectel.com/python/2022/12/QPYcom_V3.6.0.zip) Tool to the appropriate location on the computer.
+- Download [firmware package](https://github.com/QuecPython/solution-POC/releases/download/v2.0.1/EC600MCNLER06A01M08_POC_XBND_OCPU_QPY_BETA0117.zip ).
+- Download [Experimental Source Code](https://github.com/QuecPython/solution-POC/archive/refs/tags/v2.0.1.zip).
+- Apply for a Bernard **chip platform** testing account.
+
+According to the steps shown in the figure below, obtain the IMEI number and provide it to the sales personnel of Mobile Remote to apply for a walkie talkie testing account.
+
+
+
+> 💡 **Tips**
+> - Non commercial testing, please contact the sales personnel of Mobile Far East (li.bao@quectel.com ) Apply for a Bernard **chip platform ** testing account.
+> - Please follow the business process for commercial applications.
+
+## Hardware connection
+
+Connect the hardware according to the following diagram:
+
+
+
+1. Connect the horn to the pins labeled 'SPK+' and 'SPK -' in the diagram.
+2. Connect the LCD screen to the pin bank labeled with the word 'LCD'.
+3. Insert an available Nano SIM card into the position shown in the diagram.
+4. Connect the antenna to the antenna connector marked with the word 'LTE'.
+5. Connect the development board and computer using a Type-C data cable.
+
+## Equipment development
+
+### Power on
+
+After completing the hardware connection work, long press the button labeled `PWK` on the development board until the network light flashes or a COM port containing the words `Quectel USB`appears in the port list of the computer device manager, indicating successful boot.
+
+
+
+### Download firmware
+
+Refer to [this chapter](https://python.quectel.com/doc/Application_guide/zh/dev-tools/QPYcom/qpycom-dw.html#%E4%B8%8B%E8%BD%BD%E5%9B%BA%E4%BB%B6) Burn firmware package [EC600MCNLER06A01M08-POC_XBND_SCPU_QPYBETA0117. zip](https://github.com/QuecPython/solution-POC/releases/download/v2.0.1/EC600MCNLER06A01M08_POC_XBND_OCPU_QPY_BETA0117.zip) To the development board.
+
+### Script import and execution
+
+1. Refer to [this chapter](https://python.quectel.com/doc/Getting_started/zh/first_python.html#PC%E4%B8%8E%E6%A8%A1%E7%BB%84%E9%97%B4%E7%9A%84%E6%96%87%E4%BB%B6%E4%BC%A0%E8%BE%93) Import all files from the `code` folder in the source code directory into the module file system, as shown in the following figure:
+
+
+
+2. Refer to [this chapter](https://python.quectel.com/doc/Getting_started/en/first_python.html#%E6%89%A7%E8%A1%8C%E8%84%9A%E6%9C%AC%E6%96%87%E4%BB%B6)Execute the main program file `poc_main.py`.
+3. Refer to [this chapter](https://python.quectel.com/doc/Getting_started/en/first_python.html#%E5%81%9C%E6%AD%A2%E7%A8%8B%E5%BA%8F%E8%BF%90%E8%A1%8C) Stop the program from running.
+
+## Debugging
+
+### Program startup
+
+After executing the ` poc_main.py ` script, the program starts running and enters the ` WelcomeScreen ` interface. At the same time, it obtains the SIM card status and current account, and broadcasts the information of the currently logged in user and the group they have joined through TTS voice.
+
+
+
+> 🚩 **Warning**
+> When the SIM card is not inserted, it will not enter the main interface. After inserting the SIM card and restarting the device, it can run normally.
+>
+
+### Main screen
+
+The main interface contains multiple option lists, and each option corresponds to a new interface.
+
+- Click the 'key2' key to scroll down the checkbox.
+- Double click the 'key2' key to enter the selected interface.
+- Long press the 'key2' key to return to the previous interface.
+
+
+
+### Group List
+
+Entering the group management interface can query the list of groups that the current account has joined, and the message prompt box will indicate which group it is currently in, as shown in the following figure:
+
+
+
+### Member list
+
+By entering the member list interface, all members of the current group can be queried, as shown in the following figure:
+
+
+
+### Intercom
+
+- Long press the 'key1' key to communicate with members in the same group, and the menu bar will display the 'microphone' icon.
+- After speaking, release the 'key1' key to end the intercom function.
+- When actively calling or being called by the other party, there will be a message pop-up prompt.
+- When the other party is speaking, the menu bar displays the 'earpiece' icon.
+
+**Active call icon:**
+
+
+**Call icon for the other party:**
+
+
diff --git a/docs/Application_guide/en/solutions/poc/software_design.md b/docs/Application_guide/en/solutions/poc/software_design.md
new file mode 100644
index 0000000000000000000000000000000000000000..379fbc563f3fc547eb40980bbf9a4ff99e90f63a
--- /dev/null
+++ b/docs/Application_guide/en/solutions/poc/software_design.md
@@ -0,0 +1,872 @@
+# Software Design
+
+## Software framework
+
+### Software Design Diagram
+
+
+
+- Key module
+ - KeyManger: Used to manage key functions.
+- Service module
+ - DevInfoService: Device Information Service, used to query device IMEI ICCID、 Firmware version information, etc;
+ - MediaService: a media service used to manage TTS broadcasts, microphones, and audio processing;
+ - NetService: a network service used to manage network status and heartbeat detection;
+ - PocService: a POC service used for POC login, group acquisition, member acquisition, and intercom management.
+- Interface module
+ - MenuBar: Status bar, used to display signals, time, battery level, and intercom icons;
+ - PromptBox: a prompt box used to display message pop-up information;
+ - Screen: UI screen, used to display various interface information, customizable by users;
+ - PocUI: Used to manage user-defined screens.
+- Event management module:
+ - EventMap: Used for sending and binding events.
+
+### Business system startup process
+
+
+
+## Code Explanation
+
+### Core Business Module (POC)
+
+> For API functions related to the POC library, please refer to [POC Public Network Radio](https://python.quectel.com/doc/API_reference/zh/industry/poc.html) Explanation document.
+
+- #### Login
+
+ By registering the ` poc.login() ` callback function, monitor the login status and perform corresponding operations based on the login results.
+ The specific functions are as follows:
+
+ 1. Login callback: Register a callback function through ` poc.login() ` to listen for login status (` param ` parameter indicates login success or failure).
+ 2. Successful login processing: If the login is successful (` param==1 `), update the network status to normal and clean or store security data according to the platform type (standard platform or other platform).
+ 3. Login failure handling: If login fails, start a timer to regularly check the network connection status and mark the network error status.
+ 4. Network status check: Regularly check the network connection status through a timer to ensure that the device can try logging in again.
+ 5. Interface update: After successful login, notify the Welcome Screen to update the login status and query group information.
+
+ This functional module ensures that the device can correctly log in to the POC platform and automatically attempt to reconnect in case of login failure.
+
+ ```python
+ class PocService(AbstractLoad):
+ ...
+
+ # login callback
+ poc.login(self.__poc_login_cb)
+
+ def __poc_login_cb(self, param):
+ EventMap.send("welcomescreen__check_cloud_status", param) # 登录成功首页显示已登录,且去查询组群信息
+ # login
+ if param == 1:
+ self.net_error = False
+ if self.__platform_dict.get(self.__platform) == 'std':
+ self.__securedata_xin_clear()
+ else:
+ self.__securedata_xin_store()
+ else:
+ self.__cloud_check_timer.start(5*1000, 1, lambda arg: self.__check_cloud_connect())
+ self.net_error = True
+ ```
+
+- #### Enter the group
+
+ By registering the ` poc.register_join_group_cb() ` callback function, listen for device grouping events, and update the interface and play prompt sounds based on the grouping status.
+ The specific functions are as follows:
+
+ 1. Registration callback: Register the callback function through ` poc.register_join_group_cb() ` to listen for whether the device successfully enters the group.
+ 2. Obtain group information: Use ` poc.group_getbyid() ` to query the detailed information of the current group.
+ 3. TTS voice broadcast: Based on the membership status and group type (temporary group or regular group), generate corresponding prompt information and broadcast it through TTS voice.
+ 4. Status management: Update the current group name, login status, and speaking permission status to ensure device status is synchronized with group information.
+ 5. Temporary group handling: If entering a temporary group, start a timer and automatically exit the temporary group after a specified time.
+
+ This functional module ensures that users receive timely voice prompts when entering a group, and correctly handle group switching and status updates.
+
+ ```python
+ class PocService(AbstractLoad):
+ ...
+
+ poc.register_join_group_cb(self.__poc_join_group_cb)
+
+ def __poc_join_group_cb(self, param):
+ PrintLog.log("PocService", "poc join group = {}".format(param))
+ if not param[-1]:
+ return
+ group = poc.group_getbyid(0)
+ if isinstance(group, list):
+ now_group_name = group[1]
+ if not group[2]:
+ self.__last_join_group = group
+ self.__call_time_status = False
+ self.__call_member_timer.stop()
+ if not self.__group_name:
+ self.__group_name = now_group_name
+ else:
+ if self.__group_name == now_group_name:
+ self.tts_play_enable = False
+ else:
+ self.tts_play_enable = True
+ self.__group_name = now_group_name
+ if self.__login_status:
+ if group[2]:
+ tts_msg = "进入" + "临时群组" + self.__group_name
+ else:
+ tts_msg = "进入群组" + self.__group_name
+ else:
+ tts_msg = self.__get_user_info() + "已登录" + "进入群组" + self.__group_name
+ self.tts_play_enable = True
+ if not self.__login_status:
+ self.__login_status = True
+ if self.tts_play_enable:
+ EventMap.send("mediaservice__tts_play", (tts_msg, 1))
+ if not self.__rocker_arm:
+ if not self.speak_close_first:
+ self.speak_close_first = True
+ EventMap.send("pocservice__close_speaker",None ,EventMap.MODE_ASYNC)
+ if group[2]:
+ self.__call_time_status = True
+ self.__call_member_timer.start(self.__call_quit_time * 1000, 0, lambda arg: self.__call_member_exit())
+ ```
+
+- #### Get group and member list
+
+ Retrieve group and member data by calling the POC interface, and return the data to the interface layer for rendering.
+ The specific functions are as follows:
+
+ 1. Obtain the group list: Use ` poc.get_groupcount() ` to obtain the number of groups that the current account has joined, and use ` poc.get_grouplist() ` to obtain the group list data.
+ 2. Get member list: Use ` poc.group_getbyid() ` to obtain the current group information, and then use ` poc.get_comembercount() ` and ` poc. get_comemberlist() ` to obtain the number of members and member list data.
+ 3. Exception handling: If the group or member data is invalid (such as a return value of -1 or a quantity of 0), empty data will be returned, and the interface layer will display the corresponding prompt message.
+
+ This functional module provides data support for group management and member list interfaces, ensuring that users can view and manipulate group and member information.
+
+ ```python
+ class PocService(AbstractLoad):
+ ...
+
+ EventMap.bind("group_get_list", self.__get_group_list)
+ EventMap.bind("member_get_list", self.__get_member_list)
+
+ def __get_group_list(self, event=None, msg=None):
+ group_count = poc.get_groupcount()
+ group_list = poc.get_grouplist(0, group_count)
+ return group_count, group_list
+
+ def __get_member_list(self, event=None, msg=None):
+ group = poc.group_getbyid(0)
+ if -1 == group:
+ return -1, None
+ member_count = poc.get_membercount(group[0])
+ if -1 == member_count or 0 == member_count:
+ return -1, None
+ member_list = poc.get_memberlist(group[0], 0, member_count)
+ return member_count, member_list
+ ```
+
+- #### POC
+
+ This section is the core functional module of the solution, responsible for managing intercom status, checking network status, and updating interface prompts.
+ The specific functions are as follows:
+
+ 1. Enable intercom: When long press the KEY1 key on the development board, the LCD screen will wake up and the intercom function will be activated. Simultaneously check the network status and current group status to ensure that the intercom function is functioning properly.
+ 2. Turn off intercom: When the KEY1 key is released, the intercom ends and relevant resources are released, updating the interface status.
+ 3. Network status check: If the network is abnormal (such as SIM card problems), prompt the user to replace the SIM card.
+ 4. Group status check: If the current group is invalid, prompt the user to select a valid group.
+ 5. Interface prompt update: During the intercom process, 'Speaking...' is displayed` Prompt box and update the intercom icon in the status bar.
+ 6. Audio management: Enable or disable noise reduction function and play prompt sound when intercom is turned on and off.
+
+ This functional module ensures the stability of the intercom function and the smoothness of the user experience.
+
+ ```python
+ class PocService(AbstractLoad):
+ ...
+
+ EventMap.bind("pocservice__speaker_enable", self.__speaker_enable)
+
+ def __speaker_enable(self, event, msg=None):
+ PrintLog.log("PocService", "speaker enable: {}".format(msg))
+ if msg:
+ EventMap.send("poc_play_status", True) # 唤醒LCD
+ if self.__speaker_status:
+ EventMap.send("mediaservice__noise_reduction_enable", 1)
+ poc.speak(1)
+ if self.net_error:
+ if 3 != EventMap.send("welcomescreen__get_net_status"):
+ EventMap.send("mediaservice__tts_play", ("请更换卡", 1))
+ EventMap.send("load_msgbox", "请更换sim卡")
+ return False
+
+ curr_group = poc.group_getbyid(0)
+ if -1 == curr_group:
+ EventMap.send("mediaservice__tts_play", (self.__group_name_default, 1))
+ EventMap.send("load_msgbox", self.__group_name_default)
+ else:
+ if not self.__rocker_arm:
+ EventMap.send("update_session_info", "您已被关闭发言")
+ else:
+ EventMap.send("load_msgbox", "讲话中...")
+ EventMap.send("menubar__update_poc_status", 1)
+
+ else:
+ EventMap.send("mediaservice__audio_tone")
+ return True
+ else:
+ if self.__speaker_status:
+ EventMap.send("mediaservice__noise_reduction_enable", 0)
+ poc.speak(0)
+ utime.sleep_ms(100)
+ if not self.__rocker_arm:
+ pass
+ else:
+ EventMap.send("close_msgbox")
+ EventMap.send("menubar__update_poc_status", 0)
+ EventMap.send("poc_play_status", False)
+ ```
+
+- #### Call callback from the other party
+
+ By registering the ` poc.register_audio_cb() ` callback function, listen for the other party's call information, and update the device status and interface prompts based on the call status.
+ The specific functions are as follows:
+
+ 1. Register audio callback: Register the callback function through ` poc.register_audio_cb() ` to listen for the other party's call information (` params ` parameters include voice status, user ID, username, and interrupt flag).
+ 2. Call status processing:
+ - If the other party is calling (` params[0]==self.BAND_CAL `), update the device status to 'active call'.
+ - If the other party starts playing voice (` params[0]==self.BND_LISTN_START `), update the device status to "call ended" and set the speaking permission based on the interrupt flag.
+ - If the other party stops playing voice (` params[0]==self.BND_LISTN_STOP ` or ` params[0]==self.BND_SPEAK-STOP `), interrupt the logic and update the device status.
+ 3. Interface update: When the other party calls, display a message prompt box, wake up the LCD screen, and update the intercom icon in the status bar.
+ 4. Status management: Update the calling status, speaking status, and session information of the device based on the call status, ensuring that the device status is synchronized with the call information.
+
+ This functional module ensures that the device can correctly process the call information of the other party and update the interface and status in real time.
+
+ ```python
+ class PocService(AbstractLoad):
+ ...
+
+ poc.register_audio_cb(self.__poc_audio_cb)
+
+ def __poc_audio_cb(self, params):
+ PrintLog.log("PocService", "poc audio: {}".format(params))
+ if params[0] == self.BAND_CALL:
+ self.main_call_end_state = self.CALL_STATE.IN_CALL
+ self.__speaker_status = 3
+ self.last_audio = params[0]
+
+ elif params[0] == self.BND_LISTEN_START:
+ self.last_audio = params[0]
+ self.main_call_end_state = self.CALL_STATE.CALL_END
+ if params[-1] == 0:
+ self.__speaker_status = 0
+ else:
+ self.__speaker_status = 2
+ self.__session_info = params[2]
+ state_msg = self.__session_info
+ EventMap.send("load_msgbox", state_msg)
+ EventMap.send("poc_play_status", True)
+ EventMap.send("menubar__update_poc_status", 2)
+ EventMap.send("pocservice__call_member_status", 1)
+
+ elif params[0] == self.BND_LISTEN_STOP or params[0] == self.BND_SPEAK_STOP:
+ if params[0] == self.BND_LISTEN_STOP and self.main_call_end_state == self.CALL_STATE.IN_CALL:
+ return
+ if params[0] == self.BND_LISTEN_STOP:
+ self.__speaker_status = params[-1]
+ self.__error_ptt_handler(params)
+ else:
+ pass
+ ```
+
+### UI
+
+- #### MenuBar
+
+ The MenuBar class updates various components in the status bar by binding and sending events, ensuring that users can view key device information in real-time.
+ The specific functions are as follows:
+
+ 1. Update signal strength: Obtain signal strength through events and display corresponding signal icons and network types (such as 4G).
+ 2. Update time: Obtain the current time through the event and display it in the status bar.
+ 3. Update battery level: Obtain the current battery level through events and update the battery level icon.
+ 4. Update intercom status: Display the corresponding icon based on the intercom status (intercom, playback) and control the visibility of the icon.
+
+ The size of the status bar is 240 × 40, located above the LCD screen.
+
+ ```python
+ class MenuBar(AbstractLoad):
+ NAME = "MenuBar"
+ ...
+
+ def __update_time(self, arg=None):
+ time = EventMap.send("devinfoservice__get_time")
+ if time:
+ self.lab_time.set_text(time[1])
+
+ def __update_battery(self, arg=None):
+ battery = EventMap.send("screen_get_battery")
+ if battery:
+ self.img_battery.set_src(battery)
+
+ def __update_signal(self, arg=None):
+ sig = EventMap.send("screen_get_signal")
+ if 0 < sig <= 31:
+ self.img_signal.set_src('U:/img/signal_' + str(int(sig * 5 / 31)) + '.png')
+ self.lab_signal.set_text("4G")
+ else:
+ self.img_signal.set_src("U:/img/signal_0.png")
+ self.lab_signal.set_text("x")
+
+ def __update_poc_status(self, event, msg):
+ PrintLog.log(MenuBar.NAME, "poc status: {}".format(msg))
+ if 0 == msg:
+ self.img_poc.add_flag(lv.obj.FLAG.HIDDEN)
+ elif 1 == msg:
+ self.img_poc.clear_flag(lv.obj.FLAG.HIDDEN)
+ self.img_poc.set_src("U:/img/poc_speaking.png")
+ elif 2 == msg:
+ self.img_poc.clear_flag(lv.obj.FLAG.HIDDEN)
+ self.img_poc.set_src("U:/img/poc_play.png")
+ ```
+
+- #### PromptBox
+
+ The PromptBox class displays message content in the form of pop ups and supports dynamic updates and closing of pop ups.
+ The specific functions are as follows:
+
+ 1. Display message pop-up: Create a pop-up based on the incoming message content (` msg `) and metadata (` meta `) and center it on the screen.
+ 2. Dynamically update messages: If a pop-up window already exists, close the old pop-up window before displaying a new message to ensure the real-time nature of the message.
+ 3. Close Pop up: Provides the function to close pop ups, release resources, and hide pop ups.
+
+ The size of the pop-up window is 180 × 90, and the message content supports automatic line wrapping and is displayed in the center.
+
+ ##### Define
+
+ ```python
+ class PromptBox(AbstractLoad):
+ NAME = "PromptBox"
+ ...
+
+ def __close(self, event=None, msg=None):
+ if self.prompt_box is not None:
+ self.prompt_box.delete()
+ self.prompt_box = None
+
+ def __show(self, event, msg):
+ if self.prompt_box is not None:
+ self.prompt_box.delete()
+ self.prompt_box = None
+
+ meta = msg.get("meta")
+ show_msg = msg.get("msg")
+
+ self.prompt_box = lv.msgbox(meta, "PromptBox", "", [], False)
+ self.prompt_box.set_size(180, 90)
+ self.prompt_box.align(lv.ALIGN.CENTER, 0, 0)
+ self.prompt_label = lv.label(self.prompt_box)
+ self.prompt_label.set_pos(0, 0)
+ self.prompt_label.set_size(140, 50)
+ self.prompt_label.add_style(FontStyle.consolas_12_txt000000_bg2195f6, lv.PART.MAIN | lv.STATE.DEFAULT)
+ self.prompt_label.set_text(show_msg)
+ self.prompt_label.set_long_mode(lv.label.LONG.WRAP)
+ self.prompt_label.set_style_text_align(lv.TEXT_ALIGN.CENTER, 0)
+ ```
+
+ ##### Usage
+
+ ```python
+ class PocUI(AbstractLoad):
+ ...
+
+ def load_msgbox(self, event, msg):
+ """
+ {
+ "type": "promptbox",
+ "title": "[promptbox]"
+ "msg": "hello world",
+ "mode": 0
+ }
+ """
+ if isinstance(msg, dict):
+ _type = msg.get("type", PromptBox.NAME)
+ _type = "{}__show".format(type.lower())
+ _msg = {
+ "meta":self.curr_screen.meta,
+ "msg": msg.get("msg", "[promptbox]"),
+ "mode": msg.get("mode", 0)
+ }
+ EventMap.send(_type, _msg)
+ else:
+ _msg = {
+ "meta":self.curr_screen.meta,
+ "title": "[promptbox]",
+ "msg": msg,
+ "mode": 0
+ }
+ EventMap.send("promptbox__show", _msg)
+
+ def close_msgbox(self, event, msg):
+ EventMap.send("promptbox__close")
+ ```
+
+- #### UI Screen
+
+ The Membership Screen class inherits from Screen and is used to display member information on an LCD screen. It has a size of 240 × 200 and, together with the status bar, forms the complete LCD display area.
+
+ The specific functions are as follows:
+
+ 1. Load member list: Retrieve member list data from the event and dynamically create list items to display on the screen.
+ 2. Manage selection status: Display the currently selected member item by highlighting the background color and scrolling effect.
+ 3. Button operation: Supports button events (such as single click, long press) to switch selected items or return to the main interface.
+ 4. Exception handling: If the member list is empty or there are no members, display a prompt pop-up and return to the main interface.
+ 5. Interface update: Dynamically update the list content when the member list changes.
+
+ The design of this class implements dynamic loading and interactive management of member lists, ensuring that users can easily view and manipulate member information.
+
+ ##### Load and add styles
+
+ ```python
+ class MemberScreen(Screen):
+ NAME = "MemberScreen"
+
+ def __init__(self):
+ ...
+
+ self.meta = lv.obj() # lvgl meta object
+ self.meta.add_style(CommonStyle.default, lv.PART.MAIN | lv.STATE.DEFAULT)
+ # list------------------------------------------------------------------------------------------
+ self.list_menu = lv.list(self.meta)
+
+ def load_before(self):
+ EventMap.bind("get_member_check_list", self.__get_member_check_list)
+ EventMap.bind("send_select_member_list", self.__send_select_member_list)
+ EventMap.bind("update_member_info", self.update_member_info)
+
+ def load(self):
+ self.__load_member_list()
+ self.__member_screen_list_create()
+ self.__load_group_cur()
+ if self.member_list is None or self.member_list == -1 or not len(self.member_list):
+ EventMap.send("load_msgbox", "此群组无成员")
+ return False
+ if self.cur >= 0:
+ self.clear_state()
+ self.cur = 0
+ self.add_state()
+
+ def add_state(self):
+ currBtn = self.list_menu.get_child(self.curr_idx)
+ currBtn.set_style_bg_color(lv.color_make(0xe6, 0x94, 0x10), lv.PART.MAIN | lv.STATE.DEFAULT)
+ currBtn.set_style_bg_grad_color(lv.color_make(0xe6, 0x94, 0x10), lv.PART.MAIN | lv.STATE.DEFAULT)
+ self.btn_list[self.curr_idx][2].set_long_mode(lv.label.LONG.SCROLL_CIRCULAR)
+ currBtn.scroll_to_view(lv.ANIM.OFF)
+
+ def clear_state(self):
+ currBtn = self.list_menu.get_child(self.curr_idx)
+ currBtn.set_style_bg_color(LVGLColor.BASE_COLOR_WHITE, lv.PART.MAIN | lv.STATE.DEFAULT)
+ currBtn.set_style_bg_grad_color(LVGLColor.BASE_COLOR_WHITE, lv.PART.MAIN | lv.STATE.DEFAULT)
+ self.btn_list[self.curr_idx][2].set_long_mode(lv.label.LONG.SCROLL_CIRCULAR)
+ currBtn.scroll_to_view(lv.ANIM.OFF)
+
+ def key2_once_click(self, event=None, msg=None):
+ self.clear_state()
+ self.curr_idx = self.next_idx(self.curr_idx, self.count)
+ self.add_state()
+
+ def key2_long_press(self, event=None, msg=None):
+ EventMap.send("close_msgbox")
+ EventMap.send("load_screen",{"screen": "MainScreen"})
+ if self.curr_idx > 0:
+ self.clear_state()
+ self.curr_idx = 0
+ ```
+
+ ##### Create a member list and display member information
+
+ ```python
+ class MemberScreen(Screen):
+ ...
+
+ def __member_screen_list_create(self):
+ """成员界面列表重新创建"""
+ # 把之前的list删掉
+ if self.member_update_flag:
+ self.list_menu.delete()
+ # 再创建list
+ self.list_menu = lv.list(self.meta)
+ self.list_menu.set_pos(0, 40)
+ self.list_menu.set_size(240, 200)
+ self.list_menu.set_style_pad_left(0, 0)
+ self.list_menu.set_style_pad_right(0, 0)
+ self.list_menu.set_style_pad_top(0, 0)
+ self.list_menu.set_style_pad_row(1, 0)
+ self.list_menu.add_style(CommonStyle.container_bgffffff, lv.PART.MAIN | lv.STATE.DEFAULT)
+ self.list_menu.add_style(MainScreenStyle.list_scrollbar, lv.PART.SCROLLBAR | lv.STATE.DEFAULT)
+ self.list_menu.add_style(MainScreenStyle.list_scrollbar, lv.PART.SCROLLBAR | lv.STATE.SCROLLED)
+ if self.count:
+ self.add_member_msg(0, self.count)
+ self.member_update_flag = False
+ else:
+ EventMap.send("load_msgbox", "无成员")
+
+ def add_member_msg(self, index, end):
+ self.member_btn_list = []
+ for each in self.member_list[index:end]:
+ btn = lv.btn(self.list_menu)
+ btn.set_pos(20, 0)
+ btn.set_size(240, 47)
+ btn.add_style(MainScreenStyle.btn_group, lv.PART.MAIN | lv.STATE.DEFAULT)
+ img = lv.img(btn)
+ img.align(lv.ALIGN.LEFT_MID, 10, 0)
+ img.set_size(32, 32)
+ img.set_src('U:/img/number_{}.png'.format(each[4] + 1))
+ lab = lv.label(btn)
+ lab.align(lv.ALIGN.LEFT_MID, 50, 13)
+ lab.set_size(210, 40)
+ lab.set_text(each[1])
+ self.btn_list.append((btn, img, lab))
+ self.add_state()
+
+ def __load_group_cur(self):
+ ret = EventMap.send("get_group_name")
+ if ret:
+ print(ret)
+ EventMap.send("load_msgbox", '当前群组: {}'.format(ret))
+ self.msgbox_close_timer.start(self.msgbox_close_time * 1000, 0, lambda arg: EventMap.send("close_msgbox"))
+ ```
+
+- #### load UI screen
+
+ The PocUI class loads specified screens in an event driven manner and handles resource management and status updates during screen switching.
+ The specific functions are as follows:
+
+ 1. Screen switching: Based on the input screen name (` msg ["screen"] `), find the corresponding screen from the screen list and load it.
+ 2. Resource management: Release the resources of the current screen and update the status before loading a new screen.
+ 3. Status bar display: If the loaded screen is not a Welcome Screen, the status bar will be displayed.
+ 4. Screen lifecycle management: Call the screen's ` load_before() `, ` load() `, and ` load_after() ` methods to ensure that the initialization logic of the screen is executed correctly.
+ 5. Image cache optimization: After screen loading, refresh the image cache and set the cache size to optimize performance.
+
+ This class is the core logic of UI screen loading, ensuring smooth interface switching and efficient resource management.
+
+ ```python
+ class PocUI(AbstractLoad):
+ ...
+
+ def load_screen(self, event, msg):
+ for scr in self.screen_list:
+ if scr.NAME != msg["screen"]:
+ continue
+ if self.curr_screen:
+ if scr.NAME != self.curr_screen.NAME:
+ scr.set_last_screen(self.curr_screen.NAME)
+ self.curr_screen.deactivate()
+ self.curr_screen = scr
+
+ PrintLog.log("PocUI", "load screen:{}".format(scr.NAME))
+
+ if self.curr_screen.NAME != "WelcomeScreen":
+ EventMap.send("menubar__show", self.curr_screen.meta)
+
+ scr.load_before()
+ scr.load()
+ scr.load_after()
+ lv.img.cache_invalidate_src(None)
+ lv.img.cache_set_size(8)
+ lv.scr_load(self.curr_screen.meta) # load lvgl meta object
+ ```
+
+### key module
+
+- #### Function Description
+
+ Use buttons to scroll, select, and activate intercom services on the screen.
+
+ - KEY1
+ Long press: Activate intercom service.
+ - KEY2
+ Click: scroll down the selection box;
+ Double click: Enter the selected screen;
+ Long press: Return to the previous interface.
+
+- #### Implementation principle
+
+ ```python
+ class KeyManger(object):
+
+ def __init__(self):
+ ...
+
+ self.key1 = ExtInt(ExtInt.GPIO13, ExtInt.IRQ_RISING_FALLING, ExtInt.PULL_PU, self.__key1_event_handler)
+ self.key1.enable() # key1
+
+ self.key2 = ExtInt(ExtInt.GPIO12, ExtInt.IRQ_RISING_FALLING, ExtInt.PULL_PU, self.__key2_event_handler)
+ self.key2.enable() # key2
+
+ def __key1_event_handler(self, event):
+ if event[1] == 1:
+ self.__key1_press_handle()
+ else:
+ self.__key1_up_handle()
+
+ def __key1_press_handle(self):
+ self.__key1_long_timer.start(500, 0, self.__key1_long_handle)
+
+ def __key1_long_handle(self, arg):
+ self.__key1_long_timer_flag = True
+ EventMap.send("ppt_press")
+
+ def __key1_up_handle(self):
+ self.__key1_long_timer.stop()
+
+ if self.__key1_long_timer_flag:
+ self.__key1_long_timer_flag = False
+ EventMap.send("ppt_release")
+ return
+
+ def __key2_event_handler(self, event):
+ if event[1] == 1:
+ self.__key2_press_handle()
+ else:
+ self.__key2_up_handle()
+
+ def __key2_press_handle(self):
+ self.__key2_long_timer.start(1500, 0, self.__key2_long_handle)
+
+ def __key2_long_handle(self, arg):
+ self.__key2_long_timer_flag = True
+ EventMap.send("key2_long_press")
+
+ def __key2_up_handle(self):
+ """key2键 抬起"""
+ self.__key2_long_timer.stop()
+
+ if self.__key2_long_timer_flag:
+ self.__key2_long_timer_flag = False
+ return
+ self.__key2_count += 1
+
+ if not self.__key2_double_timer_flag:
+ self.__key2_double_timer_flag = True
+ self.__key2_double_timer.start(300, 0, self.__key2_up_timer)
+
+ def __key2_up_timer(self, args):
+ if 2 <= self.__key2_count:
+ EventMap.send("key2_double_click")
+ else:
+ EventMap.send("key2_once_click")
+ self.__key2_count = 0
+ self.__key2_double_timer_flag = False
+ ```
+
+### Event management
+
+- The EventMap class maintains an event mapping table (` __event_map `) to enable the sending and binding of events, supporting both synchronous and asynchronous message sending modes.
+ The specific functions are as follows:
+ - Event binding: Use the ` bind() ` method to associate the event name with the callback function and store it in ` __event_map `.
+ - Event unbinding: Remove the callback function of the specified event using the 'unbind()' method.
+ - Event sending:
+ - Synchronized sending (` MODE_SYNC `): Directly executes callback function in the current thread and returns the execution result.
+ - Asynchronous send (` MODE_SYNC `): Execute callback function in a new thread without blocking the current thread.
+ - Error handling: Capture exceptions when executing callback functions and record error logs (if logging is enabled).
+ - Logging: Supports recording the execution information of events for debugging and troubleshooting purposes.
+- This functional module is the core of communication between various modules in the system, ensuring that events can be efficiently and reliably transmitted and processed.
+
+```python
+class EventMap(object):
+ """===example===
+
+ import EventMap
+
+ def time_out(event=None, msg=None):
+ pass
+
+ EventMap.bind("time_out", time_out)
+
+ EventMap.send("time_out")
+ """
+ __event_map = dict()
+ __event_log = None
+
+ MODE_SYNC = 0
+ MODE_ASYNC = 1
+
+ @classmethod
+ def bind(cls, event, callback):
+ """
+ :param event: event name
+ :param callback: event callback
+ """
+ if None == event or "" == event:
+ return
+ cls.__event_map[event] = callback
+
+ @classmethod
+ def unbind(cls, event):
+ """
+ :param event: event name
+ """
+ if None == event or "" == event:
+ return
+ cls.__event_map.pop(event, None)
+
+ @classmethod
+ def send(cls, event, msg=None, mode=MODE_SYNC):
+ """
+ :param event: event name
+ :param msg: event message
+ :param mode: send mode, sync or async
+ """
+ if event not in cls.__event_map:
+ return
+
+ if cls.MODE_SYNC == mode:
+ res = None
+ try:
+ if event in cls.__event_map:
+ res = cls.__event_map[event](event, msg)
+ except Exception as e:
+ if cls.__event_log:
+ cls.__event_log.info("ERROR executed (event) -> {} (params) -> {} (result) -> {}".format(event, msg, res))
+ usys.print_exception(e)
+ if cls.__event_log:
+ cls.__event_log.info("SYNC executed (event) -> {} (params) -> {} (result) -> {}".format(event, msg, res))
+ return res
+
+ elif cls.MODE_ASYNC == mode:
+ try:
+ _thread.start_new_thread(cls.__event_map[event], (event, msg))
+ except Exception as e:
+ if cls.__event_log:
+ cls.__event_log.info("ERROR executed (event) -> {} (params) -> {} (result) -> {}".format(event, msg, res))
+ usys.print_exception(e)
+ if cls.__event_log:
+ cls.__event_log.info("ASYNC executed (event) -> {} (params) -> {} (result) -> {}".format(event, msg, None))
+
+```
+
+### Main program
+
+- The APP class adopts a modular design and implements dynamic loading and lifecycle management of each component through a unified management interface.
+ The specific functions are as follows:
+ - Core component management:
+ - Manage UI interface (`set_ui()`), button module (`add_key()`), status bar (`add_mar()`), message box (`add_msgbox()`), and screen (`add_screen()`)
+ - Ensure that the added components comply with the AbstractLoad abstract class specification through type checking
+ - Service management:
+ - Add backend services (such as network services and audio services) through `add_service()`
+ - Call the `instance_after()` of the service to initialize and maintain the service list (`__service_list`)
+ - Application startup:
+ - Start the UI component (`ui.start()`) and all services in sequence in the `exec()` method
+ - Call LVGL's task handler (` lv.task_handler() `) to maintain GUI operation
+- The design of this class implements a modular architecture for applications, providing an extensible framework foundation for large-scale embedded GUI applications.
+
+```python
+class App(object):
+ __service_list = []
+ __ui = None
+ __key = None
+
+ @classmethod
+ def set_ui(cls, ui):
+ cls.__ui = ui
+
+ @classmethod
+ def add_key(cls, key):
+ cls.__key = key
+
+ @classmethod
+ def add_bar(cls, bar:AbstractLoad):
+ """
+ This is only responsible for adding screen bars to the UI, which are managed by the UI
+ """
+ try:
+ if isinstance(bar, AbstractLoad):
+ cls.__ui.add_bar(bar)
+ except Exception as e:
+ raise Exception("[App](abort) add_bar error: ", e)
+ return cls
+
+ @classmethod
+ def add_msgbox(cls, msgbox:AbstractLoad):
+ """
+ This is only responsible for adding message boxes to the UI, which are managed by the UI
+ """
+ try:
+ if isinstance(msgbox, AbstractLoad):
+ cls.__ui.add_msgbox(msgbox)
+ except Exception as e:
+ raise Exception("[App](abort) add_msgbox error: ", e)
+ return cls
+
+ @classmethod
+ def add_screen(cls, screen:AbstractLoad):
+ """
+ This is only responsible for adding screens to the UI, which is managed by the UI
+ """
+ if None == cls.__ui:
+ raise Exception("UI is None.")
+ try:
+ if isinstance(screen, AbstractLoad):
+ cls.__ui.add_screen(screen)
+ except Exception as e:
+ raise Exception("[App](abort) add_screen error: ", e)
+ return cls
+
+ @classmethod
+ def add_service(cls, service:AbstractLoad):
+ """
+ add service
+ """
+ try:
+ if isinstance(service, AbstractLoad):
+ service.instance_after() # 初始化服务
+ cls.__service_list.append(service)
+ except Exception as e:
+ raise Exception("[App](abort) add_service error: ", e)
+ return cls
+
+ @classmethod
+ def exec(cls):
+ """
+ startup App
+ """
+ if None == cls.__ui:
+ raise Exception("[App](abort) exec interrupt, UI is null.")
+ try:
+ # start ui
+ cls.__ui.start()
+
+ import lvgl as lv
+ lv.task_handler()
+
+ # start services
+ for service in App.__service_list:
+ service.load_before()
+ service.load()
+ service.load_after()
+ except Exception as e:
+ print("[App] exec error: ", e)
+```
+
+## UML
+
+### Service module
+
+`services.py` defines multiple services to provide various services. These`services` inherit the `AbstractLoad` abstract loading base class, making it easier to provide various service items during the loading process.
+
+1. `BatteryManger`: Provides battery level management
+2. `DevInfoService`: Provides device information services
+3. `MediaService`: Provides audio services
+4. `NetService`: Provides network services
+5. `PocService`: Provides PoC intercom service
+
+The relationship between each 'service' is shown in the following figure:
+
+
+
+> If users need to add a `service`, they can refer to the existing `service` style and add it to the corresponding position in `poc_main.py`.
+
+### Screen module
+
+In `ui.py`, multiple UI interfaces are defined, such as:
+
+1. `PocUI`: Main UI, providing `MenuBar` , `PromptBox` and `Screen`, and Response Handling of Key Events
+2. `MenuBar`: Menu bar (used to display network status, time, battery level, and other icons, always displayed at the top of the screen, with a size of 240 * 20)
+3. `PromptBox`: Message prompt box (used for message prompts, displayed on the current UI interface)
+4. `Screen`: UI screen, also known as UI interface, is used to display various interfaces to users. Such as `GroupScreen`, `WelcomeScreen` and `MemberScreen`, etc
+
+The relationship between various UI interfaces is shown in the following figure:
+
+
+
+> If users need to add a `Screen`, they can refer to the existing `Screen` style and add it to the corresponding position in `poc_main.py`.
diff --git a/docs/Application_guide/en/solutions/tracker/README.md b/docs/Application_guide/en/solutions/tracker/README.md
index aaa6e4322443741f9c10a6c67ce8b88a52662100..3f6d55632407d7479617bfe2a04a4ca34c8010dc 100644
--- a/docs/Application_guide/en/solutions/tracker/README.md
+++ b/docs/Application_guide/en/solutions/tracker/README.md
@@ -1,372 +1,23 @@
-# Smart Tracker Solution
+# Tracker Solution
-## Introduction
+This intelligent locator solution is based on the EC200UEUAA QuecPython standard development board and has the following features:
-This document describes the design framework of Quecel smart tracker in the QuecPython solution, including the software and hardware system framework, description of key components, introduction and functional examples of system initialization process and business process, to help you quickly understand the overall architecture and functions of Quectel smart tracker.
-
-### Overview
-
-- Smart tracker
-- Terminal device functions meet the majority of requirements in tracker application scenarios
-- The visual operation platform and the mobile APP make device management and data viewing more convenient.
-
-
-
-### Functions
-
-- Multi-technology positioning, geo-fence alarm, danger alarm, SOS alarm reporting, audio monitoring, recording, historical track playback, remote control, etc.
-- Smart positioning
- - The system utilizes 4G communication/multi-technology positioning/distributed services to provide a one-stop solution from end to service for the smart tracker industry.
-- All-platform support
- - The device operation platform and mobile APP have all-round functions, enabling terminal device manufacturers to quickly manage devices and end users without the need to build your own service platforms.
-- Reliable and stable
- - The terminal device has high positioning accuracy, high sensitivity to danger perception, low power consumption, and stable operation. Terminal device manufacturers can develop customized solutions directly based on the public version, greatly shortening the hardware development cycle.
-
-
-
-### Features
-
-- Intelligent perception, recognition, and reporting of location information and danger alarms.
-- Support integration with various IoT platforms such as Alibaba IoT Platform, ThingsBoard, and other private services.
-- Secondary development with QuecPython to formulate modular and customizable solutions, thus shortening development cycles.
-- Visual operation platform and mobile APP to control terminal devices.
-
-### Applications
-
-- Vehicle tracking
-- Logistics and transportation
-- People tracking
-- Electronic student ID card
-- Pet tracking
-- Special industries (agricultural irrigation, rare species monitoring, etc.)
-
-
-
-## Application Framework
-
-### Function Overview
-
-The software functions of smart tracker solution are demonstrated in the diagram below. The solution is divided into functions based on the actual business of the tracker and developed in a modular way.
-
-
-
-- Transmission Protocol Parsing
- + Connection and data interaction with Alibaba IoT Platform
- + Connection and data interaction with ThingsBoard
- + GT06 protocol
- + JT/T808 protocol
-- Network Management
- + MQTT protocol (Alibaba IoT/ThingsBoard/other platforms)
- + TCP/UDP protocol (GT06/JTT808 protocol)
- + APN settings (network registration and data call)
- + LTE NET (4G network registration and data call)
-- Peripheral Management
- + GNSS: Turn on/off the GNSS module, read positioning data from the GNSS module, and inject AGPS data.
- + G-sensor: Read data of sensors
- + Charge IC: Charging management, obtaining device charging status
- + Battery: Battery management, reading battery voltage and calculating battery level
- + LED: LED indicator
-- Data Storage
- + Storage of system configuration parameters
- + Storage of location data backup
- + AGPS download storage
- + Log information storage
-- Device Upgrade
- + OTA upgrade
-- Business Function Management
- + Connection and reconnection of network and IoT platforms
- + Device data acquisition and reporting
- + Alarm detection and reporting
- + Processing of IoT platform downlink commands
- + Device low power consumption
-
-### Data Interaction Process
-
-The data interaction process between the module and the IoT platform is described in the following diagram.
-
-
-
-Process description:
-
-1. The mobile APP sends commands to the IoT platform. The server issues commands to the module through TCP/UDP/MQTT protocols, and the module parses the command data.
-2. The module reports data to the IoT platform through TCP/UDP/MQTT protocols. The IoT platform processes the data and synchronously displays it on the mobile APP.
-
-### Design Philosophy and Patterns
-
-- This system is designed as a listener pattern, that is, transmit messages and listen for events through callback functions.
-- The software functions are split according to the tracker's business requirements, which are implemented based on functional modules. Each part is independently developed to reduce dependencies and can be debugged and run independently, thus achieving decoupling effects.
-- Interactions between functions are realized through callback functions. All business function processing, such as downlink command processing, alarm detection, data acquisition and reporting, and device control, is done in the `Tracker` class.
-
-
-
-1. All functional modules are registered in the `Tracker` class through `Tracker.add_module`.
-2. The Server module (IoT platform interaction module) transmits service downlink data to `Tracker.server_callback()` for processing through callback functions.
-3. The NetManage module transmits network disconnection events to `Tracker.net_callback` for processing through callback functions.
-
-### Software Architecture Diagram
-
-The software system framework is described as follows:
-
-- Display layer, connection with different IoT platforms
-- Transport layer, data interaction over different protocols
-- Business layer, mainly used for device data acquisition, device control, downlink commands receiving and processing of IoT platforms, and data integration and reporting.
-- Device layer, functions including obtaining and parsing location data, reading sensor data, battery management and historical data storage, and device information acquisition and device functions setting, such as device version, IMEI number, APN settings, network data call and device low power consumption.
-
-
-
-### Business Process
-
-
-
-Business Process Description:
-
-1. Power on the device.
-2. Configure APN and connect to the network (network registration and data call); Configure IoT platform and establish a connection, with retry on failure.
-3. Detect the boot of objects and acquire data.
- - Power on the GNSS object and wait for positioning data.
- - Power on the G-Sensor and detect the calibration.
- - Turn on LED indicators (network status/positioning status/charging status, etc.).
- - Acquire battery level and detect charging status.
- - Detect alarms (overspeed/vibration/geo-fence/low battery level, etc.).
-4. After connecting to the IoT platform, check if there is any historical data that needs to be reported and proceed with reporting.
-5. Upon successful connection to the IoT platform, report current device information (location/alarms).
-6. If the connection to the IoT platform fails, store the current device information (location/alarms).
-7. When the device has no tasks, enter low power mode and wake up the device periodically to detect device information and report it.
-8. After connecting to the IoT platform, wait for commands to be issued by the IoT platform
-9. Parse commands
- - Device control commands, such as modifying device business parameters and controlling device shutdown or reboot.
- - OTA upgrade commands for OTA upgrades
- - Device information query commands, which should be responded with device information
-
-### System Initialization Process
-
-
-
-1. Initialize basic functional objects, such as low power management, configuration parameters, battery, historical files, positioning, and sensors.
-2. Initialize IoT platform server object, such as Alibaba IoT Platform, ThingsBoard, or other private service platform (GT06, JT/T808, etc.).
-3. Initialize the core business object (Tracker), and add various functional objects to the Tracker object through *tracker.add_module()*, then register *Tracker.server_callback()* to the Server object for receiving downlink messages and commands from the server.
-
-## Application Development
-
-### Get Solution Resource
-
-Tracker solution resources can be downloaded from [https://github.com/QuecPython/solution-tracker](https://github.com/QuecPython/solution-tracker)
-
-> The solution project has a sub-project named `modules`. Do not forget to download the sub-project together.
->
-> The command for downloading the sub-project synchronously: `git clone --recursive https://github.com/QuecPython/solution-tracker.git`
-
-Resource package directory:
-
-
-
-- *code*
-
-This directory contains the software solution code.
-
-
-
-- *docs*
-
-This directory contains project documents such as user guides and functional interface specifications.
-
-
-
-- *object_model_demo*
-
-This directory contains a TSL model file of the Alibaba IoT Platform, which can be directly imported into the Alibaba IoT Platform for debugging.
-
-### Solution Overview
-
-This is a public version of the tracker solution, which does not include all functions. The solution provides the functional implementation of the core components of the tracker and functions such as data interaction, and event forwarding with the server. You can continue to develop business functions based on this framework. The current software framework has the following features:
-
-- Data interaction over MQTT (Alibaba IoT Platform and ThingsBoard are supported currently.)
-- Read and write configuration file
-- OTA upgrade
-- LED indicator
-- Device network management
-- Device information management
+- MQTT protocol communication (current solution supports Alibaba IoT platform/TinsBoard platform)
+- Read and write configuration files
+- OTA remote upgrade
+- LED indicator light
+- Device Network Management
+- Equipment Information Management
- Battery level and charging management
-- Backup data storage
-- GNSS positioning/LBS positioning/Wi-Fi positioning
+- Backup information storage
+- GNSS positioning/base station positioning/WiFi positioning
- Low power management
-- Log storage and recording
-
-### Set up Environment
-
-#### Install USB Driver
-
-Please download and install the driver according to the platform of the module to be debugged. [Click here to download USB Drivers](https://python.quectel.com/en/resource-download?cid=2)
-
-
-
-#### Download Development and Debugging Tool
-
-It is recommended to use QPYcom for development and debugging. The processes described in this document are under the premise that QPYcom is used and USB driver installation is successful.
-
-[Click here to download QPYcom](https://python.quectel.com/en/resource-download?cid=260)
-
-
-
-[Click here to view QPYcom User Guide](https://python.quectel.com/doc/Application_guide/en/dev-tools/QPYcom/qpycom-gui.html)
-
-#### Modify Code Configuration Parameters
-
-The configuration parameters used in the current solution code are not configured. Please modify configurations according to the instructions below.
-
-Find the configuration files starting with `settings_` in the *code* folder and modify the configuration based on actual parameters, as shown below.
-
-- `settings_server.py` is used to configure the IoT platform connection information.
-
-```python
-class AliIotConfig:
-
- product_key = ""
- product_secret = ""
- device_name = ""
- device_secret = ""
- server = "iot-as-mqtt.cn-shanghai.aliyuncs.com"
- qos = 1
-
-
-class ThingsBoardConfig:
-
- host = ""
- port = 1883
- username = ""
- qos = 0
- client_id = ""
-```
-
-- `settings_loc.py` is used to configure the information of the module used for positioning (UART port of the external GNSS communication, authentication information for LBS/Wi-Fi positioning).
-
-```python
-gps_cfg = {
- "UARTn": UART.UART1,
- "buadrate": 115200,
- "databits": 8,
- "parity": 0,
- "stopbits": 1,
- "flowctl": 0,
- "gps_mode": _gps_mode.external,
- "nmea": 0b010111,
- "PowerPin": None,
- "StandbyPin": None,
- "BackupPin": None,
-}
-
-wifi_cfg = {
- "token": "xxxxxxxxxx"
-}
-```
-
-- `settings_user.py` is used to configure parameters related to user business functions (e.g., alarm switch, low battery level threshold).
-
-```python
-class _server:
- none = 0x0
- AliIot = 0x1
- ThingsBoard = 0x2
-
-class _drive_behavior_code:
- none = 0x0
- sharply_start = 0x1
- sharply_stop = 0x2
- sharply_turn_left = 0x3
- sharply_turn_right = 0x4
-
-class _ota_upgrade_module:
- none = 0x0
- sys = 0x1
- app = 0x2
-
-debug = 1
-log_level = "DEBUG"
-checknet_timeout = 60
-server = _server.AliIot
-phone_num = ""
-low_power_alert_threshold = 20
-low_power_shutdown_threshold = 5
-over_speed_threshold = 50
-sw_ota = 1
-sw_ota_auto_upgrade = 1
-sw_voice_listen = 0
-sw_voice_record = 0
-sw_fault_alert = 1
-sw_low_power_alert = 1
-sw_over_speed_alert = 1
-sw_sim_abnormal_alert = 1
-sw_disassemble_alert = 1
-sw_drive_behavior_alert = 1
-drive_behavior_code = _drive_behavior_code.none
-loc_method = _loc_method.all
-loc_gps_read_timeout = 300
-work_mode = _work_mode.cycle
-work_mode_timeline = 3600
-work_cycle_period = 30
-user_ota_action = -1
-ota_status = {
- "sys_current_version": "",
- "sys_target_version": "--",
- "app_current_version": "",
- "app_target_version": "--",
- "upgrade_module": _ota_upgrade_module.none,
- "upgrade_status": _ota_upgrade_status.none,
-}
-```
-
-#### Download Firmware
-
-Download the corresponding QuecPython firmware according to the current debugging module model from the QuecPython official website, and download the firmware into the module with QPYcom.
-
-[Click here to download firmware](https://python.quectel.com/en/resource-download?cid=4)
-
-
-
-Use QPYcom to download firmware.
-
-1. Select firmware
-
-
-
-2. Download firmware
-
-
-
-3. Wait for the completion of firmware download
-
-
-
-4. Successful download
-
-
-
-5. Connect to the interactive port
-
-
-
-6. View the download information
-
-
-
-#### Download Code
-
-- It is recommended to rename the *`main.py`* file to *`_main.py`* before downloading the code because the *`main.py`* file will run automatically when the module is powered on, which is not convenient for debugging. During the test, we can manually run the *`_main.py`* file for easier debugging.
-
-- When downloading the code via USB, you need to reserve a USB port or test point for the device. Or you can use an EVB for debugging, and install the driver in advance.
-
-1. Select "**`Quectel USB NMEA PORT`**". This serial port is for interaction, and QPYcom logs will also be output through this serial port.
-
-
-
-2. Download the business functional code to the device in batches. Click "**Download script**" and wait for the download to complete. After the download is complete, view the result on the "File" page.
-
-
-
-3. After successful download, it is recommended to reboot the device and run the function (If the *`main.py`* file was downloaded, the function will run automatically after the device is rebooted; if the *`main.py`* file was renamed to *`_main.py`* before downloading, you need to manually run the *`_main.py`* file to start the function).
+- Log storage record
-
+
-4. View the running result
+------
-
+- [development resources](./dev_resources.md)
+- [quick start](./quick_start.md)
+- [software design](./software_design.md)
\ No newline at end of file
diff --git a/docs/Application_guide/en/solutions/tracker/dev_resources.md b/docs/Application_guide/en/solutions/tracker/dev_resources.md
new file mode 100644
index 0000000000000000000000000000000000000000..1fd41a68487b841412ef975d99a319f0c80b4d65
--- /dev/null
+++ b/docs/Application_guide/en/solutions/tracker/dev_resources.md
@@ -0,0 +1,68 @@
+# Development resources summary
+
+## Development board documentation
+
+- model:EC200UEUAA QuecPython standard borad
+- Purchase link:[click](https://www.waveshare.com/ec200u-au-c4-p01.htm)
+- docs:
+ - [specification](https://python.quectel.com/wp-content/uploads/2024/09/EC200UA_C4-P01%E7%B3%BB%E5%88%97%E5%BC%80%E5%8F%91%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://python.quectel.com/wp-content/uploads/2024/09/EC200UA_C4-P01%E7%B3%BB%E5%88%97%E5%BC%80%E5%8F%91%E6%9D%BF%E5%8E%9F%E7%90%86%E5%9B%BE.pdf)
+ - [Screen printing](https://python.quectel.com/wp-content/uploads/2024/09/EC200UA_C4-P01%E7%B3%BB%E5%88%97%E5%BC%80%E5%8F%91%E6%9D%BF%E4%B8%9D%E5%8D%B0.pdf)
+ - [User guidance](https://python.quectel.com/doc/Getting_started/zh/evb/ec200x-evb.html)
+
+## module information
+
+- model:[EC200UEUAA](https://python.quectel.com/modules-cat/ec200u-series)
+- [specification](https://python.quectel.com/wp-content/uploads/2024/09/Quectel_EC200U%E7%B3%BB%E5%88%97_LTE_Standard_%E6%A8%A1%E5%9D%97%E4%BA%A7%E5%93%81%E8%A7%84%E6%A0%BC%E4%B9%A6_V1.4.pdf)
+- [driver download](https://python.quectel.com/wp-content/uploads/2024/09/Quectel_Windows_USB_DriverU_V1.0.19.zip)
+
+## Accessories Information
+
+- GNSS antenna+adapter cable
+ - model:YLY001CA + YM0003AA
+ - buy link:[click](https://e.tb.cn/h.TpAFyEz02BnCHRD?tk=fznae6ITVEX)
+
+## 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://python.quectel.com/doc/Application_guide/zh/dev-tools/QPYcom/index.html)
+- Editor - VSCode
+ - download [VSCode](https://code.visualstudio.com/)
+
+## Firmware
+
+- version:EC200UEUAAR03A04M08_OCPU_QPY_BETA0418
+- download [Firmware](https://python.quectel.com/wp-content/uploads/2024/09/QPY_OCPU_BETA0001_EC200U_EUAA_FW.zip)
+
+## Source code
+
+- version: V2.0.0
+
+- [github repo](https://github.com/QuecPython/solution-tracker/tree/master)
+
+ ```bash
+ # 1.pull source code
+ git clone https://github.com/QuecPython/solution-tracker.git
+
+ # 2.enter root dir
+ cd solution-tracker/
+
+ # 3.check branch
+ git checkout master
+
+ # 4.init sub module
+ git submodule init
+
+ # 5.update sub module
+ git submodule update
+
+ # 6.enter sub module dir
+ cd code/modules/
+
+ # 7.check branch
+ git checkout master
+ ```
+
+- [Download Zip package](https://codeload.github.com/QuecPython/solution-tracker/zip/refs/heads/master)
\ No newline at end of file
diff --git a/docs/Application_guide/en/solutions/tracker/quick_start.md b/docs/Application_guide/en/solutions/tracker/quick_start.md
new file mode 100644
index 0000000000000000000000000000000000000000..02c361383c0e15265574ee1a566ed3b3bdca3c3d
--- /dev/null
+++ b/docs/Application_guide/en/solutions/tracker/quick_start.md
@@ -0,0 +1,269 @@
+# Quick Start
+
+## Hardware preparation
+
+- A Windows computer, recommended for the 'Win10' system
+- A set of [EC200UEUAA QuecPython standard development board ](https://python.quectel.com/doc/Getting_started/zh/evb/ec200x-evb.html)(including LTE antenna, Type-C data cable, etc.)
+- One [GNSS antenna](https://e.tb.cn/h.TpAFyEz02BnCHRD?tk=fznae6ITVEX)
+- A pin and jumper cap
+- A functional Nano SIM card
+
+## Environment construction
+
+- Download and install EC200U series module driver: [QuecPython_USB_Driver_Win10_U_G]( https://python.quectel.com/wp-content/uploads/2024/09/Quectel_Windows_USB_DriverU_V1.0.19.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://python.quectel.com/wp-content/uploads/2024/09/QPY_OCPU_BETA0001_EC200U_EUAA_FW.zip)
+- Download [Experimental Source Code](https://codeload.github.com/QuecPython/solution-tracker/zip/refs/heads/master)
+
+## Hardware connection
+
+Connect the hardware according to the following diagram:
+
+
+
+1. Connect the LTE antenna to the antenna connector labeled with the word 'LTE'
+2. Connect the GNSS antenna to the antenna connector marked with the word 'GNSS'
+3. Insert a usable Nano SIM card into the back of the development board at the position shown in the diagram
+4. Use jumper caps to short-circuit the two pins marked with the words 'GNSS-EN' to enable the development board's built-in GNSS function
+5. Connect the development board and computer using a Type-C data cable
+
+## Cloud Service Platform
+
+Follow these steps to create, configure, and connect to the Alibaba Cloud IoT platform:
+
+### Create products and devices
+
+For details, please refer to the Alibaba Cloud documentation: [Creating Products and Devices](https://help.aliyun.com/document_detail/73705.html).
+
+- create product
+
+- create device
+
+
+
+### Define object model
+
+For details, please refer to the Alibaba Cloud documentation: [Defining Product Models](https://help.aliyun.com/document_detail/117636.html).
+
+The object model can provide a more intuitive view of the uploaded data values. This solution provides a demo of the object model, which can be directly imported into the `object_model_demo/ai_cloud_object_model.json` file in the engineering project for automatic generation, without the need for manual creation.
+
+
+
+## Device development
+
+This section focuses on how to modify the configurations or code that users need to pay attention to in their business, so that they can quickly get started.
+
+Before starting, use VSCode to open the project source code and locate the configuration file starting with `settings _` in the code for configuration.
+
+> This solution supports two optional platforms: Alibaba IoT and Thingsboard. This mainly introduces the configuration and connection of using Alibaba IoT.
+
+### IoT Platform Connection Information
+
+`settings_server.py` is used to configure IoT platform connection information.
+
+
+
+```python
+class AliIotConfig:
+ product_key = ""
+ product_secret = None
+ device_name = ""
+ device_secret = ""
+ server = "iot-as-mqtt.cn-shanghai.aliyuncs.com"
+ qos = 1
+
+class ThingsBoardConfig:
+ host = ""
+ port = 1883
+ username = ""
+ qos = 0
+ client_id = ""
+```
+
+### Positioning module configuration information
+
+`settings_loc.py` is used to configure the configuration information of the positioning module (built-in GNSS/external GNSS serial port, authentication information for base station/WiFi positioning)
+
+> This solution is based on the built-in GNSS function implementation of the EC200UEUAA QuecPython standard development board.
+
+```python
+# GNSS
+gps_cfg = {
+ "gps_mode": _gps_mode.internal, # builtin GNSS
+ "UARTn": UART.UART2,
+ "buadrate": 115200,
+ "databits": 8,
+ "parity": 0,
+ "stopbits": 1,
+ "flowctl": 0,
+ "PowerPin": None,
+ "StandbyPin": None,
+ "BackupPin": None,
+}
+
+# Cell
+cell_cfg = {
+ "serverAddr": "www.queclocator.com",
+ "port": 80,
+ "token": "xxxxxxxxxx",
+ "timeout": 3,
+ "profileIdx": profile_idx,
+}
+
+# Wifi
+wifi_cfg = {
+ "token": "xxxxxxxxxx"
+}
+```
+
+### User business configuration information
+
+`settings_user.py` is used to configure relevant configuration parameters for user business functions (such as alarm switches, low power thresholds, etc.)
+
+```python
+class _server:
+ none = 0x0
+ AliIot = 0x1
+ ThingsBoard = 0x2
+
+class _drive_behavior_code:
+ none = 0x0
+ sharply_start = 0x1
+ sharply_stop = 0x2
+ sharply_turn_left = 0x3
+ sharply_turn_right = 0x4
+
+class _ota_upgrade_module:
+ none = 0x0
+ sys = 0x1
+ app = 0x2
+
+debug = 1
+log_level = "DEBUG"
+checknet_timeout = 60
+server = _server.AliIot
+phone_num = ""
+low_power_alert_threshold = 20
+low_power_shutdown_threshold = 5
+over_speed_threshold = 50
+sw_ota = 1
+sw_ota_auto_upgrade = 1
+sw_voice_listen = 0
+sw_voice_record = 0
+sw_fault_alert = 1
+sw_low_power_alert = 1
+sw_over_speed_alert = 1
+sw_sim_abnormal_alert = 1
+sw_disassemble_alert = 1
+sw_drive_behavior_alert = 1
+drive_behavior_code = _drive_behavior_code.none
+loc_method = _loc_method.all
+loc_gps_read_timeout = 300
+work_mode = _work_mode.cycle
+work_mode_timeline = 3600
+work_cycle_period = 30
+user_ota_action = -1
+ota_status = {
+ "sys_current_version": "",
+ "sys_target_version": "--",
+ "app_current_version": "",
+ "app_target_version": "--",
+ "upgrade_module": _ota_upgrade_module.none,
+ "upgrade_status": _ota_upgrade_status.none,
+}
+```
+
+### Power on
+
+After completing the hardware connection work, the development board will automatically power on and check if there are any COM ports containing the words' Quectel USB 'in the port list of the computer device manager.
+
+
+
+### Download firmware
+
+Refer to [this chapter](https://python.quectel.com/doc/Application_guide/en/dev-tools/QPYcom/qpycom-dw.html# Download firmware), burn firmware package [QPy_OCPU_SETA0001_EC200U_SUAA_FW](https://python.quectel.com/wp-content/uploads/2024/09/QPY_OCPU_BETA0001_EC200U_EUAA_FW.zip) To the development board.
+
+### Script import and execution
+
+1. Refer to [this chapter](https://python.quectel.com/doc/Getting_started/en/first_python.html) To transfer files between modules, import all files from the 'code' folder in the source code directory into the module file system, as shown in the following figure:
+
+ 
+
+2. Refer to [this chapter](https://python.quectel.com/doc/Getting_started/zh/first_python.html#), Execute the script file and execute the main program file ` _main. py `.
+3. Refer to [this chapter](https://python.quectel.com/doc/Getting_started/zh/first_python.html# Stop program running), stop program running.
+
+## Debugging
+
+### Program startup
+
+After executing the ` _main.py ` script, the program starts running and the project running status can be viewed on the interactive page:
+
+> The program needs to run for a period of time to obtain GNSS positioning information, please refer to the [relevant document for details](https://python.quectel.com/doc/FAQ/zh/hardware/gnss.html#%3Cstrong%3E%E4%BB%80%E4%B9%88%E6%98%AFGNSS%E7%9A%84%E5%86%B7%E5%90%AF%E5%8A%A8%E3%80%81%E6%B8%A9%E5%90%AF%E5%8A%A8%E5%92%8C%E7%83%AD%E5%90%AF%E5%8A%A8%3C/strong%3E ).
+
+
+
+On the Alibaba Cloud IoT platform, device status information can be viewed.
+
+
+
+### Cloud control
+
+Send instructions to the device end for device control and data exchange through online debugging.
+
+
+
+### OTA
+
+> **Firmware upgrade only supports differential upgrade, not full package upgrade **;
+>**Project file upgrade package, made by modifying the project code file extension to '. bin', uploaded to the cloud, can upload multiple files **.
+
+#### Firmware Upgrade
+
+1. Create firmware upgrade differential package (contact firmware developers);
+2. Create an OTA module and name it after the device platform, such as: ` EC200U-EUAA`。
+
+
+
+3. Create OTA upgrade package
+
+ The upgrade package name is named after `PROJECT-NAME` in `settings.py`, for example: ` QuecPython-Tracker`
+
+
+
+4. Select batch upgrade and create upgrade plan
+
+
+
+
+
+5. Wait for device upgrade and view upgrade results
+ + When the device enables OTA upgrade and OTA automatic upgrade, wait for the device upgrade to complete and view the upgrade results;
+
+ + When the device enables OTA upgrade but does not enable automatic upgrade, the OTA upgrade can be performed by issuing the object model setting command `user_ota.action=1` through the online debugging module.
+
+
+
+
+
+
+#### Project Upgrade
+
+1. Create an OTA module named `PROJECT-NAME` in `settings.py`, for example: ` QuecPython-Tracker`。
+
+
+
+2. Change the file extension of the project that needs to be upgraded to `.bin`
+3. Create OTA upgrade package
+ + Here, it is necessary to write the device full path file name corresponding to the upgrade file name in the custom information pushed to the device, such as:`{"files":{"common.bin":"/usr/modules/common.py","settings.bin":"/usr/settings.py","test_tracker.bin":"/usr/test_tracker.py"}}`
+
+
+
+4. Select batch upgrade and create upgrade plan
+
+5. Wait for device upgrade and view upgrade results
+
+ + When the device enables OTA upgrade and OTA automatic upgrade, wait for the device upgrade to complete and view the upgrade results;
+ + When the device enables OTA upgrade but does not enable automatic upgrade, the OTA upgrade can be performed by issuing the object model setting command `user_ota.action=1` through the online debugging module.
+
+
\ No newline at end of file
diff --git a/docs/Application_guide/en/solutions/tracker/software_design.md b/docs/Application_guide/en/solutions/tracker/software_design.md
new file mode 100644
index 0000000000000000000000000000000000000000..d94f4fb8c2210e600cf4f7d7dab73627d7e617ba
--- /dev/null
+++ b/docs/Application_guide/en/solutions/tracker/software_design.md
@@ -0,0 +1,832 @@
+# Software Design
+
+## Introduction
+
+This document mainly describes the design framework of the QuecPython locator for mobile communication, including the software and hardware system framework, key component function description, system initialization process and business process introduction, as well as functional examples, to facilitate users to quickly understand the overall architecture and functions of the QuecPython locator.
+
+## Function Introduction
+
+The software functions in the intelligent locator solution are introduced as shown in the following figure. The solution is divided into functions based on the actual business of the locator and developed in a modular manner.
+
+
+
+- Transmission Protocol Analysis
+ + Alibaba IoT Platform Connection and Data Interaction
+ + ThingsBoard Platform Connection and Data Interaction
+ + GT06 protocol
+ + JT/T808 protocol
+- network management
+ + MQTT protocol
+ + TCP/UDP protocol
+ + APN setting
+ + LTE NET
+- External Device Management
+ + GNSS positioning data reading, enabling, AGPS injection, etc
+ + G-Sensor sensor data reading
+ + Charge IC charging management, obtaining device charging status
+ + Battery management, reading battery voltage, converting battery capacity
+ + LED indicator light
+- Data Storage
+ + System configuration parameter storage
+ + Positioning data supplementary transmission and storage
+ + AGPS download storage
+ + Log information storage
+- Device Upgrade
+ + OTA
+- Business Function Management
+ + Connection and reconnection between network and IoT platform
+ + Equipment data collection and reporting
+ + Alarm detection and reporting
+ + IoT platform downlink instruction processing
+ + Low power sleep mode of the device
+
+## Data exchange process
+
+The data exchange process between modules and IoT platforms is described in the following figure:
+
+
+
+Process description:
+1. The mobile app sends instructions to the IoT platform, and the server sends the instruction data to the module end through TCP/UDP/MQTT protocol for parsing and processing;
+2. The module reports data to the IoT platform through TCP/UDP/MQTT protocol, which processes it and synchronously displays it on the mobile phone.
+
+## Software framework
+
+### Design Ideas
+
+- This system is designed in listener mode and monitors message transmission events through callback functions;
+- The software splits its functions according to the business requirements of the locator, mainly implementing them in modules. Each part is independently developed and implemented to reduce dependence on each other, and can be independently debugged and run to achieve decoupling effect;
+- The event interaction between functions is completed through callback functions, and all business function processing is handled in the 'Tracker' class, such as downstream instruction processing, alarm detection, data collection and reporting, device control, etc.
+
+
+
+1. All functional modules are controlled by registering them in the `Tracker` class through `Tracker.add_module`;
+2. The Server module (IoT platform interaction module) passes the service-oriented downlink data to `Tracker.server_callback` for processing through callbacks;
+3. The NetManage module passes the network disconnection event to `Tracker.net_callback` for processing through callbacks.
+
+### Software Architecture Diagram
+
+The introduction and description of the software system framework are as follows:
+
+- Display layer, integrating with different IoT platforms;
+- Transport layer, using different protocols for interaction;
+- The business layer is mainly used to collect device data, control device modules, receive and process downstream instructions from the IoT platform, and integrate and report data;
+- The device layer mainly includes functions such as obtaining and parsing positioning data, reading sensor data, battery management, and storing historical data. It also collects device data information and sets device functions, such as device version information, IMEI number, APN settings, network dialing, and device low power consumption.
+
+
+
+## Introduction to functional components
+
+### Core Business Module (Tracker)
+
+1. Function description
+
+ Implement core business logic, interact and parse data with the server, control device modules, and transmit all functions in the form of events to the sub threads of the business event message queue for processing.
+
+2. Implementation principle
+
+- By registering functional modules, obtain data from various functional modules, such as positioning information, battery information, sensor information, etc
+
+ ```python
+ class Tracker:
+ ...
+
+ def add_module(self, module):
+ if isinstance(module, AliIot):
+ self.__server = module
+ elif isinstance(module, AliIotOTA):
+ self.__server_ota = module
+ elif isinstance(module, Battery):
+ self.__battery = module
+ elif isinstance(module, History):
+ self.__history = module
+ elif isinstance(module, GNSS):
+ self.__gnss = module
+ elif isinstance(module, CellLocator):
+ self.__cell = module
+ elif isinstance(module, WiFiLocator):
+ self.__wifi = module
+ elif isinstance(module, NMEAParse):
+ self.__nmea_parse = module
+ elif isinstance(module, CoordinateSystemConvert):
+ self.__csc = module
+ elif isinstance(module, NetManage):
+ self.__net_manage = module
+ elif isinstance(module, PowerManage):
+ self.__pm = module
+ elif isinstance(module, TempHumiditySensor):
+ self.__temp_sensor = module
+ elif isinstance(module, Settings):
+ self.__settings = module
+ else:
+ return False
+ return True
+
+ def running(self, args=None):
+ if self.__running_tag == 1:
+ return
+ self.__running_tag = 1
+ # 禁用设备休眠
+ self.__pm.autosleep(0)
+ self.__pm.set_psm(mode=0)
+ # 启动业务事件消息队列监听子线程
+ self.__business_start()
+ # 发送OTA版本刷新指令到事件队列中进行执行
+ self.__business_queue.put((0, "ota_refresh"))
+ # 发送上报定位数据事件(包含网络的连接,设备数据的采集,设备数据的上报)
+ self.__business_queue.put((0, "loc_report"))
+ # 发送OTA升级查询指令事件
+ self.__business_queue.put((0, "check_ota"))
+ # 发送设备休眠事件
+ self.__business_queue.put((0, "into_sleep"))
+ self.__running_tag = 0
+ ```
+
+- By calling back and monitoring the command messages issued by the server, perform business processing
+
+ ```python
+ class Tracker:
+ ...
+
+ def server_callback(self, args):
+ # 服务端下行消息传入业务事件消息队列中进行处理
+ self.__business_queue.put((1, args))
+ ```
+
+ ```python
+ class Tracker:
+ ...
+
+ def __business_running(self):
+ while True:
+ data = self.__business_queue.get()
+ with self.__business_lock:
+ self.__business_tag = 1
+ ...
+ # 处理IoT 平台下行指令功能
+ if data[0] == 1:
+ self.__server_option(*data[1])
+ self.__business_tag = 0
+ ```
+
+ ```python
+ class Tracker:
+ ...
+
+ def __server_option(self, topic, data):
+ if topic.endswith("/property/set"):
+ # 处理属性设置的下行消息
+ self.__server_property_set(data)
+ elif topic.find("/rrpc/request/") != -1:
+ # 处理透传数据的下行消息
+ msg_id = topic.split("/")[-1]
+ self.__server_rrpc_response(msg_id, data)
+ elif topic.find("/thing/service/") != -1:
+ # 处理服务数据的下行消息
+ service = topic.split("/")[-1]
+ self.__server_service_response(service, data)
+ elif topic.startswith("/ota/device/upgrade/") or topic.endswith("/ota/firmware/get_reply"):
+ # 处理OTA升级的下行消息
+ user_cfg = self.__settings.read("user")
+ if self.__server_ota_flag == 0:
+ if user_cfg["sw_ota"] == 1:
+ self.__server_ota_flag = 1
+ if user_cfg["sw_ota_auto_upgrade"] == 1 or user_cfg["user_ota_action"] == 1:
+ # 满足OTA升级条件,执行OTA升级流程
+ self.__server_ota_process(data)
+ else:
+ self.__server_ota_flag = 0
+ self.__server_ota.set_ota_data(data["data"])
+ ota_info = self.__server_ota.get_ota_info()
+ ota_info["ota_status"] = 1
+ self.__server_ota_state_save(**ota_info)
+ else:
+ module = data.get("data", {}).get("module")
+ self.__server.ota_device_progress(-1, "Device is not alowed ota.", module)
+ ```
+
+- Wake up the device from sleep and report business data through RTC callback wake-up operation
+
+ ```python
+ class Tracker:
+ ...
+
+ def __into_sleep(self):
+ while True:
+ if self.__business_queue.size() == 0 and self.__business_tag == 0:
+ break
+ utime.sleep_ms(500)
+ user_cfg = self.__settings.read("user")
+ # 根据休眠时长自动调整休眠模式,autosleep或者psm
+ if user_cfg["work_cycle_period"] < user_cfg["work_mode_timeline"]:
+ self.__pm.autosleep(1)
+ else:
+ self.__pm.set_psm(mode=1, tau=user_cfg["work_cycle_period"], act=5)
+ # 启动RTC定时唤醒设备
+ self.__set_rtc(user_cfg["work_cycle_period"], self.running)
+
+ def __set_rtc(self, period, callback):
+ # 设置RTC唤醒时钟,唤醒设备
+ self.__business_rtc.enable_alarm(0)
+ if callback and callable(callback):
+ self.__business_rtc.register_callback(callback)
+ atime = utime.localtime(utime.mktime(utime.localtime()) + period)
+ alarm_time = (atime[0], atime[1], atime[2], atime[6], atime[3], atime[4], atime[5], 0)
+ _res = self.__business_rtc.set_alarm(alarm_time)
+ log.debug("alarm_time: %s, set_alarm res %s." % (str(alarm_time), _res))
+ return self.__business_rtc.enable_alarm(1) if _res == 0 else -1
+ ```
+
+3. Registration function module and callback function configuration
+
+ ```python
+ def main():
+ # 初始化网络功能模块
+ net_manage = NetManage(PROJECT_NAME, PROJECT_VERSION)
+ # 初始化配置参数功能模块
+ settings = Settings()
+ # 初始化电池检测功能模块
+ battery = Battery()
+ # 初始化历史数据功能模块
+ history = History()
+ # 初始化IoT 平台(阿里Iot)功能模块
+ server_cfg = settings.read("server")
+ server = AliIot(**server_cfg)
+ # 初始化IoT 平台(阿里Iot)OTA功能模块
+ server_ota = AliIotOTA(PROJECT_NAME, FIRMWARE_NAME)
+ server_ota.set_server(server)
+ # 初始化低功耗功能模块
+ power_manage = PowerManage()
+ # 初始化温湿度传感器功能模块
+ temp_sensor = TempHumiditySensor(i2cn=I2C.I2C1, mode=I2C.FAST_MODE)
+ loc_cfg = settings.read("loc")
+ # 初始化GNSS定位功能模块
+ gnss = GNSS(**loc_cfg["gps_cfg"])
+ # 初始化基站定位功能模块
+ cell = CellLocator(**loc_cfg["cell_cfg"])
+ # 初始化Wifi定位功能模块
+ wifi = WiFiLocator(**loc_cfg["wifi_cfg"])
+ # 初始化GNSS定位数据解析功能模块
+ nmea_parse = NMEAParse()
+ # 初始化WGS84与GCJ02坐标系转换功能模块
+ cyc = CoordinateSystemConvert()
+
+ # 初始化Tracker业务功能模块
+ tracker = Tracker()
+ # 将基础功能模块注册到Tracker类中进行控制
+ tracker.add_module(settings)
+ tracker.add_module(battery)
+ tracker.add_module(history)
+ tracker.add_module(net_manage)
+ tracker.add_module(server)
+ tracker.add_module(server_ota)
+ tracker.add_module(power_manage)
+ tracker.add_module(temp_sensor)
+ tracker.add_module(gnss)
+ tracker.add_module(cell)
+ tracker.add_module(wifi)
+ tracker.add_module(nmea_parse)
+ tracker.add_module(cyc)
+
+ # 将基础事件添加到事件列表中
+ server.add_event("over_speed_alert")
+ server.add_event("sim_abnormal_alert")
+ server.add_event("low_power_alert")
+ server.add_event("fault_alert")
+
+ # 设置网络模块的回调, 当网络断开,进行业务处理
+ net_manage.set_callback(tracker.net_callback)
+ # 设置服务端下行数据接收的回调,当服务端下发指令时,进行业务处理
+ server.set_callback(tracker.server_callback)
+
+ # 启动Tracker项目业务功能.
+ tracker.running()
+
+ if __name__ == "__main__":
+ # 主文件启动
+ main()
+ ```
+
+### Location module
+
+1. Function Description
+
+ Obtain current device location information through built-in or external GNSS, base station, and WiFi.
+
+2. Implementation principle
+
+- Built in GNSS enables and reads GNSS data through the `quecgnss` interface
+
+ ```python
+ class GNSS:
+ ...
+
+ def __internal_read(self):
+ log.debug("__internal_read start.")
+ # 开启GNSS
+ self.__internal_open()
+
+ # 清除串口缓存的GNSS历史数据
+ while self.__break == 0:
+ gnss_data = quecgnss.read(1024)
+ if gnss_data[0] == 0:
+ self.__break = 1
+ self.__break = 0
+
+ self.__gps_nmea_data_clean()
+ self.__gps_data_check_timer.start(2000, 1, self.__gps_data_check_callback)
+ cycle = 0
+ # 读取GNSS原始数据
+ while self.__break == 0:
+ gnss_data = quecgnss.read(1024)
+ if gnss_data and gnss_data[1]:
+ this_gps_data = gnss_data[1].decode() if len(gnss_data) > 1 and gnss_data[1] else ""
+ self.__reverse_gps_data(this_gps_data)
+ if self.__check_gps_valid():
+ self.__break = 1
+ cycle += 1
+ if cycle >= self.__retry:
+ if self.__break != 1:
+ self.__break = 1
+ if self.__break != 1:
+ utime.sleep(1)
+ self.__gps_data_check_timer.stop()
+ self.__break = 0
+
+ self.__gps_data_check_callback(None)
+ # 关闭GNSS
+ self.__internal_close()
+ log.debug("__internal_read %s." % ("success" if self.__get_gps_data() else "failed"))
+ return self.__get_gps_data()
+ ```
+
+- External GNSS reads GNSS data through UART serial port
+
+ ```python
+ class GNSS:
+ ...
+
+ def __external_read(self):
+ # 开启GNSS UART串口
+ self.__external_open()
+ log.debug("__external_read start")
+
+ # 清除串口缓存的GNSS历史数据
+ while self.__break == 0:
+ self.__gps_timer.start(50, 0, self.__gps_timer_callback)
+ signal = self.__external_retrieve_queue.get()
+ log.debug("[first] signal: %s" % signal)
+ if signal:
+ to_read = self.__external_obj.any()
+ log.debug("[first] to_read: %s" % to_read)
+ if to_read > 0:
+ self.__set_gps_data(self.__external_obj.read(to_read).decode())
+ self.__gps_timer.stop()
+ self.__break = 0
+
+ self.__gps_nmea_data_clean()
+ self.__gps_data_check_timer.start(2000, 1, self.__gps_data_check_callback)
+ cycle = 0
+ # 读取GNSS原始数据
+ while self.__break == 0:
+ self.__gps_timer.start(1500, 0, self.__gps_timer_callback)
+ signal = self.__external_retrieve_queue.get()
+ log.debug("[second] signal: %s" % signal)
+ if signal:
+ to_read = self.__external_obj.any()
+ log.debug("[second] to_read: %s" % to_read)
+ if to_read > 0:
+ self.__reverse_gps_data(self.__external_obj.read(to_read).decode())
+ if self.__check_gps_valid():
+ self.__break = 1
+
+ self.__gps_timer.stop()
+ cycle += 1
+ if cycle >= self.__retry:
+ self.__break = 1
+ if self.__break != 1:
+ utime.sleep(1)
+ self.__gps_data_check_timer.stop()
+ self.__break = 0
+
+ # To check GPS data is usable or not.
+ self.__gps_data_check_callback(None)
+ # 关闭GNSS串口
+ self.__external_close()
+ log.debug("__external_read %s." % ("success" if self.__get_gps_data() else "failed"))
+ return self.__get_gps_data()
+ ```
+
+- The base station positioning obtains information such as latitude, longitude, and accuracy through the cellLocator base station positioning interface
+
+ ```python
+ class CellLocator:
+ ...
+
+ def __read_thread(self):
+ loc_data = ()
+ try:
+ # 读取基站定位信息
+ loc_data = cellLocator.getLocation(
+ self.__serverAddr,
+ self.__port,
+ self.__token,
+ self.__timeout,
+ self.__profileIdx
+ )
+ loc_data = loc_data if isinstance(loc_data, tuple) and loc_data[0] and loc_data[1] else ()
+ except Exception as e:
+ sys.print_exception(e)
+ self.__queue.put(loc_data)
+ ```
+
+- WiFi positioning obtains information such as latitude, longitude, accuracy, and MAC address through the WiFi locator and WiFi Scan interfaces
+
+ ```python
+ class WiFiLocator:
+
+ def __init__(self, token):
+ self.__wifilocator = wifilocator(token) if wifilocator else None
+
+ def __read_thread(self):
+ loc_data = ()
+ try:
+ # 读取Wifi定位信息
+ loc_data = self.__wifilocator_obj.getwifilocator()
+ loc_data = loc_data if isinstance(loc_data, tuple) and loc_data[0] and loc_data[1] else ()
+ except Exception as e:
+ sys.print_exception(e)
+ self.__queue.put(loc_data)
+ ```
+
+### Battery module
+
+1. Function Description
+
+ Read the battery level and voltage, obtain the charging status of the battery, and notify the user of changes in the battery charging status through callback functions.
+
+2. Implementation principle
+
+- There are two ways to obtain battery voltage
+ + Obtain power supply voltage through the Power module;
+ + Obtain voltage through ADC for calculation.
+
+ ```python
+ class Battery(object):
+ ...
+
+ def __get_power_vbatt(self):
+ """Get vbatt from power"""
+ # 通过Power模块获取电源电压
+ return int(sum([Power.getVbatt() for i in range(100)]) / 100)
+
+ def __get_adc_vbatt(self):
+ """Get vbatt from adc"""
+ # 通过ADC获取电压进行计算
+ self.__adc.open()
+ utime.sleep_ms(self.__adc_period)
+ adc_list = list()
+ for i in range(self.__adc_period):
+ adc_list.append(self.__adc.read(self.__adc_num))
+ utime.sleep_ms(self.__adc_period)
+ adc_list.remove(min(adc_list))
+ adc_list.remove(max(adc_list))
+ adc_value = int(sum(adc_list) / len(adc_list))
+ self.__adc.close()
+ vbatt_value = adc_value * (self.__factor + 1)
+ return vbatt_value
+ ```
+
+- At present, only simulation calculation is provided for battery power, and a data relationship table of voltage and temperature corresponding to battery power is entered for fuzzy calculation
+
+ ```python
+ 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,
+ },
+ },
+ }
+ ```
+
+ ```python
+ class Battery:
+ ...
+
+ 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)
+ ```
+
+- The charging status of the battery is determined by the pin interruption and the voltage level of the acquisition pin to determine the current charging status of the device
+
+ ```python
+ class Battery:
+ ...
+
+ def __update_charge_status(self):
+ """Update Charge status by gpio status"""
+ if not self.__usb:
+ chrg_level = self.__chrg_gpio.read()
+ stdby_level = self.__stdby_gpio.read()
+ if chrg_level == 1 and stdby_level == 1:
+ # Not charge.
+ self.__charge_status = 0
+ elif chrg_level == 0 and stdby_level == 1:
+ # Charging.
+ self.__charge_status = 1
+ elif chrg_level == 1 and stdby_level == 0:
+ # Charge over.
+ self.__charge_status = 2
+ else:
+ raise TypeError("CHRG and STDBY cannot be 0 at the same time!")
+ else:
+ self.__usb_charge()
+
+ @property
+ def charge_status(self):
+ """Get charge status
+ Returns:
+ 0 - Not charged
+ 1 - Charging
+ 2 - Finished charging
+ """
+ self.__update_charge_status()
+ return self.__charge_status
+ ```
+
+### Low power module (power_manage)
+
+1. Function Description
+
+ Periodically wake up the device and perform business processing. After the business processing is completed, the device enters sleep mode.
+
+ The currently supported sleep modes are:
+
+ - autosleep;
+ - psm。
+
+2. Implementation principle
+
+ Set the corresponding sleep mode to put the device into sleep mode and wake it up through RTC timer
+
+ ```python
+ class PowerManage:
+ ...
+
+ def autosleep(self, val):
+ """Set device autosleep.
+
+ Args:
+ val (int): 0 - disable, 1 - enable.
+
+ Returns:
+ bool: True - success. False - failed.
+ """
+ return True if hasattr(pm, "autosleep") and val in (0, 1) and pm.autosleep(val) == 0 else False
+
+ def set_psm(self, mode=1, tau=None, act=None):
+ """Set device psm.
+
+ Args:
+ mode (int): 0 - disable psm, 1 - enable psm.
+ tau (int/None): tau seconds. When mode is 0, this value is None. (default: `None`)
+ act (int/None): act seconds. When mode is 0, this value is None. (default: `None`)
+
+ Returns:
+ bool: True - success. False - failed.
+ """
+ if not hasattr(pm, "set_psm_time") or not hasattr(pm, "get_psm_time"):
+ return False
+ if mode == 0:
+ return pm.set_psm_time(0)
+ else:
+ self.__init_tau(tau)
+ self.__init_act(act)
+ res = pm.set_psm_time(self.__tau_unit, self.__tau_time, self.__act_unit, self.__act_time)
+ log.info("set_psm_time: %s" % res)
+ if res:
+ get_psm_res = pm.get_psm_time()
+ log.debug("get_psm_res: %s" % str(get_psm_res))
+ if get_psm_res[0] == 1 and get_psm_res[1:] == [self.__tau_unit, self.__tau_time, self.__act_unit, self.__act_time]:
+ log.debug("PSM time equal set time.")
+ return res
+ ```
+
+### AliyunIot
+
+1. Function Description
+
+ Interact with Alibaba IoT IoT module through MQTT protocol.
+
+ - Device connection login platform
+ - Send object model data to the server
+ - Receive instructions issued by the server
+ - OTA upgrade
+
+ > Taking the Alibaba IoT MQTT protocol as an example, the actual application is developed based on the IoT platform and protocol that is actually connected, and the basic logical pattern is consistent.
+
+2. Implementation principle
+
+ Log in and exchange data according to the communication rules of Alibaba IoT IoT module through MQTT protocol.
+
+- Login
+
+ ```python
+ class AliIot:
+ ...
+
+ def connect(self):
+ res = -1
+ self.__server = "%s.%s" % (self.__product_key, self.__domain)
+ log.debug("self.__product_key: %s" % self.__product_key)
+ log.debug("self.__product_secret: %s" % self.__product_secret)
+ log.debug("self.__device_name: %s" % self.__device_name)
+ log.debug("self.__device_secret: %s" % self.__device_secret)
+ log.debug("self.__server: %s" % self.__server)
+ self.__server = aLiYun(self.__product_key, self.__product_secret, self.__device_name, self.__device_secret, self.__server)
+ res = self.__server.setMqtt(self.__device_name)
+ if res == 0:
+ self.__server.setCallback(self.__subscribe_callback)
+ res = self.__subscribe_topics()
+ if res == 0:
+ self.__server.start()
+ return res
+ ```
+
+- data uplink
+
+ ```python
+ class AliIot:
+ ...
+
+ def properties_report(self, data):.
+ # 属性上报
+ _timestamp = self.__timestamp
+ _id = self.__id
+ params = {key: {"value": val, "time": _timestamp} for key, val in data.items()}
+ properties = {
+ "id": _id,
+ "version": "1.0",
+ "sys": {
+ "ack": 1
+ },
+ "params": params,
+ "method": "thing.event.property.post",
+ }
+ pub_res = self.__server.publish(self.ica_topic_property_post, ujson.dumps(properties), qos=self.__qos) if self.__server else -1
+ return self.__get_post_res(_id) if pub_res is True else False
+
+ def event_report(self, event, data):
+ # 事件上报
+ _timestamp = self.__timestamp
+ _id = self.__id
+ params = {"value": data, "time": _timestamp}
+ properties = {
+ "id": _id,
+ "version": "1.0",
+ "sys": {
+ "ack": 1
+ },
+ "params": params,
+ "method": "thing.event.%s.post" % event,
+ }
+ pub_res = self.__server.publish(self.ica_topic_event_post.format(event), ujson.dumps(properties), qos=self.__qos) if self.__server else -1
+ return self.__get_post_res(_id) if pub_res is True else False
+ ```
+
+- data downlink
+
+ ```python
+ class AliIot:
+ ...
+
+ def __subscribe_callback(self, topic, data):
+ topic = topic.decode()
+ try:
+ data = ujson.loads(data)
+ except:
+ pass
+ log.debug("topic: %s, data: %s" % (topic, str(data)))
+
+ if topic.endswith("/post_reply"):
+ self.__put_post_res(data["id"], True if int(data["code"]) == 200 else False)
+ return
+ elif topic.endswith("/thing/ota/firmware/get_reply"):
+ self.__put_post_res(data["id"], True if int(data["code"]) == 200 else False)
+
+ if self.__callback and callable(self.__callback):
+ # 传入Tracker.server_callback中进行处理
+ self.__callback((topic, data))
+ ```
+
+- OTA upgrade
+
+ ```python
+ class AliIotOTA:
+ ...
+
+ def start(self):
+ # 开始OTA升级
+ if self.__module == self.__project_name:
+ self.__start_sota()
+ elif self.__module == self.__firmware_name:
+ self.__start_fota()
+ else:
+ return False
+ return True
+
+ def __start_fota(self):
+ log.debug("__start_fota")
+ fota_obj = fota()
+ url1 = self.__files[0]["url"]
+ url2 = self.__files[1]["url"] if len(self.__files) > 1 else ""
+ log.debug("start httpDownload")
+ if url2:
+ res = fota_obj.httpDownload(url1=url1, url2=url2, callback=self.__fota_callback) if fota_obj else -1
+ else:
+ res = fota_obj.httpDownload(url1=url1, callback=self.__fota_callback) if fota_obj else -1
+ log.debug("httpDownload res: %s" % res)
+ if res == 0:
+ self.__ota_timer.start(600 * 1000, 0, self.__ota_timer_callback)
+ fota_res = self.__fota_queue.get()
+ self.__ota_timer.stop()
+ return fota_res
+ else:
+ self.__server.ota_device_progress(-2, "Download File Failed.", module=self.__module)
+ return False
+ ```
+
+### UML
+
+There are dependency and inheritance relationships between various component objects in the project software code. We can use the locator product as the top-level object, which consists of several corresponding functions. This chapter establishes an association between it and the dependent component objects through UML class diagrams, as shown in the following figure.
+
+
+
+## Event Process Description
+
+### operation flow
+
+
+
+Business Process Description:
+
+1. Power on and start the device;
+2. Network (APN) configuration and (dial-up) connection, IoT platform configuration and connection, retry if failed;
+3. Device module startup detection and data collection;
+ - GNSS positioning module starts, waiting for positioning data;
+ - G-Sensor three-axis acceleration sensor module startup and calibration detection;
+ - LED indicator lights (network status/location status/charging status, etc.) start;
+ - Battery power collection and charging status detection;
+ - Alarm detection (overspeed detection/vibration detection/fence detection/low power detection, etc.).After the IoT platform is successfully connected, check if there is any historical data that needs to be reported;
+4. IoT platform connection successful, report current device information (location/alarm);
+5. If the IoT platform connection fails, the current device information (location/alarm) will be stored;
+6. The device has no task, enters low-power mode, and wakes up the device at a scheduled time for device information detection and reporting;
+ After the IoT platform is successfully connected, wait for the IoT platform to issue command information;
+7. Interpretation of instruction information.
+ - Device control instructions, such as modifying device business parameters, controlling device shutdown and restart, etc;
+ - Issue OTA upgrade instructions to perform OTA upgrade;
+ - Device information query command, respond to device information.
+
+### System initialization process
+
+
+
+1. Initialization of basic functional modules, low-power management, configuration parameters, battery, historical files, positioning, sensors;
+2. Initialize the IoT platform client module, Alibaba IoT or ThingsBoard platform or private service platform (GT06, JT/T808, etc.);
+3. Initialize the core business module (Tracker), add each functional module to the Tracker object through the `add_module` interface, and then register the `Tracker.server_callback` in the Server object to receive downstream message instructions from the server.
\ No newline at end of file
diff --git a/docs/Application_guide/zh/media/solutions/DTU-EG912U/DTU-components-4.png b/docs/Application_guide/zh/media/solutions/DTU-EG912U/DTU-components-4.png
new file mode 100644
index 0000000000000000000000000000000000000000..bd8a07483c3e7862c43f95abce942fe546f330ef
Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/DTU-EG912U/DTU-components-4.png differ
diff --git a/docs/Application_guide/zh/media/solutions/DTU-EG912U/DTU.png b/docs/Application_guide/zh/media/solutions/DTU-EG912U/DTU.png
new file mode 100644
index 0000000000000000000000000000000000000000..fcff7cf89819d519a246056b986b9670e958c413
Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/DTU-EG912U/DTU.png differ
diff --git a/docs/Application_guide/zh/media/solutions/DTU-EG912U/DTU_application_areas.jpg b/docs/Application_guide/zh/media/solutions/DTU-EG912U/DTU_application_areas.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..6a089140e5a14c89b8aa6204396376da97849ef3
Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/DTU-EG912U/DTU_application_areas.jpg differ
diff --git a/docs/Application_guide/zh/media/solutions/DTU-EG912U/DTU_application_areas.png b/docs/Application_guide/zh/media/solutions/DTU-EG912U/DTU_application_areas.png
new file mode 100644
index 0000000000000000000000000000000000000000..6a089140e5a14c89b8aa6204396376da97849ef3
Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/DTU-EG912U/DTU_application_areas.png differ
diff --git a/docs/Application_guide/zh/media/solutions/DTU-EG912U/EG912U.png b/docs/Application_guide/zh/media/solutions/DTU-EG912U/EG912U.png
new file mode 100644
index 0000000000000000000000000000000000000000..52f77c7272168ef6c39a888797a8d4fed4588832
Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/DTU-EG912U/EG912U.png differ
diff --git a/docs/Application_guide/zh/media/solutions/DTU-EG912U/EG912U1.png b/docs/Application_guide/zh/media/solutions/DTU-EG912U/EG912U1.png
new file mode 100644
index 0000000000000000000000000000000000000000..8f7b5d99aa90acdeda4876e03a2cd10768c04577
Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/DTU-EG912U/EG912U1.png differ
diff --git a/docs/Application_guide/zh/media/solutions/DTU-EG912U/EVB_link.png b/docs/Application_guide/zh/media/solutions/DTU-EG912U/EVB_link.png
new file mode 100644
index 0000000000000000000000000000000000000000..00727a602a84b37f3db29842639c4b999b877b15
Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/DTU-EG912U/EVB_link.png differ
diff --git a/docs/Application_guide/zh/media/solutions/DTU-EG912U/EVB_link1.png b/docs/Application_guide/zh/media/solutions/DTU-EG912U/EVB_link1.png
new file mode 100644
index 0000000000000000000000000000000000000000..23683c529a1a5059bdf805c1517e002632b88501
Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/DTU-EG912U/EVB_link1.png differ
diff --git a/docs/Application_guide/zh/media/solutions/DTU-EG912U/cloud_down.png b/docs/Application_guide/zh/media/solutions/DTU-EG912U/cloud_down.png
new file mode 100644
index 0000000000000000000000000000000000000000..152741449a4c2785e61cf9f8fad945f3feea7802
Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/DTU-EG912U/cloud_down.png differ
diff --git a/docs/Application_guide/zh/media/solutions/DTU-EG912U/cloud_up.png b/docs/Application_guide/zh/media/solutions/DTU-EG912U/cloud_up.png
new file mode 100644
index 0000000000000000000000000000000000000000..4bc1d774051009c24fb7f8bcc7f6222c48efdd70
Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/DTU-EG912U/cloud_up.png differ
diff --git a/docs/Application_guide/zh/media/solutions/DTU-EG912U/debug_log.png b/docs/Application_guide/zh/media/solutions/DTU-EG912U/debug_log.png
new file mode 100644
index 0000000000000000000000000000000000000000..f56e908927718dacf402095c07180bc33d70651c
Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/DTU-EG912U/debug_log.png differ
diff --git a/docs/Application_guide/zh/media/solutions/DTU-EG912U/debug_log_down_data.png b/docs/Application_guide/zh/media/solutions/DTU-EG912U/debug_log_down_data.png
new file mode 100644
index 0000000000000000000000000000000000000000..b020bdacebfc014c0b76610e9d7e1d712e196a33
Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/DTU-EG912U/debug_log_down_data.png differ
diff --git a/docs/Application_guide/zh/media/solutions/DTU-EG912U/debugview.png b/docs/Application_guide/zh/media/solutions/DTU-EG912U/debugview.png
new file mode 100644
index 0000000000000000000000000000000000000000..ceb61c02b8301368c4c8c8d36229797cc8f9248e
Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/DTU-EG912U/debugview.png differ
diff --git a/docs/Application_guide/zh/media/solutions/DTU-EG912U/dtu_init2.png b/docs/Application_guide/zh/media/solutions/DTU-EG912U/dtu_init2.png
new file mode 100644
index 0000000000000000000000000000000000000000..a1ec4f2fe1f4e25e805c3f939c21919d991a6e6b
Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/DTU-EG912U/dtu_init2.png differ
diff --git a/docs/Application_guide/zh/media/solutions/DTU-EG912U/flow.png b/docs/Application_guide/zh/media/solutions/DTU-EG912U/flow.png
new file mode 100644
index 0000000000000000000000000000000000000000..f5a21e7505b0973f7ee1083fdeb9f671783385c4
Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/DTU-EG912U/flow.png differ
diff --git a/docs/Application_guide/zh/media/solutions/DTU-EG912U/mqtt_config.png b/docs/Application_guide/zh/media/solutions/DTU-EG912U/mqtt_config.png
new file mode 100644
index 0000000000000000000000000000000000000000..9d81ec4e940c358fdf410a062923c5c542c29b0c
Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/DTU-EG912U/mqtt_config.png differ
diff --git a/docs/Application_guide/zh/media/solutions/DTU-EG912U/qcom_down.png b/docs/Application_guide/zh/media/solutions/DTU-EG912U/qcom_down.png
new file mode 100644
index 0000000000000000000000000000000000000000..e5e661ad34343b1496497e97630d0e7ca78eb4e4
Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/DTU-EG912U/qcom_down.png differ
diff --git a/docs/Application_guide/zh/media/solutions/DTU-EG912U/qcom_test.png b/docs/Application_guide/zh/media/solutions/DTU-EG912U/qcom_test.png
new file mode 100644
index 0000000000000000000000000000000000000000..69f9bc5177a6a1c31ad03be86802bb6e83802b43
Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/DTU-EG912U/qcom_test.png differ
diff --git a/docs/Application_guide/zh/media/solutions/DTU-EG912U/qpycom_add file.png b/docs/Application_guide/zh/media/solutions/DTU-EG912U/qpycom_add file.png
new file mode 100644
index 0000000000000000000000000000000000000000..3016d9c9c44c44a0f505311549199a1972aad1d7
Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/DTU-EG912U/qpycom_add file.png differ
diff --git a/docs/Application_guide/zh/media/solutions/DTU-EG912U/qpycom_port.png b/docs/Application_guide/zh/media/solutions/DTU-EG912U/qpycom_port.png
new file mode 100644
index 0000000000000000000000000000000000000000..f44cbd4a68956e2ad868961b4d93ed13425acec2
Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/DTU-EG912U/qpycom_port.png differ
diff --git a/docs/Application_guide/zh/media/solutions/DTU-EG912U/qpycom_proj.png b/docs/Application_guide/zh/media/solutions/DTU-EG912U/qpycom_proj.png
new file mode 100644
index 0000000000000000000000000000000000000000..449d64140e6b9c766b2af82c045ea3488d331146
Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/DTU-EG912U/qpycom_proj.png differ
diff --git a/docs/Application_guide/zh/media/solutions/DTU-EG912U/qpycom_proj2.png b/docs/Application_guide/zh/media/solutions/DTU-EG912U/qpycom_proj2.png
new file mode 100644
index 0000000000000000000000000000000000000000..1958ec0a5d4b64bb22bc29d1bd00252e65be1d74
Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/DTU-EG912U/qpycom_proj2.png differ
diff --git a/docs/Application_guide/zh/media/solutions/DTU-EG912U/qpycom_run2.png b/docs/Application_guide/zh/media/solutions/DTU-EG912U/qpycom_run2.png
new file mode 100644
index 0000000000000000000000000000000000000000..37e530548557935773623e2320223216cd2eb456
Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/DTU-EG912U/qpycom_run2.png differ
diff --git a/docs/Application_guide/zh/media/solutions/DTU-EG912U/repl_logs.png b/docs/Application_guide/zh/media/solutions/DTU-EG912U/repl_logs.png
new file mode 100644
index 0000000000000000000000000000000000000000..785382aef1fe3cea174d9108d1807edef2dbb84a
Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/DTU-EG912U/repl_logs.png differ
diff --git a/docs/Application_guide/zh/media/solutions/DTU-EG912U/system_config.png b/docs/Application_guide/zh/media/solutions/DTU-EG912U/system_config.png
new file mode 100644
index 0000000000000000000000000000000000000000..68ddee6d7a4494210cac1d1380a4d1ce9aa09a32
Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/DTU-EG912U/system_config.png differ
diff --git a/docs/Application_guide/zh/sidebar.yaml b/docs/Application_guide/zh/sidebar.yaml
index eae1de20624669dd337c6ab7bd8f1872458b2a8f..af948e8d1cbdfe67bad311bc187cdc5dcd8141a2 100644
--- a/docs/Application_guide/zh/sidebar.yaml
+++ b/docs/Application_guide/zh/sidebar.yaml
@@ -333,6 +333,20 @@ items:
file: solutions/SensorHub/quick_start.md
- label: 软件设计讲解
file: solutions/SensorHub/software_design.md
+ - label: DTU(基于EG912U核心板)
+ file: solutions/DTU-EG912U/README.md
+ items:
+ - label: 开发资源汇总
+ file: solutions/DTU-EG912U/dev_resources.md
+ - label: 快速上手
+ file: solutions/DTU-EG912U/quick_start.md
+ items:
+ - label: 基于TCP协议设备开发
+ file: solutions/DTU-EG912U/tcp_demo.md
+ - label: 基于MQTT协议设备开发
+ file: solutions/DTU-EG912U/mqtt_demo.md
+ - label: 软件设计讲解
+ file: solutions/DTU-EG912U/software_design.md
- label: 公网对讲机
file: solutions/poc/README.md
items:
@@ -342,6 +356,15 @@ items:
file: solutions/poc/quick_start.md
- label: 软件设计讲解
file: solutions/poc/software_design.md
+ - label: 智能定位器
+ file: solutions/tracker/README.md
+ items:
+ - label: 开发资源汇总
+ file: solutions/tracker/dev_resources.md
+ - label: 快速上手
+ file: solutions/tracker/quick_start.md
+ - label: 软件设计讲解
+ file: solutions/tracker/software_design.md
- label: HeliosSDK
file: helios-sdk/README.md
items:
diff --git a/docs/Application_guide/zh/solutions/DTU-EG912U/README.md b/docs/Application_guide/zh/solutions/DTU-EG912U/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..04753f8736a2f0186d4495365681fddf31b630e3
--- /dev/null
+++ b/docs/Application_guide/zh/solutions/DTU-EG912U/README.md
@@ -0,0 +1,21 @@
+# 基于 EG912U 核心版 DTU
+
+基于 EG912U 核心版 DTU,支持 4G,可实现串口与 4G(CAT1)的数据互传,相比于传统 2G/3G 网络,覆盖更广、速率更快、延时更低。开发方便快捷,支持透传,支持 Python 二次开发。体型小巧安装方便,可使本产品应用于各种行业和复杂场景满足通信数传的需求,如电网、交通、消防、工业生产、气象环境、农业、矿产等等。
+
+**功能列表**:
+
+- 支持Mqtt透明传输
+- 支持TCP/UDP透明传输
+- 支持4G全网通
+- 支持Python语言二次开发
+
+ **产品图示**:
+
+
+
+------
+
+- [开发资源汇总](./dev_resources.md)
+- [快速上手](./quick_start.md)
+- [软件设计讲解](./software_design.md)
+
diff --git a/docs/Application_guide/zh/solutions/DTU-EG912U/dev_resources.md b/docs/Application_guide/zh/solutions/DTU-EG912U/dev_resources.md
new file mode 100644
index 0000000000000000000000000000000000000000..39c2e17df6d38aa5905088ebba375960a61df876
--- /dev/null
+++ b/docs/Application_guide/zh/solutions/DTU-EG912U/dev_resources.md
@@ -0,0 +1,49 @@
+# 开发资源汇总
+
+本文档列出了 EG912U DTU 所需的硬件资源和相关文档。
+
+## 开发板资源
+
+型号:[EG912U 核心板](https://python.quectel.com/doc/Getting_started/zh/evb/bg-eg-core-evb.html)
+
+- 开发板文档
+ - [EG912U core board product specifications and user guide](https://python.quectel.com/wp-content/uploads/2024/11/EG912U%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)
+
+## 模块资源
+
+型号:[EG912U 核心板](https://python.quectel.com/doc/Getting_started/zh/evb/bg-eg-core-evb.html)
+
+- 规格书: [Quectel EG912U Series LTE Standard Module Product Specification Book](https://python.quectel.com/wp-content/uploads/2024/09/Quectel_EG912U-GL_LTE_Standard_%E6%A8%A1%E5%9D%97%E4%BA%A7%E5%93%81%E8%A7%84%E6%A0%BC%E4%B9%A6_V1.2.pdf)
+- 驱动:[QuecPython_USB_Driver_Win10_U_G](https://python.quectel.com/wp-content/uploads/2024/09/Quectel_Windows_USB_DriverU_V1.0.19.zip)
+
+## 配件资源
+
+- LTE 天线
+- Nano Sim 卡
+- Mini USB 数据线
+
+## 开发工具
+
+- QPYcom - QuecPython 调试工具
+ - 版本:V3.6.0
+ - 下载链接:[QPYcom](https://images.quectel.com/python/2022/12/QPYcom_V3.6.0.zip)
+- QCOM - 串口调试工具
+ - 版本:V1.6
+ - 下载链接:[Click to jump](https://python.quectel.com/wp-content/uploads/2024/09/QCOM_V1.6.zip)
+- VSCode - 代码编辑器
+ - 下载链接:[Click to jump](https://code.visualstudio.com/)
+
+- 固件版本: QPY_OCPU_BETA0002_EG912U_GLAA_FW
+ - 下载链接:[Click to jump](https://python.quectel.com/wp-content/uploads/2024/09/QPY_OCPU_BETA0002_EG912U_GLAA_FW.zip)
+
+## 实验源码
+
+- 版本:v1.0.0
+
+- Github 下载
+
+ ```shell
+ git clone https://github.com/QuecPython/solution-simple-DTU
+ cd solution-simple-DTU
+ ```
+
diff --git a/docs/Application_guide/zh/solutions/DTU-EG912U/mqtt_demo.md b/docs/Application_guide/zh/solutions/DTU-EG912U/mqtt_demo.md
new file mode 100644
index 0000000000000000000000000000000000000000..28dacf790960c348b6d01aa05d476789f73637e0
--- /dev/null
+++ b/docs/Application_guide/zh/solutions/DTU-EG912U/mqtt_demo.md
@@ -0,0 +1,148 @@
+# 基于MQTT协议设备开发
+
+## 修改配置文件
+
+工程配置文件路径:`code/dtu_config.json`。
+
+基于 TCP 私有服务器数据透传做如下配置:
+
+- 默认 `system_config.cloud` 配置项定义为 `"tcp"` 即 TCP 透传模式,系统会自行读取 `socket_private_cloud_config` 配置项。 此处改为 mqtt 协议模式。
+
+ ```python
+ {
+ "system_config": {
+ "cloud": "mqtt" # The mqtt transparent transmission mode is configured by default
+ }
+ }
+ ```
+
+- 本实验采用 MQTT 透传模式,用户需根据实际情况设置 `mqtt_private_cloud_config` 配置项中的 MQTT 服务器域名(*server*)、端口(*port*)、客户端id(*client_id*)以及订阅和发布主题等参数,如下。
+
+ ```python
+ {
+ "mqtt_private_cloud_config": {
+ "server": "mq.tongxinmao.com",
+ "port": 18830,
+ "client_id": "txm_1682300809",
+ "user": "",
+ "password": "",
+ "clean_session": true,
+ "qos": 0,
+ "keepalive": 60,
+ "subscribe": {"down": "/public/TEST/down"}, # Downlink data transparent topic
+ "publish": {"up": "/public/TEST/up"} # Uplink data transparent transmission topic
+ }
+ }
+ ```
+
+- `uart_config` 配置项是串口配置参数,默认是根据当前实验开发板做的配置,不可更改。如用户采用其他开发板则需要根据实际硬件进行配置。
+
+```python
+{
+ "uart_config": {
+ "port": 2, # Serial port number. Set this parameter based on the actual hardware configuration
+ "baudrate": 115200, # Baud rate
+ "bytesize": 8, # data bits
+ "parity": 0, # Parity check
+ "stopbits": 1, # stop bit
+ "flowctl": 0, # fluid control
+
+ }
+ }
+}
+```
+
+ 完整配置文件模版如下:
+
+```json
+{
+ "system_config": {
+ "cloud": "tcp"
+ },
+ "mqtt_private_cloud_config": {
+ "server": "mq.tongxinmao.com",
+ "port": 18830,
+ "client_id": "txm_1682300809",
+ "user": "",
+ "password": "",
+ "clean_session": true,
+ "qos": 0,
+ "keepalive": 60,
+ "subscribe": {"down": "/public/TEST/down"},
+ "publish": {"up": "/public/TEST/up"}
+ },
+ "socket_private_cloud_config": {
+ "domain": "112.31.84.164",
+ "port": 8305,
+ "timeout": 5,
+ "keep_alive": 5
+ },
+ "uart_config": {
+ "port": 2,
+ "baudrate": 115200,
+ "bytesize": 8,
+ "parity": 0,
+ "stopbits": 1,
+ "flowctl": 0,
+ "rs485_config": {
+ "gpio_num": 28,
+ "direction": 0
+ }
+ }
+}
+```
+
+参数说明:
+
+- `system_config.config`: 指定当前使用的私有云类型。目前支持tcp和mqtt。
+- `mqtt_private_cloud_config`: MQTT私有云配置。
+- `socket_private_cloud_config`: tcp私有云配置。
+- `uart_config`:串口参数配置。
+
+## 脚本导入并运行
+
+ 下载安装 **QPYCom** 工具后使用该工具下载脚本至 QuecPython 模组。
+
+> 💡 **Tips**
+>
+> QPYCom 安装和使用教程:https://python.quectel.com/doc/Application_guide/zh/dev-tools/QPYcom/index.html
+
+## 业务调试
+
+**查看 REPL 交互口日志**
+
+程序运行后,在 REPL 交互页面可以看到日志输出如下图所示。 DTU服务中有2个线程处理数据,一个是用于检测读取串口数据并转发数据给云端,一个是检测云端下行数据透传给串口,如下图所示。 
+
+**上行数据透传**
+
+使用串口调试工具模拟mcu给模组发送上行数据。
+
+- 在`Input String`输入框中输入`hello world!`字符串。
+- 点击`Send Command`按钮通过串口发送数据。
+
+
+
+ DTU接收串口数据,直接透传至mqtt云端。
+
+
+
+云端接收上行数据日志
+
+ps:通信猫云平台仅用于测试,可根据实际需要更换云平台
+
+
+
+**下行数据透传**
+
+云端发送下行数据。
+
+- 设置云端下行数据主题(与DTU应用配置的订阅主题一致)。
+- 输入下行数据。
+- 发布。
+
+
+
+使用QCOM观察串行调试工具,模拟mcu接收模块下行数据。
+
+
+
diff --git a/docs/Application_guide/zh/solutions/DTU-EG912U/quick_start.md b/docs/Application_guide/zh/solutions/DTU-EG912U/quick_start.md
new file mode 100644
index 0000000000000000000000000000000000000000..ac4bb8f9c5bf8c7e29f6ef430b76678e12fe7fbc
--- /dev/null
+++ b/docs/Application_guide/zh/solutions/DTU-EG912U/quick_start.md
@@ -0,0 +1,39 @@
+# 快速上手
+
+## 硬件准备
+
+- 一台windows电脑,推荐使用win10系统
+- 一套 [EG912U Core Board](https://python.quectel.com/doc/Getting_started/zh/evb/bg-eg-core-evb.html) 开发板
+- 一张 Nano sim 卡
+- 一根 天线
+- 一根 Mini USB 数据线
+- 一根 USB 转 TTL 模块
+
+## 环境搭建
+
+- 下载并安装驱动:[QuecPython_USB_Driver_Win10_U_G](https://python.quectel.com/wp-content/uploads/2024/09/Quectel_Windows_USB_DriverU_V1.0.19.zip)
+- 下载并安装 [VSCode](https://code.visualstudio.com/)
+- 下载 [QPYCom](https://python.quectel.com/wp-content/uploads/2024/09/QPYcom_V3.6.0.zip) 并解压
+- 下载固件包 [QPY_OCPU_BETA0002_EG912U_GLAA_FW](https://python.quectel.com/wp-content/uploads/2024/09/QPY_OCPU_BETA0002_EG912U_GLAA_FW.zip)。([使用 QPYcom 烧录固件](https://python.quectel.com/doc/Application_guide/zh/dev-tools/QPYcom/qpycom-dw.html))
+- [下载源码](https://github.com/QuecPython/solution-simple-DTU)。
+
+## 硬件连接
+
+按照一下图示进行硬件连接:
+
+
+
+
+
+
+
+1.MAIN端口连接到天线。
+2.TX(EG912U开发板)连接RX(USB转TTL模块);RX(EG912U开发板)连接TX(USB转TTL模块);GND(EG912U开发板)连接到公共接地中的GND(USB到TTL模块)。
+3.插入Nano Sim卡。
+4.使用USB数据线连接到计算机,使用USB转TTL模块连接到计算机。
+
+## 设备开发
+
+- [基于tcp协议设备开发](./tcp_demo.md)
+- [基于mqtt协议设备开发](./mqtt_demo.md)
+
diff --git a/docs/Application_guide/zh/solutions/DTU-EG912U/software_design.md b/docs/Application_guide/zh/solutions/DTU-EG912U/software_design.md
new file mode 100644
index 0000000000000000000000000000000000000000..2239c42e6796e6fbc2a278fc3fbb269a6573d332
--- /dev/null
+++ b/docs/Application_guide/zh/solutions/DTU-EG912U/software_design.md
@@ -0,0 +1,188 @@
+# 软件设计讲解
+
+## 应用流程图
+
+ 一般了解一个程序代码大多从启动部分开始,这里也采取这种方式,先寻找程序的启动源头。本例程,一般的程序启动顺序如下图所示:
+
+
+
+整体上业务可以总结为如下流程:
+
+1. 启动喂狗线程(华系列 4G DTU 载有硬件狗)
+2. 初始化 DTU 对象后,读取系统配置
+3. 初始化串口外设
+4. 检查网络状态
+5. 初始化云端配置和消息队列
+6. 启动数据上下、下行业务线程
+
+> 💡 基本原理:本 DTU 采用 **多线程 + 消息队列** 实现串口和云端数据的上下行转发。其中,上行线程(Uplink data thread)用于读取串口数据并发送至云端;下行线程(Downlink data thread)读取消息队列中的云端数据通过串口转发;消息队列用于缓存云端的下行数据。
+
+## 目录结构
+
+- usr
+ - `_main.py`:主脚本
+ - `dtu_config.json`:配置文件
+ - `dtu.py`:DTU 模型对象
+ - `logging.py`:日志模块
+ - `cloud_abc.py`:云对象模型抽象基类
+ - `mqttIot.py`:Mqtt 云对象模型实现
+ - `network.py`:网络
+ - `serial.py`:串口模型对象实现
+ - `socketIot.py`:Socket 云对象模型实现
+ - `threading.py`:线程、队列和互斥锁
+ - `utils.py`:工具类
+
+## API 说明
+
+### 对象模型
+
+ 本方案中定义了多个对象模型,其中主要有 `DTU` 对象模型、云对象模型(`CloudABS`)和串口对象模型(`Serial`)。
+
+#### DTU对象模型
+
+DTU类在 `dtu.py` 模块中定义,主要用于初始化串行端口、云以及上下游数据服务。
+
+实现MQTT协议的云通信功能,提供连接、订阅、发布和监控功能。云对象初始化如下:
+
+```python
+self.cloud = MqttIot(
+ mqtt_config['client_id'],
+ mqtt_config['server'],
+ port=mqtt_config['port'],
+ user=mqtt_config['user'],
+ password=mqtt_config['password'],
+ keepalive=mqtt_config['keepalive'],
+ clean_session=mqtt_config['clean_session'],
+ qos=mqtt_config['qos'],
+ subscribe_topic=mqtt_config['subscribe'],
+ publish_topic=mqtt_config['publish'],
+ queue=self.queue,
+ error_trans=True
+)
+```
+
+实现TCP/UDP协议的云通信功能,提供连接、发送、接收和监听功能。socket对象初始化如下:
+
+```python
+self.cloud = SocketIot(
+ ip_type=socket_config['ip_type'],
+ keep_alive=socket_config['keep_alive'],
+ domain=socket_config['domain'],
+ port=socket_config['port'],
+ queue=self.queue,
+ error_trans=True
+)
+```
+
+`up_transaction_handler` 方法: 上行数据传输业务线程的入口函数。
+
+`down_transaction_handler` 方法: 行数据传输业务线程的入口函数。
+
+```python
+def down_transaction_handler(self):
+ while True:
+ topic, data = self.cloud.recv()
+ logger.info('down transfer msg: {}'.format(data))
+ self.serial.write(data)
+
+def up_transaction_handler(self):
+ while True:
+ data = self.serial.read(1024, timeout=100)
+ if data:
+ logger.info('up transfer msg: {}'.format(data))
+ self.cloud.send(data)
+```
+
+`run方法:启动业务操作,包括基于配置文件创建串行端口和云对象,以及为上下游行业创建业务数据处理线程。
+
+#### Serial object model
+
+- In the `serial.py` module, the serial port model class `Serial` is defined. This class is mainly used to implement the read and write operations of the serial port. The main interfaces include:`Serial`
+ - `__init__`: Serial port initialization.
+ - `open`:Open the serial port.
+ - `close`:Shut down the serial port.
+ - `write`:Serial port write.
+ - `read`:Serial port read.
+
+Example of serial port::
+
+```python
+from usr.serial import Serial
+
+# init Serial object
+s = Serial(port=2, baudrate=115200, bytesize=8, parity=0, stopbits=1, flowctl=0, rs485_config=None)
+# open serial
+s.open()
+
+# serial write method
+s.write(b"hello world!")
+
+# serial read method
+recv_data = s.read()
+print(recv_data)
+```
+
+## 业务代码讲解
+
+数传业务主要在 DTU 类(`dtu.py`)中实现,该类主要用于管理串口、云、以及数据的上下行业务。
+
+DTU 对象在主脚本中通过调用 `run` 方法来开启整个 DTU 业务,其中该方法主要用于创建并运行两个线程,分别是上行数据处理线程(线程工作函数是 `up_transaction_handler`)和下行数据处理线程(线程工作函数是 `down_transaction_handler`)。在线程函数中分别通过两个 property 属性来获取对应的串口对象和云对象。其中串口对象属性是 `serial`,线程在调用该属性时即刻创建并打开配置的串口对象提供读写接口。其中云对象属性是 `cloud`,线程在调用该属性时即刻创建并连云对象提供接收和发送接口。
+
+函数调用时序图:
+
+```mermaid
+sequenceDiagram
+Title: Device data transmit-processing timing
+
+
+participant cloud as cloud
+participant dtu as DTU
+participant serial as Serial
+
+loop down_transaction_handler thread
+cloud ->> dtu: cloud.recv
+dtu ->> serial: Serial.write
+end
+
+loop up_transaction_handler thread
+serial ->> dtu: Serial.read
+dtu ->> cloud: cloud.send
+end
+```
+
+ 上行数据处理线程函数 `DTU.up_transaction_handler` 实现如下:
+
+```python
+class DTU(object):
+
+ # ...
+
+ def up_transaction_handler(self):
+ while True:
+ data = self.serial.read(1024, timeout=100)
+ if data:
+ logger.info('up transfer msg: {}'.format(data))
+ self.cloud.send(data)
+
+ # ...
+```
+
+ `up_transaction_handler`函数按照 1KB 的 buffer 读取串口数据(用户可以自行调整buffer大小),并格式化消息后通过 `CloudABC.send` 接口发送数据至云端。用户继承 `CloudABC` 并自定义云对象并实现 。
+
+ 下行数据处理线程函数 `down_transaction_handler` 实现如下:
+
+```python
+class DTU(object):
+
+ # ...
+
+ def down_transaction_handler(self):
+ while True:
+ topic, data = self.cloud.recv()
+ logger.info('down transfer msg: {}'.format(data))
+ self.serial.write(data)
+
+ # ...
+```
+
+ `down_transaction_handler` 函数通过调用 `CloudABC.recv` 来获取下行消息,并通过 `Serial.write` 转发消息。
\ No newline at end of file
diff --git a/docs/Application_guide/zh/solutions/DTU-EG912U/tcp_demo.md b/docs/Application_guide/zh/solutions/DTU-EG912U/tcp_demo.md
new file mode 100644
index 0000000000000000000000000000000000000000..4913e07a0fc60ad2275e81cf65a4d17ba35c7cd0
--- /dev/null
+++ b/docs/Application_guide/zh/solutions/DTU-EG912U/tcp_demo.md
@@ -0,0 +1,113 @@
+# 基于TCP协议设备开发
+
+## 修改配置文件
+
+工程配置文件路径:`code/dtu_config.json`。
+
+基于 TCP 私有服务器数据透传做如下配置:
+
+打开 TCP 服务器 :http://tt.ai-thinker.com:8000/ttcloud
+
+- 默认 `system_config.cloud` 配置项定义为 `"tcp"` 即 TCP 透传模式,系统会自行读取 `socket_private_cloud_config` 配置项。
+
+ ```python
+ {
+ "system_config": {
+ "cloud": "tcp" # The tcp transparent mode is configured by default
+ }
+ }
+ ```
+
+- 本实验采用 TCP 透传模式,用户需根据实际情况设置 `socket_private_cloud_config` 配置项中的 TCP 服务器域名(*domain*)和端口(*port*)。
+
+ ```python
+ {
+ "socket_private_cloud_config": {
+ "domain": "36.137.226.30", # ip
+ "port": 42298, # port number
+ "timeout": 5, # time-out period (unit: s)
+ "keep_alive": 1 # heartbeat cycle (unit: s)
+ }
+ }
+ ```
+
+- `uart_config` 配置项是串口配置参数,默认是根据当前实验开发板做的配置,不可更改。如用户采用其他开发板则需要根据实际硬件进行配置。
+
+```python
+{
+ "uart_config": {
+ "port": 2, # Serial port number. Set this parameter based on the actual hardware configuration
+ "baudrate": 115200, # Baud rate
+ "bytesize": 8, # data bits
+ "parity": 0, # parity check
+ "stopbits": 1, # stop bit
+ "flowctl": 0, # fluid control
+ }
+}
+```
+
+ 完整配置文件模版如下:
+
+```json
+{
+ "system_config": {
+ "cloud": "tcp"
+ },
+ "mqtt_private_cloud_config": {
+ "server": "mq.tongxinmao.com",
+ "port": 18830,
+ "client_id": "txm_1682300809",
+ "user": "",
+ "password": "",
+ "clean_session": true,
+ "qos": 0,
+ "keepalive": 60,
+ "subscribe": {"down": "/public/TEST/down"},
+ "publish": {"up": "/public/TEST/up"}
+ },
+ "socket_private_cloud_config": {
+ "ip_type":"IPv4",
+ "domain": "36.137.226.30",
+ "port": "42298",
+ "keep_alive": 1
+ },
+ "uart_config": {
+ "port": 2,
+ "baudrate": 115200,
+ "bytesize": 8,
+ "parity": 0,
+ "stopbits": 1,
+ "flowctl": 0,
+ }
+}
+```
+
+参数说明:
+
+- `system_config.config`: 指定当前使用的私有云类型。目前支持tcp和mqtt。
+- `mqtt_private_cloud_config`: MQTT私有云配置。
+- `socket_private_cloud_config`: tcp私有云配置。
+- `uart_config`:串口参数配置。
+
+## 脚本导入并运行
+
+ 下载安装 **QPYCom** 工具后使用该工具下载脚本至 QuecPython 模组。
+
+> 💡 **Tips**
+>
+> QPYCom 安装和使用教程 :https://python.quectel.com/doc/Application_guide/zh/dev-tools/QPYcom/index.html
+
+## 业务调试
+
+程序运行后,在 REPL 交互页面可以看到日志输出如下图所示。
+
+左侧图示,我们使用 QCOM 模拟 MCU 打开用于透传的模组串口(即 USB 转 TTL 模块对应的 COM 口)。
+
+右侧图示,REPL 交互口输出的模组日志。
+
+使用串口工具 QCOM 模拟 MCU 串口上行数据,通过 DTU 透传至 TCP 回显服务器,再由回显服务器将相同数据通过 DTU 下行透传至 QCOM。
+
+
+
+ 本案例中采用的是 TCP 回显服务器,所以 QCOM 上行数据,经过 DTU 透传至 TCP 服务器接收到之后会立即按原路径下行。
+
diff --git a/docs/Application_guide/zh/solutions/DTU/README.md b/docs/Application_guide/zh/solutions/DTU/README.md
index 841e878c50a1d22dc8f560acebe010368b8eb638..5015c46f3bdce2696be87da74e1a26108a9e0656 100644
--- a/docs/Application_guide/zh/solutions/DTU/README.md
+++ b/docs/Application_guide/zh/solutions/DTU/README.md
@@ -16,11 +16,9 @@
-## 开发指南
+------
-[开发资源汇总](./dev_resources.md)
-
-[快速上手](./quick_start.md)
-
-[软件设计讲解](./software_design.md)
+- [开发资源汇总](./dev_resources.md)
+- [快速上手](./quick_start.md)
+- [软件设计讲解](./software_design.md)
diff --git a/docs/Application_guide/zh/solutions/DTU/mqtt_demo.md b/docs/Application_guide/zh/solutions/DTU/mqtt_demo.md
index 58bcef1333d4c06d1c9866e2bf9cd3bc18497775..2841ece7297694dab0957e7e0d44ec2e48b976e7 100644
--- a/docs/Application_guide/zh/solutions/DTU/mqtt_demo.md
+++ b/docs/Application_guide/zh/solutions/DTU/mqtt_demo.md
@@ -6,7 +6,7 @@
基于 TCP 私有服务器数据透传做如下配置:
-- 默认 `system_config.cloud` 配置项定义为 `"tcp"` 即 TCP 透传模式,系统会自行读取 `socket_private_cloud_config` 配置项。
+- 设置 `system_config.cloud` 配置项定义为 `"mqtt"` 即 MQTT 透传模式。
```python
{