From e491cdb48129752324c4e3764f99bd9203c56dec Mon Sep 17 00:00:00 2001
From: lgq <1015864684@qq.com>
Date: 星期二, 31 三月 2026 09:48:44 +0800
Subject: [PATCH] 1.新增VF205门禁机代码

---
 vf205_access/resource/image/accessCtrl.png                                         |    0 
 vf205_access/resource/image/wifi_dark.png                                          |    0 
 vf205_access/dxmodules/dxUart.js                                                   |  242 
 vf205_access/src/view/config/identityVerificationView.js                           |  185 
 vf205_access/.temp/zipFolder/VF105_V12/dxAudio/2.0.0.zip                           |    0 
 vf205_access/resource/image/userMgmt.png                                           |    0 
 vf205_access/resource/image/help.png                                               |    0 
 vf205_access/dxmodules/dxSqlite.js                                                 |   54 
 vf205_access/src/common/utils/utils.js                                             |  132 
 vf205_access/resource/image/light_close.png                                        |    0 
 vf205_access/dxmodules/dxPwm.js                                                    |  116 
 vf205_access/.temp/zipFolder/VF105_V12/dxEventBus/2.0.2.zip                        |    0 
 vf205_access/dxmodules/libJLReader.so                                              |    0 
 vf205_access/resource/image/faceError.png                                          |    0 
 vf205_access/dxmodules/libvbar-drv-soc.so                                          |    0 
 vf205_access/.temp/zipFolder/VF105_V12/dxWatchdog/1.0.1.zip                        |    0 
 vf205_access/.temp/zipFolder/VF105_V12/dxFacial/1.0.0.zip                          |    0 
 vf205_access/resource/image/eth_disable.png                                        |    0 
 vf205_access/resource/image/space.png                                              |    0 
 vf205_access/dxmodules/dxDriver.js                                                 |   81 
 vf205_access/dxmodules/dxNfc.js                                                    |  409 
 vf205_access/dxmodules/dxGpioKey.js                                                |   84 
 vf205_access/resource/CN/wav/recg_s.wav                                            |    0 
 vf205_access/dxmodules/libvbar-m-dxeid.so                                          |    0 
 vf205_access/resource/EN/wav/verify_300_f.wav                                      |    0 
 vf205_access/resource/EN/wav/verify_10x_f.wav                                      |    0 
 vf205_access/resource/image/mini_background.png                                    |    0 
 vf205_access/src/view/config/menu/deviceInfo/systemInfoView.js                     |   94 
 vf205_access/.temp/zipFolder/VF105_V12/dxEid/1.0.0.zip                             |    0 
 vf205_access/dxmodules/libyuv.so                                                   |    0 
 vf205_access/dxmodules/libvbar-b-dxface.so                                         |    0 
 vf205_access/dxmodules/libalc.so                                                   |    0 
 vf205_access/.temp/zipFolder/VF105_V12/dxNfcCard/1.0.0.zip                         |    0 
 vf205_access/resource/image/co2_f.png                                              |    0 
 vf205_access/resource/CN/wav/btn13.wav                                             |    0 
 vf205_access/resource/CN/wav/verify.wav                                            |    0 
 vf205_access/dxmodules/dxEid.js                                                    |   46 
 vf205_access/dxmodules/uiUtils.js                                                  |  292 
 vf205_access/resource/image/delete.png                                             |    0 
 vf205_access/.temp/zipFolder/VF105_V12/dxDisplay/2.0.0.zip                         |    0 
 vf205_access/resource/image/close.png                                              |    0 
 vf205_access/dxmodules/dxCameraCalibration.js                                      |  136 
 vf205_access/resource/image/user.png                                               |    0 
 vf205_access/resource/image/title_bg.png                                           |    0 
 vf205_access/.temp/dxide_debug.log                                                 |   11 
 vf205_access/src/view/config/menu/factoryTestView.js                               |   77 
 vf205_access/dxmodules/libvbar-drv-face.so                                         |    0 
 vf205_access/.temp/zipFolder/VF105_V12/dxPwm/1.0.0.zip                             |    0 
 vf205_access/dxmodules/vgUartWorker.js                                             |  166 
 vf205_access/resource/image/lock.png                                               |    0 
 vf205_access/resource/CN/wav/recognition_s.wav                                     |    0 
 vf205_access/resource/image/success_fill.png                                       |    0 
 vf205_access/dxmodules/libvbar-m-key.so                                            |    0 
 vf205_access/resource/image/face.png                                               |    0 
 vf205_access/resource/image/register.png                                           |    0 
 vf205_access/.temp/zipFolder/VF105_V12/dxSqliteDB/1.0.0.zip                        |    0 
 vf205_access/resource/CN/wav/recognition.wav                                       |    0 
 vf205_access/resource/CN/wav/user2.wav                                             |    0 
 vf205_access/.temp/zipFolder/VF105_V12/dxWatchdog/1.0.0.zip                        |    0 
 vf205_access/.temp/zipFolder/VF105_V12/dxCapturer/1.0.0.zip                        |    0 
 vf205_access/dxmodules/libvbar-m-capturer.so                                       |    0 
 vf205_access/resource/CN/wav/door_open.wav                                         |    0 
 vf205_access/resource/image/faceRec2.png                                           |    0 
 vf205_access/resource/image/grey_btn.png                                           |    0 
 vf205_access/src/view/config/menu/helpView.js                                      |   41 
 vf205_access/dxmodules/libvbar-m-dxmap.so                                          |    0 
 vf205_access/resource/image/enter_b.png                                            |    0 
 vf205_access/resource/EN/wav/verify_400_s.wav                                      |    0 
 vf205_access/resource/image/sysSettings.png                                        |    0 
 vf205_access/resource/image/config_btn.png                                         |    0 
 vf205_access/dxmodules/libvbar-m-channel.so                                        |    0 
 vf205_access/resource/image/back_2.png                                             |    0 
 vf205_access/resource/image/user_s.png                                             |    0 
 vf205_access/resource/image/recQuery.png                                           |    0 
 vf205_access/.temp/zipFolder/VF105_V12/dxHttpClient/2.0.4.zip                      |    0 
 vf205_access/src/view/config/menu/deviceInfo/dataCapacityInfoView.js               |  118 
 vf205_access/resource/CN/wav/btn21.wav                                             |    0 
 vf205_access/resource/EN/wav/recognition.wav                                       |    0 
 vf205_access/resource/CN/wav/read.wav                                              |    0 
 vf205_access/.temp/zipFolder/VF105_V12/dxNfc/1.0.0.zip                             |    0 
 vf205_access/src/view/config/menu/systemSetting/passwordOpenDoorSettingView.js     |  144 
 vf205_access/resource/image/rectangle.png                                          |    0 
 vf205_access/resource/image/mqtt_dark.png                                          |    0 
 vf205_access/dxmodules/mqttWorker.js                                               |   64 
 vf205_access/dxmodules/uiStyle.js                                                  |  149 
 vf205_access/.temp/zipFolder/VF105_V12/dxHttpServer/1.0.1.zip                      |    0 
 vf205_access/resource/image/ethernet.png                                           |    0 
 vf205_access/src/view/config/menu/dockingSetting.js                                |  135 
 vf205_access/src/config.json                                                       |  115 
 vf205_access/.temp/md5s.json                                                       |  330 
 vf205_access/src/view/config/menu/systemSetting/passwordManagementView.js          |  115 
 vf205_access/dxmodules/libvbar-m-dxcapturer_calibration.so                         |    0 
 vf205_access/resource/langPack.js                                                  |  664 +
 vf205_access/resource/image/mini_password.png                                      |    0 
 vf205_access/resource/image/ph3_s.png                                              |    0 
 vf205_access/resource/image/doorControl.png                                        |    0 
 vf205_access/.temp/zipFolder/VF105_V12/dxOs/1.0.0.zip                              |    0 
 vf205_access/.temp/md5snew.json                                                    |  330 
 vf205_access/dxmodules/libvbar-m-dxhttp.so                                         |    0 
 vf205_access/resource/image/app.png                                                |    0 
 vf205_access/resource/CN/wav/emergency_s.wav                                       |    0 
 vf205_access/.temp/zipFolder/VF105_V12/dxSqlite/1.0.0.zip                          |    0 
 vf205_access/.temp/zipFolder/VF105_V12/dxHttpClient/2.0.3.zip                      |    0 
 vf205_access/dxmodules/dxConfig.js                                                 |  140 
 vf205_access/.temp/zipFolder/VF105_V12/dxConfig/2.0.0.zip                          |    0 
 vf205_access/resource/EN/wav/read.wav                                              |    0 
 vf205_access/dxmodules/uiLabel.js                                                  |   34 
 vf205_access/.temp/zipFolder/VF105_V12/dxCommon/1.0.1.zip                          |    0 
 vf205_access/resource/EN/wav/stranger.wav                                          |    0 
 vf205_access/dxmodules/dxStd.js                                                    |  399 
 vf205_access/.temp/zipFolder/VF105_V12/dxDisplay/1.0.0.zip                         |    0 
 vf205_access/.temp/zipFolder/VF105_V12/dxCapturer/1.0.1.zip                        |    0 
 vf205_access/src/service/gpiokeyService.js                                         |   52 
 vf205_access/resource/image/factoryTest.png                                        |    0 
 vf205_access/src/screen.js                                                         | 1470 +++
 vf205_access/src/view/config/menu/systemSetting/faceRecognitionSettingView.js      |  167 
 vf205_access/dxmodules/libvbar-drv-capturer.so                                     |    0 
 vf205_access/.temp/zipFolder/VF105_V12/dxAlsa/1.0.0.zip                            |    0 
 vf205_access/.temp/zipFolder/VF105_V12/dxWorkerPool/2.0.0.zip                      |    0 
 vf205_access/.temp/zipFolder/VF105_V12/dxEventBus/2.0.0.zip                        |    0 
 vf205_access/.temp/zipFolder/VF105_V12/dxHttp/1.0.0.zip                            |    0 
 vf205_access/resource/CN/wav/control_f.wav                                         |    0 
 vf205_access/resource/CN/wav/network.wav                                           |    0 
 vf205_access/resource/image/down.png                                               |    0 
 vf205_access/dxmodules/libvbar-m-common.so                                         |    0 
 vf205_access/dxmodules/uiList.js                                                   |   45 
 vf205_access/README_CN.md                                                          |   19 
 vf205_access/resource/CN/wav/btn22.wav                                             |    0 
 vf205_access/src/view/config/menu/recordQuery/recordQueryDetailView.js             |  227 
 vf205_access/resource/image/select_arrow.png                                       |    0 
 vf205_access/resource/image/localUser.png                                          |    0 
 vf205_access/.temp/zipFolder/VF105_V12/dxGpio/1.0.0.zip                            |    0 
 vf205_access/src/services.js                                                       |  109 
 vf205_access/resource/image/background.jpg                                         |    0 
 vf205_access/src/view/config/menu/systemSettingView.js                             |  184 
 vf205_access/resource/image/co2_s.png                                              |    0 
 vf205_access/.temp/zipFolder/VF105_V12/dxStd/2.0.3.zip                             |    0 
 vf205_access/dxmodules/dxWatchdog.js                                               |  123 
 vf205_access/.temp/zipFolder/VF105_V12/dxNtp/2.0.0.zip                             |    0 
 vf205_access/dxmodules/libvbar-b-dxpwm.so                                          |    0 
 vf205_access/src/service/platService.js                                            |    4 
 vf205_access/resource/CN/wav/recg_f.wav                                            |    0 
 vf205_access/src/service/grainService.js                                           |  676 +
 vf205_access/src/view/config/menu/systemSetting/timeSettingView.js                 |  124 
 vf205_access/resource/EN/wav/verify_200_f.wav                                      |    0 
 vf205_access/src/view/topView.js                                                   |  170 
 vf205_access/dxmodules/libvbar-m-dxmqtt.so                                         |    0 
 vf205_access/.temp/zipFolder/VF105_V12/dxCommon/1.0.0.zip                          |    0 
 vf205_access/dxmodules/uiTextarea.js                                               |   76 
 vf205_access/src/view/pwdView.js                                                   |   72 
 vf205_access/resource/image/delete_fill.png                                        |    0 
 vf205_access/resource/EN/wav/recg_s.wav                                            |    0 
 vf205_access/resource/image/empty.png                                              |    0 
 vf205_access/resource/image/eth_enable.png                                         |    0 
 vf205_access/dxmodules/dxBase64.js                                                 |  308 
 vf205_access/resource/image/network_dark.png                                       |    0 
 vf205_access/.temp/zipFolder/VF105_V12/dxMqtt/1.0.1.zip                            |    0 
 vf205_access/resource/CN/wav/verify_400_f.wav                                      |    0 
 vf205_access/.temp/zipFolder/VF105_V12/dxOta/1.0.0.zip                             |    0 
 vf205_access/resource/image/pwd_btn.png                                            |    0 
 vf205_access/src/ui.js                                                             |   32 
 vf205_access/resource/CN/wav/verify_10x_s.wav                                      |    0 
 vf205_access/dxmodules/libid_jpg_codec.so                                          |    0 
 vf205_access/dxmodules/libvbar-m-dxkey.so                                          |    0 
 vf205_access/dxmodules/uiFont.js                                                   |   18 
 vf205_access/.temp/zipFolder/VF105_V12/dxFace/1.1.8.zip                            |    0 
 vf205_access/resource/image/setting.png                                            |    0 
 vf205_access/dxmodules/uiCheckbox.js                                               |   48 
 vf205_access/resource/image/commMgmt.png                                           |    0 
 vf205_access/.temp/zipFolder/VF105_V12/dxCapturer/1.0.2.zip                        |    0 
 vf205_access/resource/CN/wav/calibration_s.wav                                     |    0 
 vf205_access/resource/image/setting32.png                                          |    0 
 vf205_access/.temp/zipFolder/VF105_V12/dxNet/1.0.0.zip                             |    0 
 vf205_access/dxmodules/dxEventBus.js                                               |  167 
 vf205_access/resource/image/idleImage.jpg                                          |    0 
 vf205_access/.temp/zipFolder/VF105_V12/dxNfcCard/1.0.1.zip                         |    0 
 vf205_access/dxmodules/libvbar-m-dxalsa.so                                         |    0 
 vf205_access/resource/CN/wav/verify_200_s.wav                                      |    0 
 vf205_access/resource/image/back.png                                               |    0 
 vf205_access/dxmodules/libvbar-m-dxui.so                                           |    0 
 vf205_access/resource/CN/wav/btn23.wav                                             |    0 
 vf205_access/dxmodules/faceWorker.js                                               |   23 
 vf205_access/dxmodules/gpioKeyWorker.js                                            |   23 
 vf205_access/resource/image/black_btn.png                                          |    0 
 vf205_access/.temp/zipFolder/VF105_V12/dxNetwork/1.0.0.zip                         |    0 
 vf205_access/resource/image/view_f.png                                             |    0 
 vf205_access/.temp/zipFolder/VF105_V12/dxUi/1.0.2.zip                              |    0 
 vf205_access/dxmodules/libvbar-m-dxchannel.so                                      |    0 
 vf205_access/.temp/zipFolder/VF105_V12/dxMap/1.0.0.zip                             |    0 
 vf205_access/dxmodules/dxNet.js                                                    |  341 
 vf205_access/src/view/pinyin/dict.js                                               |  410 
 vf205_access/dxmodules/dxCommon.js                                                 |  733 +
 vf205_access/dxmodules/dxNtp.js                                                    |   63 
 vf205_access/src/view/config/menu/recordQueryView.js                               |  276 
 vf205_access/.temp/zipFolder/VF105_V12/dxHttpServer/1.0.5.zip                      |    0 
 vf205_access/dxmodules/uiKeyboard.js                                               |  102 
 vf205_access/dxmodules/libvbar-drv-tts.so                                          |    0 
 vf205_access/resource/image/menu_btn.png                                           |    0 
 vf205_access/src/view/config/menu/cloudCertView.js                                 |   42 
 vf205_access/.temp/zipFolder/VF105_V12/dxPwm/2.0.1.zip                             |    0 
 vf205_access/.temp/zipFolder/VF105_V12/dxStd/1.0.0.zip                             |    0 
 vf205_access/resource/image/sys_info.png                                           |    0 
 vf205_access/resource/image/vip.png                                                |    0 
 vf205_access/src/view/config/menu/localUserView.js                                 |  315 
 vf205_access/dxmodules/dxGpio.js                                                   |  123 
 vf205_access/.temp/zipFolder/VF105_V12/dxGpioKey/1.0.1.zip                         |    0 
 vf205_access/resource/CN/wav/btn32.wav                                             |    0 
 vf205_access/src/service/uart485Service.js                                         |  190 
 vf205_access/.temp/zipFolder/VF105_V12/dxNtp/2.0.2.zip                             |    0 
 vf205_access/resource/EN/wav/network.wav                                           |    0 
 vf205_access/resource/image/config.png                                             |    0 
 vf205_access/resource/EN/wav/verify_200_s.wav                                      |    0 
 vf205_access/resource/image/network.png                                            |    0 
 vf205_access/src/view/config/newPwdView.js                                         |  137 
 vf205_access/resource/image/faceAdd.png                                            |    0 
 vf205_access/resource/CN/wav/user2_s.wav                                           |    0 
 vf205_access/.temp/zipFolder/VF105_V12/dxMqttClient/1.0.1.zip                      |    0 
 vf205_access/resource/image/card.png                                               |    0 
 vf205_access/dxmodules/nfcWorker.js                                                |   27 
 vf205_access/resource/image/close_small.png                                        |    0 
 vf205_access/dxmodules/libvbar-m-dxsqlite.so                                       |    0 
 vf205_access/.temp/zipFolder/VF105_V12/dxCapturer/1.0.3.zip                        |    0 
 vf205_access/dxmodules/dxOta.js                                                    |  256 
 vf205_access/dxmodules/libvbar-b-dxgpio.so                                         |    0 
 vf205_access/README.md                                                             |    9 
 vf205_access/dxmodules/libvbar-m-alsa.so                                           |    0 
 vf205_access/resource/CN/wav/failed.wav                                            |    0 
 vf205_access/src/main.js                                                           |   78 
 vf205_access/resource/image/recordQuery.png                                        |    0 
 vf205_access/dxmodules/libvbar-p-dxnfc.so                                          |    0 
 vf205_access/resource/CN/wav/verify_10x_f.wav                                      |    0 
 vf205_access/dxmodules/libie_jpg.so                                                |    0 
 vf205_access/dxmodules/dxUi.js                                                     |  216 
 vf205_access/dxmodules/libvbar-drv-gpio.so                                         |    0 
 vf205_access/resource/EN/wav/register.wav                                          |    0 
 vf205_access/resource/image/deviceInfo.png                                         |    0 
 vf205_access/dxmodules/uiButtons.js                                                |  107 
 vf205_access/resource/image/systemSetting.png                                      |    0 
 vf205_access/resource/image/advance.png                                            |    0 
 vf205_access/dxmodules/dxLogger.js                                                 |   59 
 vf205_access/dxmodules/dxQrRule.js                                                 |  215 
 vf205_access/dxmodules/uiButton.js                                                 |   16 
 vf205_access/resource/image/o2_f.png                                               |    0 
 vf205_access/.temp/zipFolder/VF105_V12/dxLogger/2.0.3.zip                          |    0 
 vf205_access/resource/CN/wav/light_close.wav                                       |    0 
 vf205_access/resource/EN/wav/verify.wav                                            |    0 
 vf205_access/src/view/emergencyPwdView.js                                          |  140 
 vf205_access/src/view/config/menu/doorControlView.js                               |  258 
 vf205_access/resource/image/logo.png                                               |    0 
 vf205_access/dxmodules/libvbar-drv-capturer_calibration.so                         |    0 
 vf205_access/dxmodules/uiLine.js                                                   |   24 
 vf205_access/dxmodules/uiSlider.js                                                 |   42 
 vf205_access/.temp/zipFolder/VF105_V12/dxGpioKey/1.0.0.zip                         |    0 
 vf205_access/resource/CN/wav/verify_300_s.wav                                      |    0 
 vf205_access/dxmodules/libvbar-m-dxnet.so                                          |    0 
 vf205_access/resource/image/arrow_right.png                                        |    0 
 vf205_access/src/view/viewUtils.js                                                 |  475 +
 vf205_access/dxmodules/uiImage.js                                                  |   27 
 vf205_access/.temp/zipFolder/VF105_V12/dxWorkerPool/2.0.1.zip                      |    0 
 vf205_access/dxmodules/cameraCalibrationWorker.js                                  |   57 
 vf205_access/src/view/config/menu/systemSetting/passLogSettingView.js              |  117 
 vf205_access/resource/image/cloudCert.png                                          |    0 
 vf205_access/resource/image/failBg.png                                             |    0 
 vf205_access/src/controller.js                                                     |   66 
 vf205_access/.temp/zipFolder/VF105_V12/dxPwm/2.0.0.zip                             |    0 
 vf205_access/dxmodules/capturerWorker.js                                           |   27 
 vf205_access/resource/EN/wav/recognition_s.wav                                     |    0 
 vf205_access/src/view/config/menu/systemSetting/displaySettingView.js              |  289 
 vf205_access/resource/image/wifi.png                                               |    0 
 vf205_access/dxmodules/uiView.js                                                   |   27 
 vf205_access/.temp/zipFolder/VF105_V12/dxNtp/2.0.3.zip                             |    0 
 vf205_access/dxmodules/libvbar-b-dxwatchdog.so                                     |    0 
 vf205_access/resource/image/right.png                                              |    0 
 vf205_access/dxmodules/libvbar-drv-display.so                                      |    0 
 vf205_access/resource/image/user_w.png                                             |    0 
 vf205_access/src/view/config/configView.js                                         |  136 
 vf205_access/resource/CN/wav/access_f.wav                                          |    0 
 vf205_access/resource/CN/wav/stranger.wav                                          |    0 
 vf205_access/.temp/zipFolder/VF105_V12/dxSqlite/2.0.0.zip                          |    0 
 vf205_access/dxmodules/dxHttp.js                                                   |  155 
 vf205_access/resource/image/4g_dark.png                                            |    0 
 vf205_access/resource/image/mini_config.png                                        |    0 
 vf205_access/resource/CN/wav/door_close.wav                                        |    0 
 vf205_access/.temp/zipFolder/VF105_V12/dxBase64/1.0.0.zip                          |    0 
 vf205_access/.temp/zipFolder/VF105_V12/dxDriver/1.1.4.zip                          |    0 
 vf205_access/.temp/zipFolder/VF105_V12/dxMap/2.0.1.zip                             |    0 
 vf205_access/resource/CN/wav/verify_300_f.wav                                      |    0 
 vf205_access/src/service/faceService.js                                            |  447 +
 vf205_access/resource/image/ethernet_dark.png                                      |    0 
 vf205_access/resource/image/input_bg.png                                           |    0 
 vf205_access/.temp/zipFolder/VF105_V12/dxNet/1.0.2.zip                             |    0 
 vf205_access/dxmodules/libie_jpg_codec.so                                          |    0 
 vf205_access/resource/image/app_btn.png                                            |    0 
 vf205_access/resource/image/4g.png                                                 |    0 
 vf205_access/resource/image/light_open.png                                         |    0 
 vf205_access/resource/wav/alarm.wav                                                |    0 
 vf205_access/resource/CN/wav/btn31.wav                                             |    0 
 vf205_access/resource/image/app_qrcode.png                                         |    0 
 vf205_access/resource/CN/wav/access_s.wav                                          |    0 
 vf205_access/resource/EN/wav/verify_400_f.wav                                      |    0 
 vf205_access/resource/image/successBg.png                                          |    0 
 vf205_access/src/view/mainView.js                                                  | 1646 +++
 vf205_access/src/view/appView.js                                                   |   47 
 vf205_access/dxmodules/netWorker.js                                                |   25 
 vf205_access/src/service/configService.js                                          |  273 
 vf205_access/.temp/zipFolder/VF105_V12/dxCryptoES/2.0.0.zip                        |    0 
 vf205_access/resource/image/faceEmpty.png                                          |    0 
 vf205_access/resource/CN/wav/verify_200_f.wav                                      |    0 
 vf205_access/resource/CN/wav/light_open.wav                                        |    0 
 vf205_access/resource/image/emergencyOpen.png                                      |    0 
 vf205_access/resource/image/userGuide.png                                          |    0 
 vf205_access/resource/image/backspace.png                                          |    0 
 vf205_access/app.dxproj                                                            |  123 
 vf205_access/resource/image/enter.png                                              |    0 
 vf205_access/.temp/zipFolder/VF105_V12/dxDriver/1.1.0.zip                          |    0 
 vf205_access/dxmodules/liblombo_jpeg.so                                            |    0 
 vf205_access/dxmodules/libvbar-drv-memory.so                                       |    0 
 vf205_access/resource/image/eye-off.png                                            |    0 
 vf205_access/.temp/zipFolder/VF105_V12/dxLogger/2.0.0.zip                          |    0 
 vf205_access/src/view/config/menu/systemSetting/swipeCardRecognitionSettingView.js |   96 
 vf205_access/src/view/i18n.js                                                      |   82 
 vf205_access/dxmodules/uiBase.js                                                   |  582 +
 vf205_access/resource/font/AlibabaPuHuiTi-2-65-Medium.ttf                          |    0 
 vf205_access/src/service/codeService.js                                            |  205 
 vf205_access/src/service/sqliteService.js                                          |  616 +
 vf205_access/resource/image/ph3_f.png                                              |    0 
 vf205_access/resource/EN/wav/verify_10x_s.wav                                      |    0 
 vf205_access/resource/image/qrcode_small.png                                       |    0 
 vf205_access/dxmodules/dxMqtt.js                                                   |  225 
 vf205_access/src/driver.js                                                         | 1226 ++
 vf205_access/.temp/zipFolder/VF105_V12/dxAudio/1.0.1.zip                           |    0 
 vf205_access/dxmodules/libvbar-drv-audio_gain.so                                   |    0 
 vf205_access/resource/CN/wav/verify_400_s.wav                                      |    0 
 vf205_access/dxmodules/libvbar-m-net.so                                            |    0 
 vf205_access/src/view/config/menu/deviceInfoView.js                                |  110 
 vf205_access/dxmodules/libid_jpg.so                                                |    0 
 vf205_access/src/service/mqttService.js                                            | 1832 ++++
 vf205_access/src/common/consts/configConst.js                                      |   99 
 vf205_access/resource/CN/wav/emergency.wav                                         |    0 
 vf205_access/resource/image/o2_s.png                                               |    0 
 vf205_access/resource/CN/wav/btn11.wav                                             |    0 
 vf205_access/resource/image/eye_fill.png                                           |    0 
 vf205_access/.temp/zipFolder/VF105_V12/dxCameraCalibration/test.zip                |    0 
 vf205_access/dxmodules/dxWorkerPool.js                                             |  167 
 vf205_access/dxmodules/libvbar-drv-watchdog.so                                     |    0 
 vf205_access/resource/EN/wav/calibration_s.wav                                     |    0 
 vf205_access/resource/image/user_f.png                                             |    0 
 vf205_access/resource/image/mini_app.png                                           |    0 
 vf205_access/resource/image/trackFace.png                                          |    0 
 vf205_access/.temp/zipFolder/VF105_V12/dxCameraCalibration/1.0.0.zip               |    0 
 vf205_access/src/view/config/menu/voiceBroadcastView.js                            |  137 
 vf205_access/resource/image/devInfo.png                                            |    0 
 vf205_access/resource/image/basic.png                                              |    0 
 vf205_access/dxmodules/libvbar-drv-pwm.so                                          |    0 
 vf205_access/dxmodules/libvbar-m-dxcommon.so                                       |    0 
 vf205_access/resource/image/networkSetting.png                                     |    0 
 vf205_access/.temp/zipFolder/VF105_V12/dxBase64/2.0.0.zip                          |    0 
 vf205_access/resource/image/mqtt_enable.png                                        |    0 
 vf205_access/resource/image/faceRec.png                                            |    0 
 vf205_access/resource/EN/wav/recg_f.wav                                            |    0 
 vf205_access/resource/image/add.png                                                |    0 
 vf205_access/src/service/nfcService.js                                             |   44 
 vf205_access/src/view/pinyin/pinyin.js                                             | 1049 ++
 vf205_access/dxmodules/libvbar-m-dxcapturer.so                                     |    0 
 vf205_access/dxmodules/dxAlsa.js                                                   |  105 
 vf205_access/resource/image/mqtt.png                                               |    0 
 vf205_access/src/service/accessService.js                                          |  501 +
 vf205_access/resource/image/voiceBroadcast.png                                     |    0 
 vf205_access/src/view/config/menu/networkSettingView.js                            |  441 +
 vf205_access/resource/CN/wav/btn33.wav                                             |    0 
 vf205_access/resource/image/view_s.png                                             |    0 
 vf205_access/src/view/idleView.js                                                  |   54 
 vf205_access/dxmodules/dxCapturer.js                                               |  336 
 vf205_access/resource/CN/wav/register.wav                                          |    0 
 vf205_access/.temp/zipFolder/VF105_V12/dxDriver/2.0.0.zip                          |    0 
 vf205_access/src/view/config/menu/localUser/localUserAddView.js                    |  682 +
 vf205_access/resource/image/unlock.png                                             |    0 
 vf205_access/.temp/zipFolder/VF105_V12/dxUart/1.0.0.zip                            |    0 
 vf205_access/dxmodules/libvbar-p-nfc.so                                            |    0 
 vf205_access/dxmodules/uiDropdown.js                                               |   53 
 vf205_access/resource/image/user_1.png                                             |    0 
 vf205_access/.temp/zipFolder/VF105_V12/dxCommonUtils/1.0.1.zip                     |    0 
 vf205_access/resource/image/eye_fill_show.png                                      |    0 
 vf205_access/src/view/config/menu/localUser/faceEnterView.js                       |  117 
 vf205_access/.temp/zipFolder/VF105_V12/dxEventBus/2.0.3.zip                        |    0 
 vf205_access/dxmodules/libvbar-m-vgmqtt.so                                         |    0 
 vf205_access/.temp/zipFolder/VF105_V12/dxQrRule/1.0.0.zip                          |    0 
 vf205_access/.temp/zipFolder/VF105_V12/dxOta/2.0.2.zip                             |    0 
 vf205_access/dxmodules/libvbar-m-eid.so                                            |    0 
 vf205_access/dxmodules/libvccore.so                                                |    0 
 vf205_access/dxmodules/dxMap.js                                                    |  109 
 vf205_access/resource/CN/wav/emergency_f.wav                                       |    0 
 vf205_access/resource/EN/wav/verify_300_s.wav                                      |    0 
 vf205_access/resource/CN/wav/btn12.wav                                             |    0 
 vf205_access/dxmodules/dxFace.js                                                   |  287 
 vf205_access/dxmodules/uiSwitch.js                                                 |   49 
 vf205_access/resource/image/eye-fill.png                                           |    0 
 397 files changed, 26,360 insertions(+), 0 deletions(-)

diff --git a/vf205_access/.temp/dxide_debug.log b/vf205_access/.temp/dxide_debug.log
new file mode 100644
index 0000000..dd85166
--- /dev/null
+++ b/vf205_access/.temp/dxide_debug.log
@@ -0,0 +1,11 @@
+[2026/3/31 08:59:19] --- Start runUsb ---
+[2026/3/31 08:59:19] Platform: win32
+[2026/3/31 08:59:19] Kill command defined: wmic process where "name='node.exe' and commandline like '%device_manager.js%'" delete || powershell -NoProfile -ExecutionPolicy Bypass -Command "Get-CimInstance Win32_Process | Where-Object { $_.Name -eq 'node.exe' -and $_.CommandLine -like '*device_manager.js*' } | ForEach-Object { Stop-Process -Id $_.ProcessId -Force }"
+[2026/3/31 08:59:20] Node.js check passed
+[2026/3/31 08:59:20] Process exited with code: 0, signal: null
+[2026/3/31 08:59:20] Kill stdout: 删锟斤拷实锟斤拷 \\ACER-LGQ\ROOT\CIMV2:Win32_Process.Handle="42064"

+实锟斤拷删锟斤拷锟缴癸拷锟斤拷
+[2026/3/31 08:59:21] Manager script path: c:\Users\lgq10\.vscode\extensions\dxide.dxide-1.0.40\src\device\device_manager.js
+[2026/3/31 08:59:21] Spawning child process...
+[2026/3/31 08:59:21] Sending connect command: {"cmd":"connect","lang":"zh","model":"VF105_V12"}
+[2026/3/31 09:25:48] Process exited with code: 0, signal: null
diff --git a/vf205_access/.temp/md5s.json b/vf205_access/.temp/md5s.json
new file mode 100644
index 0000000..5283314
--- /dev/null
+++ b/vf205_access/.temp/md5s.json
@@ -0,0 +1,330 @@
+{
+  "app.dxproj": "cb10fd21e8e17ada45c25e1e1ba3226e",
+  "dxmodules\\cameraCalibrationWorker.js": "5812507304ced88da3677a3c68f79a78",
+  "dxmodules\\capturerWorker.js": "a3104a1d73ab1bd4f596495d817ecf39",
+  "dxmodules\\dxAlsa.js": "d82fe4f74383edf6198269968a82b5e7",
+  "dxmodules\\dxBase64.js": "7cb517ecd99830dde0ec13a501e831ea",
+  "dxmodules\\dxCameraCalibration.js": "8e42bf3752616896b88f9e9efbe20783",
+  "dxmodules\\dxCapturer.js": "7420d8e269fb8ebfc48c306e0a8fa7de",
+  "dxmodules\\dxCommon.js": "19f77916eb02e6fd01106597aca412bd",
+  "dxmodules\\dxConfig.js": "24072559b3cb1ec5c206cb358eaaaaae",
+  "dxmodules\\dxDriver.js": "c5969e91097030b90e9bcb62a827e344",
+  "dxmodules\\dxEid.js": "07d966e53b69629f152baf54cd163372",
+  "dxmodules\\dxEventBus.js": "81adf285545c12d49d7784327c41970a",
+  "dxmodules\\dxFace.js": "81790e30c6da75ae3bcb96afcafa5b02",
+  "dxmodules\\dxGpio.js": "30c34469e2dc8d80026fc5eac5bfd1f7",
+  "dxmodules\\dxGpioKey.js": "97ef2763bad50e0c82cfa5fb9b79f1eb",
+  "dxmodules\\dxHttp.js": "fa75a0a2951399fb5af7618d7ab4c6f1",
+  "dxmodules\\dxLogger.js": "f6d3f73086944fcdeeffa579ef6d1508",
+  "dxmodules\\dxMap.js": "2255d584c240c35a567f2c7b92e0a9da",
+  "dxmodules\\dxMqtt.js": "277fafb81971c8f3508a8a38f8f2703a",
+  "dxmodules\\dxNet.js": "58b13f928daeb1bae680c2350873baca",
+  "dxmodules\\dxNfc.js": "feb5bc21d4b13ab9736de1941290312d",
+  "dxmodules\\dxNtp.js": "0c90048eeb11e7e3b458e4d6e48932f2",
+  "dxmodules\\dxOta.js": "760dc97eb0724280f16f8616a2be171f",
+  "dxmodules\\dxPwm.js": "dc0734c231d7d4cd5f26a34c315cc4a2",
+  "dxmodules\\dxQrRule.js": "bfa9e2b4725c4fa358a2988f63c67210",
+  "dxmodules\\dxSqlite.js": "fb6a2f60b49d67a8ef36148355e5e30e",
+  "dxmodules\\dxStd.js": "6f239f2fd7d23e7ed053b762b235bd3c",
+  "dxmodules\\dxUart.js": "71edddfd98de79ccbd91e4e013af269b",
+  "dxmodules\\dxUi.js": "97bd858defaec480d755c162105a3f76",
+  "dxmodules\\dxWatchdog.js": "c4a7d5c8f0c203e6dafbc289a0f4fcbd",
+  "dxmodules\\dxWorkerPool.js": "5aad9b8f838d1339fc64083188d3ba69",
+  "dxmodules\\faceWorker.js": "d1d0d4f5e5503ca87bd69d1d2ee3ad00",
+  "dxmodules\\gpioKeyWorker.js": "78a7489cc3cf098fb4d218b17294175d",
+  "dxmodules\\libalc.so": "3128cc7cd0cc978e02db995433962c87",
+  "dxmodules\\libid_jpg.so": "18887cb0d0df6256604ed039d47dfc7b",
+  "dxmodules\\libid_jpg_codec.so": "c36bd0c28d2b43e9296736856da05129",
+  "dxmodules\\libie_jpg.so": "1343b7bc765f6464cf8e483c03edd542",
+  "dxmodules\\libie_jpg_codec.so": "508defffc1c72b0ae90afab117d6db80",
+  "dxmodules\\libJLReader.so": "ce7f448dea6a1c8988469d03ecfa6575",
+  "dxmodules\\liblombo_jpeg.so": "49508ccd603ed795efee3d0f8e7e3e2a",
+  "dxmodules\\libvbar-b-dxface.so": "689ee554f67057262860f7726042327b",
+  "dxmodules\\libvbar-b-dxgpio.so": "ca009351ab7d9719a71cd6105e9acba6",
+  "dxmodules\\libvbar-b-dxpwm.so": "b3e0e7cc950811385ceb204876fd8b19",
+  "dxmodules\\libvbar-b-dxwatchdog.so": "878352b309e9a9e17ce3ac83774d0fa9",
+  "dxmodules\\libvbar-drv-audio_gain.so": "14d23fe5134ff95982f1655058084709",
+  "dxmodules\\libvbar-drv-capturer.so": "295aaa64df97ee08053c26789ff57437",
+  "dxmodules\\libvbar-drv-capturer_calibration.so": "cdb2ca2205e36d82ebcce910e457bd9b",
+  "dxmodules\\libvbar-drv-display.so": "31c2a7a2ed4166d27359d208e4d34568",
+  "dxmodules\\libvbar-drv-face.so": "2c54abd0de9a287be3bbea490d0c45c4",
+  "dxmodules\\libvbar-drv-gpio.so": "e663856deb2d403558426455097e0bab",
+  "dxmodules\\libvbar-drv-memory.so": "0ed48486e154f24d6681a0195a7525ad",
+  "dxmodules\\libvbar-drv-pwm.so": "b9c2154b7020d41b01d63f6caac1510f",
+  "dxmodules\\libvbar-drv-soc.so": "73e4b6657af4bcff0affaacf55702096",
+  "dxmodules\\libvbar-drv-tts.so": "97076b55a3338196f512c61101ac0e9a",
+  "dxmodules\\libvbar-drv-watchdog.so": "9367e995f85cb191da0567d0acd4ed67",
+  "dxmodules\\libvbar-m-alsa.so": "1154ff7cb2f84ee378f29e0d03551f96",
+  "dxmodules\\libvbar-m-capturer.so": "8f0b6383db39494904294c3f60c5f013",
+  "dxmodules\\libvbar-m-channel.so": "6b6f7d8edb178b11b9a93123e0a7abdb",
+  "dxmodules\\libvbar-m-common.so": "074eb14e701c5ed910b979339453f484",
+  "dxmodules\\libvbar-m-dxalsa.so": "bb4fcf0be6ccb0cc2d7b295002925148",
+  "dxmodules\\libvbar-m-dxcapturer.so": "506307dec2552200eaa22412987b643e",
+  "dxmodules\\libvbar-m-dxcapturer_calibration.so": "c41e691d69621ab5a96322f47d3eb286",
+  "dxmodules\\libvbar-m-dxchannel.so": "ff80aaf50113c160c663a80015471079",
+  "dxmodules\\libvbar-m-dxcommon.so": "d4ca3ce51543d07c81cc75974adcbccb",
+  "dxmodules\\libvbar-m-dxeid.so": "3458f8221dd572220003e4344837d846",
+  "dxmodules\\libvbar-m-dxhttp.so": "1ec2f9ccc26aebc390944340afde6044",
+  "dxmodules\\libvbar-m-dxkey.so": "e49a86e25944050bda8565677713431a",
+  "dxmodules\\libvbar-m-dxmap.so": "55ebd66234d59490ab56f88398419dde",
+  "dxmodules\\libvbar-m-dxmqtt.so": "0cbeb2b46441ee89678516a1a941cd58",
+  "dxmodules\\libvbar-m-dxnet.so": "eed60270cabaf872983c6f905b0ceb03",
+  "dxmodules\\libvbar-m-dxsqlite.so": "15a0eb0d18b58cad3868f86e9edfb409",
+  "dxmodules\\libvbar-m-dxui.so": "ca22e1a0c52977749a32b2cc70e942a9",
+  "dxmodules\\libvbar-m-eid.so": "e7d1db4d1bfab4c462c9d22807099268",
+  "dxmodules\\libvbar-m-key.so": "f7f1f2ae6c9c1f298376375a8b16b6ee",
+  "dxmodules\\libvbar-m-net.so": "afa1adebb44fc9734b26b99e87e0728d",
+  "dxmodules\\libvbar-m-vgmqtt.so": "56e94165ba896867fbe3ead167022d3f",
+  "dxmodules\\libvbar-p-dxnfc.so": "14d17fe22a0dbfc00b13c4d9cef8512f",
+  "dxmodules\\libvbar-p-nfc.so": "f1a1f96558b2509c5b629790cec16386",
+  "dxmodules\\libvccore.so": "9c383ca78ee117ea3295baefb1f1fee2",
+  "dxmodules\\libyuv.so": "2c4faa3ab51260f5285cd91dda44b3a9",
+  "dxmodules\\mqttWorker.js": "4eedadbd41d6bd183cde2830a3347ad1",
+  "dxmodules\\netWorker.js": "c5d4c9022f8912b47249b14477aed70a",
+  "dxmodules\\nfcWorker.js": "88fadfc469cc397b66fd5e52db073bde",
+  "dxmodules\\uiBase.js": "9ea5cd2b5ed52d183fde2d87b8f70ca1",
+  "dxmodules\\uiButton.js": "8ffe0ffce9ac6b341c9993e260b52b05",
+  "dxmodules\\uiButtons.js": "52cb9727c2225f75ac6144e756a6d511",
+  "dxmodules\\uiCheckbox.js": "5aa8c851e8b2333cbe46cdd69452ab8c",
+  "dxmodules\\uiDropdown.js": "2b73bfacf3d4b115ab3997c83284c478",
+  "dxmodules\\uiFont.js": "257aa2f90ce2f0ace4095a03d3447b0b",
+  "dxmodules\\uiImage.js": "b2a0a963993474205bc7dc91c8696ec1",
+  "dxmodules\\uiKeyboard.js": "b225c62ff2f4b8aa0bdb675776b236a1",
+  "dxmodules\\uiLabel.js": "e0ae808d468459a6fedc7ba9a551359e",
+  "dxmodules\\uiLine.js": "cc18bc32c0a6f0f8db7992d6e0b4fd81",
+  "dxmodules\\uiList.js": "8b779a85cd54b25bc50ec616ed9f08d1",
+  "dxmodules\\uiSlider.js": "91b743902824b5decf5535dad49fc97e",
+  "dxmodules\\uiStyle.js": "60350cf77db84793bf093bda341f2cb9",
+  "dxmodules\\uiSwitch.js": "9a836405abe0b09f5a2940cf22698968",
+  "dxmodules\\uiTextarea.js": "0d5008a5a95b78ea8efde3408ba6fb4a",
+  "dxmodules\\uiUtils.js": "a04cc3baa5ba1dc6d1ab65b526464fa6",
+  "dxmodules\\uiView.js": "26fe7b992ac82bf5d45447f2921bff2f",
+  "dxmodules\\vgUartWorker.js": "fc3e9e0051836d5063c0eecf555d9521",
+  "README.md": "c472daef5243f3790f2faee1cf8e2255",
+  "README_CN.md": "a46b1c92c09f375881a49d8c42adf6b3",
+  "resource\\CN\\wav\\access_f.wav": "f951f3cc1f03aaa794231413fd4efcc6",
+  "resource\\CN\\wav\\access_s.wav": "6d1b31bdcaaa13ba719e3223b55d5235",
+  "resource\\CN\\wav\\btn11.wav": "a623797305d7b0e6b8cb6b2ab3d43591",
+  "resource\\CN\\wav\\btn12.wav": "26bbfc3eed36211713dca9afb423e168",
+  "resource\\CN\\wav\\btn13.wav": "67d6fe32693cb2e7653c2ff2141ce873",
+  "resource\\CN\\wav\\btn21.wav": "53071472fce6128fdd2ed304e4d78406",
+  "resource\\CN\\wav\\btn22.wav": "e35c87d370695099d3b6d7f512496395",
+  "resource\\CN\\wav\\btn23.wav": "f25db5592331f1e6deb67beecb3c1131",
+  "resource\\CN\\wav\\btn31.wav": "054a4f36ebda08fadca3162d955560bf",
+  "resource\\CN\\wav\\btn32.wav": "64eb5fef123eafd7b52108ebcd6bace9",
+  "resource\\CN\\wav\\btn33.wav": "67d6fe32693cb2e7653c2ff2141ce873",
+  "resource\\CN\\wav\\calibration_s.wav": "d2ff1f1f4a40bf4166130dc079939079",
+  "resource\\CN\\wav\\control_f.wav": "4dbaca7e4d227a720620b846544b469a",
+  "resource\\CN\\wav\\door_close.wav": "325ca8082f8e9fceb2c7eeeb78d8645b",
+  "resource\\CN\\wav\\door_open.wav": "f3b5291fc8babaffd32107198cdd5afa",
+  "resource\\CN\\wav\\emergency.wav": "a1855c22f3ef2f69d5c84d3a2852ae1f",
+  "resource\\CN\\wav\\emergency_f.wav": "946ac86e74b849ad8f1bec3615cf9b39",
+  "resource\\CN\\wav\\emergency_s.wav": "a717e3417891ff306225ac075ba28082",
+  "resource\\CN\\wav\\failed.wav": "891194e741b0bc8f6332f78eb607cc85",
+  "resource\\CN\\wav\\light_close.wav": "b1ac09e91ac4ce3825614ad1654a3f58",
+  "resource\\CN\\wav\\light_open.wav": "16b7b6b8c6eb469645a15e4a54a3e014",
+  "resource\\CN\\wav\\network.wav": "7bbc6d740918a20acfb5ef75df685bdb",
+  "resource\\CN\\wav\\read.wav": "c83edd035dc15f7a716644319e849215",
+  "resource\\CN\\wav\\recg_f.wav": "5cd4d88db4e3f8332b9e73fe05222c83",
+  "resource\\CN\\wav\\recg_s.wav": "4afadeb018b08518d5d3dd1cfc5e0d64",
+  "resource\\CN\\wav\\recognition.wav": "da00dd97d1e8ca0ed20dc43eb4daafc8",
+  "resource\\CN\\wav\\recognition_s.wav": "df9916d6fe3d285894668e63d1aeeb1d",
+  "resource\\CN\\wav\\register.wav": "a91d6ebb846dc834816a954168da1352",
+  "resource\\CN\\wav\\stranger.wav": "2e6690d7ddcd3609ca3e6d6717b61a9c",
+  "resource\\CN\\wav\\user2.wav": "868a9b15aac20b62457f98c955f4e5e0",
+  "resource\\CN\\wav\\user2_s.wav": "98904054df059be8cd69e08c302317e7",
+  "resource\\CN\\wav\\verify.wav": "2bc2b96e0ca05052985fda98fb552ef9",
+  "resource\\CN\\wav\\verify_10x_f.wav": "bf26ce11bbd801f5efeff8c9250f219f",
+  "resource\\CN\\wav\\verify_10x_s.wav": "2d04b22277844d9c35e08e4e2c67c11c",
+  "resource\\CN\\wav\\verify_200_f.wav": "393036b5fc28a3c04580593d59e26e7e",
+  "resource\\CN\\wav\\verify_200_s.wav": "585267371d37f3f45e3826ec7dcafbd3",
+  "resource\\CN\\wav\\verify_300_f.wav": "e44977e8b6dcac8adbf304894afd24e0",
+  "resource\\CN\\wav\\verify_300_s.wav": "d8e23a91e4999b2d77454aab824bd611",
+  "resource\\CN\\wav\\verify_400_f.wav": "05752c8c9c2bf4334943999842529d8b",
+  "resource\\CN\\wav\\verify_400_s.wav": "740a63ffe907dda0f2d0e14cb9a83f74",
+  "resource\\EN\\wav\\calibration_s.wav": "b5497547d9e7e6fb5b28ee307b27752b",
+  "resource\\EN\\wav\\network.wav": "1e8ccfd03ca83976fefdba1edcf1b194",
+  "resource\\EN\\wav\\read.wav": "8c1f6ee62c7bf74db5ecab28d3988eeb",
+  "resource\\EN\\wav\\recg_f.wav": "e303563b867dd6eaebac18679ca760df",
+  "resource\\EN\\wav\\recg_s.wav": "183a843b668aa919311a6d352af80f35",
+  "resource\\EN\\wav\\recognition.wav": "1c9e06bc338c49c120aa101b1fac8de0",
+  "resource\\EN\\wav\\recognition_s.wav": "f887f2b1615121bbe815fef7f64d3b92",
+  "resource\\EN\\wav\\register.wav": "de5d0048f840243fdd1392c09d9ac164",
+  "resource\\EN\\wav\\stranger.wav": "31775350903916827fdec25b9c65dd94",
+  "resource\\EN\\wav\\verify.wav": "2e77ec2c754e1dea329988d4e462aa2f",
+  "resource\\EN\\wav\\verify_10x_f.wav": "7ccc23490436b9f1de32200230953a62",
+  "resource\\EN\\wav\\verify_10x_s.wav": "0630e0410fca3c7fd7e701c69e8ea4bc",
+  "resource\\EN\\wav\\verify_200_f.wav": "64ce473b0f560cc1613469ab94197ce6",
+  "resource\\EN\\wav\\verify_200_s.wav": "e3d28c408cc3bef5461620c75b15abdf",
+  "resource\\EN\\wav\\verify_300_f.wav": "7fa0d7bf85d040b72a89cfb9e2f06bcf",
+  "resource\\EN\\wav\\verify_300_s.wav": "3e69fd763477d6cc30543d838f33d718",
+  "resource\\EN\\wav\\verify_400_f.wav": "d074b8f6e4e968b6d1984b123ed4d387",
+  "resource\\EN\\wav\\verify_400_s.wav": "9141136d3310a5fac5917d3f6056249f",
+  "resource\\font\\AlibabaPuHuiTi-2-65-Medium.ttf": "092a99ee52bbaef7481cc96c5b85b992",
+  "resource\\image\\4g.png": "e5b27ed5a596cb16c7ab695d82fe3014",
+  "resource\\image\\4g_dark.png": "414b3a9fcefd8ea6909158b51038d4d8",
+  "resource\\image\\accessCtrl.png": "6be30c8f648ec7153ae2c39a15884181",
+  "resource\\image\\add.png": "498480ce68e4d6047eb74d3aa5229f56",
+  "resource\\image\\advance.png": "d98aeb99a04163bce23b6c2638cd705a",
+  "resource\\image\\app.png": "7640c7358a3f5dba1f887b8413b93a9d",
+  "resource\\image\\app_btn.png": "aa325cea46fd3918c86d76bf009b1663",
+  "resource\\image\\app_qrcode.png": "0a20655d02ff0e473106bf41f7c9687b",
+  "resource\\image\\arrow_right.png": "edc6876d6fa1e2d0be2e606c73e0f2ec",
+  "resource\\image\\back.png": "aa5869ff78051dbdc5f688f1805064da",
+  "resource\\image\\background.jpg": "90d464f4221f62132ebf74e69446b6d7",
+  "resource\\image\\backspace.png": "26302e37dd8618e92c3a47d68039d0ec",
+  "resource\\image\\back_2.png": "b3f16ab01606d85c2c70124d50b3af1b",
+  "resource\\image\\basic.png": "84eedd84efdc5fdb54138dd29cf6fc41",
+  "resource\\image\\black_btn.png": "13ee1720aff247ba3f8e22e00f89a316",
+  "resource\\image\\card.png": "c05047d2ad6549db001d08790cb5d9ff",
+  "resource\\image\\close.png": "a5353c231df804fcc4577672ab3a4302",
+  "resource\\image\\close_small.png": "7d6cddddc38ce8d4950789169213add4",
+  "resource\\image\\cloudCert.png": "4481cfb9c2d1f44f0a0dd0489cb6fc2b",
+  "resource\\image\\co2_f.png": "7e6f00c03b71a4dbe439491083ca731c",
+  "resource\\image\\co2_s.png": "4fb691286b8856f1ed25ef8bacdb6099",
+  "resource\\image\\commMgmt.png": "5cd157e1b8c82fdf9ddba1f6d5047b9b",
+  "resource\\image\\config.png": "50d2091b9f7fba5915dbed0aa0dcf918",
+  "resource\\image\\config_btn.png": "e54cbc27d30e7c6480b83107a631e7ef",
+  "resource\\image\\delete.png": "014bad6d9a94a133c58ef350e198101e",
+  "resource\\image\\delete_fill.png": "947fc08278354a1151d5599382c2c5f3",
+  "resource\\image\\deviceInfo.png": "3e40246e01c1f7eede4d76fcbba33825",
+  "resource\\image\\devInfo.png": "1a80aba6780a45f8775bdfdcff4df23a",
+  "resource\\image\\doorControl.png": "68993ef92bb8c6b2d0dab2c75cc7533d",
+  "resource\\image\\down.png": "c4d5c1883db4694ccedb7c1140d89da9",
+  "resource\\image\\emergencyOpen.png": "890877dee840dabe60487f8ce57b41f6",
+  "resource\\image\\empty.png": "8283ac78099d9c13ef4b552ce86f5c38",
+  "resource\\image\\enter.png": "787e076256c8a47e07f2091a57585fb5",
+  "resource\\image\\enter_b.png": "02cb6c84fec128a639e3cf0828a6ee5f",
+  "resource\\image\\ethernet.png": "f3abb111d96a11a56f7ed77b21abab4c",
+  "resource\\image\\ethernet_dark.png": "10656303a6d22e204014f55ed0fb3efb",
+  "resource\\image\\eth_disable.png": "7017f5cc2c9b4f802f082f6c0f5bb581",
+  "resource\\image\\eth_enable.png": "84d1334e524ac669c3b79e8a69b41eb1",
+  "resource\\image\\eye-fill.png": "9ae71914bd47423be04d0a22eb4f3995",
+  "resource\\image\\eye-off.png": "295c3e8255ced50cf2667ecda524e11e",
+  "resource\\image\\eye_fill.png": "d0ac0d07f13e02e5fae7a12a0858ec49",
+  "resource\\image\\eye_fill_show.png": "265cf669797b94a138982c01c29d0bd9",
+  "resource\\image\\face.png": "d695a5f29dbf051fc0c6e0d4e177f5c5",
+  "resource\\image\\faceAdd.png": "5e0e3d4eb3f034a179a8eef5c08d4c63",
+  "resource\\image\\faceEmpty.png": "9ef3bd1d776183e203e69d5c91e4b129",
+  "resource\\image\\faceError.png": "19841af9136d4483642a254ab1a6f57c",
+  "resource\\image\\faceRec.png": "f1bfcb61f4642c6c1bbc04856fb57905",
+  "resource\\image\\faceRec2.png": "580c72783b4cfc64ec0a9593e77c456a",
+  "resource\\image\\factoryTest.png": "4bdb36420046870efcabd4a040e31913",
+  "resource\\image\\failBg.png": "5d6dca3cc98032a10ef4bc0658f7e546",
+  "resource\\image\\grey_btn.png": "b0ca6e44c0e01a17d0bdda5f7e057cc2",
+  "resource\\image\\help.png": "7d75da0510ca74870858a639882dc2ef",
+  "resource\\image\\idleImage.jpg": "90d464f4221f62132ebf74e69446b6d7",
+  "resource\\image\\input_bg.png": "8a8f5c43f1118869a7679ccbaaf47de2",
+  "resource\\image\\light_close.png": "607b38280bb5321327cacce5bd6c3fe9",
+  "resource\\image\\light_open.png": "1a8df3753b6f0df9e7abb5b53dabd72e",
+  "resource\\image\\localUser.png": "6429f43f7fee002d66d50a3d92a087da",
+  "resource\\image\\lock.png": "c1419aa2a9c9da4b7dbf3529a1af37f3",
+  "resource\\image\\logo.png": "5768b9344bedc53096d2227bee5d52d4",
+  "resource\\image\\menu_btn.png": "df98739cd4804d08b23eaf33bb92e1bc",
+  "resource\\image\\mini_app.png": "82ee9005b5d162a6fbb0d32764088da4",
+  "resource\\image\\mini_background.png": "620bf06dbfffe37f717b91fb3ed8ef40",
+  "resource\\image\\mini_config.png": "6bf78553fb53673a89e80613cfbee4c1",
+  "resource\\image\\mini_password.png": "6892385a457e084953bcf9acb2ae9957",
+  "resource\\image\\mqtt.png": "542ebc6bdbb66ea0f25cf29aeb9d264c",
+  "resource\\image\\mqtt_dark.png": "d4aab5adc128846c47a3b8bb015c757b",
+  "resource\\image\\mqtt_enable.png": "fc766f5fcbb95eca648ee10d421cc8fe",
+  "resource\\image\\network.png": "0a0119e3d5fce101b28575a4e44aaf7e",
+  "resource\\image\\networkSetting.png": "3e83d354e8293ed112fe7cc405b94187",
+  "resource\\image\\network_dark.png": "3c5f8ce5732e95ad613cdd41dc5adbc0",
+  "resource\\image\\o2_f.png": "b787951eba880b3ae82b42594b4e30df",
+  "resource\\image\\o2_s.png": "50564fb865bb7f5ed0352e43ea17d853",
+  "resource\\image\\ph3_f.png": "e95a348c887298dc4ed0555c577ea5bb",
+  "resource\\image\\ph3_s.png": "96e68d741b75fcd6938a6909014cccb0",
+  "resource\\image\\pwd_btn.png": "8764458bee98bff728445837e126231e",
+  "resource\\image\\qrcode_small.png": "285bbe7e8f968c8bf4506a563dffcac2",
+  "resource\\image\\recordQuery.png": "d340255a0c2342382bff6f8c57f6376b",
+  "resource\\image\\recQuery.png": "1b8c58663a6e61f4f885e784ee4e87d4",
+  "resource\\image\\rectangle.png": "394e2e483120908674f6de7fb879bfcf",
+  "resource\\image\\register.png": "7fa975d92007703532ba8011f2a0109f",
+  "resource\\image\\right.png": "a6f6bc770ad7a8220effcc96e750aaaa",
+  "resource\\image\\select_arrow.png": "9d82daa1092375abc413d581f36aaf2d",
+  "resource\\image\\setting.png": "92365fd93f2cfa63c7901ce3d8900a42",
+  "resource\\image\\setting32.png": "e531bf8a9ce7f6cf93a8ea9baf95377c",
+  "resource\\image\\space.png": "de9816e31308bd7ce187fe03ab634a37",
+  "resource\\image\\successBg.png": "1ef294bd7e1688bba47c2337906b1d1d",
+  "resource\\image\\success_fill.png": "09166b0cd4da44b76b4f6cdc2c550103",
+  "resource\\image\\sysSettings.png": "0a84bbe887481a1cce1ca562f83d5b89",
+  "resource\\image\\systemSetting.png": "9aee20d073df321250a5bbc57d16d5f1",
+  "resource\\image\\sys_info.png": "20dc23c019d07cd2c3ce32a160b7b63f",
+  "resource\\image\\title_bg.png": "82fbdcc4133899d03072dcd57a92f203",
+  "resource\\image\\trackFace.png": "e90f92eb629563ede01aadca2b719de9",
+  "resource\\image\\unlock.png": "7b97b659c36d3ba4f435f44792b90a80",
+  "resource\\image\\user.png": "6429f43f7fee002d66d50a3d92a087da",
+  "resource\\image\\userGuide.png": "3227210f670f66cd6c29641e1212b0b8",
+  "resource\\image\\userMgmt.png": "5dad96f344513f970c2b582d7feb537d",
+  "resource\\image\\user_1.png": "36ab26e22dc39ea28c03f05f4ab891ce",
+  "resource\\image\\user_f.png": "d82d235224deccd2235ab15dbf1fda26",
+  "resource\\image\\user_s.png": "709953f3695cae9ac1bb50533f1a96ba",
+  "resource\\image\\user_w.png": "bc2ca556f37181815c0093d802f2f24f",
+  "resource\\image\\view_f.png": "4fbdda957ef2966bc4938990725d0246",
+  "resource\\image\\view_s.png": "93ddad11d282c5a8f56233682290b38c",
+  "resource\\image\\vip.png": "0e816b4860ee87ed1169154e3f0fc524",
+  "resource\\image\\voiceBroadcast.png": "e6f1a31ba7159962d18b77deef71c106",
+  "resource\\image\\wifi.png": "fd668b648ac984ed92fad8e40e151283",
+  "resource\\image\\wifi_dark.png": "37505f892ac6a43cb8dc5ea685de9740",
+  "resource\\langPack.js": "b537e7ad7b7bd36ebef146692604007d",
+  "resource\\wav\\alarm.wav": "fe9d43cfb930f873973cc31fd6e8c132",
+  "src\\common\\consts\\configConst.js": "8cdbeff06611f7c94fc349afb2d04364",
+  "src\\common\\utils\\utils.js": "f45a9074748680b00ba663ad6490acf0",
+  "src\\config.json": "c6c52fdf036881dd11081f96b491fee5",
+  "src\\controller.js": "f09517062ac2a8641ea17909f9e635fd",
+  "src\\driver.js": "02c38e2dcc749c50fb348b94629278d0",
+  "src\\main.js": "a893be0e60fcd2ca32c94baf8534f996",
+  "src\\screen.js": "a2f377ed5832bb9139dfcaadffe091c7",
+  "src\\service\\accessService.js": "ca2abf5ea0cae58a1fc9ccffb9f03454",
+  "src\\service\\codeService.js": "63934baff614eedf7f8c7ee4855f9ebe",
+  "src\\service\\configService.js": "d991f7261781465e306cd9d4548eab4d",
+  "src\\service\\faceService.js": "4e6ef420f61bb617e3b57491f9305cb2",
+  "src\\service\\gpiokeyService.js": "71c8f8a2589492153671f1d7ed96e6c8",
+  "src\\service\\grainService.js": "99f05184d3fcdf5c4e54fce08500267b",
+  "src\\service\\mqttService.js": "78d18810234846a26b49161dc6f193af",
+  "src\\service\\nfcService.js": "45705bc6a95206927085f11e7208cac2",
+  "src\\service\\platService.js": "a38387366ed212029bb46c6d3a85f2e9",
+  "src\\service\\sqliteService.js": "f2f0864ae07d893789bfc1666b584410",
+  "src\\service\\uart485Service.js": "c62ad21c538095f950dffe12d6770aa0",
+  "src\\services.js": "b87698f1e9e03bcfac820956034b06fe",
+  "src\\ui.js": "e9adc3aac685e711427667fa7705be6f",
+  "src\\view\\appView.js": "3ada10f0136eb464c035aec809a6e600",
+  "src\\view\\config\\configView.js": "6e30bb6aa2a9f6e6187dc6d86d832901",
+  "src\\view\\config\\identityVerificationView.js": "aa8cdd417184b2bdcef1a6cbd49df487",
+  "src\\view\\config\\menu\\cloudCertView.js": "7c9181ccfa5b5e96a234f1f55307ccb9",
+  "src\\view\\config\\menu\\deviceInfo\\dataCapacityInfoView.js": "9b6d8db4b83758d778f84ac2a1a266c8",
+  "src\\view\\config\\menu\\deviceInfo\\systemInfoView.js": "9396136cd353b10bb9a56f9bda2315d5",
+  "src\\view\\config\\menu\\deviceInfoView.js": "b33452d2a4d7188c5d14c6f76b726e90",
+  "src\\view\\config\\menu\\dockingSetting.js": "13a156aa4889a7d032a6fa26605e85b8",
+  "src\\view\\config\\menu\\doorControlView.js": "ffd1d5bc1bb7c652bc678c52e9969fda",
+  "src\\view\\config\\menu\\factoryTestView.js": "9588321c8282257e9707ebedb5920cda",
+  "src\\view\\config\\menu\\helpView.js": "00e750b2b637dc318f75e840d901fb5c",
+  "src\\view\\config\\menu\\localUser\\faceEnterView.js": "d993d07711e15cf5f0fee01a22753bfa",
+  "src\\view\\config\\menu\\localUser\\localUserAddView.js": "bf4646521acd0e14832eb732bc424e77",
+  "src\\view\\config\\menu\\localUserView.js": "c870b92aaaec5aff368e07e9f254e8aa",
+  "src\\view\\config\\menu\\networkSettingView.js": "325d70ed8ab1e170ffc1fa03fff637f5",
+  "src\\view\\config\\menu\\recordQuery\\recordQueryDetailView.js": "7077207b15bf1d7eae3a9a01dc68dc77",
+  "src\\view\\config\\menu\\recordQueryView.js": "67b573825af0639a4103bdc97b0f2c4a",
+  "src\\view\\config\\menu\\systemSetting\\displaySettingView.js": "c57f3b9faf85e048864c08d592481a72",
+  "src\\view\\config\\menu\\systemSetting\\faceRecognitionSettingView.js": "4d6b4e8b6c0f6e0ccbaaaa169e65b780",
+  "src\\view\\config\\menu\\systemSetting\\passLogSettingView.js": "d51958ac39b104846586b1ed6590414c",
+  "src\\view\\config\\menu\\systemSetting\\passwordManagementView.js": "98a6ca138cc1e2bc33ff6a3248e11263",
+  "src\\view\\config\\menu\\systemSetting\\passwordOpenDoorSettingView.js": "6e2ab3793e6c569097b702c339ef1602",
+  "src\\view\\config\\menu\\systemSetting\\swipeCardRecognitionSettingView.js": "871b483fbc3d778df95b803c130101e1",
+  "src\\view\\config\\menu\\systemSetting\\timeSettingView.js": "6950faa3a3296a573d048eb782c0e6ca",
+  "src\\view\\config\\menu\\systemSettingView.js": "ca3ac7b0e0390c7d542b62d569f57b24",
+  "src\\view\\config\\menu\\voiceBroadcastView.js": "a809af8acdae03f15c6e677bef6f20a1",
+  "src\\view\\config\\newPwdView.js": "32e3cfb0cc7f88361f1c69797cdb14b8",
+  "src\\view\\emergencyPwdView.js": "c6413bc04d38d54e57f590ce44204bcb",
+  "src\\view\\i18n.js": "94f43798d35026189125bf2534d1bffd",
+  "src\\view\\idleView.js": "b95c100ae4b2757ea2b0844a3df35c9e",
+  "src\\view\\mainView.js": "ec96a69994b99ed36778338198f74765",
+  "src\\view\\pinyin\\dict.js": "e40764bfc6bab80119c584315c0c48b7",
+  "src\\view\\pinyin\\pinyin.js": "c0809d9d1ebe5937cb6831b2b70db439",
+  "src\\view\\pwdView.js": "226b8b83a13b82cc925519ae051f8b3f",
+  "src\\view\\topView.js": "c9d8a4e3bc362edb1a5007135323beea",
+  "src\\view\\viewUtils.js": "ceaaad4fb40024b448a66a03911a7279",
+  "src\\worker\\accessWorker.js": "1b1253b5a7fbb2e733be2a9b0714ecca",
+  "src\\worker\\httpWorker.js": "47ddc63bdd95ecf36f7eaaa5f409424c"
+}
\ No newline at end of file
diff --git a/vf205_access/.temp/md5snew.json b/vf205_access/.temp/md5snew.json
new file mode 100644
index 0000000..5283314
--- /dev/null
+++ b/vf205_access/.temp/md5snew.json
@@ -0,0 +1,330 @@
+{
+  "app.dxproj": "cb10fd21e8e17ada45c25e1e1ba3226e",
+  "dxmodules\\cameraCalibrationWorker.js": "5812507304ced88da3677a3c68f79a78",
+  "dxmodules\\capturerWorker.js": "a3104a1d73ab1bd4f596495d817ecf39",
+  "dxmodules\\dxAlsa.js": "d82fe4f74383edf6198269968a82b5e7",
+  "dxmodules\\dxBase64.js": "7cb517ecd99830dde0ec13a501e831ea",
+  "dxmodules\\dxCameraCalibration.js": "8e42bf3752616896b88f9e9efbe20783",
+  "dxmodules\\dxCapturer.js": "7420d8e269fb8ebfc48c306e0a8fa7de",
+  "dxmodules\\dxCommon.js": "19f77916eb02e6fd01106597aca412bd",
+  "dxmodules\\dxConfig.js": "24072559b3cb1ec5c206cb358eaaaaae",
+  "dxmodules\\dxDriver.js": "c5969e91097030b90e9bcb62a827e344",
+  "dxmodules\\dxEid.js": "07d966e53b69629f152baf54cd163372",
+  "dxmodules\\dxEventBus.js": "81adf285545c12d49d7784327c41970a",
+  "dxmodules\\dxFace.js": "81790e30c6da75ae3bcb96afcafa5b02",
+  "dxmodules\\dxGpio.js": "30c34469e2dc8d80026fc5eac5bfd1f7",
+  "dxmodules\\dxGpioKey.js": "97ef2763bad50e0c82cfa5fb9b79f1eb",
+  "dxmodules\\dxHttp.js": "fa75a0a2951399fb5af7618d7ab4c6f1",
+  "dxmodules\\dxLogger.js": "f6d3f73086944fcdeeffa579ef6d1508",
+  "dxmodules\\dxMap.js": "2255d584c240c35a567f2c7b92e0a9da",
+  "dxmodules\\dxMqtt.js": "277fafb81971c8f3508a8a38f8f2703a",
+  "dxmodules\\dxNet.js": "58b13f928daeb1bae680c2350873baca",
+  "dxmodules\\dxNfc.js": "feb5bc21d4b13ab9736de1941290312d",
+  "dxmodules\\dxNtp.js": "0c90048eeb11e7e3b458e4d6e48932f2",
+  "dxmodules\\dxOta.js": "760dc97eb0724280f16f8616a2be171f",
+  "dxmodules\\dxPwm.js": "dc0734c231d7d4cd5f26a34c315cc4a2",
+  "dxmodules\\dxQrRule.js": "bfa9e2b4725c4fa358a2988f63c67210",
+  "dxmodules\\dxSqlite.js": "fb6a2f60b49d67a8ef36148355e5e30e",
+  "dxmodules\\dxStd.js": "6f239f2fd7d23e7ed053b762b235bd3c",
+  "dxmodules\\dxUart.js": "71edddfd98de79ccbd91e4e013af269b",
+  "dxmodules\\dxUi.js": "97bd858defaec480d755c162105a3f76",
+  "dxmodules\\dxWatchdog.js": "c4a7d5c8f0c203e6dafbc289a0f4fcbd",
+  "dxmodules\\dxWorkerPool.js": "5aad9b8f838d1339fc64083188d3ba69",
+  "dxmodules\\faceWorker.js": "d1d0d4f5e5503ca87bd69d1d2ee3ad00",
+  "dxmodules\\gpioKeyWorker.js": "78a7489cc3cf098fb4d218b17294175d",
+  "dxmodules\\libalc.so": "3128cc7cd0cc978e02db995433962c87",
+  "dxmodules\\libid_jpg.so": "18887cb0d0df6256604ed039d47dfc7b",
+  "dxmodules\\libid_jpg_codec.so": "c36bd0c28d2b43e9296736856da05129",
+  "dxmodules\\libie_jpg.so": "1343b7bc765f6464cf8e483c03edd542",
+  "dxmodules\\libie_jpg_codec.so": "508defffc1c72b0ae90afab117d6db80",
+  "dxmodules\\libJLReader.so": "ce7f448dea6a1c8988469d03ecfa6575",
+  "dxmodules\\liblombo_jpeg.so": "49508ccd603ed795efee3d0f8e7e3e2a",
+  "dxmodules\\libvbar-b-dxface.so": "689ee554f67057262860f7726042327b",
+  "dxmodules\\libvbar-b-dxgpio.so": "ca009351ab7d9719a71cd6105e9acba6",
+  "dxmodules\\libvbar-b-dxpwm.so": "b3e0e7cc950811385ceb204876fd8b19",
+  "dxmodules\\libvbar-b-dxwatchdog.so": "878352b309e9a9e17ce3ac83774d0fa9",
+  "dxmodules\\libvbar-drv-audio_gain.so": "14d23fe5134ff95982f1655058084709",
+  "dxmodules\\libvbar-drv-capturer.so": "295aaa64df97ee08053c26789ff57437",
+  "dxmodules\\libvbar-drv-capturer_calibration.so": "cdb2ca2205e36d82ebcce910e457bd9b",
+  "dxmodules\\libvbar-drv-display.so": "31c2a7a2ed4166d27359d208e4d34568",
+  "dxmodules\\libvbar-drv-face.so": "2c54abd0de9a287be3bbea490d0c45c4",
+  "dxmodules\\libvbar-drv-gpio.so": "e663856deb2d403558426455097e0bab",
+  "dxmodules\\libvbar-drv-memory.so": "0ed48486e154f24d6681a0195a7525ad",
+  "dxmodules\\libvbar-drv-pwm.so": "b9c2154b7020d41b01d63f6caac1510f",
+  "dxmodules\\libvbar-drv-soc.so": "73e4b6657af4bcff0affaacf55702096",
+  "dxmodules\\libvbar-drv-tts.so": "97076b55a3338196f512c61101ac0e9a",
+  "dxmodules\\libvbar-drv-watchdog.so": "9367e995f85cb191da0567d0acd4ed67",
+  "dxmodules\\libvbar-m-alsa.so": "1154ff7cb2f84ee378f29e0d03551f96",
+  "dxmodules\\libvbar-m-capturer.so": "8f0b6383db39494904294c3f60c5f013",
+  "dxmodules\\libvbar-m-channel.so": "6b6f7d8edb178b11b9a93123e0a7abdb",
+  "dxmodules\\libvbar-m-common.so": "074eb14e701c5ed910b979339453f484",
+  "dxmodules\\libvbar-m-dxalsa.so": "bb4fcf0be6ccb0cc2d7b295002925148",
+  "dxmodules\\libvbar-m-dxcapturer.so": "506307dec2552200eaa22412987b643e",
+  "dxmodules\\libvbar-m-dxcapturer_calibration.so": "c41e691d69621ab5a96322f47d3eb286",
+  "dxmodules\\libvbar-m-dxchannel.so": "ff80aaf50113c160c663a80015471079",
+  "dxmodules\\libvbar-m-dxcommon.so": "d4ca3ce51543d07c81cc75974adcbccb",
+  "dxmodules\\libvbar-m-dxeid.so": "3458f8221dd572220003e4344837d846",
+  "dxmodules\\libvbar-m-dxhttp.so": "1ec2f9ccc26aebc390944340afde6044",
+  "dxmodules\\libvbar-m-dxkey.so": "e49a86e25944050bda8565677713431a",
+  "dxmodules\\libvbar-m-dxmap.so": "55ebd66234d59490ab56f88398419dde",
+  "dxmodules\\libvbar-m-dxmqtt.so": "0cbeb2b46441ee89678516a1a941cd58",
+  "dxmodules\\libvbar-m-dxnet.so": "eed60270cabaf872983c6f905b0ceb03",
+  "dxmodules\\libvbar-m-dxsqlite.so": "15a0eb0d18b58cad3868f86e9edfb409",
+  "dxmodules\\libvbar-m-dxui.so": "ca22e1a0c52977749a32b2cc70e942a9",
+  "dxmodules\\libvbar-m-eid.so": "e7d1db4d1bfab4c462c9d22807099268",
+  "dxmodules\\libvbar-m-key.so": "f7f1f2ae6c9c1f298376375a8b16b6ee",
+  "dxmodules\\libvbar-m-net.so": "afa1adebb44fc9734b26b99e87e0728d",
+  "dxmodules\\libvbar-m-vgmqtt.so": "56e94165ba896867fbe3ead167022d3f",
+  "dxmodules\\libvbar-p-dxnfc.so": "14d17fe22a0dbfc00b13c4d9cef8512f",
+  "dxmodules\\libvbar-p-nfc.so": "f1a1f96558b2509c5b629790cec16386",
+  "dxmodules\\libvccore.so": "9c383ca78ee117ea3295baefb1f1fee2",
+  "dxmodules\\libyuv.so": "2c4faa3ab51260f5285cd91dda44b3a9",
+  "dxmodules\\mqttWorker.js": "4eedadbd41d6bd183cde2830a3347ad1",
+  "dxmodules\\netWorker.js": "c5d4c9022f8912b47249b14477aed70a",
+  "dxmodules\\nfcWorker.js": "88fadfc469cc397b66fd5e52db073bde",
+  "dxmodules\\uiBase.js": "9ea5cd2b5ed52d183fde2d87b8f70ca1",
+  "dxmodules\\uiButton.js": "8ffe0ffce9ac6b341c9993e260b52b05",
+  "dxmodules\\uiButtons.js": "52cb9727c2225f75ac6144e756a6d511",
+  "dxmodules\\uiCheckbox.js": "5aa8c851e8b2333cbe46cdd69452ab8c",
+  "dxmodules\\uiDropdown.js": "2b73bfacf3d4b115ab3997c83284c478",
+  "dxmodules\\uiFont.js": "257aa2f90ce2f0ace4095a03d3447b0b",
+  "dxmodules\\uiImage.js": "b2a0a963993474205bc7dc91c8696ec1",
+  "dxmodules\\uiKeyboard.js": "b225c62ff2f4b8aa0bdb675776b236a1",
+  "dxmodules\\uiLabel.js": "e0ae808d468459a6fedc7ba9a551359e",
+  "dxmodules\\uiLine.js": "cc18bc32c0a6f0f8db7992d6e0b4fd81",
+  "dxmodules\\uiList.js": "8b779a85cd54b25bc50ec616ed9f08d1",
+  "dxmodules\\uiSlider.js": "91b743902824b5decf5535dad49fc97e",
+  "dxmodules\\uiStyle.js": "60350cf77db84793bf093bda341f2cb9",
+  "dxmodules\\uiSwitch.js": "9a836405abe0b09f5a2940cf22698968",
+  "dxmodules\\uiTextarea.js": "0d5008a5a95b78ea8efde3408ba6fb4a",
+  "dxmodules\\uiUtils.js": "a04cc3baa5ba1dc6d1ab65b526464fa6",
+  "dxmodules\\uiView.js": "26fe7b992ac82bf5d45447f2921bff2f",
+  "dxmodules\\vgUartWorker.js": "fc3e9e0051836d5063c0eecf555d9521",
+  "README.md": "c472daef5243f3790f2faee1cf8e2255",
+  "README_CN.md": "a46b1c92c09f375881a49d8c42adf6b3",
+  "resource\\CN\\wav\\access_f.wav": "f951f3cc1f03aaa794231413fd4efcc6",
+  "resource\\CN\\wav\\access_s.wav": "6d1b31bdcaaa13ba719e3223b55d5235",
+  "resource\\CN\\wav\\btn11.wav": "a623797305d7b0e6b8cb6b2ab3d43591",
+  "resource\\CN\\wav\\btn12.wav": "26bbfc3eed36211713dca9afb423e168",
+  "resource\\CN\\wav\\btn13.wav": "67d6fe32693cb2e7653c2ff2141ce873",
+  "resource\\CN\\wav\\btn21.wav": "53071472fce6128fdd2ed304e4d78406",
+  "resource\\CN\\wav\\btn22.wav": "e35c87d370695099d3b6d7f512496395",
+  "resource\\CN\\wav\\btn23.wav": "f25db5592331f1e6deb67beecb3c1131",
+  "resource\\CN\\wav\\btn31.wav": "054a4f36ebda08fadca3162d955560bf",
+  "resource\\CN\\wav\\btn32.wav": "64eb5fef123eafd7b52108ebcd6bace9",
+  "resource\\CN\\wav\\btn33.wav": "67d6fe32693cb2e7653c2ff2141ce873",
+  "resource\\CN\\wav\\calibration_s.wav": "d2ff1f1f4a40bf4166130dc079939079",
+  "resource\\CN\\wav\\control_f.wav": "4dbaca7e4d227a720620b846544b469a",
+  "resource\\CN\\wav\\door_close.wav": "325ca8082f8e9fceb2c7eeeb78d8645b",
+  "resource\\CN\\wav\\door_open.wav": "f3b5291fc8babaffd32107198cdd5afa",
+  "resource\\CN\\wav\\emergency.wav": "a1855c22f3ef2f69d5c84d3a2852ae1f",
+  "resource\\CN\\wav\\emergency_f.wav": "946ac86e74b849ad8f1bec3615cf9b39",
+  "resource\\CN\\wav\\emergency_s.wav": "a717e3417891ff306225ac075ba28082",
+  "resource\\CN\\wav\\failed.wav": "891194e741b0bc8f6332f78eb607cc85",
+  "resource\\CN\\wav\\light_close.wav": "b1ac09e91ac4ce3825614ad1654a3f58",
+  "resource\\CN\\wav\\light_open.wav": "16b7b6b8c6eb469645a15e4a54a3e014",
+  "resource\\CN\\wav\\network.wav": "7bbc6d740918a20acfb5ef75df685bdb",
+  "resource\\CN\\wav\\read.wav": "c83edd035dc15f7a716644319e849215",
+  "resource\\CN\\wav\\recg_f.wav": "5cd4d88db4e3f8332b9e73fe05222c83",
+  "resource\\CN\\wav\\recg_s.wav": "4afadeb018b08518d5d3dd1cfc5e0d64",
+  "resource\\CN\\wav\\recognition.wav": "da00dd97d1e8ca0ed20dc43eb4daafc8",
+  "resource\\CN\\wav\\recognition_s.wav": "df9916d6fe3d285894668e63d1aeeb1d",
+  "resource\\CN\\wav\\register.wav": "a91d6ebb846dc834816a954168da1352",
+  "resource\\CN\\wav\\stranger.wav": "2e6690d7ddcd3609ca3e6d6717b61a9c",
+  "resource\\CN\\wav\\user2.wav": "868a9b15aac20b62457f98c955f4e5e0",
+  "resource\\CN\\wav\\user2_s.wav": "98904054df059be8cd69e08c302317e7",
+  "resource\\CN\\wav\\verify.wav": "2bc2b96e0ca05052985fda98fb552ef9",
+  "resource\\CN\\wav\\verify_10x_f.wav": "bf26ce11bbd801f5efeff8c9250f219f",
+  "resource\\CN\\wav\\verify_10x_s.wav": "2d04b22277844d9c35e08e4e2c67c11c",
+  "resource\\CN\\wav\\verify_200_f.wav": "393036b5fc28a3c04580593d59e26e7e",
+  "resource\\CN\\wav\\verify_200_s.wav": "585267371d37f3f45e3826ec7dcafbd3",
+  "resource\\CN\\wav\\verify_300_f.wav": "e44977e8b6dcac8adbf304894afd24e0",
+  "resource\\CN\\wav\\verify_300_s.wav": "d8e23a91e4999b2d77454aab824bd611",
+  "resource\\CN\\wav\\verify_400_f.wav": "05752c8c9c2bf4334943999842529d8b",
+  "resource\\CN\\wav\\verify_400_s.wav": "740a63ffe907dda0f2d0e14cb9a83f74",
+  "resource\\EN\\wav\\calibration_s.wav": "b5497547d9e7e6fb5b28ee307b27752b",
+  "resource\\EN\\wav\\network.wav": "1e8ccfd03ca83976fefdba1edcf1b194",
+  "resource\\EN\\wav\\read.wav": "8c1f6ee62c7bf74db5ecab28d3988eeb",
+  "resource\\EN\\wav\\recg_f.wav": "e303563b867dd6eaebac18679ca760df",
+  "resource\\EN\\wav\\recg_s.wav": "183a843b668aa919311a6d352af80f35",
+  "resource\\EN\\wav\\recognition.wav": "1c9e06bc338c49c120aa101b1fac8de0",
+  "resource\\EN\\wav\\recognition_s.wav": "f887f2b1615121bbe815fef7f64d3b92",
+  "resource\\EN\\wav\\register.wav": "de5d0048f840243fdd1392c09d9ac164",
+  "resource\\EN\\wav\\stranger.wav": "31775350903916827fdec25b9c65dd94",
+  "resource\\EN\\wav\\verify.wav": "2e77ec2c754e1dea329988d4e462aa2f",
+  "resource\\EN\\wav\\verify_10x_f.wav": "7ccc23490436b9f1de32200230953a62",
+  "resource\\EN\\wav\\verify_10x_s.wav": "0630e0410fca3c7fd7e701c69e8ea4bc",
+  "resource\\EN\\wav\\verify_200_f.wav": "64ce473b0f560cc1613469ab94197ce6",
+  "resource\\EN\\wav\\verify_200_s.wav": "e3d28c408cc3bef5461620c75b15abdf",
+  "resource\\EN\\wav\\verify_300_f.wav": "7fa0d7bf85d040b72a89cfb9e2f06bcf",
+  "resource\\EN\\wav\\verify_300_s.wav": "3e69fd763477d6cc30543d838f33d718",
+  "resource\\EN\\wav\\verify_400_f.wav": "d074b8f6e4e968b6d1984b123ed4d387",
+  "resource\\EN\\wav\\verify_400_s.wav": "9141136d3310a5fac5917d3f6056249f",
+  "resource\\font\\AlibabaPuHuiTi-2-65-Medium.ttf": "092a99ee52bbaef7481cc96c5b85b992",
+  "resource\\image\\4g.png": "e5b27ed5a596cb16c7ab695d82fe3014",
+  "resource\\image\\4g_dark.png": "414b3a9fcefd8ea6909158b51038d4d8",
+  "resource\\image\\accessCtrl.png": "6be30c8f648ec7153ae2c39a15884181",
+  "resource\\image\\add.png": "498480ce68e4d6047eb74d3aa5229f56",
+  "resource\\image\\advance.png": "d98aeb99a04163bce23b6c2638cd705a",
+  "resource\\image\\app.png": "7640c7358a3f5dba1f887b8413b93a9d",
+  "resource\\image\\app_btn.png": "aa325cea46fd3918c86d76bf009b1663",
+  "resource\\image\\app_qrcode.png": "0a20655d02ff0e473106bf41f7c9687b",
+  "resource\\image\\arrow_right.png": "edc6876d6fa1e2d0be2e606c73e0f2ec",
+  "resource\\image\\back.png": "aa5869ff78051dbdc5f688f1805064da",
+  "resource\\image\\background.jpg": "90d464f4221f62132ebf74e69446b6d7",
+  "resource\\image\\backspace.png": "26302e37dd8618e92c3a47d68039d0ec",
+  "resource\\image\\back_2.png": "b3f16ab01606d85c2c70124d50b3af1b",
+  "resource\\image\\basic.png": "84eedd84efdc5fdb54138dd29cf6fc41",
+  "resource\\image\\black_btn.png": "13ee1720aff247ba3f8e22e00f89a316",
+  "resource\\image\\card.png": "c05047d2ad6549db001d08790cb5d9ff",
+  "resource\\image\\close.png": "a5353c231df804fcc4577672ab3a4302",
+  "resource\\image\\close_small.png": "7d6cddddc38ce8d4950789169213add4",
+  "resource\\image\\cloudCert.png": "4481cfb9c2d1f44f0a0dd0489cb6fc2b",
+  "resource\\image\\co2_f.png": "7e6f00c03b71a4dbe439491083ca731c",
+  "resource\\image\\co2_s.png": "4fb691286b8856f1ed25ef8bacdb6099",
+  "resource\\image\\commMgmt.png": "5cd157e1b8c82fdf9ddba1f6d5047b9b",
+  "resource\\image\\config.png": "50d2091b9f7fba5915dbed0aa0dcf918",
+  "resource\\image\\config_btn.png": "e54cbc27d30e7c6480b83107a631e7ef",
+  "resource\\image\\delete.png": "014bad6d9a94a133c58ef350e198101e",
+  "resource\\image\\delete_fill.png": "947fc08278354a1151d5599382c2c5f3",
+  "resource\\image\\deviceInfo.png": "3e40246e01c1f7eede4d76fcbba33825",
+  "resource\\image\\devInfo.png": "1a80aba6780a45f8775bdfdcff4df23a",
+  "resource\\image\\doorControl.png": "68993ef92bb8c6b2d0dab2c75cc7533d",
+  "resource\\image\\down.png": "c4d5c1883db4694ccedb7c1140d89da9",
+  "resource\\image\\emergencyOpen.png": "890877dee840dabe60487f8ce57b41f6",
+  "resource\\image\\empty.png": "8283ac78099d9c13ef4b552ce86f5c38",
+  "resource\\image\\enter.png": "787e076256c8a47e07f2091a57585fb5",
+  "resource\\image\\enter_b.png": "02cb6c84fec128a639e3cf0828a6ee5f",
+  "resource\\image\\ethernet.png": "f3abb111d96a11a56f7ed77b21abab4c",
+  "resource\\image\\ethernet_dark.png": "10656303a6d22e204014f55ed0fb3efb",
+  "resource\\image\\eth_disable.png": "7017f5cc2c9b4f802f082f6c0f5bb581",
+  "resource\\image\\eth_enable.png": "84d1334e524ac669c3b79e8a69b41eb1",
+  "resource\\image\\eye-fill.png": "9ae71914bd47423be04d0a22eb4f3995",
+  "resource\\image\\eye-off.png": "295c3e8255ced50cf2667ecda524e11e",
+  "resource\\image\\eye_fill.png": "d0ac0d07f13e02e5fae7a12a0858ec49",
+  "resource\\image\\eye_fill_show.png": "265cf669797b94a138982c01c29d0bd9",
+  "resource\\image\\face.png": "d695a5f29dbf051fc0c6e0d4e177f5c5",
+  "resource\\image\\faceAdd.png": "5e0e3d4eb3f034a179a8eef5c08d4c63",
+  "resource\\image\\faceEmpty.png": "9ef3bd1d776183e203e69d5c91e4b129",
+  "resource\\image\\faceError.png": "19841af9136d4483642a254ab1a6f57c",
+  "resource\\image\\faceRec.png": "f1bfcb61f4642c6c1bbc04856fb57905",
+  "resource\\image\\faceRec2.png": "580c72783b4cfc64ec0a9593e77c456a",
+  "resource\\image\\factoryTest.png": "4bdb36420046870efcabd4a040e31913",
+  "resource\\image\\failBg.png": "5d6dca3cc98032a10ef4bc0658f7e546",
+  "resource\\image\\grey_btn.png": "b0ca6e44c0e01a17d0bdda5f7e057cc2",
+  "resource\\image\\help.png": "7d75da0510ca74870858a639882dc2ef",
+  "resource\\image\\idleImage.jpg": "90d464f4221f62132ebf74e69446b6d7",
+  "resource\\image\\input_bg.png": "8a8f5c43f1118869a7679ccbaaf47de2",
+  "resource\\image\\light_close.png": "607b38280bb5321327cacce5bd6c3fe9",
+  "resource\\image\\light_open.png": "1a8df3753b6f0df9e7abb5b53dabd72e",
+  "resource\\image\\localUser.png": "6429f43f7fee002d66d50a3d92a087da",
+  "resource\\image\\lock.png": "c1419aa2a9c9da4b7dbf3529a1af37f3",
+  "resource\\image\\logo.png": "5768b9344bedc53096d2227bee5d52d4",
+  "resource\\image\\menu_btn.png": "df98739cd4804d08b23eaf33bb92e1bc",
+  "resource\\image\\mini_app.png": "82ee9005b5d162a6fbb0d32764088da4",
+  "resource\\image\\mini_background.png": "620bf06dbfffe37f717b91fb3ed8ef40",
+  "resource\\image\\mini_config.png": "6bf78553fb53673a89e80613cfbee4c1",
+  "resource\\image\\mini_password.png": "6892385a457e084953bcf9acb2ae9957",
+  "resource\\image\\mqtt.png": "542ebc6bdbb66ea0f25cf29aeb9d264c",
+  "resource\\image\\mqtt_dark.png": "d4aab5adc128846c47a3b8bb015c757b",
+  "resource\\image\\mqtt_enable.png": "fc766f5fcbb95eca648ee10d421cc8fe",
+  "resource\\image\\network.png": "0a0119e3d5fce101b28575a4e44aaf7e",
+  "resource\\image\\networkSetting.png": "3e83d354e8293ed112fe7cc405b94187",
+  "resource\\image\\network_dark.png": "3c5f8ce5732e95ad613cdd41dc5adbc0",
+  "resource\\image\\o2_f.png": "b787951eba880b3ae82b42594b4e30df",
+  "resource\\image\\o2_s.png": "50564fb865bb7f5ed0352e43ea17d853",
+  "resource\\image\\ph3_f.png": "e95a348c887298dc4ed0555c577ea5bb",
+  "resource\\image\\ph3_s.png": "96e68d741b75fcd6938a6909014cccb0",
+  "resource\\image\\pwd_btn.png": "8764458bee98bff728445837e126231e",
+  "resource\\image\\qrcode_small.png": "285bbe7e8f968c8bf4506a563dffcac2",
+  "resource\\image\\recordQuery.png": "d340255a0c2342382bff6f8c57f6376b",
+  "resource\\image\\recQuery.png": "1b8c58663a6e61f4f885e784ee4e87d4",
+  "resource\\image\\rectangle.png": "394e2e483120908674f6de7fb879bfcf",
+  "resource\\image\\register.png": "7fa975d92007703532ba8011f2a0109f",
+  "resource\\image\\right.png": "a6f6bc770ad7a8220effcc96e750aaaa",
+  "resource\\image\\select_arrow.png": "9d82daa1092375abc413d581f36aaf2d",
+  "resource\\image\\setting.png": "92365fd93f2cfa63c7901ce3d8900a42",
+  "resource\\image\\setting32.png": "e531bf8a9ce7f6cf93a8ea9baf95377c",
+  "resource\\image\\space.png": "de9816e31308bd7ce187fe03ab634a37",
+  "resource\\image\\successBg.png": "1ef294bd7e1688bba47c2337906b1d1d",
+  "resource\\image\\success_fill.png": "09166b0cd4da44b76b4f6cdc2c550103",
+  "resource\\image\\sysSettings.png": "0a84bbe887481a1cce1ca562f83d5b89",
+  "resource\\image\\systemSetting.png": "9aee20d073df321250a5bbc57d16d5f1",
+  "resource\\image\\sys_info.png": "20dc23c019d07cd2c3ce32a160b7b63f",
+  "resource\\image\\title_bg.png": "82fbdcc4133899d03072dcd57a92f203",
+  "resource\\image\\trackFace.png": "e90f92eb629563ede01aadca2b719de9",
+  "resource\\image\\unlock.png": "7b97b659c36d3ba4f435f44792b90a80",
+  "resource\\image\\user.png": "6429f43f7fee002d66d50a3d92a087da",
+  "resource\\image\\userGuide.png": "3227210f670f66cd6c29641e1212b0b8",
+  "resource\\image\\userMgmt.png": "5dad96f344513f970c2b582d7feb537d",
+  "resource\\image\\user_1.png": "36ab26e22dc39ea28c03f05f4ab891ce",
+  "resource\\image\\user_f.png": "d82d235224deccd2235ab15dbf1fda26",
+  "resource\\image\\user_s.png": "709953f3695cae9ac1bb50533f1a96ba",
+  "resource\\image\\user_w.png": "bc2ca556f37181815c0093d802f2f24f",
+  "resource\\image\\view_f.png": "4fbdda957ef2966bc4938990725d0246",
+  "resource\\image\\view_s.png": "93ddad11d282c5a8f56233682290b38c",
+  "resource\\image\\vip.png": "0e816b4860ee87ed1169154e3f0fc524",
+  "resource\\image\\voiceBroadcast.png": "e6f1a31ba7159962d18b77deef71c106",
+  "resource\\image\\wifi.png": "fd668b648ac984ed92fad8e40e151283",
+  "resource\\image\\wifi_dark.png": "37505f892ac6a43cb8dc5ea685de9740",
+  "resource\\langPack.js": "b537e7ad7b7bd36ebef146692604007d",
+  "resource\\wav\\alarm.wav": "fe9d43cfb930f873973cc31fd6e8c132",
+  "src\\common\\consts\\configConst.js": "8cdbeff06611f7c94fc349afb2d04364",
+  "src\\common\\utils\\utils.js": "f45a9074748680b00ba663ad6490acf0",
+  "src\\config.json": "c6c52fdf036881dd11081f96b491fee5",
+  "src\\controller.js": "f09517062ac2a8641ea17909f9e635fd",
+  "src\\driver.js": "02c38e2dcc749c50fb348b94629278d0",
+  "src\\main.js": "a893be0e60fcd2ca32c94baf8534f996",
+  "src\\screen.js": "a2f377ed5832bb9139dfcaadffe091c7",
+  "src\\service\\accessService.js": "ca2abf5ea0cae58a1fc9ccffb9f03454",
+  "src\\service\\codeService.js": "63934baff614eedf7f8c7ee4855f9ebe",
+  "src\\service\\configService.js": "d991f7261781465e306cd9d4548eab4d",
+  "src\\service\\faceService.js": "4e6ef420f61bb617e3b57491f9305cb2",
+  "src\\service\\gpiokeyService.js": "71c8f8a2589492153671f1d7ed96e6c8",
+  "src\\service\\grainService.js": "99f05184d3fcdf5c4e54fce08500267b",
+  "src\\service\\mqttService.js": "78d18810234846a26b49161dc6f193af",
+  "src\\service\\nfcService.js": "45705bc6a95206927085f11e7208cac2",
+  "src\\service\\platService.js": "a38387366ed212029bb46c6d3a85f2e9",
+  "src\\service\\sqliteService.js": "f2f0864ae07d893789bfc1666b584410",
+  "src\\service\\uart485Service.js": "c62ad21c538095f950dffe12d6770aa0",
+  "src\\services.js": "b87698f1e9e03bcfac820956034b06fe",
+  "src\\ui.js": "e9adc3aac685e711427667fa7705be6f",
+  "src\\view\\appView.js": "3ada10f0136eb464c035aec809a6e600",
+  "src\\view\\config\\configView.js": "6e30bb6aa2a9f6e6187dc6d86d832901",
+  "src\\view\\config\\identityVerificationView.js": "aa8cdd417184b2bdcef1a6cbd49df487",
+  "src\\view\\config\\menu\\cloudCertView.js": "7c9181ccfa5b5e96a234f1f55307ccb9",
+  "src\\view\\config\\menu\\deviceInfo\\dataCapacityInfoView.js": "9b6d8db4b83758d778f84ac2a1a266c8",
+  "src\\view\\config\\menu\\deviceInfo\\systemInfoView.js": "9396136cd353b10bb9a56f9bda2315d5",
+  "src\\view\\config\\menu\\deviceInfoView.js": "b33452d2a4d7188c5d14c6f76b726e90",
+  "src\\view\\config\\menu\\dockingSetting.js": "13a156aa4889a7d032a6fa26605e85b8",
+  "src\\view\\config\\menu\\doorControlView.js": "ffd1d5bc1bb7c652bc678c52e9969fda",
+  "src\\view\\config\\menu\\factoryTestView.js": "9588321c8282257e9707ebedb5920cda",
+  "src\\view\\config\\menu\\helpView.js": "00e750b2b637dc318f75e840d901fb5c",
+  "src\\view\\config\\menu\\localUser\\faceEnterView.js": "d993d07711e15cf5f0fee01a22753bfa",
+  "src\\view\\config\\menu\\localUser\\localUserAddView.js": "bf4646521acd0e14832eb732bc424e77",
+  "src\\view\\config\\menu\\localUserView.js": "c870b92aaaec5aff368e07e9f254e8aa",
+  "src\\view\\config\\menu\\networkSettingView.js": "325d70ed8ab1e170ffc1fa03fff637f5",
+  "src\\view\\config\\menu\\recordQuery\\recordQueryDetailView.js": "7077207b15bf1d7eae3a9a01dc68dc77",
+  "src\\view\\config\\menu\\recordQueryView.js": "67b573825af0639a4103bdc97b0f2c4a",
+  "src\\view\\config\\menu\\systemSetting\\displaySettingView.js": "c57f3b9faf85e048864c08d592481a72",
+  "src\\view\\config\\menu\\systemSetting\\faceRecognitionSettingView.js": "4d6b4e8b6c0f6e0ccbaaaa169e65b780",
+  "src\\view\\config\\menu\\systemSetting\\passLogSettingView.js": "d51958ac39b104846586b1ed6590414c",
+  "src\\view\\config\\menu\\systemSetting\\passwordManagementView.js": "98a6ca138cc1e2bc33ff6a3248e11263",
+  "src\\view\\config\\menu\\systemSetting\\passwordOpenDoorSettingView.js": "6e2ab3793e6c569097b702c339ef1602",
+  "src\\view\\config\\menu\\systemSetting\\swipeCardRecognitionSettingView.js": "871b483fbc3d778df95b803c130101e1",
+  "src\\view\\config\\menu\\systemSetting\\timeSettingView.js": "6950faa3a3296a573d048eb782c0e6ca",
+  "src\\view\\config\\menu\\systemSettingView.js": "ca3ac7b0e0390c7d542b62d569f57b24",
+  "src\\view\\config\\menu\\voiceBroadcastView.js": "a809af8acdae03f15c6e677bef6f20a1",
+  "src\\view\\config\\newPwdView.js": "32e3cfb0cc7f88361f1c69797cdb14b8",
+  "src\\view\\emergencyPwdView.js": "c6413bc04d38d54e57f590ce44204bcb",
+  "src\\view\\i18n.js": "94f43798d35026189125bf2534d1bffd",
+  "src\\view\\idleView.js": "b95c100ae4b2757ea2b0844a3df35c9e",
+  "src\\view\\mainView.js": "ec96a69994b99ed36778338198f74765",
+  "src\\view\\pinyin\\dict.js": "e40764bfc6bab80119c584315c0c48b7",
+  "src\\view\\pinyin\\pinyin.js": "c0809d9d1ebe5937cb6831b2b70db439",
+  "src\\view\\pwdView.js": "226b8b83a13b82cc925519ae051f8b3f",
+  "src\\view\\topView.js": "c9d8a4e3bc362edb1a5007135323beea",
+  "src\\view\\viewUtils.js": "ceaaad4fb40024b448a66a03911a7279",
+  "src\\worker\\accessWorker.js": "1b1253b5a7fbb2e733be2a9b0714ecca",
+  "src\\worker\\httpWorker.js": "47ddc63bdd95ecf36f7eaaa5f409424c"
+}
\ No newline at end of file
diff --git a/vf205_access/.temp/zipFolder/VF105_V12/dxAlsa/1.0.0.zip b/vf205_access/.temp/zipFolder/VF105_V12/dxAlsa/1.0.0.zip
new file mode 100644
index 0000000..71b6970
--- /dev/null
+++ b/vf205_access/.temp/zipFolder/VF105_V12/dxAlsa/1.0.0.zip
Binary files differ
diff --git a/vf205_access/.temp/zipFolder/VF105_V12/dxAudio/1.0.1.zip b/vf205_access/.temp/zipFolder/VF105_V12/dxAudio/1.0.1.zip
new file mode 100644
index 0000000..bedd38f
--- /dev/null
+++ b/vf205_access/.temp/zipFolder/VF105_V12/dxAudio/1.0.1.zip
Binary files differ
diff --git a/vf205_access/.temp/zipFolder/VF105_V12/dxAudio/2.0.0.zip b/vf205_access/.temp/zipFolder/VF105_V12/dxAudio/2.0.0.zip
new file mode 100644
index 0000000..5e10702
--- /dev/null
+++ b/vf205_access/.temp/zipFolder/VF105_V12/dxAudio/2.0.0.zip
Binary files differ
diff --git a/vf205_access/.temp/zipFolder/VF105_V12/dxBase64/1.0.0.zip b/vf205_access/.temp/zipFolder/VF105_V12/dxBase64/1.0.0.zip
new file mode 100644
index 0000000..633273c
--- /dev/null
+++ b/vf205_access/.temp/zipFolder/VF105_V12/dxBase64/1.0.0.zip
Binary files differ
diff --git a/vf205_access/.temp/zipFolder/VF105_V12/dxBase64/2.0.0.zip b/vf205_access/.temp/zipFolder/VF105_V12/dxBase64/2.0.0.zip
new file mode 100644
index 0000000..633273c
--- /dev/null
+++ b/vf205_access/.temp/zipFolder/VF105_V12/dxBase64/2.0.0.zip
Binary files differ
diff --git a/vf205_access/.temp/zipFolder/VF105_V12/dxCameraCalibration/1.0.0.zip b/vf205_access/.temp/zipFolder/VF105_V12/dxCameraCalibration/1.0.0.zip
new file mode 100644
index 0000000..814f496
--- /dev/null
+++ b/vf205_access/.temp/zipFolder/VF105_V12/dxCameraCalibration/1.0.0.zip
Binary files differ
diff --git a/vf205_access/.temp/zipFolder/VF105_V12/dxCameraCalibration/test.zip b/vf205_access/.temp/zipFolder/VF105_V12/dxCameraCalibration/test.zip
new file mode 100644
index 0000000..974da4e
--- /dev/null
+++ b/vf205_access/.temp/zipFolder/VF105_V12/dxCameraCalibration/test.zip
Binary files differ
diff --git a/vf205_access/.temp/zipFolder/VF105_V12/dxCapturer/1.0.0.zip b/vf205_access/.temp/zipFolder/VF105_V12/dxCapturer/1.0.0.zip
new file mode 100644
index 0000000..e727818
--- /dev/null
+++ b/vf205_access/.temp/zipFolder/VF105_V12/dxCapturer/1.0.0.zip
Binary files differ
diff --git a/vf205_access/.temp/zipFolder/VF105_V12/dxCapturer/1.0.1.zip b/vf205_access/.temp/zipFolder/VF105_V12/dxCapturer/1.0.1.zip
new file mode 100644
index 0000000..809e931
--- /dev/null
+++ b/vf205_access/.temp/zipFolder/VF105_V12/dxCapturer/1.0.1.zip
Binary files differ
diff --git a/vf205_access/.temp/zipFolder/VF105_V12/dxCapturer/1.0.2.zip b/vf205_access/.temp/zipFolder/VF105_V12/dxCapturer/1.0.2.zip
new file mode 100644
index 0000000..e2a4d0d
--- /dev/null
+++ b/vf205_access/.temp/zipFolder/VF105_V12/dxCapturer/1.0.2.zip
Binary files differ
diff --git a/vf205_access/.temp/zipFolder/VF105_V12/dxCapturer/1.0.3.zip b/vf205_access/.temp/zipFolder/VF105_V12/dxCapturer/1.0.3.zip
new file mode 100644
index 0000000..3460d10
--- /dev/null
+++ b/vf205_access/.temp/zipFolder/VF105_V12/dxCapturer/1.0.3.zip
Binary files differ
diff --git a/vf205_access/.temp/zipFolder/VF105_V12/dxCommon/1.0.0.zip b/vf205_access/.temp/zipFolder/VF105_V12/dxCommon/1.0.0.zip
new file mode 100644
index 0000000..ce067d5
--- /dev/null
+++ b/vf205_access/.temp/zipFolder/VF105_V12/dxCommon/1.0.0.zip
Binary files differ
diff --git a/vf205_access/.temp/zipFolder/VF105_V12/dxCommon/1.0.1.zip b/vf205_access/.temp/zipFolder/VF105_V12/dxCommon/1.0.1.zip
new file mode 100644
index 0000000..0efae86
--- /dev/null
+++ b/vf205_access/.temp/zipFolder/VF105_V12/dxCommon/1.0.1.zip
Binary files differ
diff --git a/vf205_access/.temp/zipFolder/VF105_V12/dxCommonUtils/1.0.1.zip b/vf205_access/.temp/zipFolder/VF105_V12/dxCommonUtils/1.0.1.zip
new file mode 100644
index 0000000..e8e15f9
--- /dev/null
+++ b/vf205_access/.temp/zipFolder/VF105_V12/dxCommonUtils/1.0.1.zip
Binary files differ
diff --git a/vf205_access/.temp/zipFolder/VF105_V12/dxConfig/2.0.0.zip b/vf205_access/.temp/zipFolder/VF105_V12/dxConfig/2.0.0.zip
new file mode 100644
index 0000000..066e3c8
--- /dev/null
+++ b/vf205_access/.temp/zipFolder/VF105_V12/dxConfig/2.0.0.zip
Binary files differ
diff --git a/vf205_access/.temp/zipFolder/VF105_V12/dxCryptoES/2.0.0.zip b/vf205_access/.temp/zipFolder/VF105_V12/dxCryptoES/2.0.0.zip
new file mode 100644
index 0000000..cefaedd
--- /dev/null
+++ b/vf205_access/.temp/zipFolder/VF105_V12/dxCryptoES/2.0.0.zip
Binary files differ
diff --git a/vf205_access/.temp/zipFolder/VF105_V12/dxDisplay/1.0.0.zip b/vf205_access/.temp/zipFolder/VF105_V12/dxDisplay/1.0.0.zip
new file mode 100644
index 0000000..de43995
--- /dev/null
+++ b/vf205_access/.temp/zipFolder/VF105_V12/dxDisplay/1.0.0.zip
Binary files differ
diff --git a/vf205_access/.temp/zipFolder/VF105_V12/dxDisplay/2.0.0.zip b/vf205_access/.temp/zipFolder/VF105_V12/dxDisplay/2.0.0.zip
new file mode 100644
index 0000000..e25dc30
--- /dev/null
+++ b/vf205_access/.temp/zipFolder/VF105_V12/dxDisplay/2.0.0.zip
Binary files differ
diff --git a/vf205_access/.temp/zipFolder/VF105_V12/dxDriver/1.1.0.zip b/vf205_access/.temp/zipFolder/VF105_V12/dxDriver/1.1.0.zip
new file mode 100644
index 0000000..b495407
--- /dev/null
+++ b/vf205_access/.temp/zipFolder/VF105_V12/dxDriver/1.1.0.zip
Binary files differ
diff --git a/vf205_access/.temp/zipFolder/VF105_V12/dxDriver/1.1.4.zip b/vf205_access/.temp/zipFolder/VF105_V12/dxDriver/1.1.4.zip
new file mode 100644
index 0000000..de46bf0
--- /dev/null
+++ b/vf205_access/.temp/zipFolder/VF105_V12/dxDriver/1.1.4.zip
Binary files differ
diff --git a/vf205_access/.temp/zipFolder/VF105_V12/dxDriver/2.0.0.zip b/vf205_access/.temp/zipFolder/VF105_V12/dxDriver/2.0.0.zip
new file mode 100644
index 0000000..341100e
--- /dev/null
+++ b/vf205_access/.temp/zipFolder/VF105_V12/dxDriver/2.0.0.zip
Binary files differ
diff --git a/vf205_access/.temp/zipFolder/VF105_V12/dxEid/1.0.0.zip b/vf205_access/.temp/zipFolder/VF105_V12/dxEid/1.0.0.zip
new file mode 100644
index 0000000..14140bd
--- /dev/null
+++ b/vf205_access/.temp/zipFolder/VF105_V12/dxEid/1.0.0.zip
Binary files differ
diff --git a/vf205_access/.temp/zipFolder/VF105_V12/dxEventBus/2.0.0.zip b/vf205_access/.temp/zipFolder/VF105_V12/dxEventBus/2.0.0.zip
new file mode 100644
index 0000000..6c3a0fd
--- /dev/null
+++ b/vf205_access/.temp/zipFolder/VF105_V12/dxEventBus/2.0.0.zip
Binary files differ
diff --git a/vf205_access/.temp/zipFolder/VF105_V12/dxEventBus/2.0.2.zip b/vf205_access/.temp/zipFolder/VF105_V12/dxEventBus/2.0.2.zip
new file mode 100644
index 0000000..408f14c
--- /dev/null
+++ b/vf205_access/.temp/zipFolder/VF105_V12/dxEventBus/2.0.2.zip
Binary files differ
diff --git a/vf205_access/.temp/zipFolder/VF105_V12/dxEventBus/2.0.3.zip b/vf205_access/.temp/zipFolder/VF105_V12/dxEventBus/2.0.3.zip
new file mode 100644
index 0000000..d7b3c50
--- /dev/null
+++ b/vf205_access/.temp/zipFolder/VF105_V12/dxEventBus/2.0.3.zip
Binary files differ
diff --git a/vf205_access/.temp/zipFolder/VF105_V12/dxFace/1.1.8.zip b/vf205_access/.temp/zipFolder/VF105_V12/dxFace/1.1.8.zip
new file mode 100644
index 0000000..8e5d0e3
--- /dev/null
+++ b/vf205_access/.temp/zipFolder/VF105_V12/dxFace/1.1.8.zip
Binary files differ
diff --git a/vf205_access/.temp/zipFolder/VF105_V12/dxFacial/1.0.0.zip b/vf205_access/.temp/zipFolder/VF105_V12/dxFacial/1.0.0.zip
new file mode 100644
index 0000000..4862fe6
--- /dev/null
+++ b/vf205_access/.temp/zipFolder/VF105_V12/dxFacial/1.0.0.zip
Binary files differ
diff --git a/vf205_access/.temp/zipFolder/VF105_V12/dxGpio/1.0.0.zip b/vf205_access/.temp/zipFolder/VF105_V12/dxGpio/1.0.0.zip
new file mode 100644
index 0000000..5c31150
--- /dev/null
+++ b/vf205_access/.temp/zipFolder/VF105_V12/dxGpio/1.0.0.zip
Binary files differ
diff --git a/vf205_access/.temp/zipFolder/VF105_V12/dxGpioKey/1.0.0.zip b/vf205_access/.temp/zipFolder/VF105_V12/dxGpioKey/1.0.0.zip
new file mode 100644
index 0000000..d85fc45
--- /dev/null
+++ b/vf205_access/.temp/zipFolder/VF105_V12/dxGpioKey/1.0.0.zip
Binary files differ
diff --git a/vf205_access/.temp/zipFolder/VF105_V12/dxGpioKey/1.0.1.zip b/vf205_access/.temp/zipFolder/VF105_V12/dxGpioKey/1.0.1.zip
new file mode 100644
index 0000000..3037e37
--- /dev/null
+++ b/vf205_access/.temp/zipFolder/VF105_V12/dxGpioKey/1.0.1.zip
Binary files differ
diff --git a/vf205_access/.temp/zipFolder/VF105_V12/dxHttp/1.0.0.zip b/vf205_access/.temp/zipFolder/VF105_V12/dxHttp/1.0.0.zip
new file mode 100644
index 0000000..3420ede
--- /dev/null
+++ b/vf205_access/.temp/zipFolder/VF105_V12/dxHttp/1.0.0.zip
Binary files differ
diff --git a/vf205_access/.temp/zipFolder/VF105_V12/dxHttpClient/2.0.3.zip b/vf205_access/.temp/zipFolder/VF105_V12/dxHttpClient/2.0.3.zip
new file mode 100644
index 0000000..9b7112f
--- /dev/null
+++ b/vf205_access/.temp/zipFolder/VF105_V12/dxHttpClient/2.0.3.zip
Binary files differ
diff --git a/vf205_access/.temp/zipFolder/VF105_V12/dxHttpClient/2.0.4.zip b/vf205_access/.temp/zipFolder/VF105_V12/dxHttpClient/2.0.4.zip
new file mode 100644
index 0000000..511e164
--- /dev/null
+++ b/vf205_access/.temp/zipFolder/VF105_V12/dxHttpClient/2.0.4.zip
Binary files differ
diff --git a/vf205_access/.temp/zipFolder/VF105_V12/dxHttpServer/1.0.1.zip b/vf205_access/.temp/zipFolder/VF105_V12/dxHttpServer/1.0.1.zip
new file mode 100644
index 0000000..90c429e
--- /dev/null
+++ b/vf205_access/.temp/zipFolder/VF105_V12/dxHttpServer/1.0.1.zip
Binary files differ
diff --git a/vf205_access/.temp/zipFolder/VF105_V12/dxHttpServer/1.0.5.zip b/vf205_access/.temp/zipFolder/VF105_V12/dxHttpServer/1.0.5.zip
new file mode 100644
index 0000000..c128e69
--- /dev/null
+++ b/vf205_access/.temp/zipFolder/VF105_V12/dxHttpServer/1.0.5.zip
Binary files differ
diff --git a/vf205_access/.temp/zipFolder/VF105_V12/dxLogger/2.0.0.zip b/vf205_access/.temp/zipFolder/VF105_V12/dxLogger/2.0.0.zip
new file mode 100644
index 0000000..c1f6d3e
--- /dev/null
+++ b/vf205_access/.temp/zipFolder/VF105_V12/dxLogger/2.0.0.zip
Binary files differ
diff --git a/vf205_access/.temp/zipFolder/VF105_V12/dxLogger/2.0.3.zip b/vf205_access/.temp/zipFolder/VF105_V12/dxLogger/2.0.3.zip
new file mode 100644
index 0000000..9eb380e
--- /dev/null
+++ b/vf205_access/.temp/zipFolder/VF105_V12/dxLogger/2.0.3.zip
Binary files differ
diff --git a/vf205_access/.temp/zipFolder/VF105_V12/dxMap/1.0.0.zip b/vf205_access/.temp/zipFolder/VF105_V12/dxMap/1.0.0.zip
new file mode 100644
index 0000000..0e44130
--- /dev/null
+++ b/vf205_access/.temp/zipFolder/VF105_V12/dxMap/1.0.0.zip
Binary files differ
diff --git a/vf205_access/.temp/zipFolder/VF105_V12/dxMap/2.0.1.zip b/vf205_access/.temp/zipFolder/VF105_V12/dxMap/2.0.1.zip
new file mode 100644
index 0000000..2294988
--- /dev/null
+++ b/vf205_access/.temp/zipFolder/VF105_V12/dxMap/2.0.1.zip
Binary files differ
diff --git a/vf205_access/.temp/zipFolder/VF105_V12/dxMqtt/1.0.1.zip b/vf205_access/.temp/zipFolder/VF105_V12/dxMqtt/1.0.1.zip
new file mode 100644
index 0000000..b59864e
--- /dev/null
+++ b/vf205_access/.temp/zipFolder/VF105_V12/dxMqtt/1.0.1.zip
Binary files differ
diff --git a/vf205_access/.temp/zipFolder/VF105_V12/dxMqttClient/1.0.1.zip b/vf205_access/.temp/zipFolder/VF105_V12/dxMqttClient/1.0.1.zip
new file mode 100644
index 0000000..5fdd302
--- /dev/null
+++ b/vf205_access/.temp/zipFolder/VF105_V12/dxMqttClient/1.0.1.zip
Binary files differ
diff --git a/vf205_access/.temp/zipFolder/VF105_V12/dxNet/1.0.0.zip b/vf205_access/.temp/zipFolder/VF105_V12/dxNet/1.0.0.zip
new file mode 100644
index 0000000..4406132
--- /dev/null
+++ b/vf205_access/.temp/zipFolder/VF105_V12/dxNet/1.0.0.zip
Binary files differ
diff --git a/vf205_access/.temp/zipFolder/VF105_V12/dxNet/1.0.2.zip b/vf205_access/.temp/zipFolder/VF105_V12/dxNet/1.0.2.zip
new file mode 100644
index 0000000..84d2120
--- /dev/null
+++ b/vf205_access/.temp/zipFolder/VF105_V12/dxNet/1.0.2.zip
Binary files differ
diff --git a/vf205_access/.temp/zipFolder/VF105_V12/dxNetwork/1.0.0.zip b/vf205_access/.temp/zipFolder/VF105_V12/dxNetwork/1.0.0.zip
new file mode 100644
index 0000000..5b68fe0
--- /dev/null
+++ b/vf205_access/.temp/zipFolder/VF105_V12/dxNetwork/1.0.0.zip
Binary files differ
diff --git a/vf205_access/.temp/zipFolder/VF105_V12/dxNfc/1.0.0.zip b/vf205_access/.temp/zipFolder/VF105_V12/dxNfc/1.0.0.zip
new file mode 100644
index 0000000..c7ea2de
--- /dev/null
+++ b/vf205_access/.temp/zipFolder/VF105_V12/dxNfc/1.0.0.zip
Binary files differ
diff --git a/vf205_access/.temp/zipFolder/VF105_V12/dxNfcCard/1.0.0.zip b/vf205_access/.temp/zipFolder/VF105_V12/dxNfcCard/1.0.0.zip
new file mode 100644
index 0000000..4145a05
--- /dev/null
+++ b/vf205_access/.temp/zipFolder/VF105_V12/dxNfcCard/1.0.0.zip
Binary files differ
diff --git a/vf205_access/.temp/zipFolder/VF105_V12/dxNfcCard/1.0.1.zip b/vf205_access/.temp/zipFolder/VF105_V12/dxNfcCard/1.0.1.zip
new file mode 100644
index 0000000..46c4fb9
--- /dev/null
+++ b/vf205_access/.temp/zipFolder/VF105_V12/dxNfcCard/1.0.1.zip
Binary files differ
diff --git a/vf205_access/.temp/zipFolder/VF105_V12/dxNtp/2.0.0.zip b/vf205_access/.temp/zipFolder/VF105_V12/dxNtp/2.0.0.zip
new file mode 100644
index 0000000..122d16d
--- /dev/null
+++ b/vf205_access/.temp/zipFolder/VF105_V12/dxNtp/2.0.0.zip
Binary files differ
diff --git a/vf205_access/.temp/zipFolder/VF105_V12/dxNtp/2.0.2.zip b/vf205_access/.temp/zipFolder/VF105_V12/dxNtp/2.0.2.zip
new file mode 100644
index 0000000..b4dbb22
--- /dev/null
+++ b/vf205_access/.temp/zipFolder/VF105_V12/dxNtp/2.0.2.zip
Binary files differ
diff --git a/vf205_access/.temp/zipFolder/VF105_V12/dxNtp/2.0.3.zip b/vf205_access/.temp/zipFolder/VF105_V12/dxNtp/2.0.3.zip
new file mode 100644
index 0000000..0d5693c
--- /dev/null
+++ b/vf205_access/.temp/zipFolder/VF105_V12/dxNtp/2.0.3.zip
Binary files differ
diff --git a/vf205_access/.temp/zipFolder/VF105_V12/dxOs/1.0.0.zip b/vf205_access/.temp/zipFolder/VF105_V12/dxOs/1.0.0.zip
new file mode 100644
index 0000000..63b21be
--- /dev/null
+++ b/vf205_access/.temp/zipFolder/VF105_V12/dxOs/1.0.0.zip
Binary files differ
diff --git a/vf205_access/.temp/zipFolder/VF105_V12/dxOta/1.0.0.zip b/vf205_access/.temp/zipFolder/VF105_V12/dxOta/1.0.0.zip
new file mode 100644
index 0000000..a746838
--- /dev/null
+++ b/vf205_access/.temp/zipFolder/VF105_V12/dxOta/1.0.0.zip
Binary files differ
diff --git a/vf205_access/.temp/zipFolder/VF105_V12/dxOta/2.0.2.zip b/vf205_access/.temp/zipFolder/VF105_V12/dxOta/2.0.2.zip
new file mode 100644
index 0000000..69e3e43
--- /dev/null
+++ b/vf205_access/.temp/zipFolder/VF105_V12/dxOta/2.0.2.zip
Binary files differ
diff --git a/vf205_access/.temp/zipFolder/VF105_V12/dxPwm/1.0.0.zip b/vf205_access/.temp/zipFolder/VF105_V12/dxPwm/1.0.0.zip
new file mode 100644
index 0000000..8060516
--- /dev/null
+++ b/vf205_access/.temp/zipFolder/VF105_V12/dxPwm/1.0.0.zip
Binary files differ
diff --git a/vf205_access/.temp/zipFolder/VF105_V12/dxPwm/2.0.0.zip b/vf205_access/.temp/zipFolder/VF105_V12/dxPwm/2.0.0.zip
new file mode 100644
index 0000000..8cc1c22
--- /dev/null
+++ b/vf205_access/.temp/zipFolder/VF105_V12/dxPwm/2.0.0.zip
Binary files differ
diff --git a/vf205_access/.temp/zipFolder/VF105_V12/dxPwm/2.0.1.zip b/vf205_access/.temp/zipFolder/VF105_V12/dxPwm/2.0.1.zip
new file mode 100644
index 0000000..eda71da
--- /dev/null
+++ b/vf205_access/.temp/zipFolder/VF105_V12/dxPwm/2.0.1.zip
Binary files differ
diff --git a/vf205_access/.temp/zipFolder/VF105_V12/dxQrRule/1.0.0.zip b/vf205_access/.temp/zipFolder/VF105_V12/dxQrRule/1.0.0.zip
new file mode 100644
index 0000000..b422640
--- /dev/null
+++ b/vf205_access/.temp/zipFolder/VF105_V12/dxQrRule/1.0.0.zip
Binary files differ
diff --git a/vf205_access/.temp/zipFolder/VF105_V12/dxSqlite/1.0.0.zip b/vf205_access/.temp/zipFolder/VF105_V12/dxSqlite/1.0.0.zip
new file mode 100644
index 0000000..6abf592
--- /dev/null
+++ b/vf205_access/.temp/zipFolder/VF105_V12/dxSqlite/1.0.0.zip
Binary files differ
diff --git a/vf205_access/.temp/zipFolder/VF105_V12/dxSqlite/2.0.0.zip b/vf205_access/.temp/zipFolder/VF105_V12/dxSqlite/2.0.0.zip
new file mode 100644
index 0000000..3114c72
--- /dev/null
+++ b/vf205_access/.temp/zipFolder/VF105_V12/dxSqlite/2.0.0.zip
Binary files differ
diff --git a/vf205_access/.temp/zipFolder/VF105_V12/dxSqliteDB/1.0.0.zip b/vf205_access/.temp/zipFolder/VF105_V12/dxSqliteDB/1.0.0.zip
new file mode 100644
index 0000000..a5085b0
--- /dev/null
+++ b/vf205_access/.temp/zipFolder/VF105_V12/dxSqliteDB/1.0.0.zip
Binary files differ
diff --git a/vf205_access/.temp/zipFolder/VF105_V12/dxStd/1.0.0.zip b/vf205_access/.temp/zipFolder/VF105_V12/dxStd/1.0.0.zip
new file mode 100644
index 0000000..d7aa3d4
--- /dev/null
+++ b/vf205_access/.temp/zipFolder/VF105_V12/dxStd/1.0.0.zip
Binary files differ
diff --git a/vf205_access/.temp/zipFolder/VF105_V12/dxStd/2.0.3.zip b/vf205_access/.temp/zipFolder/VF105_V12/dxStd/2.0.3.zip
new file mode 100644
index 0000000..3a1533e
--- /dev/null
+++ b/vf205_access/.temp/zipFolder/VF105_V12/dxStd/2.0.3.zip
Binary files differ
diff --git a/vf205_access/.temp/zipFolder/VF105_V12/dxUart/1.0.0.zip b/vf205_access/.temp/zipFolder/VF105_V12/dxUart/1.0.0.zip
new file mode 100644
index 0000000..3a080cb
--- /dev/null
+++ b/vf205_access/.temp/zipFolder/VF105_V12/dxUart/1.0.0.zip
Binary files differ
diff --git a/vf205_access/.temp/zipFolder/VF105_V12/dxUi/1.0.2.zip b/vf205_access/.temp/zipFolder/VF105_V12/dxUi/1.0.2.zip
new file mode 100644
index 0000000..a6e8753
--- /dev/null
+++ b/vf205_access/.temp/zipFolder/VF105_V12/dxUi/1.0.2.zip
Binary files differ
diff --git a/vf205_access/.temp/zipFolder/VF105_V12/dxWatchdog/1.0.0.zip b/vf205_access/.temp/zipFolder/VF105_V12/dxWatchdog/1.0.0.zip
new file mode 100644
index 0000000..e96c77a
--- /dev/null
+++ b/vf205_access/.temp/zipFolder/VF105_V12/dxWatchdog/1.0.0.zip
Binary files differ
diff --git a/vf205_access/.temp/zipFolder/VF105_V12/dxWatchdog/1.0.1.zip b/vf205_access/.temp/zipFolder/VF105_V12/dxWatchdog/1.0.1.zip
new file mode 100644
index 0000000..3d5f91d
--- /dev/null
+++ b/vf205_access/.temp/zipFolder/VF105_V12/dxWatchdog/1.0.1.zip
Binary files differ
diff --git a/vf205_access/.temp/zipFolder/VF105_V12/dxWorkerPool/2.0.0.zip b/vf205_access/.temp/zipFolder/VF105_V12/dxWorkerPool/2.0.0.zip
new file mode 100644
index 0000000..cd1a5be
--- /dev/null
+++ b/vf205_access/.temp/zipFolder/VF105_V12/dxWorkerPool/2.0.0.zip
Binary files differ
diff --git a/vf205_access/.temp/zipFolder/VF105_V12/dxWorkerPool/2.0.1.zip b/vf205_access/.temp/zipFolder/VF105_V12/dxWorkerPool/2.0.1.zip
new file mode 100644
index 0000000..c14f35a
--- /dev/null
+++ b/vf205_access/.temp/zipFolder/VF105_V12/dxWorkerPool/2.0.1.zip
Binary files differ
diff --git a/vf205_access/README.md b/vf205_access/README.md
new file mode 100644
index 0000000..562b2bd
--- /dev/null
+++ b/vf205_access/README.md
@@ -0,0 +1,9 @@
+# vf105_v12_access_new Access Control Application Source Code
+
+This directory contains the JavaScript source code for the `vf105_v12_access_new` access control application.
+
+**Important Note:**
+
+The JavaScript source code in this project is identical to the one used in the `vf203_v12_access_new` project (located at `../../vf203_v12/vf203_v12_access_new`).
+
+The only difference between the two projects lies in the underlying native shared library (`.so`) files. The specific version of the `.so` files to be used is determined and configured by the `app.dxproj` project file.
diff --git a/vf205_access/README_CN.md b/vf205_access/README_CN.md
new file mode 100644
index 0000000..d821497
--- /dev/null
+++ b/vf205_access/README_CN.md
@@ -0,0 +1,19 @@
+# vf105_v12_access_new 闂ㄧ搴旂敤婧愮爜
+
+姝ょ洰褰曞寘鍚� `vf105_v12_access_new` 闂ㄧ搴旂敤鐨� JavaScript 婧愮爜銆�
+
+**閲嶈璇存槑锛�**
+
+鏈」鐩殑 JavaScript 婧愮爜涓� `vf203_v12_access_new` 椤圭洰锛堣矾寰勶細`../../vf203_v12/vf203_v12_access_new`锛変娇鐢ㄧ殑鏄畬鍏ㄧ浉鍚岀殑涓�濂楁簮鐮併��
+
+涓や釜椤圭洰鍞竴鐨勫樊鍒湪浜庡簳灞傜殑鍘熺敓鍏变韩搴擄紙`.so`锛夋枃浠躲�傚叿浣撲娇鐢ㄥ摢涓増鏈殑 `.so` 鏂囦欢锛屾槸閫氳繃 `app.dxproj` 椤圭洰鏂囦欢鏉ュ尯鍒嗗拰閰嶇疆鐨勩��
+
+---
+
+褰撳墠椤圭洰宸蹭慨鏀规ā缁勬枃浠�-dxmodules/dxEventBus.js锛屼娇浜嬩欢鎬荤嚎鏀寔澶氫釜浜嬩欢澶勭悊鍑芥暟锛�
+
+1. 淇敼 bus.on 鍑芥暟 锛氬皢鍗曚釜浜嬩欢澶勭悊鍑芥暟鏀逛负瀛樺偍涓烘暟缁勶紝鏀寔澶氫釜澶勭悊鍑芥暟
+2. 淇敼 bus.fire 鍑芥暟 锛氭墽琛屾墍鏈夋敞鍐岀殑浜嬩欢澶勭悊鍑芥暟锛岃�屼笉浠呬粎鏄渶鍚庝竴涓�
+3. 娣诲姞閿欒澶勭悊 锛氱‘淇濅竴涓簨浠跺鐞嗗嚱鏁板嚭閿欐椂涓嶄細褰卞搷鍏朵粬澶勭悊鍑芥暟鐨勬墽琛�
+
+---
diff --git a/vf205_access/app.dxproj b/vf205_access/app.dxproj
new file mode 100644
index 0000000..0e18c5a
--- /dev/null
+++ b/vf205_access/app.dxproj
@@ -0,0 +1,123 @@
+{
+  "name": "vf105_v12_access",
+  "model": "VF105_V12",
+  "components": [
+    {
+      "component": "dxAlsa",
+      "version": "1.0.0"
+    },
+    {
+      "component": "dxBase64",
+      "version": "1.0.0"
+    },
+    {
+      "component": "dxCapturer",
+      "version": "1.0.2"
+    },
+    {
+      "component": "dxCommon",
+      "version": "1.0.0"
+    },
+    {
+      "component": "dxConfig",
+      "version": "2.0.0"
+    },
+    {
+      "component": "dxCameraCalibration",
+      "version": "test"
+    },
+    {
+      "component": "dxDriver",
+      "version": "1.1.0"
+    },
+    {
+      "component": "dxEventBus",
+      "version": "2.0.0"
+    },
+    {
+      "component": "dxEid",
+      "version": "1.0.0"
+    },
+    {
+      "component": "dxFace",
+      "version": "1.1.8"
+    },
+    {
+      "component": "dxGpio",
+      "version": "1.0.0"
+    },
+    {
+      "component": "dxGpioKey",
+      "version": "1.0.0"
+    },
+    {
+      "component": "dxHttp",
+      "version": "1.0.0"
+    },
+    {
+      "component": "dxLogger",
+      "version": "2.0.0"
+    },
+    {
+      "component": "dxMap",
+      "version": "1.0.0"
+    },
+    {
+      "component": "dxMqtt",
+      "version": "1.0.1"
+    },
+    {
+      "component": "dxNet",
+      "version": "1.0.0"
+    },
+    {
+      "component": "dxNtp",
+      "version": "2.0.0"
+    },
+    {
+      "component": "dxNfc",
+      "version": "1.0.0"
+    },
+    {
+      "component": "dxOta",
+      "version": "1.0.0"
+    },
+    {
+      "component": "dxPwm",
+      "version": "1.0.0"
+    },
+    {
+      "component": "dxQrRule",
+      "version": "1.0.0"
+    },
+    {
+      "component": "dxStd",
+      "version": "1.0.0"
+    },
+    {
+      "component": "dxSqlite",
+      "version": "1.0.0"
+    },
+    {
+      "component": "dxUi",
+      "version": "1.0.2"
+    },
+    {
+      "component": "dxUart",
+      "version": "1.0.0"
+    },
+    {
+      "component": "dxWorkerPool",
+      "version": "2.0.0"
+    },
+    {
+      "component": "dxWatchdog",
+      "version": "1.0.0"
+    }
+  ],
+  "ignore": {
+    "folder": ".temp,.git",
+    "file": "md5s.json,md5snew.json"
+  },
+  "version": "2.0.1.0"
+}
\ No newline at end of file
diff --git a/vf205_access/dxmodules/cameraCalibrationWorker.js b/vf205_access/dxmodules/cameraCalibrationWorker.js
new file mode 100644
index 0000000..4aaa65a
--- /dev/null
+++ b/vf205_access/dxmodules/cameraCalibrationWorker.js
@@ -0,0 +1,57 @@
+//build:20240524
+//鐢ㄤ簬绠�鍖朿ameraCalibration缁勪欢鐨勪娇鐢紝鎶奵ameraCalibration灏佽鍦ㄨ繖涓獁orker閲岋紝浣跨敤鑰呭彧闇�瑕佽闃卐ventcenter鐨勪簨浠跺氨鍙互鐩戝惉cameraCalibration
+import log from './dxLogger.js'
+import cameraCalibration from './dxCameraCalibration.js'
+import capturer from './dxCapturer.js'
+import std from './dxStd.js'
+import bus from './dxEventBus.js'
+import dxMap from './dxMap.js'
+import * as os from "os";
+const map = dxMap.get('default')
+const options = map.get("__cameraCalibration__run_init")
+
+function run() {
+    cameraCalibration.init()
+    log.info('cameraCalibration start......')
+    let startTime = new Date().getTime()
+    let cnt = 0
+    let timerId = std.setInterval(() => {
+        try {
+            let imageRgb = capturer.readImage(options.capturerRgbId)
+            let imageNir = capturer.readImage(options.capturerNirId)
+            let res = cameraCalibration.calibrationFromImage(imageRgb, imageNir, cnt)
+            if (res) {
+                if (cnt >= 1) {
+                    log.info("涓ゆ鏍囧畾鎴愬姛锛岀粨鏉熸爣瀹�")
+                    cameraCalibration.getMap(imageRgb, imageNir, cnt, "/app/path.txt")
+                    bus.fire(cameraCalibration.RECEIVE_MSG, "success1")
+                    capturer.destroyImage(imageRgb)
+                    capturer.destroyImage(imageNir)
+                    std.clearInterval(timerId)
+                }
+                log.info("绗�" + (cnt + 1) + "娆℃爣瀹氭垚鍔�")
+                bus.fire(cameraCalibration.RECEIVE_MSG, "success0")
+                cnt += 1
+                log.info("寮�濮嬭繘琛岀" + (cnt + 1) + "娆℃爣瀹�")
+            } else {
+                log.error("绗�" + (cnt + 1) + "娆℃爣瀹氬け璐ワ紝閲嶈瘯涓�")
+            }
+            capturer.destroyImage(imageRgb)
+            capturer.destroyImage(imageNir)
+            let endTime = new Date().getTime()
+            if (endTime - startTime > options.timeout * 1000) {
+                log.error('鏍囧畾瓒呮椂锛岃閲嶆柊鎵ц鏍囧畾')
+                bus.fire(cameraCalibration.RECEIVE_MSG, "timeout")
+                std.clearInterval(timerId)
+            }
+        } catch (error) {
+            log.error(error, error.stack)
+        }
+    }, 10)
+}
+
+try {
+    run()
+} catch (error) {
+    log.error(error, error.stack)
+}
\ No newline at end of file
diff --git a/vf205_access/dxmodules/capturerWorker.js b/vf205_access/dxmodules/capturerWorker.js
new file mode 100644
index 0000000..061bf6c
--- /dev/null
+++ b/vf205_access/dxmodules/capturerWorker.js
@@ -0,0 +1,27 @@
+//build:20240524
+//鐢ㄤ簬绠�鍖朿apturer缁勪欢鐨勪娇鐢紝鎶奵apturer灏佽鍦ㄨ繖涓獁orker閲岋紝浣跨敤鑰呭彧闇�瑕佽闃卐ventbus鐨勪簨浠跺氨鍙互鐩戝惉capturer
+import log from './dxLogger.js'
+import capturer from './dxCapturer.js'
+import dxMap from './dxMap.js'
+import std from './dxStd.js'
+const map = dxMap.get('default')
+const id = "{{id}}"
+const options = map.get("__capturer__run_init" + id)
+
+function run() {
+    capturer.worker.beforeLoop(options)
+    log.info('capturer start......,id =', options.id)
+    std.setInterval (function() {
+        try {
+            capturer.worker.loop(options)
+        } catch (error) {
+            log.error(error)
+        }
+    },10)
+}
+
+try {
+    run()
+} catch (error) {
+    log.error(error)
+}
\ No newline at end of file
diff --git a/vf205_access/dxmodules/dxAlsa.js b/vf205_access/dxmodules/dxAlsa.js
new file mode 100644
index 0000000..640a86a
--- /dev/null
+++ b/vf205_access/dxmodules/dxAlsa.js
@@ -0,0 +1,105 @@
+//build: 20240525
+//渚濊禆缁勪欢:dxDriver锛宒xCommon
+import { alsaClass } from './libvbar-m-dxalsa.so'
+import dxCommon from './dxCommon.js'
+const alsaObj = new alsaClass();
+const alsa = {}
+
+/**
+ * alsa 鍒濆鍖�
+ * @param {string} id 鍙ユ焺id锛岄潪蹇呭~锛堣嫢鍒濆鍖栧涓疄渚嬮渶瑕佷紶鍏ュ敮涓�id锛�
+ * @param {number} volume 闊抽噺锛岄潪蹇呭~
+ * @param {number} periodSize 鍛ㄦ湡澶у皬锛岄潪蹇呭~
+ * @param {number} bufferSize 缂撳瓨澶у皬锛岄潪蹇呭~
+ * @returns 鍙ユ焺id
+ */
+alsa.init = function (id, volume, periodSize, bufferSize) {
+	if (volume === undefined || volume === null) {
+		volume = 35
+	}
+	if (periodSize === undefined || periodSize === null) {
+		periodSize = 512
+	}
+	if (bufferSize === undefined || bufferSize === null) {
+		bufferSize = 2048
+	}
+	let pointer = alsaObj.alsaInit(volume, periodSize, bufferSize)
+	if (!pointer) {
+		throw new Error("alsa.init: init failed")
+	}
+	return dxCommon.handleId("alsa", id, pointer)
+}
+
+/**
+ * alsa 鍙栨秷鍒濆鍖�
+ * @param {string} id 鍙ユ焺id锛岄潪蹇呭~锛堥渶淇濇寔鍜宨nit涓殑id涓�鑷达級
+ * @returns true/false
+ */
+alsa.deinit = function (id) {
+	let pointer = dxCommon.handleId("alsa", id)
+	return alsaObj.alsaDeinit(pointer)
+}
+
+/**
+ * 鎾斁闊充箰鏂囦欢
+ * @param {string} path wav鏂囦欢缁濆璺緞锛岃矾寰勬槸浠�'/app/code/' 寮�澶达紝閫氬父鏀惧湪椤圭洰鐨剅esource鐩綍涓嬶紙鍜宻rc鍚岀骇)锛屽繀濉�
+ * @param {string} id 鍙ユ焺id锛岄潪蹇呭~锛堥渶淇濇寔鍜宨nit涓殑id涓�鑷达級
+ * @returns true/false
+ */
+alsa.play = function (path, id) {
+	if (!path) {
+		throw new Error("alsa.play: 'path' parameter should not be null")
+	}
+	let pointer = dxCommon.handleId("alsa", id)
+	return alsaObj.alsaWav(pointer, path)
+}
+
+/**
+ * TTS鏂囧瓧杞闊�
+ * @param {string} 瑕佹挱鏀剧殑闊抽鏂囧瓧锛屽繀濉�
+ * @param {string} id 鍙ユ焺id锛岄潪蹇呭~锛堥渶淇濇寔鍜宨nit涓殑id涓�鑷达級
+ * @returns true/false
+ */
+alsa.ttsPlay = function (str, id) {
+	if (!str) {
+		throw new Error("alsa.ttsPlay: 'str' parameter should not be null")
+	}
+	let pointer = dxCommon.handleId("alsa", id)
+	return alsaObj.alsaAudioPlayString(pointer, str)
+}
+
+/**
+ * 鑾峰彇闊抽噺
+ * @param {string} id 鍙ユ焺id锛岄潪蹇呭~锛堥渶淇濇寔鍜宨nit涓殑id涓�鑷达級
+ * @returns 杩斿洖鏁板瓧绫诲瀷鐨勯煶閲忥紝涓嶄細瓒呭嚭闊抽噺鑼冨洿
+ */
+alsa.getVolume = function (id) {
+	let pointer = dxCommon.handleId("alsa", id)
+	return alsaObj.alsaGetVolume(pointer)
+}
+
+/**
+ * 璁剧疆闊抽噺 璁剧疆杩囧ぇ鎴栬繃灏忎細缂虹渷绛変簬闊抽噺鑼冨洿鐨勬渶澶ф垨鏈�灏忓��
+ * @param {number} volume 闊抽噺锛屽繀濉�
+ * @param {string} id 鍙ユ焺id锛岄潪蹇呭~锛堥渶淇濇寔鍜宨nit涓殑id涓�鑷达級
+ * @returns true/false
+ */
+alsa.setVolume = function (volume, id) {
+	let pointer = dxCommon.handleId("alsa", id)
+	return alsaObj.alsaSetVolume(pointer, volume)
+}
+/**
+ * 鎾斁娴佸紡闊抽
+ * @param {ArrayBuffer} 闊抽娴� 锛屽繀濉�
+ * @param {string} id 鍙ユ焺id锛岄潪蹇呭~锛堥渶淇濇寔鍜宨nit涓殑id涓�鑷达級
+ * @returns true/false
+ */
+alsa.alsaWavData = function (buffer, id) {
+	if (!buffer) {
+		throw new Error("alsa.alsaWavData: 'buffer' parameter should not be null")
+	}
+	let pointer = dxCommon.handleId("alsa", id)
+	return alsaObj.alsaWavData(pointer, buffer)
+}
+
+export default alsa;
diff --git a/vf205_access/dxmodules/dxBase64.js b/vf205_access/dxmodules/dxBase64.js
new file mode 100644
index 0000000..5a7d7ec
--- /dev/null
+++ b/vf205_access/dxmodules/dxBase64.js
@@ -0,0 +1,308 @@
+//build:20240308
+//Base64缂栬В鐮佸伐鍏�
+//渚濊禆缁勪欢锛氭棤
+//鍩烘湰鍖呮嫭浠ヤ笅鍑芥暟:
+/**
+ * 1. encode(str): 瀛楃涓茶浆base64瀛楃涓诧紝姣斿Base64.encode("aa鐨勫仴搴穉ab")寰楀埌YWHnmoTlgaXlurdhYWI=
+ * 2. decode(b64): base64瀛楃涓茶浆鍘熷瓧绗︿覆
+ * 3. fromUint8Array(arr): byte鏁扮粍杞琤ase64瀛楃涓�
+ * 4. toUnit8Array(b64):base64瀛楃涓茶浆byte鏁扮粍
+ * 5. fromHexString(hex):16杩涘埗瀛楃涓诧紙灏忓啓锛屾棤绌烘牸锛夎浆base64瀛楃涓�
+ * 6. toHexString(b64):base64瀛楃涓茶浆16杩涘埗瀛楃涓诧紙灏忓啓锛屾棤绌烘牸
+ */
+/**
+ *  base64.ts
+ *
+ *  Licensed under the BSD 3-Clause License.
+ *    http://opensource.org/licenses/BSD-3-Clause
+ *
+ *  References:
+ *    http://en.wikipedia.org/wiki/Base64
+ *
+ * @author Dan Kogai (https://github.com/dankogai)
+ */
+let version = '3.7.7';
+/**
+ * @deprecated use lowercase `version`.
+ */
+let VERSION = version;
+let _hasBuffer = typeof Buffer === 'function';
+let _TD = typeof TextDecoder === 'function' ? new TextDecoder() : undefined;
+let _TE = typeof TextEncoder === 'function' ? new TextEncoder() : undefined;
+let b64ch = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
+let b64chs = Array.prototype.slice.call(b64ch);
+let b64tab = (function (a) {
+    let tab = {};
+    a.forEach(function (c, i) { return tab[c] = i; });
+    return tab;
+})(b64chs);
+let b64re = /^(?:[A-Za-z\d+\/]{4})*?(?:[A-Za-z\d+\/]{2}(?:==)?|[A-Za-z\d+\/]{3}=?)?$/;
+let _fromCC = String.fromCharCode.bind(String);
+let _U8Afrom = typeof Uint8Array.from === 'function'
+    ? Uint8Array.from.bind(Uint8Array)
+    : function (it) { return new Uint8Array(Array.prototype.slice.call(it, 0)); };
+let _mkUriSafe = function (src) {
+    return src
+        .replace(/=/g, '').replace(/[+\/]/g, function (m0) { return m0 == '+' ? '-' : '_'; });
+};
+let _tidyB64 = function (s) { return s.replace(/[^A-Za-z0-9\+\/]/g, ''); };
+/**
+ * polyfill version of `btoa`
+ */
+let btoaPolyfill = function (bin) {
+    // console.log('polyfilled');
+    let u32, c0, c1, c2, asc = '';
+    let pad = bin.length % 3;
+    for (let i = 0; i < bin.length;) {
+        if ((c0 = bin.charCodeAt(i++)) > 255 ||
+            (c1 = bin.charCodeAt(i++)) > 255 ||
+            (c2 = bin.charCodeAt(i++)) > 255)
+            throw new TypeError('invalid character found');
+        u32 = (c0 << 16) | (c1 << 8) | c2;
+        asc += b64chs[u32 >> 18 & 63]
+            + b64chs[u32 >> 12 & 63]
+            + b64chs[u32 >> 6 & 63]
+            + b64chs[u32 & 63];
+    }
+    return pad ? asc.slice(0, pad - 3) + "===".substring(pad) : asc;
+};
+/**
+ * does what `window.btoa` of web browsers do.
+ * @param {String} bin binary string
+ * @returns {string} Base64-encoded string
+ */
+let _btoa = typeof btoa === 'function' ? function (bin) { return btoa(bin); }
+    : _hasBuffer ? function (bin) { return Buffer.from(bin, 'binary').toString('base64'); }
+        : btoaPolyfill;
+let _fromUint8Array = _hasBuffer
+    ? function (u8a) { return Buffer.from(u8a).toString('base64'); }
+    : function (u8a) {
+        // cf. https://stackoverflow.com/questions/12710001/how-to-convert-uint8-array-to-base64-encoded-string/12713326#12713326
+        let maxargs = 0x1000;
+        let strs = [];
+        for (let i = 0, l = u8a.length; i < l; i += maxargs) {
+            strs.push(_fromCC.apply(null, u8a.subarray(i, i + maxargs)));
+        }
+        return _btoa(strs.join(''));
+    };
+/**
+ * converts a Uint8Array to a Base64 string.
+ * @param {boolean} [urlsafe] URL-and-filename-safe a la RFC4648 搂5
+ * @returns {string} Base64 string
+ */
+let fromUint8Array = function (u8a, urlsafe) {
+    if (urlsafe === void 0) { urlsafe = false; }
+    return urlsafe ? _mkUriSafe(_fromUint8Array(u8a)) : _fromUint8Array(u8a);
+};
+let fromHexString = function (hexString) {
+    let byteString = hexString.match(/.{1,2}/g);
+    let byteArray = byteString.map(function (byte) {
+        return parseInt(byte, 16);
+    });
+    let buffer = new Uint8Array(byteArray);
+    return fromUint8Array(buffer)
+}
+// This trick is found broken https://github.com/dankogai/js-base64/issues/130
+// const utob = (src: string) => unescape(encodeURIComponent(src));
+// reverting good old fationed regexp
+let cb_utob = function (c) {
+    if (c.length < 2) {
+        let cc = c.charCodeAt(0);
+        return cc < 0x80 ? c
+            : cc < 0x800 ? (_fromCC(0xc0 | (cc >>> 6))
+                + _fromCC(0x80 | (cc & 0x3f)))
+                : (_fromCC(0xe0 | ((cc >>> 12) & 0x0f))
+                    + _fromCC(0x80 | ((cc >>> 6) & 0x3f))
+                    + _fromCC(0x80 | (cc & 0x3f)));
+    }
+    else {
+        let cc = 0x10000
+            + (c.charCodeAt(0) - 0xD800) * 0x400
+            + (c.charCodeAt(1) - 0xDC00);
+        return (_fromCC(0xf0 | ((cc >>> 18) & 0x07))
+            + _fromCC(0x80 | ((cc >>> 12) & 0x3f))
+            + _fromCC(0x80 | ((cc >>> 6) & 0x3f))
+            + _fromCC(0x80 | (cc & 0x3f)));
+    }
+};
+let re_utob = /[\uD800-\uDBFF][\uDC00-\uDFFFF]|[^\x00-\x7F]/g;
+/**
+ * @deprecated should have been internal use only.
+ * @param {string} src UTF-8 string
+ * @returns {string} UTF-16 string
+ */
+let utob = function (u) { return u.replace(re_utob, cb_utob); };
+//
+let _encode = _hasBuffer
+    ? function (s) { return Buffer.from(s, 'utf8').toString('base64'); }
+    : _TE
+        ? function (s) { return _fromUint8Array(_TE.encode(s)); }
+        : function (s) { return _btoa(utob(s)); };
+/**
+ * converts a UTF-8-encoded string to a Base64 string.
+ * @param {boolean} [urlsafe] if `true` make the result URL-safe
+ * @returns {string} Base64 string
+ */
+let encode = function (src, urlsafe) {
+    if (urlsafe === void 0) { urlsafe = false; }
+    return urlsafe
+        ? _mkUriSafe(_encode(src))
+        : _encode(src);
+};
+/**
+ * converts a UTF-8-encoded string to URL-safe Base64 RFC4648 搂5.
+ * @returns {string} Base64 string
+ */
+let encodeURI = function (src) { return encode(src, true); };
+// This trick is found broken https://github.com/dankogai/js-base64/issues/130
+// const btou = (src: string) => decodeURIComponent(escape(src));
+// reverting good old fationed regexp
+let re_btou = /[\xC0-\xDF][\x80-\xBF]|[\xE0-\xEF][\x80-\xBF]{2}|[\xF0-\xF7][\x80-\xBF]{3}/g;
+let cb_btou = function (cccc) {
+    switch (cccc.length) {
+        case 4:
+            let cp = ((0x07 & cccc.charCodeAt(0)) << 18)
+                | ((0x3f & cccc.charCodeAt(1)) << 12)
+                | ((0x3f & cccc.charCodeAt(2)) << 6)
+                | (0x3f & cccc.charCodeAt(3)), offset = cp - 0x10000;
+            return (_fromCC((offset >>> 10) + 0xD800)
+                + _fromCC((offset & 0x3FF) + 0xDC00));
+        case 3:
+            return _fromCC(((0x0f & cccc.charCodeAt(0)) << 12)
+                | ((0x3f & cccc.charCodeAt(1)) << 6)
+                | (0x3f & cccc.charCodeAt(2)));
+        default:
+            return _fromCC(((0x1f & cccc.charCodeAt(0)) << 6)
+                | (0x3f & cccc.charCodeAt(1)));
+    }
+};
+/**
+ * @deprecated should have been internal use only.
+ * @param {string} src UTF-16 string
+ * @returns {string} UTF-8 string
+ */
+let btou = function (b) { return b.replace(re_btou, cb_btou); };
+/**
+ * polyfill version of `atob`
+ */
+let atobPolyfill = function (asc) {
+    // console.log('polyfilled');
+    asc = asc.replace(/\s+/g, '');
+    if (!b64re.test(asc))
+        throw new TypeError('malformed base64.');
+    asc += '=='.slice(2 - (asc.length & 3));
+    let u24, bin = '', r1, r2;
+    for (let i = 0; i < asc.length;) {
+        u24 = b64tab[asc.charAt(i++)] << 18
+            | b64tab[asc.charAt(i++)] << 12
+            | (r1 = b64tab[asc.charAt(i++)]) << 6
+            | (r2 = b64tab[asc.charAt(i++)]);
+        bin += r1 === 64 ? _fromCC(u24 >> 16 & 255)
+            : r2 === 64 ? _fromCC(u24 >> 16 & 255, u24 >> 8 & 255)
+                : _fromCC(u24 >> 16 & 255, u24 >> 8 & 255, u24 & 255);
+    }
+    return bin;
+};
+/**
+ * does what `window.atob` of web browsers do.
+ * @param {String} asc Base64-encoded string
+ * @returns {string} binary string
+ */
+let _atob = typeof atob === 'function' ? function (asc) { return atob(_tidyB64(asc)); }
+    : _hasBuffer ? function (asc) { return Buffer.from(asc, 'base64').toString('binary'); }
+        : atobPolyfill;
+//
+let _toUint8Array = _hasBuffer
+    ? function (a) { return _U8Afrom(Buffer.from(a, 'base64')); }
+    : function (a) { return _U8Afrom(_atob(a).split('').map(function (c) { return c.charCodeAt(0); })); };
+/**
+ * converts a Base64 string to a Uint8Array.
+ */
+let toUint8Array = function (a) { return _toUint8Array(_unURI(a)); };
+//
+let toHexString = function (a) {
+    let uint8 = toUint8Array(a)
+    return Array.from(uint8)
+        .map((i) => i.toString(16).padStart(2, '0'))
+        .join('');;
+}
+let _decode = _hasBuffer
+    ? function (a) { return Buffer.from(a, 'base64').toString('utf8'); }
+    : _TD
+        ? function (a) { return _TD.decode(_toUint8Array(a)); }
+        : function (a) { return btou(_atob(a)); };
+let _unURI = function (a) { return _tidyB64(a.replace(/[-_]/g, function (m0) { return m0 == '-' ? '+' : '/'; })); };
+/**
+ * converts a Base64 string to a UTF-8 string.
+ * @param {String} src Base64 string.  Both normal and URL-safe are supported
+ * @returns {string} UTF-8 string
+ */
+let decode = function (src) { return _decode(_unURI(src)); };
+/**
+ * check if a value is a valid Base64 string
+ * @param {String} src a value to check
+  */
+let isValid = function (src) {
+    if (typeof src !== 'string')
+        return false;
+    let s = src.replace(/\s+/g, '').replace(/={0,2}$/, '');
+    return !/[^\s0-9a-zA-Z\+/]/.test(s) || !/[^\s0-9a-zA-Z\-_]/.test(s);
+};
+//
+let _noEnum = function (v) {
+    return {
+        value: v, enumerable: false, writable: true, configurable: true
+    };
+};
+/**
+ * extend String.prototype with relevant methods
+ */
+let extendString = function () {
+    let _add = function (name, body) { return Object.defineProperty(String.prototype, name, _noEnum(body)); };
+    _add('fromBase64', function () { return decode(this); });
+    _add('toBase64', function (urlsafe) { return encode(this, urlsafe); });
+    _add('toBase64URI', function () { return encode(this, true); });
+    _add('toBase64URL', function () { return encode(this, true); });
+    _add('toUint8Array', function () { return toUint8Array(this); });
+};
+/**
+ * extend Uint8Array.prototype with relevant methods
+ */
+let extendUint8Array = function () {
+    let _add = function (name, body) { return Object.defineProperty(Uint8Array.prototype, name, _noEnum(body)); };
+    _add('toBase64', function (urlsafe) { return fromUint8Array(this, urlsafe); });
+    _add('toBase64URI', function () { return fromUint8Array(this, true); });
+    _add('toBase64URL', function () { return fromUint8Array(this, true); });
+};
+/**
+ * extend Builtin prototypes with relevant methods
+ */
+let extendBuiltins = function () {
+    extendString();
+    extendUint8Array();
+};
+let gBase64 = {
+    version: version,
+    VERSION: VERSION,
+    atob: _atob,
+    atobPolyfill: atobPolyfill,
+    btoa: _btoa,
+    btoaPolyfill: btoaPolyfill,
+    fromBase64: decode,
+    toBase64: encode,
+    encode: encode,
+    encodeURI: encodeURI,
+    encodeURL: encodeURI,
+    utob: utob,
+    btou: btou,
+    decode: decode,
+    isValid: isValid,
+    fromUint8Array: fromUint8Array,
+    toUint8Array: toUint8Array,
+    fromHexString: fromHexString,
+    toHexString: toHexString,
+    extendString: extendString,
+    extendUint8Array: extendUint8Array,
+    extendBuiltins: extendBuiltins
+};
+export default gBase64
\ No newline at end of file
diff --git a/vf205_access/dxmodules/dxCameraCalibration.js b/vf205_access/dxmodules/dxCameraCalibration.js
new file mode 100644
index 0000000..22a6127
--- /dev/null
+++ b/vf205_access/dxmodules/dxCameraCalibration.js
@@ -0,0 +1,136 @@
+//build: 20240528
+//渚濊禆缁勪欢:dxDriver锛宒xLogger锛宒xMap锛宒xCapturer
+import { calibrationClass } from './libvbar-m-dxcapturer_calibration.so'
+import capturer from '../dxmodules/dxCapturer.js'
+import * as os from "os";
+import dxMap from './dxMap.js'
+import log from './dxLogger.js'
+import bus from './dxEventBus.js'
+const calibrationObj = new calibrationClass();
+const map = dxMap.get('default')
+const calibration = {}
+let cnt = 0, startTime = 0;
+
+/**
+ * calibration 鍒濆鍖�
+ * @returns true/false
+ */
+calibration.init = function () {
+	return calibrationObj.init();
+}
+
+/**
+ * calibration 閿�姣�
+ * @returns true/false
+ */
+calibration.deinit = function () {
+	return calibrationObj.deinit();
+}
+
+/**
+ * 璇嗗埆鏍囧畾锛堟嬁鏂规牸绾稿鍑嗗睆骞曚笂鐨勬柟妗嗭級
+ * @param {number} imageRgb image鎸囬拡锛屽繀濉�
+ * @param {number} imageNir image鎸囬拡锛屽繀濉�
+ * @param {number} cnt 鏍囧畾娆℃暟锛屽繀濉紙0锛氱涓�娆℃爣瀹�,1锛氱浜屾鏍囧畾锛�
+ * @returns true/false
+ */
+calibration.calibrationFromImage = function (imageRgb, imageNir, cnt) {
+	return calibrationObj.calibrationFromImage(imageRgb, imageNir, cnt);
+}
+
+/**
+ * 璁$畻骞跺瓨鍌ㄦ爣瀹氱粨鏋�
+ * @param {number} imageNir image鎸囬拡锛屽繀濉�
+ * @param {string} path 瀛樺偍璺緞锛屽繀濉�
+ * @returns true/false
+ */
+calibration.getMap = function (imageRgb, imageNir,cnt, path) {
+	return calibrationObj.getMap(imageRgb, imageNir,cnt, path);
+}
+
+/**
+ * 鑾峰彇缁樺埗鏍囧畾ui妗嗕俊鎭�
+ * @param {number} cnt 鏍囧畾娆℃暟锛屽繀濉紙0锛氱涓�娆℃爣瀹�,1锛氱浜屾鏍囧畾锛�
+ * @param {number} type 妯珫灞忥紝蹇呭~锛�1锛氭í灞忥紝0锛氱珫灞忥級
+ * @returns {x:妯潗鏍�,y:绾靛潗鏍�,w:瀹�,h:楂榼
+ */
+calibration.getBox = function (cnt, type) {
+	let box = calibrationObj.getBox(cnt);
+	let coordinate = {
+		x: type == 1 ? box.x : box.y,
+		y: type == 1 ? box.y : box.x,
+		w: type == 1 ? box.w : box.h,
+		h: type == 1 ? box.h : box.w
+	}
+	return coordinate;
+}
+
+calibration.RECEIVE_MSG = '__calibration__MsgReceive'
+
+/**
+ * 绠�鍖朿ameraCalibration缁勪欢鐨勪娇鐢紝鏃犻渶杞鍘昏幏鍙栨暟鎹紝鏁版嵁浼氶�氳繃eventbus鍙戦�佸嚭鍘�
+ * 鐢变簬璇嗗埆鏍囧畾calibrationFromImage鏄樆濉炵嚎绋嬬殑鏂规硶锛屾墍浠ュ繀椤绘柊寮�涓�涓嚎绋嬫墽琛岋紝鍚﹀垯浼氶樆濉炲叾浠栫嚎绋�
+ * run 鍙細鎵ц涓�娆�
+ * @param {object} options 閰嶇疆鍙傛暟
+ * @param {string} options.capturerRgbId      蹇呭~锛宺gb鍙栧浘鍙ユ焺id
+ * @param {string} options.capturerNirId      蹇呭~锛宯ir鍙栧浘鍙ユ焺id
+ * @param {number} options.timeout      	鍗曚綅绉掞紝闈炲繀濉紙缂虹渷20绉掞級锛屾爣瀹氱殑瓒呮椂鏃堕棿锛屽湪姝ゆ湡闂村唴鏈畬鎴愪袱娆℃爣瀹氾紝鍒欐爣瀹氬け璐ョ粨鏉熺嚎绋嬶紝濡傞渶閲嶆柊鏍囧畾锛屽繀椤诲啀娆℃墽琛宺un鏂规硶
+ */
+calibration.run = function (options) {
+	if (options === undefined || options.length === 0) {
+		throw new Error("dxCameraCalibration.run:'options' parameter should not be null or empty")
+	}
+	if (options.capturerRgbId === undefined || options.capturerRgbId === null || options.capturerRgbId.length <= 0) {
+		throw new Error("dxCameraCalibration.run:'capturerRgbId' should not be null or empty")
+	}
+	if (options.capturerNirId === undefined || options.capturerNirId === null || options.capturerNirId.length <= 0) {
+		throw new Error("dxCameraCalibration.run:'capturerNirId' should not be null or empty")
+	}
+	options.timeout = options.timeout ? options.timeout : 20
+	try {
+		if(startTime == null || startTime == 0){
+			startTime = new Date().getTime()
+		}
+        let imageRgb = capturer.readImage(options.capturerRgbId)
+        let imageNir = capturer.readImage(options.capturerNirId)
+        let res = this.calibrationFromImage(imageRgb, imageNir, cnt)
+        if (res) {
+            if (cnt >= 1) {
+                log.info("涓ゆ鏍囧畾鎴愬姛锛岀粨鏉熸爣瀹�")
+                let path = "/etc/.cameraCalibration"
+                if(options.path && options.path.length > 0){
+                    path = options.path
+                }
+                this.getMap(imageRgb, imageNir, cnt, path)
+                bus.fire(this.RECEIVE_MSG, "success1")
+                capturer.destroyImage(imageRgb)
+                capturer.destroyImage(imageNir)
+				cnt = 0;
+				startTime = 0;
+                return "success1"
+            }
+            log.info("绗�" + (cnt + 1) + "娆℃爣瀹氭垚鍔�")
+            bus.fire(this.RECEIVE_MSG, "success0")
+            cnt += 1
+            log.info("寮�濮嬭繘琛岀" + (cnt + 1) + "娆℃爣瀹�")
+            return "success0"
+        } else {
+            log.error("绗�" + (cnt + 1) + "娆℃爣瀹氬け璐ワ紝閲嶈瘯涓�")
+        }
+        capturer.destroyImage(imageRgb)
+        capturer.destroyImage(imageNir)
+        let endTime = new Date().getTime()
+        if (endTime - startTime > options.timeout * 1000) {
+            log.error('鏍囧畾瓒呮椂锛岃閲嶆柊鎵ц鏍囧畾')
+            bus.fire(this.RECEIVE_MSG, "timeout")
+            cnt = 0
+			startTime = 0;
+            return "timeout"
+        }
+        return "failed"
+    } catch (error) {
+        log.error(error)
+    }
+}
+
+export default calibration;
\ No newline at end of file
diff --git a/vf205_access/dxmodules/dxCapturer.js b/vf205_access/dxmodules/dxCapturer.js
new file mode 100644
index 0000000..3943ae3
--- /dev/null
+++ b/vf205_access/dxmodules/dxCapturer.js
@@ -0,0 +1,336 @@
+//build: 20240524
+//鎽勫儚澶村彇鍥剧粍浠讹紝涓昏鐢ㄤ簬鑾峰彇浜岀淮鐮佸浘鍍忕劧鍚庡埄鐢╠xDecoder缁勪欢鏉ヨВ鏋愪簩缁寸爜鍥惧儚
+//渚濊禆缁勪欢锛歞xDriver锛宒xCommon锛宒xStd锛宒xMap
+import { capturerClass } from './libvbar-m-dxcapturer.so'
+import * as os from "os"
+import std from './dxStd.js'
+import dxMap from './dxMap.js'
+import dxCommon from './dxCommon.js';
+import bus from './dxEventBus.js'
+const capturerObj = new capturerClass();
+const map = dxMap.get('default')
+const capturer = {}
+
+/**
+ * 鍙栧浘妯″潡鍒濆鍖�
+ * @param {object} options 閰嶇疆鍙傛暟锛屽ぇ閮ㄥ垎鍙互鐢ㄩ粯璁ゅ��
+ * @param {string} options.path                 蹇呭~锛屽浘鍍忛噰闆嗚澶囪矾寰勶紝姣忕璁惧鏈夊樊寮傦紝姣斿DW200瀵瑰簲鐨勫�兼槸'/dev/video11', M500瀵瑰簲鐨�'/dev/video0'
+ * @param {number} options.width                闈炲繀濉紝鍥惧儚瀹斤紝缂虹渷鏄�0
+ * @param {number} options.height               闈炲繀濉紝鍥惧儚楂橈紝缂虹渷鏄�0
+ * @param {number} options.widthbytes           闈炲繀濉紝姣忎釜鍍忕礌鎵�鍗犲瓧鑺傛暟 GREY : 1锛� YUV : 2锛孌W200缂虹渷鏄�1 VF203缂虹渷鏄�2
+ * @param {number} options.pixel_format          闈炲繀濉紝鍍忕礌鏍煎紡锛� 缂虹渷鏄�1497715271琛ㄧずV4L2_PIX_FMT_GREY
+ * @param {number} options.max_channels          闈炲繀濉紝鏈�澶ф敮鎸佺殑鍚屾杈撳嚭channel鏁伴噺锛岀己鐪佹槸3
+ * @param {number} options.rotation             闈炲繀濉紝鏃嬭浆瑙掑害锛岀己鐪佹槸90
+ * @param {number} options.frame_num             闈炲繀濉紝甯х紪鍙凤紝缂虹渷鏄�3
+ * @param {number} options.preview_enable        闈炲繀濉紝棰勮鏄惁鍚敤锛岀己鐪佹槸3
+ * @param {number} options.preview_left          闈炲繀濉紝棰勮妗嗗乏杈规鍧愭爣锛岀己鐪佹槸0
+ * @param {number} options.preview_top           闈炲繀濉紝棰勮妗嗕笂杈规鍧愭爣锛岀己鐪佹槸0
+ * @param {number} options.preview_width         闈炲繀濉紝棰勮妗嗗搴︼紝VF203缂虹渷鏄�1024
+ * @param {number} options.preview_height        闈炲繀濉紝棰勮妗嗛珮搴︼紝VF203缂虹渷鏄�600
+ * @param {number} options.preview_rotation      闈炲繀濉紝棰勮妗嗘棆杞搴︼紝缂虹渷鏄�0
+ * @param {number} options.preview_mode          闈炲繀濉紝棰勮妗嗘ā寮忥紝缂虹渷鏄�2
+ * @param {number} options.preview_screen_index   闈炲繀濉紝棰勮妗嗙储寮曪紝缂虹渷鏄�0
+ * @param {string} id 鍙ユ焺id锛岄潪蹇呭~锛堣嫢鍒濆鍖栧涓疄渚嬮渶瑕佷紶鍏ュ敮涓�id锛�
+ */
+capturer.init = function (options, id) {
+    if (options.path === undefined || options.path === null || options.path.length < 1) {
+        throw new Error("dxCapturer.init: 'path' parameter should not be null or empty")
+    }
+    let pointer = capturerObj.init(options);
+    if (!pointer) {
+        throw new Error("dxCapturer.init: init failed")
+    }
+    dxCommon.handleId("capturer", id, pointer)
+}
+
+/**
+ * 鍥炶皟娉ㄥ唽
+ * @param {string} id 鍙ユ焺id锛岄潪蹇呭~锛堥渶淇濇寔鍜宨nit涓殑id涓�鑷达級
+ * @param {string} capturerDogId 鎽勫儚澶寸湅闂ㄧ嫍鍙ユ焺id锛岄潪蹇呭~
+ * @returns true/false
+ */
+capturer.registerCallback = function (id, capturerDogId) {
+    let pointer = dxCommon.handleId("capturer", id)
+    let capturerDogPointer = null;
+    print("capturerDogPointer:", capturerDogPointer)
+    if(capturerDogId){
+        capturerDogPointer = dxCommon.handleId("watchdog", capturerDogId)
+        print("capturerDogPointer:", capturerDogPointer)
+    }
+    return capturerObj.registerCallback(pointer, "decoderCapturerImage", capturerDogPointer)
+}
+/**
+ * 鑾峰彇鍩烘湰淇℃伅
+ * @param {string} id 鍙ユ焺id锛岄潪蹇呭~锛堥渶淇濇寔鍜宨nit涓殑id涓�鑷达級
+ * @returns 鏍煎紡绫讳技锛� {"width":800,"widthbytes":1,"height":600,"name":{},"type":6}
+ */
+capturer.getInfo = function (id) {
+    let pointer = dxCommon.handleId("capturer", id)
+    return capturerObj.getInfo(pointer)
+}
+/**
+ * 鍏抽棴鍙栧浘妯″潡
+ * @param {string} id 鍙ユ焺id锛岄潪蹇呭~锛堥渶淇濇寔鍜宨nit涓殑id涓�鑷达級
+ * @returns true/false
+ */
+capturer.close = function (id) {
+    let pointer = dxCommon.handleId("capturer", id)
+    return capturerObj.close(pointer)
+}
+
+/**
+ * 鑾峰彇鍥惧儚鏁版嵁锛岃疆璇㈠彲璋冪敤姝ゆ帴鍙o紝绫讳技capturer.msgReceive鏂规硶鐨勮幏鍙栵紝鑻ヤ娇鐢ㄨ繖涓柟娉曪紝蹇呴』鎵嬪姩閿�姣佽幏鍙栫殑image鎸囬拡
+ * @param {string} id 鍙ユ焺id锛岄潪蹇呭~锛堥渶淇濇寔鍜宨nit涓殑id涓�鑷达級
+ * @returns image鎸囬拡
+ */
+capturer.readImage = function (id) {
+    let pointer = dxCommon.handleId("capturer", id)
+    return capturerObj.readImage(pointer)
+}
+
+/**
+ * 閿�姣佽幏鍙栫殑image鎸囬拡锛屼笌capturer.readImage鏂规硶鍏卞悓浣跨敤
+ * @param {number} image image鎸囬拡锛屽繀濉�
+ * @returns true/false
+ */
+capturer.destroyImage = function (image) {
+    return capturerObj.destroyImage(image)
+}
+
+/**
+ * 浣胯兘/鍏抽棴capture棰勮
+ * @param {number}  鎽勫儚澶村惎鐢�/绂佺敤锛屽繀濉�
+ * @param {string} id 鍙ユ焺id锛岄潪蹇呭~锛堥渶淇濇寔鍜宨nit涓殑id涓�鑷达級
+ * @returns true/false
+ */
+capturer.capturerEnable = function (enable, id) {
+    if (enable == null) {
+        throw new Error("nirEnable should not be null or empty")
+    }
+    let pointer = dxCommon.handleId("capturer", id)
+    return capturerObj.capturerPreviewEnable(pointer, enable)
+}
+
+/**
+ * @brief 鍥剧墖鏂囦欢杞琲mage
+ * @param {string} fileName 鏂囦欢璺緞
+ * @param {number} type 鍥惧儚绫诲瀷 IMAGE_YUV420P = 0, 1IMAGE_YUV420SP = 1,
+ * @return imageId image鍙ユ焺id
+ */
+capturer.pictureFileToImage = function (fileName, type) {
+    if (fileName == null) {
+        throw new Error("fileName should not be null or empty")
+    }
+    if (type == null) {
+        throw new Error("type should not be null or empty")
+    }
+    return capturerObj.pictureFileToImage(fileName, type)
+}
+
+/**
+ * @brief 鍥剧墖瑁佸壀
+ * @param {string} src_pic 婧愭枃浠惰矾寰�
+ * @param {number} width 鍥惧儚瀹藉害
+ * @param {number} height 鍥惧儚楂樺害
+ * @param {string} out_pic 瑁佸壀鍚庣殑鍥剧墖璺緞
+ * @return ture/false
+ */
+capturer.pictureCropping = function (src_pic, width, height, out_pic) {
+    if (src_pic == null) {
+        throw new Error("src_pic should not be null or empty")
+    }
+    if (width == null) {
+        throw new Error("width should not be null or empty")
+    }
+    if (height == null) {
+        throw new Error("height should not be null or empty")
+    }
+    if (out_pic == null) {
+        throw new Error("out_pic should not be null or empty")
+    }
+    return capturerObj.pictureCropping(src_pic, width, height, out_pic)
+}
+
+/**
+ * 鍥剧墖鏁版嵁杞琲mage
+ * @param {string}  base64Data 鍥剧墖base64鏁版嵁
+ * @param {number}  dataLen 鏁版嵁闀垮害dataLen
+ * @param {number}  type 鍥惧儚绫诲瀷 IMAGE_YUV420P = 0, 1IMAGE_YUV420SP = 1,
+ * @returns imageId image鍙ユ焺id
+ */
+capturer.pictureDataToImage = function (base64Data, dataLen, type) {
+    if (base64Data == null) {
+        throw new Error("base64Data should not be null or empty")
+    }
+    if (dataLen == null) {
+        throw new Error("dataLen should not be null or empty")
+    }
+    if (type == null) {
+        throw new Error("type should not be null or empty")
+    }
+    return capturerObj.pictureDataToImage(base64Data, dataLen, type)
+}
+
+// image, (enum image_type)type, (enum vbar_drv_picture_type)save_type, quality, pic_data, data_len
+/**
+ * image 杞浘鐗囨暟鎹�
+ * @param {number}  imageId image鍥剧墖鍙ユ焺id
+ * @param {number}  type 鍥惧儚绫诲瀷 IMAGE_YUV420P = 0, 1IMAGE_YUV420SP = 1,
+ * @param {number}  saveType 杞崲鍚庣殑鍥剧墖绫诲瀷 TYPE_JPEG = 0, TYPE_BMP = 1, TYPE_PNG = 2, TYPE_UNKNOE = 3;
+ * @param {number}  quality 鍘嬬缉姣旓紝jpeg 0-100锛� png 鏃犳崯鍘嬬缉鏃犻渶姝ゅ弬鏁帮紝 bmp浣嶅浘鏃犻渶姝ゅ弬鏁�
+ * @returns 鍥剧墖base64鏁版嵁
+ */
+capturer.imageToPictureData = function (imageId, type, saveType, quality) {
+    if (imageId == null) {
+        throw new Error("imageId should not be null or empty")
+    }
+    if (type == null) {
+        throw new Error("type should not be null or empty")
+    }
+    if (saveType == null) {
+        throw new Error("saveType should not be null or empty")
+    }
+    if (quality == null) {
+        throw new Error("quality should not be null or empty")
+    }
+    return capturerObj.imageToPictureData(imageId, type, saveType, quality)
+}
+
+/**
+ * 杞浘鐗囨枃浠�
+ * @param {number}  imageId image鍥惧儚鍙ユ焺id
+ * @param {string}  type 鍥惧儚绫诲瀷 IMAGE_YUV420P = 0, 1IMAGE_YUV420SP = 1,
+ * @param {number}  saveType 杞崲鍚庣殑鍥剧墖绫诲瀷 YPE_JPEG = 0, TYPE_BMP = 1, TYPE_PNG = 2, TYPE_UNKNOE = 3;
+ * @param {number}  quality 鍘嬬缉姣旓紝jpeg 0-100锛� png 鏃犳崯鍘嬬缉鏃犻渶姝ゅ弬鏁帮紝 bmp浣嶅浘鏃犻渶姝ゅ弬鏁�
+ * @param {number}  savePath 鍥剧墖淇濆瓨璺緞
+ * @returns true/false
+ */
+capturer.imageToPictureFile = function (imageId, type, saveType, quality, savePath) {
+    if (imageId == null) {
+        throw new Error("imageId should not be null or empty")
+    }
+    if (type == null) {
+        throw new Error("type should not be null or empty")
+    }
+    if (saveType == null) {
+        throw new Error("saveType should not be null or empty")
+    }
+    if (quality == null) {
+        throw new Error("quality should not be null or empty")
+    }
+    if (savePath == null) {
+        throw new Error("savePath should not be null or empty")
+    }
+    return capturerObj.imageToPictureFile(imageId, type, saveType, quality, savePath)
+}
+
+/**
+* 鍥剧墖缂╂斁
+* @param {number}   imageId image鍥惧儚鍙ユ焺id
+* @param {number}   width  鐩爣鍥惧儚瀹藉害
+* @param {number}   height 鐩爣鍥惧儚楂樺害
+* @param {number}   mode       婊ゆ尝鍣ㄦā寮�
+*                   FILTER_MODE_NONE     涓嶈繘琛屾护娉紝鐩存帴閲囨牱锛涢�熷害鏈�蹇��
+*                   FILTER_MODE_LINEAR   鍙部姘村钩鏂瑰悜婊ゆ尝銆�
+*                   FILTER_MODE_BILINEAR 鍙岀嚎鎬ф护娉紱姣旂洅婊ゆ尝鏇村揩锛屼絾鍦ㄧ缉灏忓浘鍍忔椂璐ㄩ噺杈冧綆銆�
+*                   FILTER_MODE_BOX      鐩掓护娉紱鎻愪緵鏈�楂樼殑缂╂斁璐ㄩ噺
+*/
+capturer.imageResizeResolution = function (imageId, width, height, mode) {
+    if (imageId == null) {
+        throw new Error("imageId should not be null or empty")
+    }
+    if (width == null) {
+        throw new Error("width should not be null or empty")
+    }
+    if (height == null) {
+        throw new Error("height should not be null or empty")
+    }
+    if (mode == null) {
+        throw new Error("mode should not be null or empty")
+    }
+    return capturerObj.imageResizeResolution(imageId, width, height, mode)
+}
+
+/**
+ * 鍒ゆ柇capturer娑堟伅闃熷垪鏄惁涓虹┖
+ * @param {string} id 鍙ユ焺id锛岄潪蹇呭~锛堥渶淇濇寔鍜宨nit涓殑id涓�鑷达級
+ * @returns true/false
+ */
+capturer.msgIsEmpty = function (id) {
+    let pointer = dxCommon.handleId("capturer", id)
+    return capturerObj.msgIsEmpty(pointer)
+}
+
+/**
+ * 浠巆apturer娑堟伅闃熷垪涓鍙栨暟鎹�
+ * @param {string} id 鍙ユ焺id锛岄潪蹇呭~锛堥渶淇濇寔鍜宨nit涓殑id涓�鑷达級
+ * @returns image鎸囬拡
+ */
+capturer.msgReceive = function (id) {
+    let pointer = dxCommon.handleId("capturer", id)
+    return capturerObj.msgReceive(pointer)
+}
+
+/**
+ * 鏌ヨcapturer娑堟伅闃熷垪澶у皬
+ * @param {string} id 鍙ユ焺id锛岄潪蹇呭~锛堥渶淇濇寔鍜宨nit涓殑id涓�鑷达級
+ * @returns size
+ */
+capturer.msgQueueSize = function (id) {
+    let pointer = dxCommon.handleId("capturer", id)
+    return capturerObj.msgQueueSize(pointer)
+}
+
+capturer.RECEIVE_MSG = '__capturer__MsgReceive'
+
+/**
+ * 鐢ㄤ簬绠�鍖朿apturer缁勪欢鐨勪娇鐢紝鎶奵apturer灏佽鍦ㄨ繖涓獁orker閲岋紝浣跨敤鑰呭彧闇�瑕佽闃卐ventbus鐨勪簨浠跺氨鍙互鐩戝惉capturer
+ * @param {object} options capturer缁勪欢鍙傛暟锛屽弬鑰僣apturer.init锛屽繀濉�
+ * @param {string} options.id  鍙ユ焺id锛岄潪蹇呭~锛堣嫢鍒濆鍖栧涓疄渚嬮渶瑕佷紶鍏ュ敮涓�id锛�
+ */
+capturer.run = function (options) {
+    if (options === undefined || options.length === 0) {
+        throw new Error("dxcapturer.run:'options' parameter should not be null or empty")
+    }
+    if (options.id === undefined || options.id === null || typeof options.id !== 'string') {
+        // 鍙ユ焺id
+        options.id = ""
+    }
+    if (options.path === undefined || options.path === null || options.path.length <= 0) {
+        throw new Error("dxcapturer.run:'path' should not be null or empty")
+    }
+    let oldfilepre = '/app/code/dxmodules/capturerWorker'
+    let content = std.loadFile(oldfilepre + '.js').replace("{{id}}", options.id)
+    let newfile = oldfilepre + options.id + '.js'
+    std.saveFile(newfile, content)
+    let init = map.get("__capturer__run_init" + options.id)
+    if (!init) {//纭繚鍙垵濮嬪寲涓�娆�
+        map.put("__capturer__run_init" + options.id, options)
+        bus.newWorker(options.id || '__capturer', newfile)
+    }
+}
+
+/**
+ * 濡傛灉capturer鍗曠嫭涓�涓嚎绋嬶紝鍙互鐩存帴浣跨敤run鍑芥暟锛屼細鑷姩鍚姩涓�涓嚎绋嬶紝
+ * 濡傛灉鎯冲姞鍏ュ埌鍏朵粬宸叉湁鐨勭嚎绋嬶紝鍙互浣跨敤浠ヤ笅灏佽鐨勫嚱鏁�
+ */
+capturer.worker = {
+    //鍦╳hile寰幆鍓�
+    beforeLoop: function (options) {
+        capturer.init(options, options.id)
+        capturer.registerCallback(options.id)
+    },
+    //鍦╳hile寰幆閲�
+    loop: function (options) {
+        if (!capturer.msgIsEmpty(options.id)) {
+            let res = capturer.msgReceive(options.id);
+            if (options.id === undefined || options.id === null || typeof options.id !== 'string') {
+                // 鍙ユ焺id
+                options.id = ""
+            }
+            bus.fire(capturer.RECEIVE_MSG + options.id, res)
+        }
+    }
+}
+
+export default capturer;
diff --git a/vf205_access/dxmodules/dxCommon.js b/vf205_access/dxmodules/dxCommon.js
new file mode 100644
index 0000000..f8f645a
--- /dev/null
+++ b/vf205_access/dxmodules/dxCommon.js
@@ -0,0 +1,733 @@
+//build: 20240617
+// 绯荤粺鐨勪竴浜涘熀鏈搷浣溿�佽繕鏈変竴浜涘父鐢ㄧ殑宸ュ叿鍑芥暟锛屽熀鏈笂姣忎釜椤圭洰閮介渶瑕佷緷璧栬繖涓粍浠讹紝鍙﹀dxLogger涔熶緷璧栬繖涓粍浠�
+// 渚濊禆缁勪欢锛歞xDriver锛宒xMap
+import { commonClass } from './libvbar-m-dxcommon.so'
+import dxMap from './dxMap.js'
+import * as std from 'std';
+import * as os from "os"
+
+const commonObj = new commonClass();
+
+const common = {}
+/**
+ * 鑾峰彇绯荤粺鍚姩鐨勮繍琛屾椂闂�(鍗曚綅鏄)
+ * @returns 
+ */
+common.getUptime = function () {
+    return commonObj.getUptime();
+}
+
+/**
+ * 鑾峰彇绯荤粺鐨勬�诲唴瀛�(鍗曚綅鏄瓧鑺�)
+ * @returns 
+ */
+common.getTotalmem = function () {
+    return commonObj.getTotalmem();
+}
+
+/**
+ * 鑾峰彇绯荤粺鍓╀綑鍐呭瓨(鍗曚綅鏄瓧鑺�)
+ * @returns 
+ */
+common.getFreemem = function () {
+    return commonObj.getFreemem();
+}
+
+/**
+ * Deprcated, Please use `common.logMemory` instead.
+ */
+common.logMem = function (logger, interval = 10) {
+    if (logger) {
+        logger.debug("Deprcated, Please use `common.logMemory` instead.")
+    }
+}
+/**
+ * Logs the current memory usage at regular intervals for debugging and monitoring purposes.
+ * @param {object} logger The dxLogger module object.
+ * @param {number} interval The logging interval in seconds, defaulting to 10 seconds.
+ */
+common.logMemory = function (logger, interval = 10) {
+    if (!logger) return;
+
+    let first = new Date().getTime();
+    let min = common.getFreemem() / 1024;
+    let max = min;
+    const _logmemory = () => {
+        try {
+            const now = new Date().getTime();
+            const pass = (now - first) / 1000;
+            const free = common.getFreemem() / 1024;
+
+            min = Math.min(min, free);
+            max = Math.max(max, free);
+
+            // Format time
+            let passStr;
+            if (pass > 1700000000) {
+                first = now;
+                passStr = 'time synced, 0s';
+            } else if (pass >= 3600) {
+                const hours = Math.floor(pass / 3600);
+                const minutes = Math.floor((pass % 3600) / 60);
+                const seconds = Math.floor(pass % 60);
+                passStr = `${hours}h ${minutes}m ${seconds}s`;
+            } else if (pass >= 60) {
+                const minutes = Math.floor(pass / 60);
+                const seconds = Math.floor(pass % 60);
+                passStr = `${minutes}m ${seconds}s`;
+            } else {
+                passStr = `${Math.floor(pass)}s`;
+            }
+            const log = `------ ${passStr} passed, free memory (k): ${free}, min free memory (k): ${min}, max free memory (k): ${max} ------`;
+            logger.info(log);
+        } catch (err) {
+            logger.error('Error in logMemory:', err);
+        } finally {
+            os.setTimeout(_logmemory, interval * 1000);
+        }
+    };
+
+    os.setTimeout(_logmemory, interval * 1000);
+};
+
+/**
+ * The principle of converting asynchronous to synchronous is as follows: 
+ * the `request` function periodically checks a designated variable in memory for a value. 
+ * If the value is found within the timeout period, the result is returned; otherwise, 
+ * it is considered a timeout. The `response` function is responsible for storing the result
+ *  in the designated variable once the asynchronous request is completed.
+ */
+common.sync = {
+    /**
+     * Block and wait for data
+     * Usage:
+        common.sync.request(topic, 200)
+        .then((data) => {
+            log.info("Received data:", data);
+        })
+        .catch((err) => {
+            log.error("Request failed:", err.message);
+        });
+     * @param {string} topic The unique identifier for each request
+     * @param {int} timeout waitting timeout(microsecond)锛宒efault is 200 ms
+     * @returns 
+     */
+    request: function (topic, timeout = 200) {
+        return new Promise((resolve, reject) => {
+            let map = dxMap.get("SYNC");
+            let startTime = Date.now();
+
+            const checkData = () => {
+                let data = map.get(topic);
+                if (data) {
+                    map.del(topic); //del data in map
+                    resolve(data); //return data
+                } else if (Date.now() - startTime >= timeout) {
+                    map.del(topic); // del data in map with timeout
+                    reject(new Error(`Timeout exceeded for topic: ${topic}`)); 
+                } else {
+                    os.setTimeout(checkData, 10); //every 10 ms to check
+                }
+            };
+
+            os.setTimeout(checkData, 10); // first check
+        });
+    },
+
+    /**
+     * notify data to requester
+     * @param {string} topic The unique identifier for each request
+     * @param {*} data 
+     * @returns 
+     */
+    response: function (topic, data) {
+        let map = dxMap.get("SYNC");
+        map.put(topic, data); // save data in map
+    }
+};
+
+/**
+ * 鑾峰彇绯荤粺鍙敤纾佺洏鎬婚噺(鍗曚綅鏄瓧鑺�)
+ * @param {string} path 涓嶅悓鐨勭鐩樺垎鍖哄悕绉帮紙涓嶆槸鐩綍鍚嶏級锛岄潪蹇呭~锛岀己鐪佹槸'/'
+ */
+common.getTotaldisk = function (path) {
+    return commonObj.getTotaldisk(!path ? "/" : path);
+}
+
+/**
+ * 鑾峰彇绯荤粺纾佺洏鍓╀綑鍙敤閲�(鍗曚綅鏄瓧鑺�)
+ * @param {string} path 涓嶅悓鐨勭鐩樺垎鍖哄悕绉帮紙涓嶆槸鐩綍鍚嶏級锛岄潪蹇呭~锛岀己鐪佹槸'/'
+ * @returns 
+ */
+common.getFreedisk = function (path) {
+    return commonObj.getFreedisk(!path ? "/" : path);
+}
+
+/**
+ * 鑾峰彇CPU ID
+ * @param {number} len 闈炲繀濉紝缂虹渷闀垮害鏄�33浣嶉暱
+ * @returns 
+ */
+common.getCpuid = function () {
+    return commonObj.getCpuid(33);
+}
+
+/**
+ * 鑾峰彇璁惧uuid锛堝瓧绗︿覆锛�
+ * @returns 
+ */
+common.getUuid = function () {
+    return commonObj.getUuid(19);
+}
+
+/**
+ * 鑾峰彇璁惧鍞竴鏍囪瘑
+ * @returns 
+ */
+common.getSn = function () {
+    let sn = std.loadFile('/etc/.sn')
+    if (sn) {
+        return sn
+    } else {
+        return commonObj.getUuid(19);
+    }
+}
+
+/**
+ * 鑾峰彇閫氳繃uuid璁$畻鐨刴ac鍦板潃锛岃繖涓彲浠ョ敤鏉ュ垵濮嬪寲缃戝崱鐨勬椂鍊欑敤
+ * @returns 鏍煎紡绫讳技锛歜2:a1:63:3f:99:b6
+ */
+common.getUuid2mac = function () {
+    return commonObj.getUuid2mac(19);
+}
+
+/**
+ * 鑾峰彇cpu鍗犵敤鐜囷紙涓嶅ぇ浜�100鐨勬暟瀛楋級
+ * @returns 
+ */
+common.getFreecpu = function () {
+    return commonObj.getFreecpu();
+}
+
+
+/**
+ * RSA 瑙e瘑 锛堢閽ュ姞瀵嗗叕閽ヨВ瀵嗭級
+ * 姣斿鍏挜鏄�
+ * @param {ArrayBuffer} data 瑕佽В瀵嗙殑鏁版嵁锛屽繀濉�
+ * @param {string} publicKey 鍏挜锛屽繀濉�
+ * @returns 
+ */
+common.arrayBufferRsaDecrypt = function (data, publicKey) {
+    if (data === undefined || data === null) {
+        throw new Error("dxCommon.arrayBufferRsaDecrypt:'data' parameter should not be null or empty")
+    }
+    if (publicKey === undefined || publicKey === null || publicKey.length < 1) {
+        throw new Error("dxCommon.arrayBufferRsaDecrypt:'publicKey' parameter should not be null or empty")
+    }
+    return commonObj.arrayBufferRsaDecrypt(data, publicKey)
+}
+
+/**
+ * @brief   Stirng aes 鍔犲瘑
+ */
+common.aes128EcbEncrypt = function (input, key) {
+    return commonObj.aes128EcbEncrypt(input, key)
+}
+/**
+ * @brief   Stirng aes 瑙e瘑
+ */
+common.aes128EcbDecrypt = function (input, key) {
+    return commonObj.aes128EcbDecrypt(input, key)
+}
+
+/**
+ * arraybuffer ecb 128bit Pkcs5Padding aes 鍔犲瘑
+ * @param {ArrayBuffer} input 鏄庢枃
+ * @param {ArrayBuffer} key 瀵嗛挜
+ * @returns ArrayBuffer 瀵嗘枃
+ */
+common.aes128EcbPkcs5PaddingEncode = function (input, key) {
+    return commonObj.aes128Pkcs7PaddingEncode(input, key)
+}
+
+/**
+ * arraybuffer ecb 128bit Pkcs5Padding aes 瑙e瘑
+ * 
+ * @param {ArrayBuffer} input 瀵嗘枃
+ * @param {ArrayBuffer} key 瀵嗛挜
+ * @returns ArrayBuffer 鏄庢枃
+ */
+common.aesEcb128Pkcs5PaddingDecode = function (input, key) {
+    return commonObj.aes128Pkcs7PaddingDecode(input, key)
+}
+
+/**
+ * aes ECB Pkcs5Padding 128 鍔犲瘑
+ * 绀轰緥锛歝ommon.aes128EcbPkcs5PaddingEncrypt("stamp=202008鏂�&tic", "1234567890123456")
+ * 缁撴灉锛歟f7c3cff9df57b3bcb0951938c574f969e13ffdcc1eadad298ddbd1fb1a4d2f7
+ * 鍙傝�� https://www.devglan.com/online-tools/aes-encryption-decryption
+ * @param {string} input  鏄庢枃鏁版嵁
+ * @param {string} key     瀵嗛挜 16瀛楄妭瀛楃涓�
+ * @return 瀵嗘枃 16杩涘埗瀛楃涓�
+ */
+common.aes128EcbPkcs5PaddingEncrypt = function (input, key) {
+    let data = common.hexStringToArrayBuffer(common.strToUtf8Hex(input))
+    key = common.hexStringToArrayBuffer(common.strToUtf8Hex(key))
+    // 鍔犲瘑
+    let hex = common.arrayBufferToHexString(common.aes128EcbPkcs5PaddingEncode(data, key))
+    return hex
+}
+/**
+   * aes ECB Pkcs5Padding 128 瑙e瘑
+   * @param {string} input 瀵嗘枃 16杩涘埗瀛楃涓�
+   * @param {string} key   瀵嗛挜 16瀛楄妭瀛楃涓�
+   * @return 鏄庢枃
+   */
+common.aes128EcbPkcs5PaddingDecrypt = function (input, key) {
+    key = common.hexStringToArrayBuffer(common.strToUtf8Hex(key))
+    let res = common.aesEcb128Pkcs5PaddingDecode(common.hexStringToArrayBuffer(input), key)
+    return common.utf8HexToStr(common.arrayBufferToHexString(res))
+}
+
+/**
+ * 鎵ц鎿嶄綔绯荤粺鐨勫懡浠�
+ * @param {*} cmd 鍛戒护
+ * @returns 
+ */
+common.system = function (cmd) {
+    return commonObj.system(cmd)
+}
+
+/**
+ * 鎵ц鎿嶄綔绯荤粺鐨勫懡浠� 
+ * @param {*} cmd 鍛戒护 鎿嶄綔绯荤粺甯哥敤鎸囦护(linux缁濆ぇ閮ㄥ垎鎸囦护閮芥敮鎸�)锛屽繀濉�
+ * @returns 
+ */
+common.systemBrief = function (cmd) {
+    return commonObj.systemBrief(cmd)
+}
+
+/**
+ * 鎵ц鎿嶄綔绯荤粺鐨勫懡浠ゅ苟杩斿洖缁撴灉
+ * @param {*} cmd 鍛戒护 鎿嶄綔绯荤粺甯哥敤鎸囦护(linux缁濆ぇ閮ㄥ垎鎸囦护閮芥敮鎸�)锛屽繀濉�
+ * @param {*} resLen 鎺ユ敹鏁版嵁闀垮害 鏈夋椂鍊欒繑鍥炵殑鏁版嵁寰堝ぇ锛屽彲浠ラ�氳繃杩欎釜鍊兼潵杩斿洖鍥哄畾闀垮害鐨勬暟鎹紝蹇呭~
+ * @returns 
+ */
+common.systemWithRes = function (cmd, resLen) {
+    return commonObj.systemWithRes(cmd, resLen)
+}
+
+/**
+ * 鎵ц鎿嶄綔绯荤粺鐨勫懡浠ら樆濉炴墽琛�
+ * @param {*} cmd 鍛戒护  鎿嶄綔绯荤粺甯哥敤鎸囦护(linux缁濆ぇ閮ㄥ垎鎸囦护閮芥敮鎸�)锛屽繀濉�
+ * @returns 
+ */
+common.systemBlocked = function (cmd) {
+    return commonObj.systemBlocked(cmd)
+}
+
+/**
+ * 寮傛寤惰繜閲嶅惎
+ * @param {*} delay_s 寤惰繜鏃堕棿
+ * @returns 
+ */
+common.asyncReboot = function (delay_s) {
+    return commonObj.asyncReboot(delay_s)
+}
+
+/**
+ * bcc鏍¢獙
+ * @param {array} data eg:[49,50,51,52,53,54]瀵瑰簲鐨勫�兼槸7
+ * @returns 鏍¢獙璁$畻缁撴灉
+ */
+common.calculateBcc = function (data) {
+    return commonObj.calculateBcc(data)
+}
+
+/**
+ * crc鏍¢獙 姣斿瀛楃涓�'123456'鏍¢獙璁$畻鐨勭粨鏋滄槸鏁板瓧 158520161
+ * @param {string} content 瑕佹牎楠岀殑瀛楃涓叉暟鎹紝
+ * @returns 
+ */
+common.crc32 = function (content) {
+    if (content === undefined || content === null || typeof (content) != "string" || content.length < 1) {
+        throw new Error("dxCommon.crc32:'content' paramter should not be empty")
+    }
+    return commonObj.crc32(content)
+}
+
+/**
+ * 璁$畻MD5鍝堝笇锛屾瘮濡�'123456'瀵瑰簲鐨勬暟瀛楁暟缁勬槸[49,50,51,52,53,54] 瀵瑰簲鐨刴d5鏄�'e10adc3949ba59abbe56e057f20f883e'锛�
+ * 浣嗘槸杩斿洖鐨勪笉鏄�16杩涘埗瀛楃涓诧紝鏄暟瀛楁暟缁勶紝鍙互浣跨敤arrToHex鍑芥暟杞崲
+ * @param {array} arr 鏁板瓧鏁扮粍 
+ * @returns 鏁板瓧鏁扮粍
+ */
+common.md5Hash = function (arr) {
+    return commonObj.md5Hash(arr)
+}
+
+/**
+ * 鏂囦欢璁$畻MD5鍝堝笇,姣斿鏂囦欢閲岀殑鍐呭鏄�'123456'锛屽搴旂殑md5鏄�'e10adc3949ba59abbe56e057f20f883e'
+ * 浣嗘槸杩斿洖鐨勪笉鏄�16杩涘埗瀛楃涓诧紝鏄暟瀛楁暟缁勶紝鍙互浣跨敤arrToHex鍑芥暟杞崲
+ * @param {string} 鏂囦欢璺緞锛岀粷瀵硅矾寰勶紝蹇呭~锛岄�氬父鏄互/app/code寮�澶�
+ * @returns 鏁板瓧鏁扮粍
+ */
+common.md5HashFile = function (filePath) {
+    if (filePath === undefined || filePath === null || typeof (filePath) != "string") {
+        return null
+    }
+    return commonObj.md5HashFile(filePath)
+}
+
+/**
+ * 璁$畻HMAC MD5鍔犲瘑,姣斿鍔犲瘑鐨勬暟鎹槸'123456',瀵嗛挜鏄�'654321'锛屽搴旂殑缁撴灉鏄�'357cbe6d81a8ec770799879dc8629a53'
+ * 浣嗘槸鍙傛暟鍜岃繑鍥炵殑鍊奸兘鏄疉rrayBuffer
+ * @param {ArrayBuffer} data 闇�瑕佸姞瀵嗙殑鍐呭,蹇呭~
+ * @param {ArrayBuffer} key 瀵嗛挜 ,蹇呭~
+ * @returns ArrayBuffer
+ */
+common.hmacMd5Hash = function (data, key) {
+    return commonObj.hmacMd5Hash(data, key)
+}
+
+/**
+ * 璁$畻HMAC MD5鍔犲瘑,姣斿鍔犲瘑鐨勬暟鎹槸'123456',瀵嗛挜鏄�'654321'锛屽搴旂殑缁撴灉鏄�'357cbe6d81a8ec770799879dc8629a53'
+ * @param {string} data 闇�瑕佸姞瀵嗙殑鍐呭,蹇呭~
+ * @param {string} key 瀵嗛挜 ,蹇呭~
+ * @returns ArrayBuffer
+ */
+common.hmac = function (data, key) {
+    return commonObj.hmac(data, key)
+}
+
+/**
+ * 鏂囦欢璁$畻HMAC MD5鍔犲瘑锛屾瘮濡傛枃浠堕噷鐨勫唴瀹规槸'123456'锛屽瘑閽ユ槸'654321'锛屽搴旂殑缁撴灉鏄�'357cbe6d81a8ec770799879dc8629a53'
+ * @param {string} filePath 闇�瑕佸姞瀵嗙殑鍐呭瀛樺偍鐨勬枃浠惰矾寰勶紝缁濆璺緞锛屽繀濉紝閫氬父鏄互/app/code寮�澶�
+ * @param {array} key 瀵嗛挜 ,鏁板瓧鏁扮粍,蹇呭~
+ * @returns 鏁板瓧鏁扮粍
+ */
+common.hmacMd5HashFile = function (filePath, key) {
+    return commonObj.hmacMd5HashFile(filePath, key)
+}
+
+
+/**
+ * base64杞琤in鏂囦欢
+ * @param {string} file_path 鏂囦欢璺緞锛屽繀濉�
+ * @param {string} base64Data base64鏁版嵁锛屽繀濉�
+ * @returns 
+ */
+common.base64_2binfile = function (file_path, base64Data) {
+    return commonObj.base64_2binfile(file_path, base64Data);
+}
+
+/**
+ * bin鏂囦欢杞琤ase64
+ * @param {string} file_path 鏂囦欢璺緞锛屽繀濉�
+ * @returns base64Data base64鏁版嵁锛屽繀濉�
+ */
+common.binfile_2base64 = function (file_path) {
+    return commonObj.binfile_2base64(file_path);
+}
+
+/**
+ * 鍒囨崲璁惧妯″紡
+ * @description 妯″紡鍒囨崲鍚庝細閲嶅惎璁惧锛岃繘鍏ユ寚瀹氭ā寮忥紝浣跨敤鏂规硶鏃堕渶瀹屾暣缁存姢鐩镐簰鍒囨崲鐨勯�昏緫锛屽垏鎹负涓氬姟妯″紡鍚庝笉鑳戒娇鐢↖DE鍔熻兘
+ * @param {number} mode 娉ㄦ剰锛氭棫鐗堟湰妯″紡鍒囨崲浣跨敤锛�1銆�2銆�3锛夛紝鏂扮増鏈ā寮忓垏鎹娇鐢紙dev銆乼est銆乸rod銆乻afe锛�
+ * @returns true false
+ */
+common.setMode = function (mode) {
+    // 娉ㄦ剰锛氭棫鐗堟湰妯″紡鍒囨崲浣跨敤锛�1銆�2銆�3锛�
+    if (mode == 1) {
+        //鐢熶骇妯″紡
+        commonObj.systemWithRes(`echo 'app' > /etc/.mode`, 2)
+        // 1.0鐗堟湰鍒囨崲涓哄叾浠栨ā寮忓悗鍒犻櫎宸ュ巶妫�娴嬶紙鍚庣画鐗堟湰鍙兘浼氳皟鏁达級
+        commonObj.systemWithRes(`rm -rf /test`, 2)
+    } else if (mode == 2) {
+        //璋冭瘯妯″紡
+        commonObj.systemWithRes(`echo 'debug' > /etc/.mode`, 2)
+        // 1.0鐗堟湰鍒囨崲涓哄叾浠栨ā寮忓悗鍒犻櫎宸ュ巶妫�娴嬶紙鍚庣画鐗堟湰鍙兘浼氳皟鏁达級
+        commonObj.systemWithRes(`rm -rf /test`, 2)
+    } else if (mode == 3) {
+        //璇曚骇妯″紡
+        commonObj.systemWithRes(`echo 'pp' > /etc/.mode`, 2)
+    } 
+    
+    // 娉ㄦ剰锛氭柊鐗堟湰妯″紡鍒囨崲浣跨敤锛坉ev銆乼est銆乸rod銆乻afe锛�
+    else if (mode == "dev") {
+        //寮�鍙戞ā寮�
+        commonObj.systemWithRes(`echo 'dev' > /etc/.mode_v1`, 2)
+    } else if (mode == "test") {
+        //娴嬭瘯妯″紡锛堣瘯浜фā寮忥級
+        commonObj.systemWithRes(`echo 'test' > /etc/.mode_v1`, 2)
+    } else if (mode == "prod") {
+        //鐢熶骇妯″紡
+        commonObj.systemWithRes(`echo 'prod' > /etc/.mode_v1`, 2)
+    } else if (mode == "safe") {
+        //瀹夊叏妯″紡
+        commonObj.systemWithRes(`echo 'safe' > /etc/.mode_v1`, 2)
+    } else {
+        return false
+    }
+    commonObj.systemWithRes(`sync`, 2)
+    commonObj.asyncReboot(2)
+    return true
+}
+
+/**
+ * 鏌ヨ璁惧妯″紡
+ * @description 鑾峰彇璁惧褰撳墠妯″紡
+ * @returns 涓氬姟妯″紡锛�1锛屽紑鍙戞ā寮忥細2锛屽伐鍘傛ā寮忥細28锛� 寮傚父妯″紡锛�-1
+ */
+common.getMode = function () {
+    let ret = commonObj.systemWithRes(`test -e "/etc/.mode" && echo "OK" || echo "NO"`, 2)
+    if (ret.includes('NO')) {
+        return 28
+    }
+    let mode = commonObj.systemWithRes(`cat "/etc/.mode"`, 10)
+    if (mode.includes('app')) {
+        return 1
+    } else if (mode.includes('debug')) {
+        return 2
+    } else {
+        return -1
+    }
+}
+/**
+ * 鍗佸叚杩涘埗杞瓧鑺傛暟缁� eg:313233616263->[49,50,51,97,98,99]
+ * @param {string} str 16杩涘埗瀛楃涓� 灏忓啓涓斾腑闂存棤绌洪殧鐨勫崄鍏繘鍒跺瓧绗︿覆
+ * @returns 鏁板瓧鏁板瓧
+ */
+common.hexToArr = function (str) {
+    if (str === undefined || str === null || (typeof str) != 'string' || str.length < 1) {
+        throw new Error("dxCommon.hexToArr:'str' parameter should not be empty")
+    }
+    let regex = /.{2}/g;
+    let arr = str.match(regex);
+    return arr.map(item => parseInt(item, 16));
+}
+/**
+ * 瀛楄妭鏁扮粍杞崄鍏繘鍒� eg:[49,50,51,97,98,99]->313233616263
+ * @param {array}numbers 鏁板瓧鏁扮粍
+ * @returns str 16杩涘埗瀛楃涓� 灏忓啓涓斾腑闂存棤绌洪殧鐨勫崄鍏繘鍒跺瓧绗︿覆
+ */
+common.arrToHex = function (numbers) {
+    const hexArray = numbers.map(num => num.toString(16).padStart(2, '0').toLowerCase());
+    const hexString = hexArray.join('');
+    return hexString;
+}
+/**
+ * 鍗佸叚杩涘埗杞瓧绗︿覆 eg:313233616263->123abc
+ * 娉ㄦ剰濡傛灉16杩涘埗瀛楃涓叉槸鐢变腑鏂囪浆杩囧幓鐨勶紝鍐嶈浆鍥炰腑鏂囧瓧绗︿覆浼氭湁涔辩爜锛屽洜涓烘槸涓�涓竴涓瓧鑺傜殑杞崲
+ * @param {string} str 瑕佽浆鐨�16杩涘埗瀛楃涓�
+ * @returns 
+ */
+common.hexToString = function (str) {
+    let regex = /.{2}/g;
+    let arr = str.match(regex);
+    arr = arr.map(item => String.fromCharCode(parseInt(item, 16)));
+    return arr.join("");
+}
+// 灏嗗瓧绗︿覆杞崲涓� UTF-8 缂栫爜鐨�16杩涘埗瀛楃涓�
+common.strToUtf8Hex = function (str) {
+    const bytes = [];
+    for (let i = 0; i < str.length; i++) {
+        let code = str.charCodeAt(i);
+        if (code < 0x80) {
+            bytes.push(code);
+        } else if (code < 0x800) {
+            bytes.push(0xc0 | (code >> 6), 0x80 | (code & 0x3f));
+        } else if (code < 0xd800 || code >= 0xe000) {
+            bytes.push(0xe0 | (code >> 12), 0x80 | ((code >> 6) & 0x3f), 0x80 | (code & 0x3f));
+        } else {
+            // 澶勭悊 Unicode 缂栫爜
+            i++;
+            code = 0x10000 + (((code & 0x3ff) << 10) | (str.charCodeAt(i) & 0x3ff));
+            bytes.push(
+                0xf0 | (code >> 18),
+                0x80 | ((code >> 12) & 0x3f),
+                0x80 | ((code >> 6) & 0x3f),
+                0x80 | (code & 0x3f)
+            );
+        }
+    }
+    return this.arrToHex(bytes);
+}
+/**
+ * 浼犻�掕繃鏉ョ殑utf-8鐨�16杩涘埗瀛楃涓茶浆鎹㈡垚瀛楃涓�
+ * @param {string} hex 
+ * @returns 
+ */
+common.utf8HexToStr = function (hex) {
+    let array = this.hexToArr(hex)
+    var out, i, len, c;
+    var char2, char3;
+
+    out = "";
+    len = array.length;
+    i = 0;
+    while (i < len) {
+        c = array[i++];
+        switch (c >> 4) {
+            case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
+                // 0xxxxxxx
+                out += String.fromCharCode(c);
+                break;
+            case 12: case 13:
+                // 110x xxxx   10xx xxxx
+                char2 = array[i++];
+                out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F));
+                break;
+            case 14:
+                // 1110 xxxx  10xx xxxx  10xx xxxx
+                char2 = array[i++];
+                char3 = array[i++];
+                out += String.fromCharCode(((c & 0x0F) << 12) |
+                    ((char2 & 0x3F) << 6) |
+                    ((char3 & 0x3F) << 0));
+                break;
+        }
+    }
+
+    return out;
+}
+/**
+ * 瀛楃涓茶浆鍗佸叚杩涘埗 eg:123abc->313233616263
+ * @param {string} str 瑕佽浆鐨勫瓧绗︿覆
+ * @returns 
+ */
+common.stringToHex = function (str) {
+    if (str === undefined || str === null || typeof (str) != "string") {
+        return null
+    }
+    let val = "";
+    for (let i = 0; i < str.length; i++) {
+        val += str.charCodeAt(i).toString(16)
+    }
+    return val
+}
+
+/**
+ * 灏忕鏍煎紡杞崄杩涘埗鏁� eg:001001->69632
+ * @param {string} hexString 16杩涘埗瀛楃涓� 灏忓啓涓斾腑闂存棤绌洪殧鐨勫崄鍏繘鍒跺瓧绗︿覆
+ * @returns 鏁板瓧
+ */
+common.littleEndianToDecimal = function (hexString) {
+    // 灏嗗皬绔牸寮忕殑鍗佸叚杩涘埗瀛楃涓茶繘琛屽弽杞�
+    let reversedHexString = hexString
+        .match(/.{2}/g)  // 姣忎袱涓瓧绗﹀垎闅�
+        .reverse()  // 鍙嶈浆鏁扮粍
+        .join("");  // 鍚堝苟涓哄瓧绗︿覆
+
+    // 灏嗗弽杞悗鐨勫崄鍏繘鍒跺瓧绗︿覆杞崲涓哄崄杩涘埗鏁�
+    let decimal = parseInt(reversedHexString, 16);
+    return decimal;
+}
+
+
+/**
+ * 鍗佽繘鍒舵暟杞崲涓�16杩涘埗灏忕鏍煎紡瀛楃涓�
+ * eg:300->2c01
+ * eg:230->e600
+ * @param {number} decimalNumber 鍗佽繘鍒舵暟瀛�,蹇呭~
+ * @param {number} byteSize 鐢熸垚浣嶆暟 瀛楄妭鐨勪釜鏁帮紝濡傛灉瓒呭嚭瀹為檯瀛楄妭涓暟锛屼細鍦ㄥ彸杈硅ˉ0锛屼綆浜庝細鎴彇锛岄潪蹇呭~锛岀己鐪佹槸2
+ * @returns 
+ */
+common.decimalToLittleEndianHex = function (decimalNumber, byteSize) {
+    if (decimalNumber === undefined || decimalNumber === null || (typeof decimalNumber) != 'number') {
+        throw new Error("dxCommon.decimalToLittleEndianHex:'decimalNumber' parameter should be number")
+    }
+    if (byteSize === undefined || byteSize === null || (typeof byteSize) != 'number' || byteSize <= 0) {
+        byteSize = 2
+    }
+    const littleEndianBytes = [];
+    for (let i = 0; i < byteSize; i++) {
+        littleEndianBytes.push(decimalNumber & 0xFF);
+        decimalNumber >>= 8;//鐩稿綋浜庨櫎浠�256
+    }
+    const littleEndianHex = littleEndianBytes
+        .map((byte) => byte.toString(16).padStart(2, '0'))
+        .join('');
+    return littleEndianHex;
+}
+
+/**
+ * 灏�16杩涘埗瀛楃涓茶浆鎹负ArrayBuffer
+ * @param {*} hexString 瑕佽浆鎹㈢殑16杩涘埗瀛楃涓�
+ * @returns 
+ */
+common.hexStringToArrayBuffer = function (hexString) {
+    return this.hexStringToUint8Array(hexString).buffer;
+}
+
+/**
+ * 灏�16杩涘埗瀛楃涓茶浆鎹负Uint8Array
+ * @param {string} hexString 瑕佽浆鎹㈢殑16杩涘埗瀛楃涓诧紝灏忓啓涓斾腑闂存棤绌洪殧鐨勫崄鍏繘鍒跺瓧绗︿覆
+ * @returns Uint8Array瀵硅薄
+ */
+common.hexStringToUint8Array = function (hexString) {
+    if (hexString === undefined || hexString === null || (typeof hexString) != 'string' || hexString.length <= 0) {
+        throw new Error("dxCommon.hexStringToUint8Array:'hexString' parameter should not be empty")
+    }
+    let byteString = hexString.match(/.{1,2}/g);
+    let byteArray = byteString.map(function (byte) {
+        return parseInt(byte, 16);
+    });
+    let buffer = new Uint8Array(byteArray);
+    return buffer;
+}
+
+/**
+ * 灏� ArrayBuffer 杞崲涓哄崄鍏繘鍒跺瓧绗︿覆鏍煎紡
+ * @param {ArrayBuffer} buffer 
+ * @returns 灏忓啓涓斾腑闂存棤绌洪殧鐨勫崄鍏繘鍒跺瓧绗︿覆
+ */
+common.arrayBufferToHexString = function (buffer) {
+    return this.uint8ArrayToHexString(new Uint8Array(buffer))
+}
+/**
+ * 灏� Uint8Array 杞崲涓哄崄鍏繘鍒跺瓧绗︿覆鏍煎紡
+ * @param {Uint8Array} array 
+ * @returns 灏忓啓涓斾腑闂存棤绌洪殧鐨勫崄鍏繘鍒跺瓧绗︿覆
+ */
+common.uint8ArrayToHexString = function (array) {
+    let hexString = '';
+    for (let i = 0; i < array.length; i++) {
+        const byte = array[i].toString(16).padStart(2, '0');
+        hexString += byte;
+    }
+    return hexString
+}
+/**
+ * 璁剧疆/鑾峰彇缁勪欢鍙ユ焺id閫氱敤鏂规硶
+ * @param {string} name 缁勪欢鍚嶏紝蹇呭~
+ * @param {string} id 鍙ユ焺id锛岄潪蹇呭~
+ * @param {number} pointer 鍙ユ焺鎸囬拡鏁板瓧锛岄潪蹇呭~
+ * @returns 
+ */
+common.handleId = function (name, id, pointer) {
+    // 缁勪欢鍚嶄笉鑳戒负绌�
+    if (name === undefined || name === null || name === "" || typeof name !== 'string') {
+        return
+    }
+    let map = dxMap.get('handleIds')
+    // 鍙ユ焺id
+    if (id === undefined || id === null || id === "" || typeof id !== 'string') {
+        id = "__" + name + "_default"
+    }
+    if (pointer === undefined || pointer === null || typeof pointer !== 'number') {
+        // pointer涓虹┖鍒欎负鑾峰彇
+        return map.get(id)
+    } else {
+        // pointer涓嶄负绌哄垯涓鸿缃�
+        let isExist = map.get(id)
+        if (isExist) {
+            // 鍙ユ焺宸插瓨鍦�
+            return
+        }
+        map.put(id, pointer)
+    }
+}
+
+
+export default common
\ No newline at end of file
diff --git a/vf205_access/dxmodules/dxConfig.js b/vf205_access/dxmodules/dxConfig.js
new file mode 100644
index 0000000..0f4844e
--- /dev/null
+++ b/vf205_access/dxmodules/dxConfig.js
@@ -0,0 +1,140 @@
+/**
+ * 瀹炵幇瀵瑰簲鐢ㄦ墍鏈夐厤缃」锛坘ey/value)鐨勭鐞嗭細
+ * 1. 鐢ㄦ埛闇�瑕佹妸鍒濆鐨勯厤缃」淇濆瓨鍦ㄩ」鐩殑 src/config.json 锛岄厤缃枃浠剁殑鏍煎紡璇蜂繚鐣檏ey/value鏍煎紡锛堟敮鎸佹敞閲�)锛寁alue鍙兘鏄瓧绗︿覆鍜屾暟瀛楃被鍨�,渚嬪锛�
+ * {
+ *      //mqtt鐩稿叧閰嶇疆
+ *      "mqtt.ip":"192.168.2.3",
+ *      "mqtt.port":6199,
+ * }
+ * 2. 涔熸敮鎸佽嚜瀹氫箟閰嶇疆鏂囦欢锛屽垵濮嬪寲鍙互浼犻�掕嚜瀹氫箟閰嶇疆鏂囦欢鐨勮矾寰勫拰鏍囪瘑锛屽悗缁鍐欐暟鎹兘闇�瑕佷紶閫掕繖涓爣璇�
+ * 3. 鐢ㄦ埛鍦ㄥ簲鐢ㄤ腑绗竴娆′娇鐢ㄨ繖涓粍浠讹紝闇�瑕佸厛鍒濆鍖� init锛屽垵濮嬪寲浼氭妸 config.json 鐨勬暟鎹繚瀛樺埌鍐呭瓨閲岋紝浠ュ悗姣忔鑾峰彇閮芥槸浠庡唴瀛樿幏鍙�
+ * 4. 鐢ㄦ埛鍙互鍦ㄤ换浣曞湴鏂归兘鍙互閫氳繃 get 鍜� set 鏉ヨ鍐欓厤缃�
+ * 5. 濡傛灉淇敼閰嶇疆椤圭殑 value 鍚屾椂闇�瑕佷繚瀛樺埌閰嶇疆鏂囦欢锛堜繚璇侀噸鍚悗鏂伴厤缃敓鏁堬級锛屼娇鐢� setAndSave
+ * 6. 濡傛灉闇�瑕佹仮澶嶆墍鏈夐粯璁ら厤缃紝浣跨敤 reset
+ */
+import * as os from 'os';
+import dxMap from './dxMap.js'
+import common from './dxCommon.js'
+import logger from './dxLogger.js'
+import std from './dxStd.js'
+
+const map = dxMap.get("default")
+
+const config = {}
+const DEFALUT_OPTIONS = { path: '/app/code/src/config.json', savePath: '/app/data/config/config.json', flag: '___config.' }
+
+/**
+ * 鍒濆鍖栦細鎶� config.json 鎴栬嚜瀹氫箟鐨勯厤缃枃浠剁殑鏁版嵁淇濆瓨鍒板唴瀛橀噷锛屼互鍚庢瘡娆¤幏鍙栭兘鏄粠鍐呭瓨鑾峰彇
+ * @param {object} custom 闈炲繀濉紝鑷畾涔夌殑閰嶇疆鏂囦欢
+ *          @param {string} custom.path 鑷畾涔夌殑閰嶇疆鏂囦欢瀹屾暣璺緞
+ *          @param {string} custom.flag 鑷畾涔夐厤缃枃浠剁殑鏍囪瘑锛屾敞鎰忓鏋滄湁澶氫釜鑷畾涔夐厤缃枃浠讹紝杩欎釜鏍囪瘑涓嶈閲嶅
+ */
+config.init = function (custom) {
+    if (custom) {
+        if (!custom.path || !custom.flag) {
+            throw new Error('The path and flag for the custom configuration file cannot be empty.')
+        }
+    }
+    let flag = custom ? DEFALUT_OPTIONS.flag + custom.flag + '.' : DEFALUT_OPTIONS.flag;
+    const isInited = map.get('___inited' + flag)
+    if (isInited) {//鍙垵濮嬪寲涓�娆�
+        return
+    }
+    let path = custom ? custom.path : DEFALUT_OPTIONS.path
+    let savePath = custom ? '/app/data/config/config' + custom.flag + '.json' : DEFALUT_OPTIONS.savePath
+    if (!std.exist(path)) {
+        throw new Error('The config file not existed:' + path)
+    }
+    let existed = std.exist(savePath)
+    let content = existed ? std.parseExtJSON(std.loadFile(savePath)) : std.parseExtJSON(std.loadFile(path))
+    if (!existed) {
+        std.saveFile(savePath, JSON.stringify(content))
+    }
+    for (let [key, value] of Object.entries(content)) {
+        map.put(flag + key, value)
+    }
+    map.put('___inited' + flag, 'ok')
+}
+/**
+ * 鑾峰彇鎵�鏈夐厤缃」
+ * @param {string} flag 鑷畾涔夌殑閰嶇疆鏂囦欢鏍囪瘑锛屽彲浠ヤ负绌猴紝涓虹┖鍒欒繑鍥炵己鐪乧onfig.json閲屾墍鏈夊唴瀹�
+ * @returns json瀵硅薄
+ */
+config.getAll = function (flag) {
+    let _flag = _getFlag(flag)
+    let configInfo = {}
+    let keys = map.keys().filter(k => k.startsWith(_flag))
+    keys.forEach(k => {
+        let key = k.substring(_flag.length)
+        let val = map.get(k)
+        configInfo[key] = val
+    })
+    return configInfo
+}
+/**
+ * 鑾峰彇閰嶇疆锛屽彧浠巑ap鑾峰彇
+ * 濡傛灉閰嶇疆椤逛负绌猴紝杩斿洖鎵�鏈夋墍鏈夋暟鎹紱
+ * @param {string} key 閰嶇疆椤� 
+ * @param {string} flag 鑷畾涔夌殑閰嶇疆鏂囦欢鏍囪瘑锛屽彲浠ヤ负绌猴紝涓虹┖鍒欒繑鍥炵己鐪乧onfig.json閲岀殑閰嶇疆鍊�
+ * @returns 
+ */
+config.get = function (key, flag) {
+    if (!key) {
+        return this.getAll(flag);
+    }
+    let _flag = _getFlag(flag)
+    return map.get(_flag + key)
+}
+
+/**
+ * 鏇存柊閰嶇疆锛屽彧淇敼map
+ * @param {string} key 閰嶇疆椤� 
+ * @param {string} value 閰嶇疆鍊�
+ * @param {string} flag 鑷畾涔夌殑閰嶇疆鏂囦欢鏍囪瘑锛屽彲浠ヤ负绌猴紝涓虹┖鍒欐寚鍚戠己鐪乧onfig.json閲岀殑閰嶇疆鍊�
+ */
+config.set = function (key, value, flag) {
+    if (!key || value == null || value == undefined) {
+        throw new Error("key or value should not be empty")
+    }
+    let _flag = _getFlag(flag)
+    map.put(_flag + key, value)
+}
+
+/**
+ * 灏唌ap涓殑鏁版嵁鎸佷箙鍖栧埌鏈湴
+ * @param {string} flag 鑷畾涔夌殑閰嶇疆鏂囦欢鏍囪瘑锛屽彲浠ヤ负绌猴紝涓虹┖鍒欐寚鍚戠己鐪乧onfig.json閲岀殑閰嶇疆鍊�
+ */
+config.save = function (flag) {
+    //淇濆瓨
+    std.saveFile(_getSavePath(flag), JSON.stringify(this.getAll(flag)))
+}
+
+/**
+ * 鏇存柊閰嶇疆锛屼慨鏀筸ap涓旀寔涔呭寲鏈湴
+ * @param {string} key 閰嶇疆椤� 
+ * @param {string} value 閰嶇疆鍊�
+ * @param {string} flag 鑷畾涔夌殑閰嶇疆鏂囦欢鏍囪瘑锛屽彲浠ヤ负绌猴紝涓虹┖鍒欐寚鍚戠己鐪乧onfig.json閲岀殑閰嶇疆鍊�
+ */
+config.setAndSave = function (key, value, flag) {
+    this.set(key, value, flag)
+    //淇濆瓨
+    std.saveFile(_getSavePath(flag), JSON.stringify(this.getAll(flag)))
+}
+
+/**
+ * 閲嶇疆锛岄噸缃悗璇烽噸鍚姩璁惧
+ * @param {string} flag 鑷畾涔夌殑閰嶇疆鏂囦欢鏍囪瘑锛屽彲浠ヤ负绌猴紝涓虹┖鍒欐寚鍚戠己鐪乧onfig.json閲岀殑閰嶇疆鍊�
+ */
+config.reset = function (flag) {
+    common.systemBrief('rm -rf ' + _getSavePath(flag))
+}
+
+//-------------------private-------------------------------
+
+function _getFlag(flag) {
+    return flag ? DEFALUT_OPTIONS.flag + flag + '.' : DEFALUT_OPTIONS.flag
+}
+function _getSavePath(flag) {
+    return flag ? '/app/data/config/config' + flag + '.json' : DEFALUT_OPTIONS.savePath
+}
+export default config;
\ No newline at end of file
diff --git a/vf205_access/dxmodules/dxDriver.js b/vf205_access/dxmodules/dxDriver.js
new file mode 100644
index 0000000..f1d77e4
--- /dev/null
+++ b/vf205_access/dxmodules/dxDriver.js
@@ -0,0 +1,81 @@
+const dxDriver = {}
+
+/*************************************Device Resource Enumeration*************************************/
+
+/**
+ * GPIO device pins
+ */
+dxDriver.GPIO = {
+
+    // Relay
+    RELAY0:         44,
+}
+
+/**
+ * Channel communication
+ */
+dxDriver.CHANNEL = {
+
+    // 485       
+    UART_PATH:      "/dev/ttySLB2",
+
+    // USBHID
+	USBHID_PATH:    "/dev/hidg1",
+}
+
+/**
+ * Camera related parameters
+ */
+dxDriver.CAPTURER = {
+    // Camera image width
+	RGB_WIDTH:  1280,
+    // Camera image height
+	RGB_HEIGHT:	800,
+    // Camera device files
+    RGB_PATH:  "/dev/video3",
+
+    // Camera image width
+	NIR_WIDTH:  800,
+    // Camera image height
+	NIR_HEIGHT:	600,
+    // Camera device files
+    NIR_PATH:  "/dev/video0"
+}
+
+/**
+ * PWM channel
+ */
+dxDriver.PWM = {
+
+    // Fill light
+    WHITE_SUPPLEMENT_CHANNEL:       4,
+    WHITE_SUPPLEMENT_PERIOD_NS:     255000,
+    WHITE_SUPPLEMENT_DUTY:          255000 * 255 / 255,
+    
+    NIR_SUPPLEMENT_CHANNEL:         7,
+    NIR_SUPPLEMENT_PERIOD_NS:       255000,
+    NIR_SUPPLEMENT_DUTY:            255000 * 255 / 255,
+}
+
+/**
+ * GPIO pin function enumeration
+ */
+dxDriver.GPIO_FUNC = {
+	GPIO_FUNC_3:    0x03,  //0011, GPIO as function 3 / device 3
+	GPIO_OUTPUT0:   0x04,  //0100, GPIO output low  level
+	GPIO_OUTPUT1:   0x05  //0101, GPIO output high level
+};
+
+/**
+ * Door opening button
+ */
+dxDriver.GPIO_KEY_OPEN = 30
+
+/**
+ * Door magnetic status
+ */
+dxDriver.GPIO_KEY_SEN = 48
+
+
+
+export default dxDriver
\ No newline at end of file
diff --git a/vf205_access/dxmodules/dxEid.js b/vf205_access/dxmodules/dxEid.js
new file mode 100644
index 0000000..f354aa2
--- /dev/null
+++ b/vf205_access/dxmodules/dxEid.js
@@ -0,0 +1,46 @@
+import { eidClass } from './libvbar-m-dxeid.so'
+const eidObj = new eidClass();
+
+const eid = {
+    /**
+     * @brief  浜戣瘉婵�娲�
+     * @param {string} sn       璁惧sn
+     * @param {string} version  涓氬姟鑷畾涔夌増鏈彿
+     * @param {string} mac      璁惧mac鍦板潃
+     * @param {string} codeMsg  浜戣瘉婵�娲荤爜鏁版嵁
+     * @returns 
+     */
+    active: function(sn, version, mac, codeMsg){
+        
+        if(!sn){
+            throw("sn should not be null or empty")
+        }
+        if(!version){
+            throw("version should not be null or empty")
+        }
+        if(!mac){
+            throw("mac should not be null or empty")
+        }
+        if(!codeMsg){
+            throw("codeMsg should not be null or empty")
+        }
+        return eidObj.active(sn, version, mac, codeMsg);
+    },
+    /**
+     * @brief   鑾峰彇淇℃伅
+     */
+    getInfo: function(){
+        if(data == null || data.length < 1){
+            throw("data should not be null or empty")
+        }
+        return eidObj.getInfo(data)
+    },
+    /**
+     * @brief   鑾峰彇鐗堟湰鍙�
+     */
+    getVersion: function(){
+        return eidObj.getVersion()
+    },
+}
+
+export default eid;
\ No newline at end of file
diff --git a/vf205_access/dxmodules/dxEventBus.js b/vf205_access/dxmodules/dxEventBus.js
new file mode 100644
index 0000000..4e450dd
--- /dev/null
+++ b/vf205_access/dxmodules/dxEventBus.js
@@ -0,0 +1,167 @@
+//build:20240628
+//浜嬩欢鎬荤嚎锛屽埄鐢╭uickjs鐨剋orker闂存暟鎹�氫俊鏉ュ疄鐜扮嚎绋嬩箣闂村彂閫佷簨浠堕�氱煡銆�
+//worker鍜寃orker涔嬮棿涓嶈兘鐩存帴閫氫俊锛岄渶瑕侀�氳繃parent(涓荤嚎绋�)鏉ヨ浆鍙戯紝鎵�浠ラ渶瑕佸疄鐜�5绉嶅彲鑳芥�х殑浜嬩欢閫氱煡
+//1. worker1--->parent--->worker2
+//2. worker3--->parent
+//3. parent--->worker4
+//4. parent<-->parent 
+//5. worker5<--->worker5,涔熶細閫氳繃parent杞�
+//缁勪欢渚濊禆 dxLogger,dxCommon
+import std from './dxStd.js'
+import logger from './dxLogger.js'
+import * as os from "os";
+//-------------------------variable--------------------
+const bus = {}
+const all = {}
+const subs = {}
+const isMain = (os.Worker.parent === undefined)
+bus.id = isMain ? '__main' : null
+/**
+ * 鍦ㄦ�荤嚎涓婂惎鍔ㄤ竴涓獁orker锛岀粰瀹冨畾涔変竴涓敮涓�鐨刬d鏍囪瘑
+ * 鍥犱负worker鍙兘閫氳繃涓荤嚎绋嬪垱寤猴紝鎵�浠ewWorker鍑芥暟涔熷彧鑳藉湪涓荤嚎绋嬮噷鎵ц
+ * 娉ㄦ剰: worker瀵瑰簲鐨勬枃浠堕噷涓嶈兘鍖呭惈while(true)杩欑姝诲惊鐜紝鍚﹀垯灏辨敹涓嶅埌message锛屽彲浠ョ敤setInteval鏉ュ疄鐜板惊鐜�
+ * @param {string} id worker鐨勫敮涓�鏍囪瘑锛屼笉鑳戒负绌�
+ * @param {object} file worker瀵瑰簲鐨勬枃浠跺悕锛岀粷瀵硅矾寰勶紝閫氬父浠�'/app/code/src'寮�濮�
+ */
+bus.newWorker = function (id, file) {
+    if (!id) {
+        throw new Error("eventbus newWorker:'id' should not be empty")
+    } if (!file) {
+        throw new Error("eventbus newWorker:'file' should not be empty")
+    }
+    if (!isMain) {
+        throw new Error("evnetbus newWorker should be invoke in main thread")
+    }
+    if (!std.exist(file)) {
+        throw new Error("eventbus newWorker: file not found:" + file)
+    }
+    let content = std.loadFile(file) + `
+import __bus from '/app/code/dxmodules/dxEventBus.js'
+__bus.id='${id}'
+Object.keys(__bus.handlers).forEach(key => {
+    __bus.os.Worker.parent.postMessage({ __sub: key, id: __bus.id })
+})
+__bus.os.Worker.parent.onmessage = function (e) {
+    if(!e.data){
+        return
+    }
+    e = e.data
+    if (!e || !e.topic) {
+        return
+    }
+    let fun = __bus.handlers[e.topic]
+    if (fun) {
+        fun(e.data)
+    }
+}
+    `
+    let newfile = file + '_' + id + '.js'
+    std.saveFile(newfile, content)
+    let worker = new os.Worker(newfile)
+    all[id] = worker
+    worker.onmessage = function (data) {
+        if (data.data) {
+            if (data.data.__sub) {
+                sub(data.data.__sub, data.data.id)
+                return
+            }
+            //worker鍙戦�佽繃鏉ョ殑鏁版嵁鍐嶈皟鐢ㄤ竴娆′富绾跨▼鐨刦ire锛岃涔堜富绾跨▼鑷繁娑堣垂锛岃涔堣浆鍙戝埌鍏跺畠worker
+            bus.fire(data.data.topic, data.data.data)
+        }
+    }
+}
+/**
+ * 鏍规嵁id鍒犻櫎瀵瑰簲鐨剋orker锛岃繖鏍穡orker绾跨▼灏辫兘姝e父缁撴潫
+ * @param {string} id 
+ */
+bus.delWorker = function (id) {
+    delete all[id]
+}
+/**
+ * 瑙﹀彂涓�涓簨浠讹紝杩欎釜浜嬩欢浼氱珛鍒诲彂閫佺粨鏉燂紝鎺ユ敹鍒版秷鎭殑澶勭悊濡傛灉姣旇緝鑰楁椂涓嶄細褰卞搷浜嬩欢鍙戦�佺殑椤哄簭鎴栧嚭鐜颁簨浠朵涪澶�
+ * 鍚屾牱涓�涓簨浠跺彲浠ユ湁澶氫釜璁㈤槄鑰咃紝鍙互鍚屾椂閫氱煡澶氫釜璁㈤槄鑰咃紝鍚屼竴涓猼opic鍗曚綅鏃堕棿鍐呭彧澶勭悊涓�涓簨浠讹紝
+ * 鍙湁褰撳墠topic琚墍鏈夌殑璁㈤槄鑰呭鐞嗗畬涔嬪悗鎵嶅厑璁稿鐞嗗悓涓�topic涓嬩竴涓簨浠�
+ * 
+ * @param {string} topic 浜嬩欢鐨勬爣璇嗐�佷富棰� 
+ * @param {*} data 浜嬩欢闄勫甫鐨勬暟鎹�
+ */
+bus.fire = function (topic, data) {
+    if (!topic || (typeof topic) != 'string') {
+        throw new Error("eventbus :'topic' should not be null");
+    }
+    if (isMain) {
+        if (subs[topic] && subs[topic].length > 0) {
+            for (let i = 0; i < subs[topic].length; i++) {
+                const id = subs[topic][i]
+                if (id === '__main' && bus.handlers[topic]) {
+                    if (Array.isArray(bus.handlers[topic])) {
+                        // 鎵ц鎵�鏈夋敞鍐岀殑澶勭悊鍑芥暟
+                        for (let j = 0; j < bus.handlers[topic].length; j++) {
+                            try {
+                                bus.handlers[topic][j](data)
+                            } catch (error) {
+                                logger.error('Error in event handler for topic ' + topic + ': ' + error.message)
+                            }
+                        }
+                    } else {
+                        // 鍏煎鏃х増鏈紝鎵ц鍗曚釜澶勭悊鍑芥暟
+                        try {
+                            bus.handlers[topic](data)
+                        } catch (error) {
+                            logger.error('Error in event handler for topic ' + topic + ': ' + error.message)
+                        }
+                    }
+                } else {
+                    const worker = all[id]
+                    if (worker) {
+                        worker.postMessage({ topic: topic, data: data })
+                    }
+                }
+            }
+        }
+    } else {
+        os.Worker.parent.postMessage({ topic: topic, data: data })
+    }
+}
+
+
+bus.handlers = {}
+/**
+ * 璁㈤槄涓�涓簨浠�
+ * @param {string} topic 浜嬩欢鐨勬爣璇嗐�佷富棰� 锛屽繀濉�
+ * @param {function} callback 浜嬩欢澶勭悊鐨勫洖璋冨嚱鏁帮紝蹇呭~
+ */
+bus.on = function (topic, callback) {
+    if (!topic || (typeof topic) != 'string') {
+        throw new Error("The 'topic' should not be null");
+    }
+    if (!callback || (typeof callback) != 'function') {
+        throw new Error("The 'callback' should be a function");
+    }
+    sub(topic, bus.id)
+    // 鏀寔澶氫釜浜嬩欢澶勭悊鍑芥暟
+    if (!this.handlers[topic]) {
+        this.handlers[topic] = []
+    }
+    if (!Array.isArray(this.handlers[topic])) {
+        // 鍏煎鏃х増鏈紝灏嗗崟涓嚱鏁拌浆鎹负鏁扮粍
+        this.handlers[topic] = [this.handlers[topic]]
+    }
+    this.handlers[topic].push(callback)
+}
+function sub(topic, id) {
+    if (isMain) {
+        if (!subs[topic]) {
+            subs[topic] = []
+        }
+        if (!subs[topic].includes(id)) {
+            subs[topic].push(id)
+        }
+    } else {
+        if (id != null) {
+            os.Worker.parent.postMessage({ __sub: topic, id: id })
+        }
+    }
+}
+bus.os = os
+export default bus
diff --git a/vf205_access/dxmodules/dxFace.js b/vf205_access/dxmodules/dxFace.js
new file mode 100644
index 0000000..a12d723
--- /dev/null
+++ b/vf205_access/dxmodules/dxFace.js
@@ -0,0 +1,287 @@
+//build: 20250513
+//渚濊禆缁勪欢:dxDriver锛宒xStd锛宒xLogger锛宒xMap锛宒xEventBus,dxCommon
+import { faceClass } from './libvbar-b-dxface.so'
+import dxCommon from './dxCommon.js'
+import bus from './dxEventBus.js'
+const faceObj = new faceClass();
+const face = {}
+
+/**
+ * 浜鸿劯澶勭悊鍒濆鍖�
+ * @param {object} options 閰嶇疆鍙傛暟锛屽ぇ閮ㄥ垎鍙互鐢ㄩ粯璁ゅ��
+ * @param {string} options.rgbPath 蹇呭~锛宺gb鍥惧儚閲囬泦璁惧璺緞锛屾瘡绉嶈澶囨湁宸紓锛屾瘮濡侱W200瀵瑰簲鐨勫�兼槸'/dev/video11', M500瀵瑰簲鐨�'/dev/video0'
+ * @param {string} options.nirPath 蹇呭~锛岀孩澶栧浘鍍忛噰闆嗚澶囪矾寰勶紝姣忕璁惧鏈夊樊寮�
+ * @param {string} options.dbPath 鏁版嵁搴撹矾寰勶紝蹇呭~
+ * @param {number} options.score 鐗瑰緛鍊煎姣旀垚鍔熸墍闇�鏈�浣庡姣斿緱鍒� 锛岄潪蹇呭~锛堢己鐪�0.6锛�
+ * @param {number} options.dbMax 鍐呭瓨涓姞杞界殑鏈�澶х壒寰佸垪琛ㄦ暟閲忥紝闈炲繀濉紙缂虹渷5000锛�
+ * @param {string} options.mapPath 鏍囧畾缁撴灉鏂囦欢璺緞锛岄潪蹇呭~
+ * @param {string} options.picPath 淇濆瓨瀹屾暣浜鸿劯鐓х墖璺緞锛岄潪蹇呭~
+ * @param {string} capturerRgbId 蹇呭~锛宺gb鍙栧浘鍙ユ焺id
+ * @param {string} capturerNirId 蹇呭~锛宯ir鍙栧浘鍙ユ焺id
+ * @returns true/false
+ */
+face.init = function (options, capturerRgbId, capturerNirId) {
+	if (options.rgbPath === undefined || options.rgbPath === null || options.rgbPath.length < 1) {
+		throw new Error("dxFace.init: 'rgbPath' parameter should not be null or empty")
+	}
+	if (options.nirPath === undefined || options.nirPath === null || options.nirPath.length < 1) {
+		throw new Error("dxFace.init: 'nirPath' parameter should not be null or empty")
+	}
+	if (capturerRgbId === undefined || capturerRgbId === null || capturerRgbId.length < 1) {
+		throw new Error("dxFace.init: 'capturerRgbId' parameter should not be null or empty")
+	}
+	if (capturerNirId === undefined || capturerNirId === null || capturerNirId.length < 1) {
+		throw new Error("dxFace.init: 'capturerNirId' parameter should not be null or empty")
+	}
+	capturerRgbId = dxCommon.handleId("capturer", capturerRgbId)
+	capturerNirId = dxCommon.handleId("capturer", capturerNirId)
+
+	return faceObj.init(options, capturerRgbId, capturerNirId);
+}
+/**
+ * 浜鸿劯澶勭悊鍘诲垵濮嬪寲
+ * @returns true/false
+ */
+face.deinit = function () {
+	return faceObj.deinit();
+}
+
+/**
+ * 浜鸿劯宸ヤ綔妯″紡
+ * @param {number} mode 宸ヤ綔妯″紡锛屽繀濉紙 0 浜鸿劯璇嗗埆妯″紡锛�1 浜鸿劯娉ㄥ唽妯″紡锛�
+ * @returns true/false
+ */
+face.setRecgMode = function (mode) {
+	if (mode === undefined || mode === null) {
+		throw new Error("dxFace.setRecgMode: 'mode' parameter should not be null or empty")
+	}
+	return faceObj.setRecgMode(mode)
+}
+/**
+ * 浜鸿劯娉ㄥ唽
+ * @param {string} userId 	浜哄憳ID锛屽繀濉�
+ * @param {string} feature 	鐗瑰緛鍊� base64瀛楃涓诧紝蹇呭~
+ * @returns 0:鎴愬姛/闈�0:澶辫触
+ */
+face.addFaceFeatures = function (userId, feature) {
+	if (userId === undefined || userId === null) {
+		throw new Error("dxFace.addFaceFeatures: 'userId' parameter should not be null or empty")
+	}
+	if (feature === undefined || feature === null) {
+		throw new Error("dxFace.addFaceFeatures: 'feature' parameter should not be null or empty")
+	}
+
+	return faceObj.addFaceFeatures(userId, feature)
+}
+/**
+ * 浜鸿劯鐗瑰緛鍊煎姣�
+ * @param {string} feature 	鐗瑰緛鍊� base64瀛楃涓诧紝蹇呭~
+ * @param {string} score 	姣斿闃堝�硷紝闈炲繀濉紝榛樿0.6
+ * @returns string userId
+ */
+face.faceFeatureCompare = function (feature, score) {
+	if (feature === undefined || feature === null) {
+		throw new Error("dxFace.faceFeatureCompare: 'feature' parameter should not be null or empty")
+	}
+	return faceObj.faceFeatureCompare(feature, score)
+}
+/**
+ * 鏇存柊閰嶇疆
+ * @param {object} options 娉ㄥ唽鍙傛暟锛岀敱娉ㄥ唽鍥炶皟鑾峰彇锛屽弬鑰僨ace.addFaceFeatures鏂规硶
+ * @returns true/false
+ */
+face.faceUpdateConfig = function (options) {
+	if (options === null || options === undefined) {
+		throw new Error("dxFace.faceUpdateConfig: 'options' parameter should not be null or empty")
+	}
+	return faceObj.faceUpdateConfig(options)
+}
+/**
+ * 浜鸿劯鍒犻櫎
+ * @param {string} userId 浜哄憳ID锛屽繀濉�
+ * @returns true/false
+ */
+face.deleteFaceFeatures = function (userId) {
+	if (userId === null || userId === undefined) {
+		throw new Error("dxFace.deleteFaceFeatures: 'userId' parameter should not be null or empty")
+	}
+	return faceObj.deleteFaceFeatures(userId)
+}
+/**
+ * 鏍规嵁鐓х墖璺緞鍜寀serId娉ㄥ唽浜鸿劯
+ * @param {string} userId 	鐢ㄦ埛id锛屽繀濉�
+ * @param {string} picPath	鐓х墖璺緞锛屽繀濉�
+ * @returns true/false
+ */
+face.registerFaceByPicFile = function (userId, picPath) {
+	if (userId === undefined || userId === null || userId.length < 1) {
+		throw new Error("dxFace.registerFaceByPicFile: 'userId' parameter should not be null or empty")
+	}
+	if (picPath === undefined || picPath === null || picPath.length < 1) {
+		throw new Error("dxFace.registerFaceByPicFile: 'picPath' parameter should not be null or empty")
+	}
+	return faceObj.registerFaceByPicFile(userId, picPath)
+}
+/**
+ * 浜鸿劯绾跨▼鍚敤/绂佺敤锛屽姛鑳藉紑鍏�
+ * @param {bool} en 鍚敤銆佺鐢紝蹇呭~
+ * @returns true/false
+ */
+face.faceSetEnable = function (en) {
+	if (en === undefined || en === null) {
+		throw new Error("dxFace.faceSetEnable: 'en' parameter should not be null or empty")
+	}
+	return faceObj.detectSetEnable(en ? 0 : -1)
+}
+
+/**
+ * 閲嶇疆浜鸿劯鐘舵��
+ * @returns 
+ */
+face.resetFaceStatus = function () {
+	return faceObj.resetFaceStatus()
+}
+
+/**
+ * 娓呯┖浜鸿劯鏁版嵁
+ * @returns true/false
+ */
+face.faceFeaturesClean = function () {
+	return faceObj.faceFeaturesClean()
+}
+
+/**
+ * 鑾峰彇灞忓箷浜害
+ * @returns number 灞忓箷浜害
+ */
+face.getDisplayBacklight = function () {
+	return faceObj.getDisplayBacklight()
+}
+/**
+ * 璁剧疆灞忓箷浜害
+ * @param {number} light 灞忓箷浜害锛屽繀濉�
+ * @returns true/false
+ */
+face.setDisplayBacklight = function (light) {
+	if (light === undefined || light === null) {
+		throw new Error("dxFace.setDisplayBacklight: 'light' parameter should not be null or empty")
+	}
+	return faceObj.setDisplayBacklight(light)
+}
+/**
+ * 鑾峰彇灞忓箷鐘舵��
+ * @returns number 0-绂佺敤 1-鍚敤
+ */
+face.getEnableStatus = function () {
+	return faceObj.getEnableStatus()
+}
+/**
+ * 璁剧疆灞忓箷鐘舵��
+ * @param {number} enable 0-绂佺敤 1-鍚敤
+ * @returns true/false
+ */
+face.setEnableStatus = function (enable) {
+	if (enable === undefined || enable === null) {
+		throw new Error("dxFace.setEnableStatus: 'enable' parameter should not be null or empty")
+	}
+	return faceObj.setEnableStatus(enable)
+}
+/**
+/**
+ * 鑾峰彇灞忓箷鐘舵��
+ * @returns number 0-NORMAL 1-STANDBY
+ */
+face.getPowerMode = function () {
+	return faceObj.getPowerMode()
+}
+/**
+ * 璁剧疆灞忓箷鐘舵��
+ * @param {number} mode 0-NORMAL 1-STANDBY
+ * @returns true/false
+ */
+face.setPowerMode = function (mode) {
+	if (mode === undefined || mode === null) {
+		throw new Error("dxFace.setPowerMode: 'mode' parameter should not be null or empty")
+	}
+	return faceObj.setPowerMode(mode)
+}
+/**
+ * 鑾峰彇鐜鍏�
+ * @returns number 鐜鍏変寒搴�
+ */
+face.getEnvBrightness = function () {
+	return faceObj.getEnvBrightness()
+}
+/**
+ * 鑾峰彇浜鸿劯鍧愭爣
+ * @returns string 浜鸿劯鍧愭爣JSON
+ */
+face.getTrackingBox = function () {
+	return faceObj.getTrackingBox()
+}
+/**
+ * 鏌ヨ鐢ㄦ埛鎬绘暟
+ * @returns number
+ */
+face.selectCount = function () {
+	return faceObj.selectFaceFeatures(1)
+}
+/**
+ * 鏌ヨ鎵�鏈塽serId
+ * @returns JSON
+ */
+face.selectAll = function () {
+	return faceObj.selectFaceFeatures(2)
+}
+/**
+ * 鍒ゆ柇鐢ㄦ埛鏄惁瀛樺湪
+ * @returns true/false
+ */
+face.userExist = function (userId) {
+	return faceObj.selectFaceFeatures(3, userId)
+}
+/**
+ * 鍒ゆ柇face娑堟伅闃熷垪鏄惁涓虹┖
+ * @returns true/false
+ */
+face.msgIsEmpty = function () {
+	return faceObj.msgIsEmpty()
+}
+/**
+ * 浠巉ace娑堟伅闃熷垪涓鍙栨暟鎹�
+ * @returns json
+ */
+face.msgReceive = function () {
+	return JSON.parse(faceObj.msgReceive());
+}
+
+face.RECEIVE_MSG = '__face__MsgReceive'
+
+/**
+ * 鐢ㄤ簬绠�鍖杅ace缁勪欢寰厜閫氫俊鍗忚鐨勪娇鐢紝鎶奻ace灏佽鍦ㄨ繖涓獁orker閲岋紝浣跨敤鑰呭彧闇�瑕佽闃卐ventbus鐨勪簨浠跺氨鍙互鐩戝惉face
+ */
+face.run = function () {
+	let workerFile = '/app/code/dxmodules/faceWorker.js'
+	bus.newWorker('__face', workerFile)
+}
+
+/**
+ * 濡傛灉face鍗曠嫭涓�涓嚎绋嬶紝鍙互鐩存帴浣跨敤run鍑芥暟锛屼細鑷姩鍚姩涓�涓嚎绋嬶紝
+ * 濡傛灉鎯冲姞鍏ュ埌鍏朵粬宸叉湁鐨勭嚎绋嬶紝鍙互浣跨敤浠ヤ笅灏佽鐨勫嚱鏁�
+ */
+face.worker = {
+	//鍦╳hile寰幆鍓�
+	beforeLoop: function (options) {
+		// 浜鸿劯绠楁硶鍒濆鍖�
+		face.init(options, options.capturerRgbId, options.capturerNirId)
+	},
+	//鍦╳hile寰幆閲�
+	loop: function () {
+		if (!face.msgIsEmpty()) {
+			let res = face.msgReceive();
+			bus.fire(face.RECEIVE_MSG, res)
+		}
+	}
+}
+
+export default face;
diff --git a/vf205_access/dxmodules/dxGpio.js b/vf205_access/dxmodules/dxGpio.js
new file mode 100644
index 0000000..457d8ba
--- /dev/null
+++ b/vf205_access/dxmodules/dxGpio.js
@@ -0,0 +1,123 @@
+// build : 20240524
+// gpio 杈撳嚭,鍙兘杈撳嚭2绉嶇姸鎬侊紝楂樼數骞�/浣庣數骞筹紝濡傛灉鎺ュ叆缁х數鍣紝鍒欓珮鐢靛钩鏄紑锛屼綆鐢靛钩鏄叧
+import { gpioClass } from './libvbar-b-dxgpio.so'
+const gpioObj = new gpioClass();
+const gpio = {}
+
+/**
+ * 鍒濆鍖�,鍙渶瑕佹墽琛屼竴娆″嵆鍙�
+ * @returns true/false
+ */
+gpio.init = function () {
+	return gpioObj.init();
+}
+
+/**
+ * 閲婃斁gpio璧勬簮
+ * @returns true/false
+ */
+gpio.deinit = function () {
+	return gpioObj.exit();
+}
+
+/**
+ * 鐢宠gpio,姣忎釜gpio鍙渶瑕佺敵璇蜂竴娆�
+ * @param {number} gpio鐨勬爣璇嗭紝涓嶅悓鐨勮澶囦笉鍚岀殑鏍囪瘑锛屽繀濉�
+ * @returns true/false
+ */
+gpio.request = function (gpio_) {
+	let res = gpioObj.request(gpio_)
+	if (!res) {
+		return res
+	}
+	gpioObj.setFunc(gpio_, 0x04);
+	return true
+}
+
+/**
+ * 閲婃斁鎸囧畾gpio
+ * @param {number} gpio鐨勬爣璇嗭紝涓嶅悓鐨勮澶囦笉鍚岀殑鏍囪瘑锛屽繀濉�
+ * @returns true/false
+ */
+gpio.free = function (gpio_) {
+	return gpioObj.free(gpio_);
+}
+
+/**
+ * 鎸囧畾gpio杈撳嚭楂�/浣庣數骞�
+ * @param {number} gpio鐨勬爣璇嗭紝涓嶅悓鐨勮澶囦笉鍚岀殑鏍囪瘑锛屽繀濉�
+ * @param {number} value 鍙兘鏄�1鍜�0锛�1琛ㄧず楂樼數骞筹紝0琛ㄧず浣庣數骞筹紝缂虹渷鏄珮鐢靛钩锛屽繀濉�
+ * @returns true/false
+ */
+gpio.setValue = function (gpio_, value) {
+	return gpioObj.setValue(gpio_, value);
+}
+
+/**
+ * 鑾峰彇鎸囧畾gpio褰撳墠鐨勮緭鍑� 锛氶珮/浣庣數骞�
+ * @param {number} gpio鐨勬爣璇嗭紝涓嶅悓鐨勮澶囦笉鍚岀殑鏍囪瘑锛屽繀濉�
+ * @returns 1鍜�0锛�1琛ㄧず楂樼數骞筹紝0琛ㄧず浣庣數骞�
+ */
+gpio.getValue = function (gpio_) {
+	return gpioObj.getValue(gpio_);
+}
+
+/**
+ * 鐢宠gpio,姣忎釜gpio鍙渶瑕佺敵璇蜂竴娆�
+ * @param {number} gpio鐨勬爣璇嗭紝涓嶅悓鐨勮澶囦笉鍚岀殑鏍囪瘑锛屽繀濉�
+ * @returns true/false
+ */
+gpio.requestGpio = function (gpio_) {
+	let res = gpioObj.request(gpio_)
+	return res
+}
+
+/**
+ * 璁剧疆gpio鍔熻兘
+ * @param {number} gpio鐨勬爣璇嗭紝涓嶅悓鐨勮澶囦笉鍚岀殑鏍囪瘑锛屽繀濉�
+ * @param {number} gpio鍔熻兘灞炴�э紝涓嶅悓鐨勮澶囦笉鍚岀殑鍔熻兘灞炴�э紝蹇呭~
+ * @returns true/false
+ */
+gpio.setFuncGpio = function (gpio_, func) {
+	let res = gpioObj.setFunc(gpio_, func)
+	return res
+}
+
+/**
+ * 璁剧疆鎸囧畾gpio涓婃媺鐘舵��
+ * @param {number} gpio鐨勬爣璇嗭紝涓嶅悓鐨勮澶囦笉鍚岀殑鏍囪瘑锛屽繀濉�
+ * @param {number} state 涓婃媺鐘舵�侊紝蹇呭~
+ * @returns true/false
+ */
+gpio.setPullState = function (gpio_, state) {
+	return gpioObj.setPullState(gpio_, state);
+}
+
+/**
+ * 鑾峰彇鎸囧畾gpio涓婃媺鐘舵��
+ * @param {number} gpio鐨勬爣璇嗭紝涓嶅悓鐨勮澶囦笉鍚岀殑鏍囪瘑锛屽繀濉�
+ * @returns 涓婃媺鐘舵��(int)
+ */
+gpio.getPullState = function (gpio_) {
+	return gpioObj.getPullState(gpio_);
+}
+/**
+ * 璁剧疆鎸囧畾gpio鐨勯┍鍔ㄨ兘鍔�
+ * @param {number} gpio鐨勬爣璇嗭紝涓嶅悓鐨勮澶囦笉鍚岀殑鏍囪瘑锛屽繀濉�
+ * @param {number} strength 鑳藉姏锛屽繀濉�
+ * @returns true/false
+ */
+gpio.setDriveStrength = function (gpio_, strength) {
+	return gpioObj.setDriveStrength(gpio_, strength);
+}
+
+/**
+ * 鑾峰彇鎸囧畾gpio鐨勯┍鍔ㄨ兘鍔�
+ * @param {number} gpio鐨勬爣璇嗭紝涓嶅悓鐨勮澶囦笉鍚岀殑鏍囪瘑锛屽繀濉�
+ * @returns 鑳藉姏(int)
+ */
+gpio.getDriveStrength = function (gpio_) {
+	return gpioObj.getDriveStrength(gpio_);
+}
+
+export default gpio;
diff --git a/vf205_access/dxmodules/dxGpioKey.js b/vf205_access/dxmodules/dxGpioKey.js
new file mode 100644
index 0000000..44237b8
--- /dev/null
+++ b/vf205_access/dxmodules/dxGpioKey.js
@@ -0,0 +1,84 @@
+//build 20240524
+//鎺ュ彈 gpio 鐨勮緭鍏�
+//渚濊禆缁勪欢: dxLogger,dxDriver,dxEventBus
+import { gpioKeyClass } from './libvbar-m-dxkey.so'
+import bus from './dxEventBus.js'
+import * as os from "os";
+const gpioKeyObj = new gpioKeyClass();
+const gpioKey = {}
+
+/**
+ * gpioKey 鍒濆鍖�
+ * @returns true:鎴愬姛,false:澶辫触
+ */
+gpioKey.init = function () {
+	const res = gpioKeyObj.init()
+	if (res) {
+		gpioKeyObj.registerCb("gpioKeyCb")
+	}
+	return res
+}
+
+/**
+ * gpioKey 鍙栨秷鍒濆鍖�
+ * @returns true:鎴愬姛,false:澶辫触
+ */
+gpioKey.deinit = function () {
+	gpioKeyObj.unRegisterCb("gpioKeyCb")
+	return gpioKeyObj.deinit()
+}
+
+/**
+ * 鍒ゆ柇gpioKey娑堟伅闃熷垪鏄惁涓虹┖
+ * @returns true:鎴愬姛,false:澶辫触
+ */
+gpioKey.msgIsEmpty = function () {
+	return gpioKeyObj.msgIsEmpty()
+}
+
+/**
+ * 浠巊pioKey娑堟伅闃熷垪涓鍙栨暟鎹�
+ * @returns json娑堟伅瀵硅薄锛屾牸寮忥細{"code":30,"type":1,"value":1}
+ */
+gpioKey.msgReceive = function () {
+	let msg = gpioKeyObj.msgReceive()
+	return JSON.parse(msg);
+}
+
+gpioKey.RECEIVE_MSG = '__gpioKey__MsgReceive'
+
+/**
+ * 绠�鍖杇piokey缁勪欢鐨勪娇鐢紝鏃犻渶杞鍘昏幏鍙栨暟鎹紝鏁版嵁浼氶�氳繃eventbus鍙戦�佸嚭鍘�
+ * run 鍙細鎵ц涓�娆�
+ * 濡傛灉闇�瑕佸疄鏃惰幏鍙栨暟鎹紝鍙互璁㈤槄 eventbus鐨勪簨浠讹紝浜嬩欢鐨則opic鏄疓PIO_KEY锛屼簨浠剁殑鍐呭鏄被浼納"code":30,"type":1,"value":1}
+ * 鍏朵腑code鏄痝pio鐨勬爣璇嗭紝琛ㄧず鏄偅涓猤pio鏈夎緭鍏ワ紝value鍊煎彧鑳芥槸0锛�1閫氬父琛ㄧず浣庣數骞冲拰楂樼數骞�
+ * type鏄簨浠剁被鍨嬶紝閬靛惊Linux鐨勬爣鍑嗚緭鍏ヨ瀹�,浠ヤ笅鍒楀嚭甯哥敤鍑犱釜锛�
+	(0x01):鎸夐敭浜嬩欢锛屽寘鎷墍鏈夌殑閿洏鍜屾寜閽簨浠躲�備緥濡傦紝褰撴寜涓嬫垨閲婃斁閿洏涓婄殑涓�涓敭鏃讹紝灏嗘姤鍛婃绫讳簨浠躲��
+	(0x05):寮�鍏充簨浠讹紝渚嬪绗旇鏈數鑴戠洊鐨勫紑鍏冲彲浠ユ姤鍛婂紑鍚堢姸鎬併��
+	(Ox11):LED浜嬩欢锛岀敤浜庢帶鍒惰澶囦笂鐨凩ED鎸囩ず鐏紝
+	(Ox12):澹伴煶浜嬩欢锛岀敤浜庢帶鍒惰澶囦笂鐨勫0闊宠緭鍑猴紝
+	(0x16):鐢垫簮浜嬩欢锛屽彲浠ョ敤浜庢姤鍛婄數婧愭寜閽簨浠舵垨鐢垫睜鐢甸噺浣�
+ * 
+ */
+gpioKey.run = function () {
+	bus.newWorker("__gpiokey", '/app/code/dxmodules/gpioKeyWorker.js')
+}
+
+/**
+ * 濡傛灉gpioKey鍗曠嫭涓�涓嚎绋嬶紝鍙互鐩存帴浣跨敤run鍑芥暟锛屼細鑷姩鍚姩涓�涓嚎绋嬶紝
+ * 濡傛灉鎯冲姞鍏ュ埌鍏朵粬宸叉湁鐨勭嚎绋嬶紝鍙互浣跨敤浠ヤ笅灏佽鐨勫嚱鏁�
+ */
+gpioKey.worker = {
+	//鍦╳hile寰幆鍓�
+	beforeLoop: function () {
+		gpioKey.init()
+	},
+	//鍦╳hile寰幆閲�
+	loop: function () {
+		if (!gpioKey.msgIsEmpty()) {
+			let res = gpioKey.msgReceive();
+			bus.fire(gpioKey.RECEIVE_MSG, res)
+		}
+	}
+}
+export default gpioKey;
diff --git a/vf205_access/dxmodules/dxHttp.js b/vf205_access/dxmodules/dxHttp.js
new file mode 100644
index 0000000..f94b6d1
--- /dev/null
+++ b/vf205_access/dxmodules/dxHttp.js
@@ -0,0 +1,155 @@
+// http瀹㈡埛绔粍浠�
+import { httpClass } from './libvbar-m-dxhttp.so'
+
+const httpObj = new httpClass();
+
+const http = {
+
+    HTTP_METHOD : {
+        GET: "GET",
+        POST: "POST",
+        PUT: "PUT",
+        DELETE: "DELETE",
+        HEAD: "HEAD",
+        OPTIONS: "OPTIONS",
+        PATCH: "PATCH"
+    },
+    HTTP_FORMAT : {
+        JSON: "JSON",
+        FORM: "FORM",
+        URLENCODE: "URLENCODE"
+    },
+    HTTP_FORM_TYPE : {
+        STRING: "STRING",
+        FILE: "FILE"
+    },
+    /**
+     * get璇锋眰
+     * @param {string} url 
+     * @param {array} headers 闈炲繀濉紝浼氭湁榛樿濉厖 request headers
+     * @param {number} timeout 闈炲繀濉紝 瓒呮椂鏃堕棿
+     * @returns 
+     */
+    get: function (url, headers, timeout) {
+        if (!url) {
+            throw new Error("url should not be null or empty")
+        }
+        return httpObj.request({ method: 0, url: url, headers: headers, timeout: timeout})
+    },
+    /**
+     * post璇锋眰,data涓簀son/form琛ㄥ崟鏁扮粍鏍煎紡
+     * @param {string} url 
+     * @param {array} data
+     * @param {array} headers 闈炲繀濉紝浼氭湁榛樿濉厖 request headers 
+     * @param {number} timeout 闈炲繀濉紝 瓒呮椂鏃堕棿
+     * @returns 
+     */
+    post: function (url, data, headers, timeout, format = "JSON") {
+        if (!url) {
+            throw new Error("url should not be null or empty")
+        }
+        if (!data) {
+            throw new Error("data should not be null or empty")
+        }
+        if (typeof data != 'string' && format != "FORM") {
+            data = JSON.stringify(data)
+        }
+        if(format == "JSON"){
+            return httpObj.request({ method: 1, url: url, data: data, headers: headers, timeout: timeout})
+        }else{
+            return httpObj.request({ method: 1, url: url, formData: data, headers: headers, timeout: timeout})
+        }
+    },
+    /**
+     * put璇锋眰,data涓簀son/form琛ㄥ崟鏁扮粍鏍煎紡
+     * @param {string} url 
+     * @param {array} data
+     * @param {array} headers 闈炲繀濉紝浼氭湁榛樿濉厖 request headers 
+     * @param {number} timeout 闈炲繀濉紝 瓒呮椂鏃堕棿
+     * @returns 
+     */
+    put: function (url, data, headers, timeout, format = "JSON") {
+        if (!url) {
+            throw new Error("url should not be null or empty")
+        }
+        if (!data) {
+            throw new Error("data should not be null or empty")
+        }
+        if (typeof data != 'string' && format != "FORM") {
+            data = JSON.stringify(data)
+        }
+        if(format == "JSON"){
+            return httpObj.request({ method: 2, url: url, data: data, headers: headers, timeout: timeout})
+        }else{
+            return httpObj.request({ method: 2, url: url, formData: data, headers: headers, timeout: timeout})
+        }
+    },
+    /**
+     * delete璇锋眰
+     * @param {string} url 
+     * @param {array} headers 闈炲繀濉紝浼氭湁榛樿濉厖 request headers
+     * @param {number} timeout 闈炲繀濉紝 瓒呮椂鏃堕棿
+     * @returns 
+     */
+    delete: function (url, headers, timeout) {
+        if (!url) {
+            throw new Error("url should not be null or empty")
+        }
+        return httpObj.request({ method: 3, url: url, headers: headers, timeout: timeout})
+    },
+    /**
+     * 涓嬭浇鏂囦欢锛屾湰璐ㄦ槸get璇锋眰
+     * @param {string} url 
+     * @param {string} path 鐩爣璺緞(缁濆璺緞)
+     * @param {array} headers 闈炲繀濉紝浼氭湁榛樿濉厖 request headers
+     * @param {number} timeout 闈炲繀濉紝 瓒呮椂鏃堕棿
+     * @returns 涓嬭浇鏂囦欢鏈夊彲鑳借繑鍥瀗ull锛屼絾鏄笅杞芥槸鎴愬姛鐨�
+     */
+    download: function (url, path, headers, timeout) {
+        if (!url) {
+            throw new Error("url should not be null or empty")
+        }
+        if (!path) {
+            throw new Error("path should not be null or empty")
+        }
+        return httpObj.request({ method: 0, url: url, headers: headers, download: path, timeout: timeout })
+    },
+
+    /**
+     * 涓婁紶鏂囦欢锛屾湰璐ㄦ槸post璇锋眰
+     * @param {string} url 
+     * @param {string} path 婧愯矾寰�(缁濆璺緞)
+     * @returns 
+     */
+    upload: function (url, path) {
+        if (!url) {
+            throw new Error("url should not be null or empty")
+        }
+        if (!path) {
+            throw new Error("path should not be null or empty")
+        }
+        return httpObj.request({
+            method: 1,
+            url: url,
+            headers: ["application/x-www-form-urlencoded; charset=UTF-8"],
+            upload: path
+        })
+    },
+    /**
+     * 鍘熺敓鏂瑰紡
+     * 蹇呭~鍙傛暟锛歮ethod锛�0锛歡et璇锋眰锛�1锛歱ost璇锋眰锛夈�乽rl
+     * 鍙�夊弬鏁帮細headers(瀛楃涓叉暟缁勶紝瑕嗙洊榛樿header)銆乨ownload锛堟枃浠朵笅杞藉湴鍧�锛夈�乨ata(璇锋眰鎶ユ枃锛宲ost璇锋眰蹇呭~)銆乼imeout(瓒呮椂鏃堕棿/ms,缂虹渷:5000)銆乨ns(缂虹渷:"114.114.114.114,8.8.8.8")銆乽pload
+     * 榛樿header锛欰ccept-Charset:utf-8銆丆ontent-Type:application/json;charset=utf-8銆丆onnection:close
+     * @param {object} param json
+     *  濡傦細let param={
+                method:0,
+                url:"http://192.168.10.122:8000/DW200_1_0.zip",
+                download:"/testNet/aaa"
+            }
+     * @returns 
+     */
+    request: function (param) {
+        return httpObj.request(param)
+    }
+}
+export default http;
diff --git a/vf205_access/dxmodules/dxLogger.js b/vf205_access/dxmodules/dxLogger.js
new file mode 100644
index 0000000..ed79322
--- /dev/null
+++ b/vf205_access/dxmodules/dxLogger.js
@@ -0,0 +1,59 @@
+/**
+ * dxLogger module
+ * To replace the `console.log` function, allowing logs to be viewed in the corresponding VSCode plugin during debugging, 
+ * with support for three levels of logging: `debug`,`info`, and `error`.
+ * Supports printing various data types in JavaScript.
+ */
+import dxCommon from './dxCommon.js'
+const logger = {}
+
+logger.config = {
+    level: 0, // default is all,if<0,no print
+}
+logger.debug = function (...data) {
+    if (this.config.level === 0) {
+        log("DEBUG ", data)
+    }
+}
+logger.info = function (...data) {
+    if ([0, 1].includes(this.config.level)) {
+        log("INFO ", data)
+    }
+}
+logger.error = function (...data) {
+    if ([0, 1, 2].includes(this.config.level)) {
+        log("ERROR ", data)
+    }
+}
+//-----------------------------------private----------------------
+function log(level, messages) {
+    let message = messages.map(msg => getContent(msg)).join(' ');
+    let content = `[${level}${getTime()}]: ${message}`
+    dxCommon.systemBrief(`echo '${content}'`)
+}
+function getContent(message) {
+    if (message === undefined) {
+        return 'undefined'
+    } else if (message === null) {
+        return 'null'
+    }
+    if ((typeof message) == 'object') {
+        if (Object.prototype.toString.call(message) === '[object Error]') {
+            return message.message + '\n' + message.stack
+        }
+        return JSON.stringify(message)
+    }
+    return message
+}
+function getTime() {
+    const now = new Date();
+    const year = now.getFullYear();
+    const month = ('0' + (now.getMonth() + 1)).slice(-2);
+    const day = ('0' + now.getDate()).slice(-2);
+    const hours = ('0' + now.getHours()).slice(-2);
+    const minutes = ('0' + now.getMinutes()).slice(-2);
+    const seconds = ('0' + now.getSeconds()).slice(-2);
+    const milliseconds = ('0' + now.getMilliseconds()).slice(-3);
+    return year + '-' + month + '-' + day + ' ' + hours + ':' + minutes + ':' + seconds + '.' + milliseconds;
+}
+export default logger
\ No newline at end of file
diff --git a/vf205_access/dxmodules/dxMap.js b/vf205_access/dxmodules/dxMap.js
new file mode 100644
index 0000000..0f73d1d
--- /dev/null
+++ b/vf205_access/dxmodules/dxMap.js
@@ -0,0 +1,109 @@
+import { mapClass } from './libvbar-m-dxmap.so'
+/**
+ * build:20240407
+ * map 缁勪欢锛屽彲浠ュ湪鍐呭瓨閲岃鍐檏ey/value
+ */
+const mapObj = new mapClass();
+
+const map = {
+    get: function (name) {
+        if (!name || name.length == 0) {
+            throw new Error("dxMap.get:name should not be null or empty")
+        }
+        //绗竴娆ut浼氳嚜鍔ㄥ垱寤哄疄渚�
+        return {
+            /**
+             * @brief   鑾峰彇Map涓殑鎵�鏈夐敭,杩斿洖涓�涓暟缁�
+             */
+            keys: function () {
+                let all = mapObj.keys(name)
+                return all == null ? [] : all
+            },
+            /**
+             * @brief   鏍规嵁key鑾峰彇value
+             */
+            get: function (key) {
+                if (!key || key.length < 1) {
+                    throw new Error("The 'key' parameter cannot be null or empty")
+                }
+                // put绌哄瓧绗︿覆锛実et浼氭槸null
+                let value = mapObj.get(name, key)
+                if (value === undefined || value === null) {
+                    value = ""
+                }
+                return _parseString(value)
+            },
+            /**
+             * @brief   鍚慚ap涓彃鍏ラ敭鍊煎
+             */
+            put: function (key, value) {
+                if (!key || key.length < 1) {
+                    throw new Error("The 'key' parameter cannot be null or empty")
+                }
+                if (value == null || value == undefined) {
+                    throw new Error("The 'value' parameter cannot be null or empty")
+                }
+                return mapObj.insert(name, key, _stringifyValue(value))
+            },
+            /**
+             * @brief   鏍规嵁Key鍒犻櫎閿�煎
+             */
+            del: function (key) {
+                if (!key || key.length < 1) {
+                    throw new Error("The 'key' parameter cannot be null or empty")
+                }
+                return mapObj.delete(name, key)
+            },
+            /**
+             * 涓嶅啀浣跨敤浜嗭紝灏遍攢姣�
+             */
+            destroy: function () {
+                return mapObj.destroy(name)
+            },
+        }
+    }
+
+}
+function _stringifyValue(value) {
+    const type = typeof value
+    if (type === 'string') {
+        return value
+    }
+    if (type === 'number') {
+        return '#n#' + value
+    }
+    if (type === 'boolean') {
+        return '#b#' + value
+    }
+    if (type === 'object') {
+        // 濡傛灉鏄璞★紝杩涗竴姝ュ垽鏂槸鍚︿负鏁扮粍
+        if (Array.isArray(value)) {
+            return '#a#' + JSON.stringify(value);
+        }// else if (value === null) { 鍓嶉潰宸茬粡瑙勯伩浜唍ull鐨勬儏鍐�
+        return '#o#' + JSON.stringify(value)
+    }
+    if (type === 'function') {
+        throw new Error("The 'value' parameter should not be function")
+    }
+}
+function _parseString(str) {
+    if (str.startsWith('#n#')) {
+        // 瑙f瀽鏁板瓧
+        const numberStr = str.substring(3);
+        return numberStr.includes('.') ? parseFloat(numberStr) : parseInt(numberStr, 10);
+    } else if (str.startsWith('#b#')) {
+        // 瑙f瀽甯冨皵鍊�
+        return str.substring(3) === 'true';
+    } else if (str.startsWith('#a#')) {
+        // 瑙f瀽鏁扮粍
+        return JSON.parse(str.substring(3));
+    } else if (str.startsWith('#o#')) {
+        // 瑙f瀽瀵硅薄
+        return JSON.parse(str.substring(3));
+    } else {
+        // 榛樿鎯呭喌涓嬶紝灏嗗瓧绗︿覆杩斿洖
+        return str;
+    }
+}
+export default map;
+
diff --git a/vf205_access/dxmodules/dxMqtt.js b/vf205_access/dxmodules/dxMqtt.js
new file mode 100644
index 0000000..71346ac
--- /dev/null
+++ b/vf205_access/dxmodules/dxMqtt.js
@@ -0,0 +1,225 @@
+//build:20240411
+//鍒╃敤mqtt鍗忚瀹炵幇鍜宮qtt鏈嶅姟绔殑閫氫俊鎴栭�氳繃mqtt broker瀹炵幇鍜屽叾瀹僲qtt瀹㈡埛绔殑閫氫俊
+//渚濊禆缁勪欢 dxMap,dxLogger,dxDriver,dxCommon,dxEventBus,dxNet
+import { mqttClass } from './libvbar-m-dxmqtt.so'
+import * as os from "os"
+import std from './dxStd.js'
+import dxMap from './dxMap.js'
+import dxCommon from './dxCommon.js'
+import bus from './dxEventBus.js'
+const map = dxMap.get("default")
+const mqttObj = new mqttClass();
+const mqtt = {}
+/**
+ * 鍒濆鍖杕qtt鐩稿叧灞炴�у苟鍒涘缓杩炴帴,璇峰湪worker閲屼娇鐢╠xMqtt缁勪欢鎴栦娇鐢ㄧ畝鍖栧嚱鏁癲xMqtt.run
+ * @param {string} mqttAddr mqtt鏈嶅姟鍦板潃锛屽繀濉紝浠cp://寮�澶达紝鏍煎紡鏄痶cp://ip:port
+ * @param {string} clientId 瀹㈡埛绔痠d锛屽繀濉紝涓嶅悓鐨勮澶囪浣跨敤涓嶅悓鐨勫鎴风id
+ * @param {string} username 闈炲繀濉紝mqtt鐢ㄦ埛鍚�
+ * @param {string} password 闈炲繀濉紝mqtt瀵嗙爜
+ * @param {string} prefix 闈炲繀濉紝缂虹渷涓虹┖瀛楃涓诧紝杩欎釜琛ㄧず鑷姩鍦ㄤ富棰樺墠鍔犱笂涓�涓墠缂�
+ * @param {number} qos 0,1,2 闈炲繀濉紝缂虹渷鏄�1. 鍏朵腑0琛ㄧず娑堟伅鏈�澶氬彂閫佷竴娆★紝鍙戦�佸悗娑堟伅灏辫涓㈠純;1琛ㄧず娑堟伅鑷冲皯鍙戦�佷竴娆★紝鍙互淇濊瘉娑堟伅琚帴鏀舵柟鏀跺埌锛屼絾鏄細瀛樺湪鎺ユ敹鏂规敹鍒伴噸澶嶆秷鎭殑鎯呭喌;2琛ㄧず娑堟伅鍙戦�佹垚鍔熶笖鍙彂閫佷竴娆�,璧勬簮寮�閿�澶�
+ * @param {string} willTopic 闈炲繀濉紝閬楀槺涓婚锛岄�氳繃broker閫氫俊鐨勬椂鍊欒澶囨柇寮�浼氳嚜鍔ㄨЕ鍙戜竴涓猰qtt閬楀槺娑堟伅锛岃繖涓槸閬楀槺娑堟伅鐨勪富棰�
+ * @param {string} willMessage 闈炲繀濉紝閬楀槺鍐呭锛岄�氳繃broker閫氫俊鐨勬椂鍊欒澶囨柇寮�浼氳嚜鍔ㄨЕ鍙戜竴涓猰qtt閬楀槺娑堟伅锛岃繖涓槸閬楀槺娑堟伅鐨勫唴瀹�
+ * @param {string} id 鍙ユ焺id锛岄潪蹇呭~锛堣嫢鍒濆鍖栧涓疄渚嬮渶瑕佷紶鍏ュ敮涓�id锛�
+ */
+mqtt.init = function (mqttAddr, clientId, username, password, prefix = "", qos = 1, willTopic, willMessage, id) {
+
+    if (mqttAddr === undefined || mqttAddr.length === 0) {
+        throw new Error("dxMqtt.init: 'mqttAddr' parameter should not be null or empty")
+    }
+    if (clientId === undefined || clientId.length === 0) {
+        throw new Error("dxMqtt.init: 'clientId' parameter should not be null or empty")
+    }
+    // 濡傛灉mqttAddr涓嶄互tcp://寮�澶达紝鑷姩娣诲姞鍓嶇紑
+    if (!mqttAddr.startsWith('tcp://')) {
+        mqttAddr = 'tcp://' + mqttAddr
+    }
+    let pointer = mqttObj.init(mqttAddr, clientId, username, password, prefix, qos, willTopic, willMessage);
+    if (pointer === undefined || pointer === null) {
+        throw new Error("dxMqtt.init: mqtt init failed")
+    }
+
+    dxCommon.handleId("mqtt", id, pointer)
+}
+
+/**
+ * 閲嶆柊杩炴帴,姣斿杩炴帴鎴愬姛鍚庣獊鐒剁綉缁滄柇寮�锛屾棤闇�閲嶆柊init锛岀洿鎺ラ噸杩炲嵆鍙�
+ * @param {string} willTopic 闈炲繀濉紝閬楀槺涓婚锛岄�氳繃broker閫氫俊鐨勬椂鍊欒澶囨柇寮�浼氳嚜鍔ㄨЕ鍙戜竴涓猰qtt閬楀槺娑堟伅锛岃繖涓槸閬楀槺娑堟伅鐨勪富棰�
+ * @param {string} willMessage 闈炲繀濉紝閬楀槺鍐呭锛岄�氳繃broker閫氫俊鐨勬椂鍊欒澶囨柇寮�浼氳嚜鍔ㄨЕ鍙戜竴涓猰qtt閬楀槺娑堟伅锛岃繖涓槸閬楀槺娑堟伅鐨勫唴瀹�
+ * @param {string} id 鍙ユ焺id锛岄潪蹇呭~锛堥渶淇濇寔鍜宨nit涓殑id涓�鑷达級
+ */
+mqtt.reconnect = function (willTopic, willMessage, id) {
+    let pointer = dxCommon.handleId("mqtt", id)
+    return mqttObj.recreate(pointer, willTopic, willMessage);
+}
+
+/**
+ * 璁㈤槄澶氫富棰�
+ * @param {array} topics 蹇呭~锛� 瑕佽闃呯殑涓婚鏁扮粍锛屽彲浠ュ悓鏃惰闃呭涓� 
+ * @param {number} qos 闈炲繀濉紝缂虹渷鏄�1. 鍏朵腑0琛ㄧず娑堟伅鏈�澶氬彂閫佷竴娆★紝鍙戦�佸悗娑堟伅灏辫涓㈠純;1琛ㄧず娑堟伅鑷冲皯鍙戦�佷竴娆★紝鍙互淇濊瘉娑堟伅琚帴鏀舵柟鏀跺埌锛屼絾鏄細瀛樺湪鎺ユ敹鏂规敹鍒伴噸澶嶆秷鎭殑鎯呭喌;2琛ㄧず娑堟伅鍙戦�佹垚鍔熶笖鍙彂閫佷竴娆�,璧勬簮寮�閿�澶�
+ * @param {string} id 鍙ユ焺id锛岄潪蹇呭~锛堥渶淇濇寔鍜宨nit涓殑id涓�鑷达級
+ * @returns 
+ */
+mqtt.subscribes = function (topics, qos, id) {
+    if (topics === undefined || topics.length === 0) {
+        throw new Error("dxMqtt.subscribes: 'topics' parameter should not be null or empty")
+    }
+
+    if (qos === undefined) {
+        qos = 1
+    }
+    let pointer = dxCommon.handleId("mqtt", id)
+    return mqttObj.subscribes(pointer, topics, qos);
+}
+
+/**
+ * 鍒ゆ柇mqtt鏄惁杩炴帴锛岃繛鎺ユ垚鍔熷悗濡傛灉缃戠粶鏂紑锛岃繛鎺ヤ篃浼氭柇寮�
+ * @param {string} id 鍙ユ焺id锛岄潪蹇呭~锛堥渶淇濇寔鍜宨nit涓殑id涓�鑷达級
+ * @returns false澶辫触锛� true鎴愬姛
+ */
+mqtt.isConnected = function (id) {
+    let pointer = dxCommon.handleId("mqtt", id)
+    return mqttObj.isConnected(pointer);
+}
+
+/**
+ * 鏌ヨmqtt閰嶇疆
+ * @param {string} id 鍙ユ焺id锛岄潪蹇呭~锛堥渶淇濇寔鍜宨nit涓殑id涓�鑷达級
+ * @returns mqtt閰嶇疆
+ */
+mqtt.getConfig = function (id) {
+    let pointer = dxCommon.handleId("mqtt", id)
+    return mqttObj.getConfig(pointer);
+}
+
+/**
+ * mqtt閰嶇疆鏇存柊
+ * @param {object} options 閰嶇疆鍙傛暟锛屽ぇ閮ㄥ垎鍙互鐢ㄩ粯璁ゅ��
+ *      @param {string} options.mqttAddr mqtt鏈嶅姟鍦板潃锛屽繀濉紝浠cp://寮�澶达紝鏍煎紡鏄痶cp://ip:port
+ *      @param {string} options.clientId 瀹㈡埛绔痠d锛屽繀濉紝涓嶅悓鐨勮澶囪浣跨敤涓嶅悓鐨勫鎴风id
+ *      @param {string} options.userName 闈炲繀濉紝mqtt鐢ㄦ埛鍚�
+ *      @param {string} options.password 闈炲繀濉紝mqtt瀵嗙爜
+ *      @param {string} options.prefix 闈炲繀濉紝缂虹渷涓虹┖瀛楃涓诧紝杩欎釜琛ㄧず鑷姩鍦ㄤ富棰樺墠鍔犱笂涓�涓墠缂�
+ *      @param {number} options.qos 0,1,2 闈炲繀濉紝缂虹渷鏄�1. 鍏朵腑0琛ㄧず娑堟伅鏈�澶氬彂閫佷竴娆★紝鍙戦�佸悗娑堟伅灏辫涓㈠純;1琛ㄧず娑堟伅鑷冲皯鍙戦�佷竴娆★紝鍙互淇濊瘉娑堟伅琚帴鏀舵柟鏀跺埌锛屼絾鏄細瀛樺湪鎺ユ敹鏂规敹鍒伴噸澶嶆秷鎭殑鎯呭喌;2琛ㄧず娑堟伅鍙戦�佹垚鍔熶笖鍙彂閫佷竴娆�,璧勬簮寮�閿�澶�
+ *      @param {string} options.ssl 闈炲繀濉紝ssl閰嶇疆绫�
+ */
+mqtt.updateConfig = function (options, id) {
+    if (!options) {
+        throw new Error("dxMqtt.updateConfig: 'options' parameter should not be null or empty")
+    }
+    if (options.mqttAddr === undefined || options.mqttAddr.length === 0) {
+        throw new Error("dxMqtt.updateConfig: 'options.mqttAddr' parameter should not be null or empty")
+    }
+    if (options.clientId === undefined || options.clientId.length === 0) {
+        throw new Error("dxMqtt.updateConfig: 'options.clientId' parameter should not be null or empty")
+    }
+    if (options.qos === undefined || options.qos == null) {
+        throw new Error("dxMqtt.updateConfig: 'options.qos' parameter should not be null or empty")
+    }
+    // 濡傛灉mqttAddr涓嶄互tcp://寮�澶达紝鑷姩娣诲姞鍓嶇紑
+    if (!options.mqttAddr.startsWith('tcp://')) {
+        options.mqttAddr = 'tcp://' + options.mqttAddr
+    }
+    let pointer = dxCommon.handleId("mqtt", id)
+    let res = mqttObj.setConfig(pointer, options);
+    return res;
+}
+
+/**
+ * 鍙戦�乵qtt璇锋眰
+ * @param {string} topic 涓婚锛屽繀濉�
+ * @param {string} payload 娑堟伅浣撳唴瀹癸紝蹇呭~
+ * @param {string} id 鍙ユ焺id锛岄潪蹇呭~锛堥渶淇濇寔鍜宨nit涓殑id涓�鑷达級
+ */
+mqtt.send = function (topic, payload, id) {
+    if (topic === undefined || topic.length === 0) {
+        throw new Error("dxMqtt.send:'topic' parameter should not be null or empty")
+    }
+    if (payload === undefined || payload.length === 0) {
+        throw new Error("dxMqtt.send:'payload' parameter should not be null or empty")
+    }
+    let pointer = dxCommon.handleId("mqtt", id)
+    return mqttObj.sendMsg(pointer, topic, payload);
+}
+
+/**
+ * 鎺ユ敹mqtt鏁版嵁,闇�瑕佽疆璇㈠幓鑾峰彇
+ * @param {string} id 鍙ユ焺id锛岄潪蹇呭~锛堥渶淇濇寔鍜宨nit涓殑id涓�鑷达級
+ * @return mqtt璇锋眰鏁版嵁锛岀粨鏋勬槸: {topic:'涓婚',payload:'鍐呭'}
+ */
+mqtt.receive = function (id) {
+    let msg = mqttObj.msgReceive(id);
+    return JSON.parse(msg);
+}
+
+/**
+ * 鍒ゆ柇鏄惁鏈夋柊鐨勬暟鎹紝涓�鑸厛鍒ゆ柇鏈夋暟鎹悗鍐嶈皟鐢╮eceive鍘昏幏鍙栨暟鎹�
+ * @param {string} id 鍙ユ焺id锛岄潪蹇呭~锛堥渶淇濇寔鍜宨nit涓殑id涓�鑷达級
+ * @returns false 鏈夋暟鎹紱true 娌℃湁鏁版嵁
+ */
+mqtt.msgIsEmpty = function (id) {
+    return mqttObj.msgIsEmpty(id);
+}
+
+/**
+ * 閿�姣乵qtt瀹炰緥
+ * @param {string} id 鍙ユ焺id锛岄潪蹇呭~锛堥渶淇濇寔鍜宨nit涓殑id涓�鑷达級
+ */
+mqtt.destroy = function (id) {
+    let pointer = dxCommon.handleId("mqtt", id)
+    mqttObj.deinit(pointer);
+}
+
+mqtt.RECEIVE_MSG = '__mqtt__MsgReceive'
+mqtt.CONNECTED_CHANGED = '__mqtt__Connect_changed'
+mqtt.RECONNECT = '__mqtt__Reconnect'
+
+/**
+ * 鐢ㄧ畝鍗曠殑鏂瑰紡瀹炵幇mqtt瀹㈡埛绔紝鍙渶瑕佽皟鐢ㄨ繖涓�涓嚱鏁板氨鍙互瀹炵幇mqtt瀹㈡埛绔紝
+ * 鏀跺埌娑堟伅浼氳Е鍙戠粰 dxEventBus鍙戦�佷竴涓簨浠讹紝浜嬩欢鐨勪富棰樻槸mqtt.RECEIVE_MQTT_MSG锛屽唴瀹规槸{topic:'',payload:''}鏍煎紡
+ * 濡傛灉闇�瑕佸彂閫佹秷鎭紝鐩存帴浣跨敤 mqtt.send鏂规硶 mqtt鍙戦�佺殑鏁版嵁鏍煎紡绫讳技锛� { topic: "sendtopic1", payload: JSON.stringify({ a: i, b: "ssss" }) }
+ * mqtt鐨勮繛鎺ョ姸鎬佸彂鐢熷彉鍖栦細瑙﹀彂缁� dxEventBus鍙戦�佷竴涓簨浠讹紝浜嬩欢鐨勪富棰樻槸mqtt.CONNECTED_CHANGED锛屽唴瀹规槸'connected'鎴栬��'disconnect'
+ * mqtt闇�瑕佹湁缃戠粶锛屾墍浠ュ繀椤诲湪浣跨敤涔嬪墠纭繚dxNet缁勪欢瀹屾垚鍒濆鍖�
+ * @param {object} options mqtt鐩稿叧鍙傛暟,蹇呭~
+ *      @param {string} options.mqttAddr mqtt鏈嶅姟鍦板潃锛屽繀濉紝浠cp://寮�澶达紝鏍煎紡鏄痶cp://ip:port
+ *      @param {string} options.clientId 瀹㈡埛绔痠d锛屽繀濉紝涓嶅悓鐨勮澶囪浣跨敤涓嶅悓鐨勫鎴风id
+ *      @param {string} options.username 闈炲繀濉紝mqtt鐢ㄦ埛鍚�
+ *      @param {string} options.password 闈炲繀濉紝mqtt瀵嗙爜
+ *      @param {string} options.prefix 闈炲繀濉紝缂虹渷涓虹┖瀛楃涓诧紝杩欎釜琛ㄧず鑷姩鍦ㄤ富棰樺墠鍔犱笂涓�涓墠缂�
+ *      @param {number} options.qos 0,1,2 闈炲繀濉紝缂虹渷鏄�1. 鍏朵腑0琛ㄧず娑堟伅鏈�澶氬彂閫佷竴娆★紝鍙戦�佸悗娑堟伅灏辫涓㈠純;1琛ㄧず娑堟伅鑷冲皯鍙戦�佷竴娆★紝鍙互淇濊瘉娑堟伅琚帴鏀舵柟鏀跺埌锛屼絾鏄細瀛樺湪鎺ユ敹鏂规敹鍒伴噸澶嶆秷鎭殑鎯呭喌;2琛ㄧず娑堟伅鍙戦�佹垚鍔熶笖鍙彂閫佷竴娆�,璧勬簮寮�閿�澶�
+ *      @param {string} options.willTopic 闈炲繀濉紝閬楀槺涓婚锛岄�氳繃broker閫氫俊鐨勬椂鍊欒澶囨柇寮�浼氳嚜鍔ㄨЕ鍙戜竴涓猰qtt閬楀槺娑堟伅锛岃繖涓槸閬楀槺娑堟伅鐨勪富棰�
+ *      @param {string} options.willMessage 闈炲繀濉紝閬楀槺鍐呭锛岄�氳繃broker閫氫俊鐨勬椂鍊欒澶囨柇寮�浼氳嚜鍔ㄨЕ鍙戜竴涓猰qtt閬楀槺娑堟伅锛岃繖涓槸閬楀槺娑堟伅鐨勫唴瀹�
+ *      @param {array}  options.subs 闈炲繀濉紝瑕佽闃呯殑涓婚缁�
+ *      @param {string} options.id  鍙ユ焺id锛岄潪蹇呭~锛堣嫢鍒濆鍖栧涓疄渚嬮渶瑕佷紶鍏ュ敮涓�id锛�
+ */
+mqtt.run = function (options) {
+    if (options === undefined || options.length === 0) {
+        throw new Error("dxmqtt.run:'options' parameter should not be null or empty")
+    }
+    if (options.id === undefined || options.id === null || typeof options.id !== 'string') {
+        // 鍙ユ焺id
+        options.id = ""
+    }
+    let oldfilepre = '/app/code/dxmodules/mqttWorker'
+    let content = std.loadFile(oldfilepre + '.js').replace("{{id}}", options.id)
+    let newfile = oldfilepre + options.id + '.js'
+    std.saveFile(newfile, content)
+    let init = map.get("__mqtt__run_init" + options.id)
+    if (!init) {//纭繚鍙垵濮嬪寲涓�娆�
+        map.put("__mqtt__run_init" + options.id, options)
+        bus.newWorker(options.id || "__mqtt", newfile)
+    }
+}
+/**
+ * 鑾峰彇褰撳墠mqtt杩炴帴鐨勭姸鎬�
+ * @param {string} id 鍙ユ焺id锛岄潪蹇呭~锛堥渶淇濇寔鍜宨nit涓殑id涓�鑷达級
+ * @returns 'connected' 鎴栬�� 'disconnected'
+ */
+mqtt.getConnected = function (id) {
+    if (id == undefined || id == null) {
+        id = ""
+    }
+    return mqtt.isConnected(id) ? "connected" : "disconnected"
+}
+
+export default mqtt;
diff --git a/vf205_access/dxmodules/dxNet.js b/vf205_access/dxmodules/dxNet.js
new file mode 100644
index 0000000..ad7df4c
--- /dev/null
+++ b/vf205_access/dxmodules/dxNet.js
@@ -0,0 +1,341 @@
+//build:20240626
+//閫氳繃杩欎釜缁勪欢鏉ラ厤缃綉缁滃拰鐩戝惉缃戠粶鐘舵�佸彉鍖�
+//渚濊禆缁勪欢: dxMap,dxLogger,dxDriver,dxEventBus
+import dxMap from './dxMap.js'
+import bus from './dxEventBus.js'
+import { netClass } from './libvbar-m-dxnet.so'
+const netObj = new netClass();
+const map = dxMap.get("default")
+
+const net = {}
+net.TYPE = {
+    "UNKNOWN": 0,
+    "ETHERNET": 1,
+    "WIFI": 2,
+    "4G": 4
+}
+net.DHCP = {
+    STATIC: 1,
+    DYNAMIC: 2,
+    WIFI_AP: 3 //WiFi AP鐑偣妯″紡
+}
+
+/**
+ * 缃戠粶鍒濆鍖�,wifi鎴栦互澶綉锛屽鏋滆繛涓嶄笂缃戠粶浼氳嚜鍔ㄤ笉鏂殑閲嶈瘯锛屾棤闇�閲嶅init銆備絾鏄痠nit鍚庨渶瑕佽疆璇㈠幓鑾峰彇缃戠粶鐘舵�侊紙閫氳繃msgReceive)
+ * 涔熷彲浠ョ洿鎺ヤ娇鐢ㄧ畝鍖栨柟娉昫xNet.run锛屾棤闇�杞
+ * @param {object} options 鍒濆鍖栫綉缁滅殑鍙傛暟
+ *       @param {number} type 蹇呭~ 缃戠粶绫诲瀷锛屽弬鑰僴et.TYPE鏋氫妇
+ *       @param {number} dhcp 蹇呭~ DHCP锛屽弬鑰僴et.DHCP鏋氫妇
+ *       @param {string} macAddr 蹇呭~ mac鍦板潃,缂虹渷浣跨敤dxCommon.getUuid2mac()鏂规硶鏉ヨ幏鍙杕ac鍦板潃
+ *       @param {string} ip 闈炲繀濉� 缃戠粶ip鍦板潃
+ *       @param {string} gateway 闈炲繀濉� 缃戝叧鍦板潃
+ *       @param {string} netmask 闈炲繀濉� 瀛愮綉鎺╃爜
+ *       @param {string} dns0 闈炲繀濉� DNS鍦板潃
+ *       @param {string} dns1 闈炲繀濉� 澶囬�塂NS鍦板潃
+ * @returns 
+ */
+net.init = function (options) {
+    let ret = netObj.init()
+    if (!ret) {
+        return false
+    }
+    if (!options) {
+        throw new Error("dxNet.init: 'options' parameter should not be null or empty")
+    }
+    ret = netObj.setMasterCard(options.type)
+    if (!ret) {
+        return false
+    }
+    netObj.setMacaddr(options.type, options.macAddr)
+    ret = netObj.cardEnable(options.type, true)
+    if (!ret) {
+        return false
+    }
+    if (options.dhcp === 1) {
+        return netObj.setModeByCard(options.type, 1, {
+            ip: options.ip,
+            gateway: options.gateway,
+            netmask: options.netmask,
+            dns0: options.dns0,
+            dns1: options.dns1,
+        })
+    } else if (options.dhcp === 2) {
+        return netObj.setModeByCard(options.type, options.dhcp)
+    }
+    return false
+}
+
+/**
+ * 鑾峰彇Mac鍦板潃 
+ * @param {number} type  蹇呭~ 缃戠粶绫诲瀷锛屽弬鑰僴et.TYPE鏋氫妇
+ * @returns   Mac鍦板潃
+ */
+net.getMacaddr = function (type) {
+    return netObj.getMacaddr(type)
+}
+/**
+ * 璁剧疆Mac鍦板潃
+ * @param {number} type  蹇呭~ 缃戠粶绫诲瀷锛屽弬鑰僴et.TYPE鏋氫妇
+ * @param {string} addr  Mac鍦板潃,蹇呭~锛屾牸寮忕被浼� b2:a1:63:3f:99:b6
+ * @returns   true锛氭垚鍔� 涓荤綉鍗$被鍨嬶紝false 澶辫触
+ */
+net.setMacaddr = function (type, addr) {
+    if (type === null || type === undefined) {
+        throw new Error("dxNet.setMacaddr:'type' paramter should not be null or empty")
+    }
+    if (addr === null || addr === undefined || addr.length < 1) {
+        throw new Error("dxNet.setMacaddr:'addr' paramter should not be null or empty")
+    }
+    return netObj.setMacaddr(type, addr)
+}
+/**
+ * 浣胯兘缃戝崱锛屽苟娣诲姞鍒扮綉缁滅鐞嗘ā鍧�
+ * @param {number} type  蹇呭~ 缃戠粶绫诲瀷锛屽弬鑰僴et.TYPE鏋氫妇
+ * @param {boolean} on  寮�鍚�/鍏抽棴
+ * @returns   0锛氭垚鍔� <0 澶辫触
+ */
+net.cardEnable = function (type, on) {
+    if (type === null || type === undefined) {
+        throw new Error("dxNet.cardEnable: 'type' parameter should not be null or empty")
+    }
+    if (on === null) {
+        throw new Error("dxNet.cardEnable: 'on' parameter should not be null or empty")
+    }
+    return netObj.cardEnable(type, on)
+}
+/**
+ * net缃戠粶閿�姣�
+ * @return true锛氭垚鍔燂紝false 澶辫触
+ */
+net.exit = function () {
+    return netObj.exit()
+}
+/**
+ * 璁剧疆鎸囧畾缃戝崱鐨勬ā寮忓強瀵瑰簲鍙傛暟缃戠粶鍙傛暟
+ * @param {number} type   蹇呭~ 缃戠粶绫诲瀷锛屽弬鑰僴et.TYPE鏋氫妇
+ * @param {number} mode   蹇呭~ DHCP锛屽弬鑰僴et.DHCP鏋氫妇
+ * @param param  缃戠粶鍙傛暟
+ * @return true锛氭垚鍔燂紝false 澶辫触
+ */
+net.setModeByCard = function (type, mode, param) {
+    if (type === null || type === undefined) {
+        throw new Error("dxNet.setModeByCard: 'type' parameter should not be null or empty")
+    }
+    if (mode === null) {
+        throw new Error("dxNet.setModeByCard:'mode' parameter should not be null or empty")
+    }
+    return netObj.setModeByCard(type, mode, param)
+}
+/**
+ * 鑾峰彇鎸囧畾缃戝崱鐨勬ā寮忓強瀵瑰簲鍙傛暟缃戠粶鍙傛暟
+ * @param {number} type  蹇呭~ 缃戠粶绫诲瀷锛屽弬鑰僴et.TYPE鏋氫妇
+ * @returns   濡傛灉鏄潤鎬佺綉缁滄ā寮忥紝灏变細杩斿洖ip銆佺綉鍏崇瓑淇℃伅
+ */
+net.getModeByCard = function (type) {
+    if (type === null || type === undefined) {
+        throw new Error("dxNet.getModeByCard: 'type' parameter should not be null or empty")
+    }
+
+    return netObj.getModeByCard(type)
+}
+/**
+ * 璁剧疆涓荤綉鍗★紝搴旂敤绋嬪簭缃戠粶鐘舵�佺敱娆$綉鍗″喅瀹�
+ * @param {number} type  蹇呭~ 缃戠粶绫诲瀷锛屽弬鑰僴et.TYPE鏋氫妇
+ * @returns    true锛氭垚鍔燂紝false 澶辫触
+ */
+net.setMasterCard = function (type) {
+    if (type === null || type === undefined) {
+        throw new Error("dxNet.setMasterCard: 'type' parameter should not be null or empty")
+    }
+    return netObj.setMasterCard(type)
+}
+/**
+ * 鑾峰彇涓荤綉鍗�
+ * @returns   >0锛氭垚鍔� 涓荤綉鍗$被鍨嬶紝<0 澶辫触
+ */
+net.getMasterCard = function () {
+    return netObj.getMasterCard()
+}
+/**
+ * 鑾峰彇缃戠粶鐘舵�� 绫讳技{"status":4锛�"connected":true} ,鍏朵腑status濡備笅
+ *  0,    鏈垵濮嬫��
+    1,    缃戝崱澶勪簬鍏抽棴鐘舵��
+    2,    缃戝崱澶勪簬鎵撳紑鐘舵��
+    3,    缃戠嚎宸叉彃鍏ユ垨鑰厀ifi宸茶繛鎺sid 浣嗘湭鍒嗛厤ip
+    4,    宸叉垚鍔熷垎閰峣p
+    5     宸茶繛鎺ユ寚瀹氭湇鍔℃垨鑰呴�氳繃娴嬭瘯鍙互杩炴帴鍒板箍鍩熺綉
+ * @returns   缃戠粶鐘舵��
+ */
+net.getStatus = function () {
+    let status = netObj.getStatus()
+    return { "status": status, "connected": status >= 4 }
+}
+/**
+ * 璁剧疆缃戠粶鐘舵��
+ * @param {number} status 缃戠粶鐘舵�侊紝蹇呭~
+ * @returns true锛氭垚鍔燂紝false 澶辫触
+ */
+net.setStatus = function (status) {
+    if (status === null || status === undefined) {
+        throw new Error("dxNet.setStatus: 'status' parameter should not be null or empty")
+    }
+    return netObj.setStatus(status)
+}
+
+/**
+ * 閲嶆柊浣胯兘缃戝崱
+ * @param {number} type         缃戠粶绫诲瀷锛屽繀濉�
+ * @param {number} phy_reset    寮�鍚�/鍏抽棴锛屽繀濉�
+ * @returns true锛氭垚鍔燂紝false 澶辫触
+ */
+net.netCardReset = function (type, phy_reset) {
+    if (type === null || type === undefined) {
+        throw new Error("dxNet.setStatus: 'status' parameter should not be null or empty")
+    }
+    if (phy_reset === null || phy_reset === undefined) {
+        throw new Error("dxNet.setStatus: 'status' parameter should not be null or empty")
+    }
+    return netObj.netCardReset(type, phy_reset)
+}
+
+/**
+ * 鑾峰彇wifi鍒楄〃
+ * @param {*} timeout 蹇呭~
+ * @param {*} interval 蹇呭~
+ * @returns wifi鍒楄〃
+ */
+net.netGetWifiSsidList = function (timeout, interval) {
+    if (timeout === null || timeout === undefined) {
+        throw new Error("dxNet.netGetWifiSsidList: 'timeout' parameter should not be null or empty")
+    }
+    if (interval === null) {
+        throw new Error("dxNet.netGetWifiSsidList: 'interval' parameter should not be null or empty")
+    }
+    return netObj.netGetWifiSsidList(timeout, interval)
+}
+/**
+ * 杩炴帴鍒皐ifi
+ * @param {*} ssid 蹇呭~
+ * @param {*} psk 蹇呭~
+ * @param {*} params 蹇呭~
+ * @returns 
+ */
+net.netConnectWifiSsid = function (ssid, psk, params) {
+    if (ssid === null) {
+        throw new Error("dxNet.netConnectWifiSsid: 'ssid' parameter should not be null or empty")
+    }
+    if (psk === null) {
+        throw new Error("dxNet.netConnectWifiSsid: 'psk' parameter should not be null or empty")
+    }
+    if (params === null) {
+        throw new Error("dxNet.netConnectWifiSsid: 'params' parameter should not be null or empty")
+    }
+    return netObj.netConnectWifiSsid(ssid, psk, params)
+}
+/**
+ * 鑾峰彇宸蹭繚瀛樼殑鐑偣鍒楄〃
+ * @returns  宸蹭繚瀛樼殑鐑偣鍒楄〃
+ */
+net.netGetWifiSavedList = function () {
+    return netObj.netGetWifiSavedList()
+}
+/**
+ * 鏂紑褰撳墠杩炴帴鐨剋ifi鐑偣
+ * @returns  
+ */
+net.netDisconnetWifi = function () {
+    return netObj.netDisconnetWifi()
+}
+/**
+ * 鑾峰彇褰撳墠鐑偣鐨勪俊鎭�
+ * @param timeout 蹇呭~
+ * @returns  
+ */
+net.netGetCurrentWifiInfo = function (timeout) {
+    if (timeout === null) {
+        throw new Error("dxNet.netGetCurrentWifiInfo: 'timeout' parameter should not be null or empty")
+    }
+    return netObj.netGetCurrentWifiInfo(timeout)
+}
+
+/**
+ * 妫�鏌ユ秷鎭槦鍒楁槸鍚︿负绌�
+ * @returns true涓虹┖ false涓嶄负绌�
+ */
+net.msgIsEmpty = function () {
+    return netObj.msgIsEmpty()
+}
+/**
+ * 浠庢秷鎭槦鍒椾腑鍙栫綉缁滃綋鍓嶇姸鎬佹暟鎹紝杩斿洖缁撴瀯绫讳技{"type":1,"status":4锛�"connected":true}
+ * 鍏朵腑type鍙傝�僴et.TYPE鏋氫妇
+ * 鍏朵腑status鐨勫�艰鏄庡涓嬶細
+ *  0,    鏈垵濮嬫��
+    1,    缃戝崱澶勪簬鍏抽棴鐘舵��
+    2,    缃戝崱澶勪簬鎵撳紑鐘舵��
+    3,    缃戠嚎宸叉彃鍏ユ垨鑰厀ifi宸茶繛鎺sid 浣嗘湭鍒嗛厤ip
+    4,    宸叉垚鍔熷垎閰峣p
+    5     宸茶繛鎺ユ寚瀹氭湇鍔℃垨鑰呴�氳繃娴嬭瘯鍙互杩炴帴鍒板箍鍩熺綉
+ * @returns   瀛楃涓茬被鍨嬬殑娑堟伅鏁版嵁
+ */
+net.msgReceive = function () {
+    let res = JSON.parse(netObj.msgReceive());
+    if (res.status >= 4) {
+        res.connected = true
+    } else {
+        res.connected = false
+    }
+    return res
+}
+
+net.STATUS_CHANGE = '__netstatus__changed'
+
+/**
+ * 绠�鍖栫綉缁滅粍浠剁殑浣跨敤锛屾棤闇�杞鍘昏幏鍙栫綉缁滅姸鎬侊紝缃戠粶鐨勭姸鎬佷細閫氳繃eventBus鍙戦�佸嚭鍘�
+ * run 鍙細鎵ц涓�娆★紝鎵ц涔嬪悗缃戠粶鍩烘湰閰嶇疆涓嶈兘淇敼
+ * 濡傛灉闇�瑕佸疄鏃惰幏鍙栫綉缁滅姸鎬佸彉鍖栵紝鍙互璁㈤槄 eventBus鐨勪簨浠讹紝浜嬩欢鐨則opic鏄痭et.STATUS_CHANGE锛屼簨浠剁殑鍐呭鏄被浼納"type":1,"status":4锛�"connected":true}
+ * 鍏朵腑type鍙傝�僴et.TYPE鏋氫妇
+ * 鍏朵腑status鐨勫�艰鏄庡涓嬶細
+ *  0,    鏈垵濮嬫��
+    1,    缃戝崱澶勪簬鍏抽棴鐘舵��
+    2,    缃戝崱澶勪簬鎵撳紑鐘舵��
+    3,    缃戠嚎宸叉彃鍏ユ垨鑰厀ifi宸茶繛鎺sid 浣嗘湭鍒嗛厤ip
+    4,    宸叉垚鍔熷垎閰峣p
+    5     宸茶繛鎺ユ寚瀹氭湇鍔℃垨鑰呴�氳繃娴嬭瘯鍙互杩炴帴鍒板箍鍩熺綉
+ * @param {object} options 鍙傝�僫nit鐨刼ptions鎻忚堪
+ */
+net.run = function (options) {
+    if (options === undefined || options.length === 0) {
+        throw new Error("dxnet.run:'options' parameter should not be null or empty")
+    }
+    let workerFile = '/app/code/dxmodules/netWorker.js'
+    let init = map.get("__net__run_init")
+    if (!init) {//纭繚鍙垵濮嬪寲涓�娆�
+        map.put("__net__run_init", options)
+        bus.newWorker('__net', workerFile)
+    }
+}
+
+/**
+ * 濡傛灉net鍗曠嫭涓�涓嚎绋嬶紝鍙互鐩存帴浣跨敤run鍑芥暟锛屼細鑷姩鍚姩涓�涓嚎绋嬶紝
+ * 濡傛灉鎯冲姞鍏ュ埌鍏朵粬宸叉湁鐨勭嚎绋嬶紝鍙互浣跨敤浠ヤ笅灏佽鐨勫嚱鏁�
+ */
+net.worker = {
+    //鍦╳hile寰幆鍓�
+    beforeLoop: function (options) {
+        net.init(options)
+    },
+    //鍦╳hile寰幆閲�
+    loop: function () {
+        if (!net.msgIsEmpty()) {
+            let res = net.msgReceive();
+            if (res.status >= 4) {
+                res.connected = true
+            } else {
+                res.connected = false
+            }
+            bus.fire(net.STATUS_CHANGE, res)
+        }
+    }
+}
+
+export default net;
diff --git a/vf205_access/dxmodules/dxNfc.js b/vf205_access/dxmodules/dxNfc.js
new file mode 100644
index 0000000..377c6c4
--- /dev/null
+++ b/vf205_access/dxmodules/dxNfc.js
@@ -0,0 +1,409 @@
+//build:20240715
+//閫氳繃杩欎釜缁勪欢鏉ヨ鍙栧崱锛屽寘鎷琈1鍗★紝psam鍗′箣绫荤殑
+//渚濊禆缁勪欢: dxDriver,dxMap,dxLogger,dxDriver,dxCommon,dxEventBus
+import { nfcClass } from './libvbar-p-dxnfc.so'
+import dxCommon from './dxCommon.js'
+import bus from './dxEventBus.js'
+import dxMap from './dxMap.js'
+const nfcObj = new nfcClass();
+const map = dxMap.get("default")
+const nfc = {}
+
+/**
+ * NFC 鍒濆鍖�
+ * @param {number} useEid 闈炲繀濉紝鏄惁浣跨敤浜戣瘉 0涓嶄娇鐢� 1浣跨敤
+ */
+nfc.init = function (useEid = 0) {
+	let pointer = nfcObj.init(useEid)
+	if (pointer === undefined || pointer === null) {
+		throw new Error("nfc.init: init failed")
+	}
+	dxCommon.handleId("nfc", 'nfcid', pointer)
+}
+
+/**
+ * NFC 鏅�氬崱娉ㄥ唽鍥炶皟
+ */
+nfc.cbRegister = function (callback) {
+	let pointer = dxCommon.handleId("nfc", 'nfcid')
+	return nfcObj.cbRegister(pointer, "nfc_cb", 1, callback)
+}
+
+/**
+ * NFC PSAM鍗℃敞鍐屽洖璋�
+ */
+nfc.psamCbRegister = function (callback) {
+	let pointer = dxCommon.handleId("nfc", 'nfcid')
+	return nfcObj.nfcPsamCheckVgcardCallback(pointer, callback)
+}
+
+/**
+ * NFC 鍙栨秷鍒濆鍖�
+ */
+nfc.deinit = function () {
+	let pointer = dxCommon.handleId("nfc", 'nfcid')
+	let ret = nfcObj.cbUnregister(pointer, "nfc_cb")
+	if (ret === false) {
+		throw new Error("nfc.cbUnregister: cbUnregister failed")
+	}
+	return nfcObj.deinit(pointer)
+}
+
+/**
+ * NFC 鍗′俊鎭垱寤�
+ * @param {number} cardType 鍗¤姱鐗囩被鍨�(鍘熷巶瀹氫箟)
+ * @param {ArrayBuffer} cardId 鍗″彿
+ * @param {number} type 鍗$被鍨�(鎴戜滑鑷繁瀹氫箟鐨�)
+ * @returns cardInfo(pointer)
+ */
+nfc.cardInfoCreate = function (cardType, cardId, type) {
+	if (!cardType) {
+		throw new Error("cardInfoCreate:cardType should not be null or empty")
+	}
+	if (!cardId) {
+		throw new Error("cardInfoCreate:cardId should not be null or empty")
+	}
+	if (!type) {
+		throw new Error("cardInfoCreate:type should not be null or empty")
+	}
+	return nfcObj.cardInfoCreate(cardType, cardId, type);
+}
+
+/**
+ * NFC 鍗′俊鎭攢姣�
+ * @param {pointer} cardInfo 鍗′俊鎭�
+ * @returns 
+ */
+nfc.cardInfoDestory = function (cardInfo) {
+	if (!cardInfo) {
+		throw new Error("cardInfoDestory:cardInfo should not be null or empty")
+	}
+	return nfcObj.cardInfoDestory(cardInfo);
+}
+
+/**
+ * NFC 鍗′俊鎭鍒�
+ * @param {pointer} cardInfo 鍗′俊鎭�
+ * @returns cardInfo(pointer)
+ */
+nfc.cardInfoCopy = function (cardInfo) {
+	if (cardInfo == null) {
+		throw new Error("cardInfoCopy:cardInfo should not be null or empty")
+	}
+	return nfcObj.cardInfoCopy(cardInfo);
+}
+
+/**
+ * NFC 鍒ゆ柇鏄惁鏈夊崱
+ * @returns bool
+ */
+nfc.isCardIn = function () {
+	let pointer = dxCommon.handleId("nfc", 'nfcid')
+	return nfcObj.isCardIn(pointer);
+}
+
+/**
+ * NFC 璇籑1鍗℃墖鍖�
+ * @param {number} taskFlg 浠诲姟鏍囧織锛�
+ *                    0x00->AUTO 鍛婄煡鎵爜鍣ㄨ鎸囦护鍙崟鐙墽琛岋紝鏃犳寚浠ら棿鐨勪緷璧栧叧绯汇��
+ *                    0x01->START 鍛婄煡鎵爜鍣ㄥ紑濮嬪鍗℃搷浣滄垨瀵瑰崱鎿嶄綔灏氭湭缁撴潫锛屼笖鎸囦护闂村彲鑳藉瓨鍦ㄤ緷璧栧叧绯汇��
+ *                    0x02->FINISH 鍛婄煡鎵爜鍣ㄦ湰鏉℃寚浠ゆ槸鎿嶄綔鍗$殑鏈�鍚庝竴鏉℃寚浠わ紝灏嗗崱鐗囨搷浣滅幆澧冩仮澶嶅埌榛樻�併��
+ * @param {number} secNum 鎵囧尯鍙�
+ * @param {number} logicBlkNum 鍧楀彿锛堝湪鎵囧尯鍐呯殑閫昏緫鍙�0~3)
+ * @param {number} blkNums 鍧楁暟
+ * @param {array} key 瀵嗛挜, 闀垮害6bytes
+ * @param {number} keyType 瀵嗛挜绫诲瀷: A:0x60 B:0x61
+ * @returns Array 璇诲彇缁撴灉 undefined:澶辫触
+ */
+nfc.m1cardReadSector = function (taskFlg, secNum, logicBlkNum, blkNums, key, keyType) {
+	let pointer = dxCommon.handleId("nfc", 'nfcid')
+	_validate('m1cardReadSector', taskFlg, secNum, logicBlkNum, blkNums, key, keyType, ' ')
+	return nfcObj.m1cardReadSector(pointer, taskFlg, secNum, logicBlkNum, blkNums, key, keyType);
+}
+
+/**
+ * NFC 璇籑1鍗℃墖鍖�
+ * @param {number} taskFlg 浠诲姟鏍囧織锛�
+ *                    0x00->AUTO 鍛婄煡鎵爜鍣ㄨ鎸囦护鍙崟鐙墽琛岋紝鏃犳寚浠ら棿鐨勪緷璧栧叧绯汇��
+ *                    0x01->START 鍛婄煡鎵爜鍣ㄥ紑濮嬪鍗℃搷浣滄垨瀵瑰崱鎿嶄綔灏氭湭缁撴潫锛屼笖鎸囦护闂村彲鑳藉瓨鍦ㄤ緷璧栧叧绯汇��
+ *                    0x02->FINISH 鍛婄煡鎵爜鍣ㄦ湰鏉℃寚浠ゆ槸鎿嶄綔鍗$殑鏈�鍚庝竴鏉℃寚浠わ紝灏嗗崱鐗囨搷浣滅幆澧冩仮澶嶅埌榛樻�併��
+ * @param {number} secNum 鎵囧尯鍙�
+ * @param {number} logicBlkNum 鍧楀彿锛堝湪鎵囧尯鍐呯殑閫昏緫鍙�0~3)
+ * @param {number} blkNums 鍧楁暟
+ * @param {array} key 瀵嗛挜, 闀垮害6bytes
+ * @param {number} keyType 瀵嗛挜绫诲瀷: A:0x60 B:0x61
+ * @param {array} data 鍐欏叆鏁版嵁
+ * @returns int 鍐欏叆闀垮害 -1:閿欒
+ */
+nfc.m1cardWriteSector = function (taskFlg, secNum, logicBlkNum, blkNums, key, keyType, data) {
+	let pointer = dxCommon.handleId("nfc", 'nfcid')
+	_validate('m1cardWriteSector', taskFlg, secNum, logicBlkNum, blkNums, key, keyType, data)
+	return nfcObj.m1cardWriteSector(pointer, taskFlg, secNum, logicBlkNum, blkNums, key, keyType, data);
+}
+
+/**
+ * 
+ * @param {number} taskFlg 浠诲姟鏍囧織锛�
+ *                    0x00->AUTO 鍛婄煡鎵爜鍣ㄨ鎸囦护鍙崟鐙墽琛岋紝鏃犳寚浠ら棿鐨勪緷璧栧叧绯汇��
+ *                    0x01->START 鍛婄煡鎵爜鍣ㄥ紑濮嬪鍗℃搷浣滄垨瀵瑰崱鎿嶄綔灏氭湭缁撴潫锛屼笖鎸囦护闂村彲鑳藉瓨鍦ㄤ緷璧栧叧绯汇��
+ *                    0x02->FINISH 鍛婄煡鎵爜鍣ㄦ湰鏉℃寚浠ゆ槸鎿嶄綔鍗$殑鏈�鍚庝竴鏉℃寚浠わ紝灏嗗崱鐗囨搷浣滅幆澧冩仮澶嶅埌榛樻�併��
+ * @param {number} blkNums 鍧楀彿
+ * @param {array} key 瀵嗛挜, 闀垮害6bytes
+ * @param {number} keyType 瀵嗛挜绫诲瀷: A:0x60 B:0x61
+ * @returns Array 璇诲彇缁撴灉 undefined:澶辫触
+ */
+nfc.m1cardReadBlk = function (taskFlg, blkNum, key, keyType) {
+	let pointer = dxCommon.handleId("nfc", 'nfcid')
+	_validate('m1cardReadBlk', taskFlg, 1, 0, blkNum, key, keyType, ' ')
+	return nfcObj.m1cardReadBlk(pointer, taskFlg, blkNum, key, keyType);
+}
+
+/**
+ * 
+ * @param {number} taskFlg 浠诲姟鏍囧織锛�
+ *                    0x00->AUTO 鍛婄煡鎵爜鍣ㄨ鎸囦护鍙崟鐙墽琛岋紝鏃犳寚浠ら棿鐨勪緷璧栧叧绯汇��
+ *                    0x01->START 鍛婄煡鎵爜鍣ㄥ紑濮嬪鍗℃搷浣滄垨瀵瑰崱鎿嶄綔灏氭湭缁撴潫锛屼笖鎸囦护闂村彲鑳藉瓨鍦ㄤ緷璧栧叧绯汇��
+ *                    0x02->FINISH 鍛婄煡鎵爜鍣ㄦ湰鏉℃寚浠ゆ槸鎿嶄綔鍗$殑鏈�鍚庝竴鏉℃寚浠わ紝灏嗗崱鐗囨搷浣滅幆澧冩仮澶嶅埌榛樻�併��
+ * @param {number} blkNums 鍧楀彿
+ * @param {array} key 瀵嗛挜, 闀垮害6bytes
+ * @param {number} keyType 瀵嗛挜绫诲瀷: A:0x60 B:0x61
+ * @param {array} data 鍐欏叆鏁版嵁
+ * @returns int 鍐欏叆闀垮害 -1:閿欒
+ */
+nfc.m1cardWriteBlk = function (taskFlg, blkNum, key, keyType, data) {
+	let pointer = dxCommon.handleId("nfc", 'nfcid')
+	_validate('m1cardWriteBlk', taskFlg, 1, 0, blkNum, key, keyType, data)
+	return nfcObj.m1cardWriteBlk(pointer, taskFlg, blkNum, key, keyType, data);
+}
+/**
+ * ATS妫�娴�
+ */
+nfc.nfc_iso14443_type_a_get_ats = function () {
+	let pointer = dxCommon.handleId("nfc", 'nfcid')
+	return nfcObj.nfc_iso14443_type_a_get_ats(pointer)
+}
+
+/**
+ * 
+ * @param {number} taskFlg 浠诲姟鏍囧織锛�
+ *                    0x00->AUTO 鍛婄煡鎵爜鍣ㄨ鎸囦护鍙崟鐙墽琛岋紝鏃犳寚浠ら棿鐨勪緷璧栧叧绯汇��
+ *                    0x01->START 鍛婄煡鎵爜鍣ㄥ紑濮嬪鍗℃搷浣滄垨瀵瑰崱鎿嶄綔灏氭湭缁撴潫锛屼笖鎸囦护闂村彲鑳藉瓨鍦ㄤ緷璧栧叧绯汇��
+ *                    0x02->FINISH 鍛婄煡鎵爜鍣ㄦ湰鏉℃寚浠ゆ槸鎿嶄綔鍗$殑鏈�鍚庝竴鏉℃寚浠わ紝灏嗗崱鐗囨搷浣滅幆澧冩仮澶嶅埌榛樻�併��
+ * @param {ArrayBuffer} buffer 	瑕佸彂閫佺殑鏁版嵁
+ * @param {number} bufferLen 	瑕佸彂閫佺殑鏁版嵁闀垮害
+ * @returns buffer
+ */
+nfc.iso14443Apdu = function (taskFlg, buffer, bufferLen) {
+	let pointer = dxCommon.handleId("nfc", "nfcid")
+	return nfcObj.iso14443Apdu(pointer, taskFlg, buffer, bufferLen);
+}
+
+/**
+ * PSAM鍗℃柇鐢�
+ */
+nfc.nfcPsamPowerDown = function () {
+	let pointer = dxCommon.handleId("nfc", "nfcid")
+	return nfcObj.nfcPsamPowerDown(pointer);
+}
+
+/**
+ * NFC 鏀瑰彉鐘舵��
+ */
+nfc.nfcPsamChangeBaud = function () {
+	let pointer = dxCommon.handleId("nfc", "nfcid")
+	return nfcObj.nfcPsamChangeBaud(pointer);
+}
+
+/**
+ * PSAM鍗¢噸缃�
+ */
+nfc.nfcPsamCardReset = function (force) {
+	let pointer = dxCommon.handleId("nfc", "nfcid")
+	return nfcObj.nfcPsamCardReset(pointer, force);
+}
+
+/**
+ * 鍙戦�丳SAM APDU鎸囦护
+ */
+nfc.nfcPsamCardApdu = function (buffer) {
+	let pointer = dxCommon.handleId("nfc", "nfcid")
+	return nfcObj.nfcPsamCardApdu(pointer, buffer);
+}
+
+/**
+ * EID 鏇存柊浜戣瘉閰嶇疆
+ * @param {object} eidConfig 浜戣瘉閰嶇疆		
+ * 		@param {string} eidConfig.appid 骞冲彴鍒嗛厤缁欏簲鐢ㄧ殑appid
+ * 		@param {number} eidConfig.read_len; // 鍗曟璇诲崱闀垮害锛岄粯璁�0x80
+ * 		@param {number} eidConfig.declevel; // 鏄惁璇诲彇鐓х墖锛�1涓轰笉璇诲彇锛�2涓鸿鍙�
+ * 		@param {number} eidConfig.loglevel; //鏃ュ織绾у埆锛屾敮鎸�0锛�1锛�2
+ * 		@param {number} eidConfig.model; // 鏄惁鐩存帴鏌ュ嚭淇℃伅 0鏄�  1鍚� 锛堝嵆0鏄師璺繑鍥烇紝杩斿洖韬唤淇℃伅锛�1鏄浆鍙戯紝杩斿洖reqid锛�
+ * 		@param {number} eidConfig.type; // 鍗$墖绫诲瀷锛�0 韬唤璇� 1鐢靛瓙璇佺収
+ * 		@param {number} eidConfig.pic_type; // 鐓х墖瑙g爜鏁版嵁绫诲瀷 0 wlt 1 jpg
+ * 		@param {number} eidConfig.envCode; // 鐜璇嗗埆鐮�
+ * 		@param {string} eidConfig.sn[128]; // 璁惧搴忓垪鍙�
+ * 		@param {string} eidConfig.device_model[128]; // 璁惧鍨嬪彿
+ * 		@param {number} eidConfig.info_type; // 淇℃伅杩斿洖绫诲瀷锛�0 韬唤淇℃伅缁撴瀯浣� 锛�1鍘熷鏁版嵁 char   
+ */
+nfc.eidUpdateConfig = function (eidConfig) {
+	if (eidConfig == null) {
+		throw new Error("eidUpdateConfig:eidConfig should not be null or empty")
+	}
+	return nfcObj.eidUpdateConfig(eidConfig);
+}
+
+/**
+ * 璇籒TAG鐗堟湰鍙�
+ * 	@param {number} 		hdl               	nfc鍙ユ焺
+ * 	@returns {ArrayBuffer} buffer
+ */
+nfc.nfcNtagReadVersion = function () {
+	let pointer = dxCommon.handleId("nfc", 'nfcid')
+	return nfcObj.nfcNtagReadVersion(pointer);
+}
+
+/**
+ * 璇籒TAG椤靛唴瀹� 鍥哄畾璇诲彇4椤靛叡16瀛楄妭
+ * 	@param {number} 		hdl               	nfc鍙ユ焺
+ * 	@param {number} 		pageNum           	璧峰椤靛湴鍧�锛�
+ *                             						姣忔璇诲彇鍥涗釜椤�
+ *                             						濡傛灉鍦板潃(Addr)鏄�04h锛屽垯杩斿洖椤�04h銆�05h銆�06h銆�07h鍐呭
+ * 	@returns {ArrayBuffer} buffer
+ */
+nfc.nfcNtagReadPage = function (pageNum) {
+	let pointer = dxCommon.handleId("nfc", 'nfcid')
+	if (pageNum == null) {
+		throw new Error("nfcNtagReadPage:pageNum should not be null or empty")
+	}
+	return nfcObj.nfcNtagReadPage(pointer, pageNum);
+}
+
+/**
+ * 璇籒TAG澶氶〉鍐呭 璇诲彇鏁版嵁鐨刡uffer,鏈�灏忎负 椤垫暟*4锛涜璇诲彇鐨勬暟鎹暱搴� 椤垫暟*4
+ * 	@param {number} 		hdl               	nfc鍙ユ焺
+* 	@param {number} 		start_addr          璧峰椤靛湴鍧�
+ * 	@param {number} 		end_addr            缁撴潫椤靛湴鍧�         	
+ * 	@returns {ArrayBuffer} buffer
+ */
+nfc.nfcNtagFastReadPage = function (start_page, end_page) {
+	let pointer = dxCommon.handleId("nfc", 'nfcid')
+	if (start_page == null) {
+		throw new Error("nfcNtagFastReadPage:start_page should not be null or empty")
+	}
+	if (end_page == null) {
+		throw new Error("nfcNtagFastReadPage:end_page should not be null or empty")
+	}
+	return nfcObj.nfcNtagFastReadPage(pointer, start_page, end_page);
+}
+
+/**
+ * 鍐橬TAG椤靛唴瀹�
+ * 	@param {number} 		hdl               	nfc鍙ユ焺
+ * 	@param {number} 		pageNum           	鍐欏叆鐨勯〉鍙� 锛氭湁鏁圓ddr鍙傛暟
+ *                              				瀵逛簬NTAG213锛岄〉鍦板潃02h鑷�2Ch
+ *                              				瀵逛簬NTAG215锛岄〉鍦板潃02h鑷�86h
+ *                              				瀵逛簬NTAG216锛岄〉鍦板潃02h鑷矱6h
+ * 	@param {ArrayBuffer} 	pageData         	鍐欏叆椤电殑鍐呭锛氬洓瀛楄妭
+ * 	@returns {boolean} ture/false
+ */
+nfc.nfcNtagWritePage = function (pageNum, pageData) {
+	let pointer = dxCommon.handleId("nfc", 'nfcid')
+	if (pageNum == null) {
+		throw new Error("nfcNtagWritePage:pageNum should not be null or empty")
+	}
+	if (!pageData) {
+		throw new Error("nfcNtagWritePage:pageData should not be null or empty")
+	}
+	return nfcObj.nfcNtagWritePage(pointer, pageNum, pageData);
+}
+
+/**
+ * 鍒ゆ柇nfc娑堟伅闃熷垪鏄惁涓虹┖
+ * @returns bool
+ */
+nfc.msgIsEmpty = function () {
+	let pointer = dxCommon.handleId("nfc", 'nfcid')
+	return nfcObj.msgIsEmpty(pointer)
+}
+
+/**
+ * 浠巒fc娑堟伅闃熷垪涓鍙栨暟鎹�
+ * @returns json娑堟伅瀵硅薄
+ */
+nfc.msgReceive = function () {
+	let pointer = dxCommon.handleId("nfc", 'nfcid')
+	let msg = nfcObj.msgReceive(pointer)
+	return JSON.parse(msg);
+}
+
+function _validate(fun, taskFlg, secNum, logicBlkNum, blkNums, key, keyType, data) {
+	if (![0x00, 0x01, 0x02].includes(taskFlg)) {
+		throw new Error(fun, ":taskFlg error")
+	}
+	if (!(secNum >= 0)) {
+		throw new Error(fun, ":secNum error")
+	}
+	if (logicBlkNum == null || logicBlkNum == undefined || logicBlkNum < 0 || logicBlkNum > 3) {
+		throw new Error(fun, ":logicBlkNum error")
+	}
+	if (blkNums == null || blkNums == undefined || blkNums < 0 || blkNums > 59) {
+		throw new Error(fun, ":blkNums error")
+	}
+	if (key == null || key === undefined || key.length < 0) {
+		throw new Error(fun, ":key error")
+	}
+	if (![0x60, 0x61].includes(keyType)) {
+		throw new Error(fun, ":keyType error")
+	}
+	if (data === null || data === undefined) {
+		throw new Error(fun, ":data error")
+	}
+}
+
+nfc.RECEIVE_MSG = '__nfc__MsgReceive'
+
+/**
+ * 绠�鍖朜FC缁勪欢鐨勪娇鐢紝鏃犻渶杞鍘昏幏鍙栫綉缁滅姸鎬侊紝缃戠粶鐨勭姸鎬佷細閫氳繃eventcenter鍙戦�佸嚭鍘�
+ * run 鍙細鎵ц涓�娆★紝鎵ц涔嬪悗缃戠粶鍩烘湰閰嶇疆涓嶈兘淇敼
+ * 濡傛灉闇�瑕佸疄鏃惰幏鍙栧埛鍗℃暟鎹紝鍙互璁㈤槄 eventCenter鐨勪簨浠讹紝浜嬩欢鐨則opic鏄痭fc.CARD锛屼簨浠剁殑鍐呭鏄被浼�
+ * {id:'鍗d',card_type:鍗¤姱鐗囩被鍨�,id_len:鍗″彿闀垮害,type锛氬崱绫诲瀷,timestamp:'鍒峰崱鏃堕棿鎴�',monotonic_timestamp:'鐩稿寮�鏈虹殑鏃堕棿'}
+ * @param {*} options 
+ * 		@param {boolean} options.m1 闈炲繀濉紝鏅�氬崱鍥炶皟寮�鍏�
+ * 		@param {boolean} options.psam 闈炲繀濉紝psam鍗″洖璋冨紑鍏�
+ */
+nfc.run = function (options) {
+	if (options === undefined || options.length === 0) {
+		throw new Error("dxnfc.run:'options' parameter should not be null or empty")
+	}
+	let init = map.get("__nfc__run_init")
+	if (!init) {//纭繚鍙垵濮嬪寲涓�娆�
+		map.put("__nfc__run_init", options)
+		bus.newWorker("__nfc", '/app/code/dxmodules/nfcWorker.js')
+	}
+}
+
+/**
+ * 濡傛灉nfc鍗曠嫭涓�涓嚎绋嬶紝鍙互鐩存帴浣跨敤run鍑芥暟锛屼細鑷姩鍚姩涓�涓嚎绋嬶紝
+ * 濡傛灉鎯冲姞鍏ュ埌鍏朵粬宸叉湁鐨勭嚎绋嬶紝鍙互浣跨敤浠ヤ笅灏佽鐨勫嚱鏁�
+ */
+nfc.worker = {
+	//鍦╳hile寰幆鍓�
+	beforeLoop: function (options) {
+		nfc.init(options.useEid)
+		// PSAM鍜屾櫘閫氬崱鍥炶皟
+		if (options.m1) {
+			nfc.cbRegister()
+		}
+		if (options.psam) {
+			nfc.psamCbRegister()
+		}
+	},
+	//鍦╳hile寰幆閲�
+	loop: function () {
+		if (!nfc.msgIsEmpty()) {
+			let res = nfc.msgReceive();
+			bus.fire(nfc.RECEIVE_MSG, res)
+		}
+	}
+}
+export default nfc;
diff --git a/vf205_access/dxmodules/dxNtp.js b/vf205_access/dxmodules/dxNtp.js
new file mode 100644
index 0000000..1e79146
--- /dev/null
+++ b/vf205_access/dxmodules/dxNtp.js
@@ -0,0 +1,63 @@
+//build: 20240523
+//鍚屾鏃堕棿,杩愯鏃堕渶瑕佹妸杩欎釜缁勪欢鍔犺浇鍒颁竴涓嚎绋嬮噷鐨剋hile寰幆,
+//缂虹渷姣忛殧24灏忔椂鍚屾涓�娆★紝涔熸敮鎸佷簨浠惰Е鍙戜富鍔ㄥ悓姝� eventcetner.fire(ntp.MANUAL_SYNC)
+//渚濊禆缁勪欢 dxLogger,dxCommon,dxCenter
+
+import common from "./dxCommon.js"
+import dxNet from './dxNet.js'
+import log from './dxLogger.js'
+const ntp = {}
+/**
+ * 鍚屾鏃堕棿寰幆鍒濆鍖�
+ * @param {string} server 鍚屾鏃堕棿鏈嶅姟鍣ㄥ湴鍧�锛岀己鐪佹槸182.92.12.11 
+ * @param {number} interval 鍚屾鏃堕棿鐨勯棿闅旓紝鍗曚綅鏄垎閽燂紝缂虹渷鏄�24灏忔椂鍚屾涓�娆�
+ * 
+ */
+ntp.beforeLoop = function (server = '182.92.12.11', interval = 24 * 60) {
+    this.server = server
+    this.interval = interval
+    this.tempinterval = 1000//绗竴娆¢殧1绉掑氨寮�濮嬬涓�娆″鏃�
+    this.last = new Date().getTime()
+}
+/**
+ * 鏇存柊鏃跺尯GMT锛屾瘮濡�8锛岃〃绀篏MT8鍖椾含鏃堕棿
+ * @param {number} gmt  鍙栧�艰寖鍥存槸0,1,2....24琛ㄧず鏃跺尯锛�
+ */
+ntp.updateGmt = function (gmt) {
+    if (gmt != undefined && gmt != null) {
+        let cmd = `cp /etc/localtimes/localtime${gmt} /etc/localtime`
+        common.systemBrief(cmd)
+    }
+}
+/**
+ * 绔嬪埢鍚屾
+ */
+ntp.syncnow = false
+/**
+ * 鍚屾鏃堕棿
+ */
+ntp.loop = function () {
+    if (!dxNet.getStatus().connected) {//娌℃湁缃戠粶
+        return
+    }
+    const now = new Date().getTime()
+    const minus = now - this.last
+    if (ntp.syncnow || (minus > (this.tempinterval))) {
+        ntp.syncnow = false
+        let cmd = `ntpdate -u -t 1 '${this.server}' > /dev/null && echo 'Y' || echo 'N'`
+        let res = common.systemWithRes(cmd, 100).split(/\s/)[0]
+        if (res != "Y" ) {
+            // 瀵规椂澶辫触锛�1鍒嗗悗閲嶈瘯
+            log.error('ntp sync failed')
+            this.tempinterval = 60 * 1000
+        } else {
+            // 瀵规椂鎴愬姛
+            log.info('ntp sync success')
+            this.tempinterval = this.interval * 60 * 1000
+            common.systemBrief("hwclock -u -w")
+        }
+        this.last = new Date().getTime()
+    }
+}
+
+export default ntp;
\ No newline at end of file
diff --git a/vf205_access/dxmodules/dxOta.js b/vf205_access/dxmodules/dxOta.js
new file mode 100644
index 0000000..a0061ee
--- /dev/null
+++ b/vf205_access/dxmodules/dxOta.js
@@ -0,0 +1,256 @@
+//build:20240724
+// 璐熻矗鍥轰欢鐨勫崌绾�
+import log from './dxLogger.js'
+import com from './dxCommon.js'
+import http from './dxHttp.js'
+import * as os from 'os';
+
+const ota = {}
+//鑾峰彇褰撳墠纾佺洏鍓╀綑澶у皬锛坘锛夊彲鑳戒笉鍚岀殑鎿嶄綔绯荤粺鎸囦护涓嶄竴鏍�
+ota.DF_CMD = `df -k / | awk 'NR==2 {print $4}'`
+ota.OTA_ROOT = '/ota'
+ota.OTA_RUN = ota.OTA_ROOT + '/run.sh'
+
+
+/**
+ * HTTP鍗囩骇锛氱綉缁滀笅杞藉崌绾у寘鍗囩骇
+ * @param {string} url 蹇呭~锛屼笅杞藉崌绾у寘鐨刪ttp url鍦板潃 
+ * @param {string} md5 蹇呭~锛屽崌绾у寘鐨刴d5鏍囪瘑锛屼笅杞藉畬閫氳繃md5鏉ュ垽鏂槸鍚﹀畬鏁淬��32闀垮害鐨勫叏灏忓啓16杩涘埗瀛楃涓�
+ * @param {number} size 闈炲繀濉紝鍗囩骇鍖呯殑澶ф澶у皬锛屽崟浣嶆槸k锛屽鏋滄枃浠跺お澶ц�屽墿浣欑鐩樹笉澶燂紝浼氭彁鍓嶆姤閿欒锛屼笉浼氬紑濮嬪惎鍔ㄤ笅杞� 
+ * @param {number} timeout 闈炲繀濉紝灏濊瘯閾炬帴涓嬭浇鍦板潃鐨勮秴鏃舵椂闂达紙涓嶆槸涓嬭浇瀹屾垚鐨勬椂闂达級锛岀己鐪佹槸3绉�
+ * @param {string} password 闈炲繀濉紝涓嬭浇瀹夎鍖呯殑瀵嗙爜锛屽彲閫夛紝濡傛灉璁剧疆锛屼笅杞芥椂闇�瑕佽緭鍏ュ瘑鐮�
+ */
+ota.updateHttp = function (url, md5, timeout = 3, password, size) {
+    if (!url || !md5) {
+        throw new Error("The 'url' and 'md5' param should not be null")
+    }
+    if (size && (typeof size != 'number')) {
+        throw new Error("The 'size' param should be a number")
+    }
+    //1. 鏌ョ湅纾佺洏杩樺墿浣欑殑澶у皬
+    let df = parseInt(com.systemWithRes(ota.DF_CMD, 1000))
+    if (size) {
+        if (df < (3 * size)) {//澶ф鏈湴蹇呴』鏈夊畨瑁呭寘3鍊嶅ぇ灏忕殑绌洪棿
+            throw new Error('The upgrade package is too large, and not be enough space on the disk to download it')
+        }
+    }
+    //2. 涓嬭浇鏂囦欢鍒颁复鏃剁洰褰�
+    const firmware = '/upgrades.zip'
+    const temp = '/upgrades.temp'
+    com.systemBrief(`rm -rf ${firmware} && rm -rf ${temp} `) //鍏堝垹闄ta鏍圭洰褰�
+    
+    let downloadRet = http.download(url + (password ? "&password=" + password : '') , temp, null, timeout*1000)
+    let fileExist = (os.stat(temp)[1] === 0)
+    if (!fileExist) {
+        log.error("download result" + downloadRet)
+        com.systemBrief(`rm -rf ${firmware} && rm -rf ${temp} `)
+        throw new Error('Download failed, please check the url:' + url)
+    }
+    //3. 璁$畻骞舵瘮杈僲d5鏄惁涓�鏍�
+    let md5Hash = com.md5HashFile(temp)
+    md5Hash = md5Hash.map(v => v.toString(16).padStart(2, 0)).join('')
+    if (md5Hash != md5) {
+        com.systemBrief(`rm -rf ${firmware} && rm -rf ${temp} `)
+        throw new Error('Download failed with wrong md5 value')
+    }
+    //4. md5鏍¢獙閫氳繃锛屽皢鍗囩骇鍖呮斁鍒板崌绾х洰褰曚笅锛岀瓑寰呴噸鍚崌绾�
+    com.systemBrief(`mv ${temp} ${firmware} `)
+}
+
+
+/**
+ * 鏂囦欢鍗囩骇锛氶�氳繃鍏朵粬鏂瑰紡灏嗗崌绾у寘鏀惧埌鐢ㄦ埛鐩綍涓嬶紝璋冪敤姝ゆ柟娉曞崌绾�
+ * @param {string} path 蹇呭~锛屼笅杞藉崌绾у寘鐨刪ttp url鍦板潃 
+ * @param {string} md5 蹇呭~锛屽崌绾у寘鐨刴d5鏍囪瘑锛屼笅杞藉畬閫氳繃md5鏉ュ垽鏂槸鍚﹀畬鏁淬��32闀垮害鐨勫叏灏忓啓16杩涘埗瀛楃涓�
+ * @param {number} size 闈炲繀濉紝鍗囩骇鍖呯殑澶ф澶у皬锛屽崟浣嶆槸k锛屽鏋滄枃浠跺お澶ц�屽墿浣欑鐩樹笉澶燂紝浼氭彁鍓嶆姤閿欒锛屼笉浼氬紑濮嬪惎鍔ㄤ笅杞� 
+ */
+ota.updateFile = function (path, md5, size) {
+    if (!path || !md5) {
+        throw new Error("The 'path' and 'md5' param should not be null")
+    }
+    if (size && (typeof size != 'number')) {
+        throw new Error("The 'size' param should be a number")
+    }
+
+    //1. 鏌ョ湅纾佺洏杩樺墿浣欑殑澶у皬
+    let df = parseInt(com.systemWithRes(ota.DF_CMD, 1000))
+    if (size) {
+        if (df < (3 * size)) {//澶ф鏈湴蹇呴』鏈夊畨瑁呭寘3鍊嶅ぇ灏忕殑绌洪棿
+            throw new Error('The upgrade package is too large, and not be enough space on the disk to download it')
+        }
+    }
+    
+    //2. 璁$畻骞舵瘮杈僲d5鏄惁涓�鏍�
+    let md5Hash = com.md5HashFile(path)
+    md5Hash = md5Hash.map(v => v.toString(16).padStart(2, 0)).join('')
+    if (md5Hash != md5) {
+        throw new Error('With wrong md5 value')
+    }
+    
+    //3. md5鏍¢獙閫氳繃锛屽皢鍗囩骇鍖呮斁鍒板崌绾х洰褰曚笅锛岀瓑寰呴噸鍚崌绾�
+    const firmware = '/upgrades.zip'
+    com.systemBrief(`mv ${path} ${firmware} `)
+}
+
+
+/**
+ * 娉ㄦ剰锛氭鏂规硶鍗冲皢杩囨湡锛岀敤浜庡吋瀹规棫鐗堟湰锛屾柊鐗堟湰涓嶆帹鑽愪娇鐢�
+ * 鍗囩骇鍒嗕簩澶ф楠わ紝绗竴姝ユ槸鍦ㄥ簲鐢ㄧ涓嬭浇鍗囩骇鍖咃紙zip锛夛紝瑙e帇鍗囩骇鍖�
+ * 绗簩姝ュ寘鎷噸鍚澶囷紝鍒╃敤鑴氭湰澶嶅埗鐩綍鍜屾枃浠舵垨棰濆涓�浜涙搷浣�
+ * 濡傛灉鍦ㄥ崌绾у寘鏍圭洰褰曚笅鏀句竴涓猚ustom_update.sh,灏变細鍏堟墽琛岃繖涓猻hell鏂囦欢锛屾垜浠彲浠ュ湪杩欎釜鏂囦欢閲屾斁涓�浜涜嚜瀹氫箟鐨勫崌绾у姩浣�
+ * @param {string} url 蹇呭~锛屼笅杞藉崌绾у寘鐨刪ttp url鍦板潃 
+ * @param {string} md5 蹇呭~锛屽崌绾у寘鐨刴d5鏍囪瘑锛屼笅杞藉畬閫氳繃md5鏉ュ垽鏂槸鍚﹀畬鏁淬��32闀垮害鐨勫叏灏忓啓16杩涘埗瀛楃涓�
+ * @param {number} size 闈炲繀濉紝鍗囩骇鍖呯殑澶ф澶у皬锛屽崟浣嶆槸k锛屽鏋滄枃浠跺お澶ц�屽墿浣欑鐩樹笉澶燂紝浼氭彁鍓嶆姤閿欒锛屼笉浼氬紑濮嬪惎鍔ㄤ笅杞� 
+ * @param {string} shell 闈炲繀濉紝閲嶅惎璁惧鍚庣殑鍗囩骇鑴氭湰鍐呭锛岃В鍘嬪悗鐨勬枃浠跺す缂虹渷鏄� /ota/temp,鍗囩骇浼氱己鐪佹妸/ota/temp涓嬫墍鏈夋枃浠舵嫹璐濆鍒跺埌/app/code/涓�
+ * @param {number} timeout 闈炲繀濉紝灏濊瘯閾炬帴涓嬭浇鍦板潃鐨勮秴鏃舵椂闂达紙涓嶆槸涓嬭浇瀹屾垚鐨勬椂闂达級锛岀己鐪佹槸3绉�
+ */
+ota.update = function (url, md5, size, shell, timeout = 3) {
+    if (!url || !md5) {
+        throw new Error("The 'url' and 'md5' param should not be null")
+    }
+    if (size && (typeof size != 'number')) {
+        throw new Error("The 'size' param should be a number")
+    }
+    //1. 鏌ョ湅纾佺洏杩樺墿浣欑殑澶у皬
+    let df = parseInt(com.systemWithRes(ota.DF_CMD, 1000))
+    if (size) {
+        if (df < (3 * size)) {//澶ф鏈湴蹇呴』鏈夊畨瑁呭寘3鍊嶅ぇ灏忕殑绌洪棿
+            throw new Error('The upgrade package is too large, and not be enough space on the disk to download it')
+        }
+    }
+    //2. 涓嬭浇鏂囦欢鍒扮壒瀹氱洰褰�
+    const firmware = ota.OTA_ROOT + '/download.zip'
+    const temp = ota.OTA_ROOT + '/temp'
+    com.systemBrief(`rm -rf ${ota.OTA_ROOT} && mkdir ${ota.OTA_ROOT} `) //鍏堝垹闄ta鏍圭洰褰�
+    let download = `wget --no-check-certificate --timeout=${timeout} -c "${url}" -O ${firmware} 2>&1`
+    com.systemBrief(download, 1000)
+    let fileExist = (os.stat(firmware)[1] === 0)
+    let downloadRet
+    if (!fileExist) {
+        downloadRet = http.download(url, firmware, null, timeout*1000)
+    }
+    fileExist = (os.stat(firmware)[1] === 0)
+    if (!fileExist) {
+        log.error("download result" + downloadRet)
+        throw new Error('Download failed, please check the url:' + url)
+    }
+    //3. 璁$畻骞舵瘮杈僲d5鏄惁涓�鏍�
+    let md5Hash = com.md5HashFile(firmware)
+    md5Hash = md5Hash.map(v => v.toString(16).padStart(2, 0)).join('')
+    if (md5Hash != md5) {
+        log.error("download result" + downloadRet)
+        throw new Error('Download failed with wrong md5 value')
+    }
+    //4. 瑙e帇
+    com.systemBrief(`mkdir ${temp} && unzip -o ${firmware} -d ${temp}`)
+    //5. 鎵ц鑷畾涔夌殑鍗囩骇鑴氭湰
+    const custom_update = temp+'/custom_update.sh'
+    if(os.stat(custom_update)[1] === 0){
+        com.systemBrief(`chmod +x ${custom_update}`)
+        com.systemWithRes(`${custom_update}`)
+    }
+    //6. 鏋勫缓鑴氭湰鏂囦欢
+    if (!shell) {
+        //缂虹渷鍙槸鎷疯礉鐩綍骞跺垹闄ta鏍圭洰褰�
+        shell = `cp -r ${temp}/* /app/code \n rm -rf ${ota.OTA_ROOT}`
+    }
+
+    com.systemBrief(`echo "${shell}" > ${ota.OTA_RUN} && chmod +x ${ota.OTA_RUN}`)
+    fileExist = (os.stat(ota.OTA_RUN)[1] === 0)
+    if (!fileExist) {
+        throw new Error('Build shell file failed')
+    }
+    com.systemWithRes(`${ota.OTA_RUN}`)
+}
+
+/**
+ * 娉ㄦ剰锛氭鏂规硶鍗冲皢杩囨湡锛岀敤浜庡吋瀹规棫鐗堟湰锛屾柊鐗堟湰涓嶆帹鑽愪娇鐢�
+ * 鐗规畩锛氬吋瀹规棫鐨勫崌绾ф牸寮忥紝蹇呴』鏄痶ar.xz鏍煎紡锛屼笖鍙敤鏉ュ崌绾ц祫婧愭枃浠�
+ * 鍗囩骇鍒嗕簩澶ф楠わ紝绗竴姝ユ槸鍦ㄥ簲鐢ㄧ涓嬭浇鍗囩骇鍖咃紙zip锛夛紝瑙e帇鍗囩骇鍖�
+ * 绗簩姝ュ寘鎷噸鍚澶囷紝鍒╃敤鑴氭湰澶嶅埗鐩綍鍜屾枃浠舵垨棰濆涓�浜涙搷浣�
+ * 濡傛灉鍦ㄥ崌绾у寘鏍圭洰褰曚笅鏀句竴涓猚ustom_update.sh,灏变細鍏堟墽琛岃繖涓猻hell鏂囦欢锛屾垜浠彲浠ュ湪杩欎釜鏂囦欢閲屾斁涓�浜涜嚜瀹氫箟鐨勫崌绾у姩浣�
+ * @param {string} url 蹇呭~锛屼笅杞藉崌绾у寘鐨刪ttp url鍦板潃 
+ * @param {string} md5 蹇呭~锛屽崌绾у寘鐨刴d5鏍囪瘑锛屼笅杞藉畬閫氳繃md5鏉ュ垽鏂槸鍚﹀畬鏁淬��32闀垮害鐨勫叏灏忓啓16杩涘埗瀛楃涓�
+ * @param {number} size 闈炲繀濉紝鍗囩骇鍖呯殑澶ф澶у皬锛屽崟浣嶆槸k锛屽鏋滄枃浠跺お澶ц�屽墿浣欑鐩樹笉澶燂紝浼氭彁鍓嶆姤閿欒锛屼笉浼氬紑濮嬪惎鍔ㄤ笅杞� 
+ * @param {string} shell 闈炲繀濉紝閲嶅惎璁惧鍚庣殑鍗囩骇鑴氭湰鍐呭锛岃В鍘嬪悗鐨勬枃浠跺す缂虹渷鏄� /ota/temp,鍗囩骇浼氱己鐪佹妸/ota/temp涓嬫墍鏈夋枃浠舵嫹璐濆鍒跺埌/app/code/涓�
+ * @param {number} timeout 闈炲繀濉紝灏濊瘯閾炬帴涓嬭浇鍦板潃鐨勮秴鏃舵椂闂达紙涓嶆槸涓嬭浇瀹屾垚鐨勬椂闂达級锛岀己鐪佹槸3绉�
+ */
+ota.updateResource = function (url, md5, size, shell, timeout = 3) {
+    if (!url || !md5) {
+        throw new Error("The 'url' and 'md5' param should not be null")
+    }
+    if (size && (typeof size != 'number')) {
+        throw new Error("The 'size' param should be a number")
+    }
+    //1. 鏌ョ湅纾佺洏杩樺墿浣欑殑澶у皬
+    let df = parseInt(com.systemWithRes(ota.DF_CMD, 1000))
+    if (size) {
+        if (df < (3 * size)) {//澶ф鏈湴蹇呴』鏈夊畨瑁呭寘3鍊嶅ぇ灏忕殑绌洪棿
+            throw new Error('The upgrade package is too large, and not be enough space on the disk to download it')
+        }
+    }
+    //2. 涓嬭浇鏂囦欢鍒扮壒瀹氱洰褰�
+    const firmware = ota.OTA_ROOT + '/download.tar.xz'
+    const temp = ota.OTA_ROOT + '/temp'
+    com.systemBrief(`rm -rf ${ota.OTA_ROOT} && mkdir ${ota.OTA_ROOT} `) //鍏堝垹闄ta鏍圭洰褰�
+    let download = `wget --no-check-certificate --timeout=${timeout} -c "${url}" -O ${firmware} 2>&1`
+    com.systemBrief(download, 1000)
+    let fileExist = (os.stat(firmware)[1] === 0)
+    if (!fileExist) {
+        http.download(url, firmware, null, timeout*1000)
+    }
+    fileExist = (os.stat(firmware)[1] === 0)
+    if (!fileExist) {
+        throw new Error('Download failed, please check the url:' + url)
+    }
+
+    //3. 璁$畻骞舵瘮杈僲d5鏄惁涓�鏍�
+    let md5Hash = com.md5HashFile(firmware)
+    md5Hash = md5Hash.map(v => v.toString(16).padStart(2, 0)).join('')
+    if (md5Hash != md5) {
+        throw new Error('Download failed with wrong md5 value')
+    }
+    //4. 瑙e帇
+    //tar -xJvf test.tar.xz -C /path/
+    com.systemBrief(`mkdir ${temp} && tar -xJvf ${firmware} -C ${temp}`)
+    //5. 鏋勫缓鑴氭湰鏂囦欢
+    if (!shell) {
+        shell = `
+        source=${temp}/vgapp/res/image/bk.png
+        target=/app/code/resource/image/bg.png
+        if test -e "\\$source"; then
+            cp "\\$source" "\\$target"
+        fi
+        source=${temp}/vgapp/res/image/bk_90.png
+        target=/app/code/resource/image/bg_90.png
+        if test -e "\\$source"; then
+            cp "\\$source" "\\$target"
+        fi
+        source=${temp}/vgapp/res/font/AlibabaPuHuiTi-2-65-Medium.ttf
+        target=/app/code/resource/font.ttf
+        if test -e "\\$source"; then
+            cp "\\$source" "\\$target"
+        fi
+        source=${temp}/vgapp/wav/*.wav
+        target=/app/code/resource/wav/
+        cp "\\$source" "\\$target"
+        rm -rf ${ota.OTA_ROOT}
+        `
+    }
+
+    com.systemBrief(`echo "${shell}" > ${ota.OTA_RUN} && chmod +x ${ota.OTA_RUN}`)
+    fileExist = (os.stat(ota.OTA_RUN)[1] === 0)
+    if (!fileExist) {
+        throw new Error('Build shell file failed')
+    }
+    com.systemWithRes(`${ota.OTA_RUN}`)
+}
+/**
+ * 鐢辫皟鐢ㄨ�呮潵鍚姩閲嶅惎锛屼竴鑸槸update鍑芥暟娌℃湁閿欒锛岃繍琛屽畬鎴愬苟鍚戝寳鍚戞眹鎶ョ粨鏋滃悗鍐嶈皟鐢ㄩ噸鍚�
+ */
+ota.reboot = function () {
+    com.asyncReboot(2)
+}
+//-------------------------private-------------------
+
+export default ota
\ No newline at end of file
diff --git a/vf205_access/dxmodules/dxPwm.js b/vf205_access/dxmodules/dxPwm.js
new file mode 100644
index 0000000..25a709f
--- /dev/null
+++ b/vf205_access/dxmodules/dxPwm.js
@@ -0,0 +1,116 @@
+// build : 20240419
+// PWM浠h〃鑴夊啿瀹藉害璋冨埗锛圥ulse Width Modulation锛夎鐢ㄦ潵妯℃嫙杈撳嚭鐢靛帇鎴栧姛鐜囷紝浠ユ帶鍒惰渹楦e櫒銆佺數鏈虹殑閫熷害銆丩ED鐨勪寒搴︺�佹俯搴﹁皟鑺傚櫒鐨勬俯搴︾瓑绛�
+import { pwmClass } from './libvbar-b-dxpwm.so'
+import * as os from "os"
+const pwmObj = new pwmClass();
+
+const pwm = {}
+
+/**
+ * 鐢宠pwm閫氶亾,鐢宠涓�娆″嵆鍙�
+ * @param {number} channel 鐢宠鐨勯�氶亾鍙凤紝鏀寔0~7閫氶亾
+ * @returns true/false
+ */
+pwm.request = function (channel) {
+	return pwmObj.request(channel)
+}
+/**
+ * 璁剧疆PWM妯″紡
+ * @param {number} mode  
+	0 --> CPU mode,杩炵画娉㈠舰.
+	1 --> DMA mode,鎸囧畾鏁伴噺鐨勬尝褰�.
+	2 --> DMA mode,杩炵画娉㈠舰.
+ * @returns true/false
+ */
+pwm.setMode = function (mode) {
+	return pwmObj.setMode(mode)
+}
+/**
+ * 璁剧疆PWM鍛ㄦ湡 鏄寚涓�涓畬鏁寸殑PWM淇″彿鍛ㄦ湡鎵�鑺辫垂鐨勬椂闂�
+ * @param {number} periodNs  寰呰缃殑PWM鍛ㄦ湡鍊�(鍗曚綅: ns)
+ * @returns true/false
+ */
+pwm.setPeriod = function (periodNs) {
+	return pwmObj.setPeriod(periodNs)
+}
+/**
+ * 璁剧疆PWM鍗犵┖姣� 鏄寚楂樼數骞筹紙鑴夊啿锛夊湪涓�涓畬鏁寸殑鍛ㄦ湡鍐呮墍鍗犵殑鏃堕棿
+ * @param {number} dutyNs  寰呰缃殑PWM鍗犵┖姣�(璁剧疆楂樼數骞崇殑鏃堕棿, 鍗曚綅: ns)
+ * @returns true/false
+ */
+pwm.setDuty = function (dutyNs) {
+	return pwmObj.setDuty(dutyNs)
+}
+/**
+ * 璁剧疆PWM mode 2锛屾寚浠ゆ暟閲忕殑娉㈠舰妯″紡鐨勬暟閲�
+ * @param {number} dutyNs 
+ * @returns true/false
+ */
+pwm.setDmaDuty = function (dutyNs) {
+	return pwmObj.setDmaDuty(dutyNs)
+}
+/**
+ * 浣胯兘鎸囧畾閫氶亾
+ * @param {number} channel  鐢宠鐨勯�氶亾鍙凤紝鏀寔0~7閫氶亾
+ * @param {boolean} on 
+ * @returns true/false
+ */
+pwm.enable = function (channel, on) {
+	return pwmObj.enable(channel, on)
+}
+/**
+ * 鍏抽棴鎵�閫夐�氶亾
+ * @param {number} channel 杈撳叆鍙傛暟, 鐢宠鐨勯�氶亾鍙凤紝鏀寔0~7閫氶亾
+ * @returns true/false
+ */
+pwm.free = function (channel) {
+	return pwmObj.free(channel)
+}
+/**
+ * 璁剧疆鎸囧畾閫氶亾鐨凱WM鍛ㄦ湡
+ * @param {number} channel  鐢宠鐨勯�氶亾鍙凤紝鏀寔0~7閫氶亾
+ * @param {number} periodNs  寰呰缃殑PWM鍛ㄦ湡鍊�(鍗曚綅: ns)
+ * @returns true/false
+ */
+pwm.setPeriodByChannel = function (channel, periodNs) {
+	return pwmObj.setPeriodByChannel(channel, periodNs)
+}
+/**
+ * 璁剧疆鎸囧畾閫氶亾鐨凱WM鍗犵┖姣�
+ * @param {number} channel  鐢宠鐨勯�氶亾鍙凤紝鏀寔0~7閫氶亾
+ * @param {number} dutyNs 寰呰缃殑PWM鍗犵┖姣�(璁剧疆楂樼數骞崇殑鏃堕棿, 鍗曚綅: ns)
+ * @returns true/false
+ */
+pwm.setDutyByChannel = function (channel, dutyNs) {
+	return pwmObj.setDutyByChannel(channel, dutyNs);
+}
+/**
+* 铚傞福,闇�瑕佸厛request锛宻etPeriodByChannel鍜宔nable涔嬪悗鎵嶅彲浠ヤ娇鐢�
+* @param {object} options 铚傞福鐨勫弬鏁� 
+* 		@param {number} options.channel  鐢宠鐨勯�氶亾鍙凤紝鏀寔0~7閫氶亾锛屽繀濉�
+* 		@param {number} options.period  寰呰缃殑PWM鍛ㄦ湡鍊�(鍗曚綅: ns) 缂虹渷鏄�366166
+* 		@param {number} options.count 铚傞福鐨勬鏁帮紝缂虹渷鏄�1娆� 
+* 		@param {number} options.time 铚傞福鐨勬椂闂达紝缂虹渷鏄�50姣锛屽鏋滄兂闀块福锛屼竴鑸槸500姣
+* 		@param {number} options.interval 2娆¤渹楦d箣闂寸殑闂撮殧锛岀己鐪佹槸50姣
+* 		@param {number} options.volume 铚傞福鐨勯煶閲忥紝缂虹渷鏄�50
+*/
+pwm.beep = function (options) {
+	const {
+		count = 1,
+		time = 50,
+		interval = 50,
+		volume = 50,
+		period = 366166,
+	} = options;
+	for (let i = 0; i < count; i++) {
+		pwm.setDutyByChannel(options.channel, period * volume / 255)
+		os.sleep(time)
+		pwm.setDutyByChannel(options.channel, 0)
+		if (i < (count - 1)) {
+			// 鏈�鍚庝竴娆¤渹楦f棤闂撮殧
+			os.sleep(interval)
+		}
+	}
+}
+
+export default pwm;
diff --git a/vf205_access/dxmodules/dxQrRule.js b/vf205_access/dxmodules/dxQrRule.js
new file mode 100644
index 0000000..36bc9a8
--- /dev/null
+++ b/vf205_access/dxmodules/dxQrRule.js
@@ -0,0 +1,215 @@
+//build: 20240301
+//寰厜浜岀淮鐮佺爜鍒惰鍒欙紝鍖呮嫭101锛�103 绛�
+//渚濊禆缁勪欢: dxDriver,dxCommon,dxLogger
+import common from './dxCommon.js'
+import base64 from './dxBase64.js'
+import logger from './dxLogger.js'
+let sqliteObj
+
+// 姣旇緝涓や釜瀛楃涓茬殑鍓峃涓瓧绗︽槸鍚︾浉绛�
+function comparePrefix(str1, str2, N) {
+    let substring1 = str1.substring(0, N);
+    let substring2 = str2.substring(0, N);
+    return substring1 === substring2;
+}
+
+
+
+// 101鐮佸�艰В鐮�
+function decode101(str) {
+    if (str.length < 5) {
+        logger.info("鏃犳晥浜岀淮鐮�")
+        throw new Error("code invalid,length too short")
+    }
+    let decodeBuf = base64.decode(str.slice(0, -4))
+    decodeBuf=decodeBuf.substring(4)
+
+    return decodeBuf
+}
+function hexStringToArrayBuffer (hexString) {
+    var byteString = hexString.match(/.{1,2}/g);
+    var byteArray = byteString.map(function (byte) {
+        return parseInt(byte, 16);
+    });
+    var buffer = new Uint8Array(byteArray).buffer;
+    return buffer;
+}
+
+/**
+ * 103鐮佸�艰В鐮�
+ * 1銆乥ase64瑙g爜
+ * 2銆佽В鏋愮粍缁囩紪鍙�
+ * 3銆丷SA瑙e瘑
+ * 4銆佽В鏋愯韩浠界被鍨�
+ * 5銆佽В鏋愭潈闄愭爣璇�
+ * 6銆佽В鏋愮敓鐮佹椂闂�
+ * 7銆佽В鏋愮爜杩囨湡鏃堕棿
+ * 8銆佹牎楠岄�氳鐮佹槸鍚﹁繃鏈�
+ * @param {*} str 
+ * @returns 
+ */
+function decode103(str) {
+    // FIXME 杩欎釜pubKey鍚庢湡闇�瑕佷粠閰嶇疆涓煡璇�
+    let TLV_T_SIZE = 2, TLV_L_SIZE = 2, offset = 0, code, decryptedData, generationCodeTime, expirationTime
+
+    // 1銆乥ase64瑙g爜
+    let decodeBuf = base64.toHexString(str)
+    decodeBuf= hexStringToArrayBuffer(decodeBuf)
+    let view = new Uint8Array(decodeBuf)
+    let organizationNumber;
+    // 2銆佽В鏋愮粍缁囩紪鍙�
+    if (view[offset] == 0x01) {
+        offset += TLV_T_SIZE
+        let orgNumLen = view[offset]
+        offset += TLV_L_SIZE
+        let orgNumBuf = new Uint8Array(decodeBuf, offset, orgNumLen);
+        organizationNumber = String.fromCharCode.apply(null, new Uint8Array(orgNumBuf));
+        logger.info("缁勭粐缂栧彿: " + organizationNumber)
+        offset += orgNumLen
+    } else {
+        throw new Error("code invalid,organization number error")
+    }
+
+    // 3銆丷SA瑙e瘑
+    if (view[offset] == 0x02) {
+        // 缁勭粐缂栧彿鏁版嵁闀垮害
+        offset += TLV_T_SIZE
+        let cipherTextLen = view[offset]
+        offset += TLV_L_SIZE
+        // 瀵瑰瘑鏂囪繘琛孯SA瑙e瘑
+        let encryptedData = decodeBuf.slice(offset, offset + cipherTextLen)
+
+
+        // TODO 绉橀挜鍐欐锛屽悗缁渶瑕佹毚闇插嚭鏉�
+        // RSA 鏌ヨ瀵嗛挜(涔熷彲浠ュ浐瀹氾紝涔熷彲浠ュ啓鍦ㄦ枃鏈腑)锛屾牴鎹瘑閽ュ啀娆¤В瀵�
+        // RSA瑙e瘑鍚庣殑鏁版嵁
+        let arr = sqliteObj.securityFindAllByCodeAndTypeAndTimeAndkey(undefined, undefined, undefined, Math.floor(Date.parse(new Date()) / 1000), organizationNumber)
+        if (arr && arr.length > 0) {
+            for (let data of arr) {
+                decryptedData = common.arrayBufferRsaDecrypt(encryptedData, data.value)
+                if (decryptedData != null) {
+                    break
+                }
+            }
+        }
+        if (!arr && arr.length <= 0 || decryptedData == null) {
+            return str
+        }
+    }
+    // 涓�涓澶囦竴涓瘑閽ワ紝鐩稿綋浜庤澶囧唴鐢ㄤ簬瑙e瘑鐨勫叕閽ユ槸鍥哄畾鐨勶紝鍙互鎶婂叕閽ユ斁鍒伴厤缃腑锛岃繖閲屽厛榛樿鍐欐
+    // "MTlBODExMDA2MTkwMzQ4Q0I5QUY3QTc4QzAzOTQzNUU5NzNFODAzMEU4QUU1QzBEMkZFOEYwRjEzRjU4M0M5MTU5QUU5MTdDMDIzRDU0RDgxRUY2NTI0NkUyQ0Y2MUMzMTQzNTNENjA2NDU5N0Y2OTY5RUE4QjA5MUY1RTYyODM=";
+    // let buf = common.arrayBufferRsaDecrypt(deData, deData.length)
+    // 0 3 0 3 0 31 30 33 4 0 a 0 31 30 35 34 33 32 33 33 32 33 5 0 4 0 af 8c fa 5a 6 0 1 0 35 7 0 0 0
+    // 0 
+    // 3 0 3 0 31 30 33 
+    // 4 0 a 0 31 30 35 34 33 32 33 33 32 33 
+    // 5 0 4 0 af 8c fa 5a 
+    // 6 0 1 0 35 
+    // 7 0 0 0
+
+    offset = 1;
+    view = new Uint8Array(decryptedData)
+    // 4銆佽В鏋愯韩浠界被鍨�(type:103)
+    if (view[offset] == 0x03) {
+        // 韬唤绫诲瀷鏁版嵁闀垮害
+        offset += TLV_T_SIZE
+        let identityTypeLength = view[offset]
+        // 韬唤绫诲瀷鏁版嵁
+        offset += TLV_L_SIZE
+        let identityTypeBuf = new Uint8Array(decryptedData, offset, identityTypeLength);
+        let identityType = String.fromCharCode.apply(null, identityTypeBuf);
+        offset += identityTypeLength
+        logger.info("韬唤绫诲瀷鏁版嵁: " + identityType)
+    }
+
+
+    // 5銆佽В鏋愭潈闄愭爣璇�(code)
+    if (view[offset] == 0x04) {
+        // 鏉冮檺鏍囪瘑鏁版嵁闀垮害
+        offset += TLV_T_SIZE
+        let identityCodeLength = view[offset]
+        // 鏉冮檺鏍囪瘑鏁版嵁
+        offset += TLV_L_SIZE
+        let identityCodeBuf = new Uint8Array(decryptedData, offset, identityCodeLength);
+        offset += identityCodeLength
+        code = String.fromCharCode.apply(null, identityCodeBuf);
+    }
+
+
+    // 6銆佽В鏋愮敓鐮佹椂闂�
+    if (view[offset] == 0x05) {
+        // 鐢熺爜鏃堕棿鏁版嵁闀垮害
+        offset += TLV_T_SIZE
+        let createTimeLength = view[offset]
+        // 鐢熺爜鏃堕棿鏁版嵁
+        offset += TLV_L_SIZE
+        let createTimeBuf = new Uint8Array(decryptedData, offset, createTimeLength);
+        offset += createTimeLength
+        generationCodeTime = parseInt(common.arrayBufferToHexString(createTimeBuf.reverse()), 16)
+    }
+
+
+    // 7銆佽В鏋愮爜杩囨湡鏃堕棿
+    if (view[offset] == 0x06) {
+        // 鐮佽繃鏈熸椂闂存暟鎹暱搴�
+        offset += TLV_T_SIZE
+        let expireTimeLength = view[offset]
+        // 鐮佽繃鏈熸椂闂存暟鎹�
+        offset += TLV_L_SIZE
+        let expireTimeBuf = new Uint8Array(decryptedData, offset, expireTimeLength);
+        offset += expireTimeLength
+        expirationTime = parseInt(String.fromCharCode.apply(null, expireTimeBuf))
+    }
+
+    // 8銆佹牎楠岄�氳鐮佹槸鍚﹁繃鏈�
+    let timestamp = Date.now();
+    expirationTime = generationCodeTime + expirationTime
+    if (expirationTime * 1000 > timestamp) {
+        return code
+    } else {
+        return null
+    }
+
+}
+
+const code = {
+    formatCode: function (msg, sqlObj) {
+        if (!msg) {
+            throw new Error("msg should not be null or empty")
+        }
+        if (!sqlObj) {
+            throw new Error("sqlObj should not be null or empty")
+        }
+        if (!sqliteObj) {
+            sqliteObj = sqlObj
+        }
+
+        let data = {}
+        // 鍒ゆ柇鐮佸��
+        if (comparePrefix(msg, "&llgy", "&llgy".length) || comparePrefix(msg, "&v101", "&v101".length)) {
+            // 101鐮佸��
+            data.type = 101
+            data.code = decode101(msg.substring(5))
+        }
+        else if (comparePrefix(msg, "vg://v103", "vg://v103".length)) {
+            // 103鐮佸��
+            data.type = 103
+            data.code = decode103(msg.substring(9)) ? decode103(msg.substring(9)) : msg.substring(9)
+        } else if (comparePrefix(msg, "___VBAR_CONFIG_V1.1.0___", "___VBAR_CONFIG_V1.1.0___".length) || comparePrefix(msg, "___VBAR_KZB_V1.1.0___", "___VBAR_KZB_V1.1.0___".length)) {
+            //TODO 鍏堣繖鏍峰啓锛岃璁哄ソ鍚庢洿鏀规祦杞�昏緫
+            data.type = 'config'
+            data.code = msg
+        } else {
+            data.type = 100
+            data.code = msg
+        }
+        if (data.code) {
+            return data
+        } else {
+            console.log("decode fail")
+            return
+        }
+    }
+}
+
+export default code;
\ No newline at end of file
diff --git a/vf205_access/dxmodules/dxSqlite.js b/vf205_access/dxmodules/dxSqlite.js
new file mode 100644
index 0000000..b4c44ab
--- /dev/null
+++ b/vf205_access/dxmodules/dxSqlite.js
@@ -0,0 +1,54 @@
+//build: 20240525
+//渚濊禆缁勪欢:dxCommon
+import { sqliteClass } from './libvbar-m-dxsqlite.so'
+import dxCommon from './dxCommon.js'
+const sqliteObj = new sqliteClass();
+const sqlite = {}
+
+/**
+ * 鍒濆鍖栨暟鎹簱
+ * @param {string} path db鏂囦欢鍏ㄨ矾寰勶紝蹇呭~
+ * @param {string} id 鍙ユ焺id锛岄潪蹇呭~锛堣嫢鍒濆鍖栧涓疄渚嬮渶瑕佷紶鍏ュ敮涓�id锛�
+ */
+sqlite.init = function (path, id) {
+    if (path == undefined || path.length == 0) {
+        throw new Error("dxsqliteObj.initDb:path should not be null or empty")
+    }
+    let pointer = sqliteObj.open(path);
+    dxCommon.handleId("sqlite", id, pointer)
+}
+
+/**
+ * 鎵ц璇彞
+ * @param {string} sql 鑴氭湰璇彞锛屽繀濉�
+ * @param {string} id 鍙ユ焺id锛岄潪蹇呭~锛堥渶淇濇寔鍜宨nit涓殑id涓�鑷达級
+ * @returns 0:鎴愬姛锛岄潪0澶辫触
+ */
+sqlite.exec = function (sql, id) {
+    let pointer = dxCommon.handleId("sqlite", id)
+    return sqliteObj.sql_exec(pointer, sql)
+}
+
+
+/**
+ * 鎵ц鏌ヨ璇彞
+ * @param {string} sql 鑴氭湰璇彞锛屽繀濉�
+ * @param {string} id 鍙ユ焺id锛岄潪蹇呭~锛堥渶淇濇寔鍜宨nit涓殑id涓�鑷达級
+ * @returns 鏌ヨ缁撴灉锛屽舰濡傦細[{"id":"1","type":200,"code":"aad7485a","door":"澶ч棬","extra":"","tiemType":0,"beginTime":1716613766,"endTime":1716613766,"repeatBeginTime":1716613766,"repeatEndTime":1716613766,"period":"extra"}]
+ */
+sqlite.select = function (sql, id) {
+    let pointer = dxCommon.handleId("sqlite", id)
+    return sqliteObj.select(pointer, sql);
+}
+
+/**
+ * 鍏抽棴鏁版嵁搴撹繛鎺�
+ * @param {string} id 鍙ユ焺id锛岄潪蹇呭~锛堥渶淇濇寔鍜宨nit涓殑id涓�鑷达級
+ * @returns 0:鎴愬姛锛岄潪0澶辫触
+ */
+sqlite.close = function (id) {
+    let pointer = dxCommon.handleId("sqlite", id)
+    return sqliteObj.close(pointer)
+}
+
+export default sqlite;
\ No newline at end of file
diff --git a/vf205_access/dxmodules/dxStd.js b/vf205_access/dxmodules/dxStd.js
new file mode 100644
index 0000000..5b3504f
--- /dev/null
+++ b/vf205_access/dxmodules/dxStd.js
@@ -0,0 +1,399 @@
+//build 20240222
+//quickjs 鏍囧噯搴擄紝鎻愪緵鍜屾搷浣滅郴缁熺浉鍏冲嚱鏁帮紝鎻愪緵鏍囧噯IO鐩稿叧鍑芥暟
+import * as os from "os"
+import * as std from "std"
+import common from "./dxCommon.js"
+
+const dxstd = {}
+/**
+ * 閫�鍑哄簲鐢�
+ * @param {number} n 閫�鍑虹爜
+ */
+dxstd.exit = function (n) {
+    return std.exit(n);
+}
+/**
+ * 鍚姩璁℃椂鍣紝寤舵椂寮傛鎵ц鍑芥暟
+ * @param {function} func 闇�瑕佹墽琛岀殑鍑芥暟
+ * @param {number} delay 寤惰繜鐨勬椂闂达紙姣锛�
+ * @returns timer寮曠敤
+ */
+dxstd.setTimeout = function (func, delay) {
+    return os.setTimeout(func, delay)
+}
+/**
+ * 娓呴櫎鎸囧畾鐨勮鏃跺櫒
+ * @param {*} handle timer寮曠敤
+ */
+dxstd.clearTimeout = function (handle) {
+    os.clearTimeout(handle)
+}
+// 璁板綍瀹氭椂鍣╥d锛岀敤浜巆lear锛屽彧鑳藉湪鍚屼竴绾跨▼涓璫lear
+let allTimerIdsMap = {}
+
+/**
+ * interval瀹氭椂鍣�
+ * @param {function} callback 鍥炶皟鍑芥暟锛屽繀濉�
+ * @param {number} interval 闂撮殧鏃堕棿锛屽繀濉�
+ * @param {boolean} once 鍒涘缓鍚庣珛鍗虫墽琛屼竴娆★紝闈炲繀濉�
+ * @param {number} timerId 瀹氭椂鍣╥d锛岄潪蹇呭~
+ */
+dxstd.setInterval = function (callback, interval, once, timerId) {
+    if (timerId === null || timerId === undefined) {
+        timerId = new Date().getTime() + "_" + this.genRandomStr(5)
+        allTimerIdsMap[timerId] = "ready"
+    }
+    if (once === true) {
+        // 鍒涘缓鍚庣珛鍗虫墽琛屼竴娆�
+        os.setTimeout(() => {
+            if (allTimerIdsMap[timerId]) {
+                callback()
+            }
+        }, 0);
+    }
+    if (!allTimerIdsMap[timerId]) {
+        return
+    }
+    allTimerIdsMap[timerId] = os.setTimeout(() => {
+        if (allTimerIdsMap[timerId]) {
+            callback()
+            this.setInterval(callback, interval, false, timerId)
+        }
+    }, interval);
+    return timerId
+}
+
+/**
+ * 娓呴櫎interval瀹氭椂鍣�
+ * @param {number} timerId 瀹氭椂鍣╥d锛屽繀濉�
+ */
+dxstd.clearInterval = function (timerId) {
+    const timer = allTimerIdsMap[timerId];
+    if (timer) {
+        os.clearTimeout(timer);
+        delete allTimerIdsMap[timerId];
+    }
+}
+/**
+ * 鍒犻櫎褰撳墠绾跨▼鎵�鏈塱nterval瀹氭椂鍣紝娉ㄦ剰锛氬彧鏄垹闄ゅ綋鍓嶇嚎绋嬪垱寤虹殑瀹氭椂鍣紝鑻ユ湁澶氫釜绾跨▼锛屾瘡涓嚎绋嬮兘闇�瑕佽皟鐢ㄥ垹闄�
+ */
+dxstd.clearIntervalAll = function () {
+    for (let timerId in allTimerIdsMap) {
+        if (allTimerIdsMap.hasOwnProperty(timerId)) {
+            os.clearTimeout(allTimerIdsMap[timerId]);
+            delete allTimerIdsMap[timerId];
+        }
+    }
+}
+/**
+ * 鐢熸垚鎸囧畾闀垮害鐨勫瓧姣嶅拰鏁板瓧缁勫悎鐨勯殢鏈哄瓧绗︿覆
+ * @param {number} length 瀛楃涓查暱搴︼紝闈炲繀濉紝缂虹渷鏄�6
+ * @returns 
+ */
+dxstd.genRandomStr = function (length = 6) {
+    const charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
+    let result = ''
+    for (let i = 0; i < length; i++) {
+        const randomIndex = Math.floor(Math.random() * charset.length)
+        result += charset.charAt(randomIndex)
+    }
+    return result
+}
+/**
+ * 鎶婁竴娈靛瓧绗︿覆浣滀负 javascript 鑴氭湰鎵ц
+ * @param {string} str js鑴氭湰瀛楃涓�
+ * @param {boolean} async 榛樿涓篺alse锛屽鏋滀负 true锛岃剼鏈腑灏嗘帴鍙� await 骞惰繑鍥炰竴涓� Promise 
+ */
+dxstd.eval = function (str, async) {
+    return std.evalScript(str, { async: async });
+}
+/**
+ * 鍔犺浇涓�涓枃浠跺唴瀹逛綔涓� javascript 鑴氭湰鎵ц
+ * @param {string} filename js鑴氭湰鍐呭鐨勬枃浠跺悕(缁濆璺緞)
+ */
+dxstd.loadScript = function (filename) {
+    return std.loadScript(filename);
+}
+/**
+ * 鍔犺浇鏂囦欢锛岃鍙栨枃浠堕噷鐨勫唴瀹癸紙浣跨敤utf锛�
+ * @param {string} filename 鏂囦欢鍚�
+ */
+dxstd.loadFile = function (filename) {
+    return std.loadFile(filename)
+}
+/**
+ * 淇濆瓨瀛楃涓插埌鏂囦欢
+ * @param {string} filename 
+ * @param {string} content 
+ */
+dxstd.saveFile = function (filename, content) {
+    if (!content || (typeof content) != 'string') {
+        throw new Error("The 'content' value should be string and not empty")
+    }
+    if (!filename) {
+        throw new Error("The 'filename' should not be empty")
+    }
+    if (!this.exist(filename)) {
+        this.ensurePathExists(filename)
+        let fd = os.open(filename, os.O_RDWR | os.O_CREAT | os.O_TRUNC);
+        if (fd < 0) {
+            throw new Error("Create file failed:" + filename)
+        }
+        os.close(fd)
+    }
+    let fd = std.open(filename, "w");
+    fd.puts(content)
+    fd.flush();
+    fd.close();
+    common.systemBrief('sync')
+    return true
+}
+/**
+ * 纭繚鏂囦欢瀵瑰簲鐨勭洰褰曢兘瀛樺湪锛屼笉瀛樺湪灏变細鍒涘缓
+ * @param {string} filename 
+ */
+dxstd.ensurePathExists = function (filename) {
+    const pathSegments = filename.split('/');
+    let currentPath = '';
+    for (let i = 0; i < pathSegments.length - 1; i++) {
+        currentPath += pathSegments[i] + '/';
+        if (!this.exist(currentPath)) {
+            this.mkdir(currentPath);
+        }
+    }
+}
+/**
+ * 鍒ゆ柇鏂囦欢鏄惁瀛樺湪
+ * @param {string} filename  鏂囦欢鍚�
+ * @returns true/false
+ */
+dxstd.exist = function (filename) {
+    return (os.stat(filename)[1] === 0)
+}
+/**
+ * 杩斿洖涓�涓寘鍚幆澧冨彉閲忕殑閿�煎鐨勫璞°��
+ */
+dxstd.getenviron = function () {
+    return std.getenviron();
+}
+/**
+ * 杩斿洖鐜鍙橀噺鍚嶇О鐨勫�硷紝濡傛灉鏈畾涔夊垯杩斿洖undefined
+ * @param {string} name 鍙橀噺鍚�
+ */
+dxstd.getenv = function (name) {
+    return std.getenv(name);
+}
+/**
+ * 灏嗙幆澧冨彉閲忓悕鐨勫�艰缃负瀛楃涓插��
+ * @param {string} name 鍙橀噺鍚�
+ * @param {string} value 鍙橀噺鍊�
+ */
+dxstd.setenv = function (name, value) {
+    return std.setenv(name, value);
+}
+/**
+ * 鍒犻櫎鐜鍙橀噺
+ * @param {string} name 鍙橀噺鍚�
+ */
+dxstd.unsetenv = function (name) {
+    return std.unsetenv(name);
+}
+/**
+ * 浣跨敤JSON.parse鐨勮秴闆嗘潵瑙f瀽瀛楃涓层�傚彲浠ヨВ鏋愰潪鏍囧噯鐨� JSON 瀛楃涓层�傛帴鍙椾互涓嬫墿灞曪細
+ * - 鍗曡鍜屽琛屾敞閲�
+ * - 鏈姞寮曞彿鐨勫睘鎬э紙浠匒SCII瀛楃鐨凧avaScript鏍囪瘑绗︼級
+ * - 鏁扮粍鍜屽璞℃渶鍚庡彲浠ュ姞閫楀彿
+ * - 鍗曞紩鍙峰瓧绗︿覆
+ * - \f 鍜� \v 琚帴鍙椾负绌烘牸瀛楃
+ * - 鏁板瓧涓殑鍓嶉潰鍙互鏈夊姞鍙�
+ * - 鍏繘鍒讹紙0o鍓嶇紑锛夊拰鍗佸叚杩涘埗锛�0x鍓嶇紑锛夋暟瀛�
+ * @param {string} str json瀛楃涓�
+ */
+dxstd.parseExtJSON = function (str) {
+    return std.parseExtJSON(str);
+}
+/**
+ * 浼戠湢delay_ms姣
+ */
+dxstd.sleep = function (delay_ms) {
+    return os.sleep(delay_ms);
+}
+/**
+ * 杩斿洖琛ㄧず骞冲彴鐨勫瓧绗︿覆锛�"linux"銆�"darwin"銆�"win32" 鎴� "js"銆�
+ */
+dxstd.platform = function () {
+    return os.platform;
+}
+/**
+ * 鍒涘缓涓�涓柊绾跨▼锛坵orker锛夌殑鏋勯�犲嚱鏁帮紝鍏禔PI鎺ヨ繎浜嶹ebWorkers銆�
+ * 瀵逛簬鍔ㄦ�佸鍏ョ殑妯″潡锛屽畠鐩稿浜庡綋鍓嶈剼鏈垨妯″潡璺緞銆傜嚎绋嬮�氬父涓嶅叡浜换浣曟暟鎹紝鍙互閫氳繃dxMap,dxQueue,dxWpc鏉ュ叡浜拰浼犻�掓暟鎹�備笉鏀寔宓屽鐨� worker銆�
+ * @param {string} module_filename 鎸囧畾鍦ㄦ柊鍒涘缓鐨勭嚎绋嬩腑鎵ц鐨勬ā鍧楁枃浠跺悕
+ */
+dxstd.Worker = function (module_filename) {
+    return new os.Worker(module_filename)
+}
+
+dxstd.O_RDONLY = os.O_RDONLY
+dxstd.O_WRONLY = os.O_WRONLY
+dxstd.O_RDWR = os.O_RDWR
+dxstd.O_APPEND = os.O_APPEND
+dxstd.O_CREAT = os.O_CREAT
+dxstd.O_EXCL = os.O_EXCL
+dxstd.O_TRUNC = os.O_TRUNC
+/**
+ * 鎵撳紑涓�涓枃浠躲�傝繑鍥炰竴涓彞鏌勶紝濡傛灉鍑虹幇閿欒鍒欒繑鍥� < 0銆�
+ * @param {string} filename 鏂囦欢缁濆璺緞
+ * @param {number} flags O_RDONLY,O_WRONLY,O_RDWR,O_APPEND,O_CREAT,O_EXCL,O_TRUNC
+ * 1. O_RDONLY 锛氫互鍙鏂瑰紡鎵撳紑鏂囦欢
+ * 2. O_WRONLY 锛氫互鍙啓鏂瑰紡鎵撳紑鏂囦欢
+ * 3. O_RDWR 锛氫互鍙鍙啓鏂瑰紡鎵撳紑鏂囦欢
+ * 浠ヤ笂涓変釜鏄枃浠惰闂潈闄愭爣蹇楋紝浼犲叆鐨刦lags 鍙傛暟涓繀椤昏鍖呭惈鍏朵腑涓�绉嶆爣蹇楋紝鑰屼笖鍙兘鍖呭惈涓�绉嶏紝鎵撳紑鐨勬枃浠跺彧鑳芥寜鐓ц繖绉嶆潈闄愭潵鎿嶄綔锛�
+   璀浣跨敤浜� O_RDONLY 鏍囧織锛屽氨鍙兘瀵规枃浠惰繘琛岃鍙栨搷浣滐紝涓嶈兘鍐欐搷浣溿��
+
+ * 4. O_APPEND 锛氳皟鐢� open 鍑芥暟鎵撳紑鏂囦欢锛屽綋姣忔浣跨敤 write()鍑芥暟瀵规枃浠惰繘琛屽啓鎿嶄綔鏃讹紝閮戒細鑷姩鎶婃枃浠跺綋鍓嶄綅缃亸绉婚噺绉诲姩鍒版枃浠舵湯灏撅紝
+   浠庢枃浠舵湯灏惧紑濮嬪啓鍏ユ暟鎹紝涔熷氨鏄剰鍛崇潃姣忔鍐欏叆鏁版嵁閮芥槸浠庢枃浠舵湯灏惧紑濮嬨��
+   O_APPEND鏍囧織骞朵笉浼氬奖鍝嶈鏂囦欢锛屽綋璇诲彇鏂囦欢鏃讹紝 O_APPEND 鏍囧織骞朵笉浼氬奖鍝嶈浣嶇疆鍋忕Щ閲忥紝 
+   鍗充娇浣跨敤浜� O_APPEND鏍囧織锛岃鏂囦欢浣嶇疆鍋忕Щ閲忛粯璁ゆ儏鍐典笅渚濈劧鏄枃浠跺ご锛�
+   浣跨敤 lseek 鍑芥暟鏉ユ敼鍙� write()鏃剁殑鍐欎綅缃亸绉婚噺涔熶笉浼氭垚鍔燂紝
+   褰撴墽琛� write()鍑芥暟鏃讹紝妫�娴嬪埌 open 鍑芥暟鎼哄甫浜� O_APPEND 鏍囧織锛屾墍浠ュ湪 write 鍑芥暟鍐呴儴浼氳嚜鍔ㄥ皢鍐欎綅缃亸绉婚噺绉诲姩鍒版枃浠舵湯灏�
+
+ * 5. O_CREAT锛氬鏋� filename 鍙傛暟鎸囧悜鐨勬枃浠朵笉瀛樺湪鍒欏垱寤烘鏂囦欢
+ * 6. O_EXCL :姝ゆ爣蹇椾竴鑸粨鍚� O_CREAT 鏍囧織涓�璧蜂娇鐢紝鐢ㄤ簬涓撻棬鍒涘缓鏂囦欢銆�
+   鍦� flags 鍙傛暟鍚屾椂浣跨敤鍒颁簡 O_CREAT 鍜孫_EXCL 鏍囧織鐨勬儏鍐典笅锛屽鏋� filename 鍙傛暟鎸囧悜鐨勬枃浠跺凡缁忓瓨鍦紝
+   鍒� open 鍑芥暟杩斿洖閿欒銆傚彲浠ョ敤浜庢祴璇曚竴涓枃浠舵槸鍚﹀瓨鍦紝濡傛灉涓嶅瓨鍦ㄥ垯鍒涘缓姝ゆ枃浠讹紝濡傛灉瀛樺湪鍒欒繑鍥為敊璇紝杩欎娇寰楁祴璇曞拰鍒涘缓涓よ�呮垚涓轰竴涓師瀛愭搷浣溿��
+ * 7. O_TRUNC 锛氳皟鐢� open 鍑芥暟鎵撳紑鏂囦欢鐨勬椂鍊欎細灏嗘枃浠跺師鏈殑鍐呭鍏ㄩ儴涓㈠純锛屾枃浠跺ぇ灏忓彉涓� 0锛� 
+ */
+dxstd.open = function (filename, flags) {
+    return os.open(filename, flags);
+}
+/**
+ * 鍒ゆ柇缁欏畾璺緞鏄惁鏄竴涓枃浠跺す銆�
+ * @param {string} filename - 瑕佹鏌ョ殑璺緞銆�
+ * @returns {boolean} 濡傛灉鏄枃浠跺す鍒欒繑鍥� true锛屽惁鍒欒繑鍥� false,濡傛灉涓嶅瓨鍦紝鎶涘嚭寮傚父銆�
+ */
+dxstd.isDir = function (filename) {
+    let stat = os.stat(filename)
+    if (stat[1] != 0) {
+        throw new Error("No such file:" + filename)
+    }
+    return ((stat[0].mode & this.S_IFMT) === this.S_IFDIR);
+}
+/**
+ * 鍏抽棴鏂囦欢
+ * @param {*} fd 鏂囦欢鍙ユ焺 
+ */
+dxstd.close = function (fd) {
+    return os.close(fd)
+}
+dxstd.SEEK_SET = std.SEEK_SET
+dxstd.SEEK_CUR = std.SEEK_CUR
+dxstd.SEEK_END = std.SEEK_END
+/**
+ * 鍦ㄦ枃浠朵腑杩涜瀹氫綅銆備娇鐢⊿EEK_*鏉ヨ〃绀簑hence銆俹ffset鍙互鏄暟瀛楁垨bigint銆傚鏋渙ffset鏄痓igint锛屽垯杩斿洖涓�涓猙igint銆�
+ * @param {*} fd 鏂囦欢鍙ユ焺
+ * @param {number} offset 涓哄亸绉婚噺锛屾暣鏁拌〃绀烘鍚戝亸绉伙紝璐熸暟琛ㄧず璐熷悜鍋忕Щ
+ * @param {*} whence 璁惧畾浠庢枃浠剁殑鍝噷寮�濮嬪亸绉�: SEEK_SET锛� 鏂囦欢寮�澶�;SEEK_CUR锛� 褰撳墠浣嶇疆;SEEK_END锛� 鏂囦欢缁撳熬
+ */
+dxstd.seek = function (fd, offset, whence) {
+    return os.seek(fd, offset, whence)
+}
+/**
+ * 浠庢枃浠跺彞鏌刦d璇诲彇length瀛楄妭鍒颁綅浜庡瓧鑺備綅缃畂ffset鐨凙rrayBuffer缂撳啿鍖恒�傝繑鍥炶鍙栫殑瀛楄妭鏁帮紝濡傛灉鍑虹幇閿欒鍒欒繑鍥� < 0銆�
+ * @param {*} fd 鏂囦欢鍙ユ焺
+ * @param {*} buffer ArrayBuffer瀵硅薄
+ * @param {number} offset 鍋忕Щ閲�
+ * @param {number} length 璇诲彇鐨勫瓧鑺傞暱搴�
+ */
+dxstd.read = function (fd, buffer, offset, length) {
+    return os.read(fd, buffer, offset, length);
+}
+/**
+ * 浠嶢rrayBuffer缂撳啿鍖虹殑瀛楄妭浣嶇疆offset鍚戞枃浠跺彞鏌刦d鍐欏叆length瀛楄妭銆傝繑鍥炲凡鍐欏叆鐨勫瓧鑺傛暟锛屽鏋滃嚭鐜伴敊璇垯杩斿洖 < 0銆�
+ * @param {*} fd 鏂囦欢鍙ユ焺
+ * @param {*} buffer ArrayBuffer瀵硅薄
+ * @param {*} offset 鍋忕Щ閲�
+ * @param {*} length 鍐欑殑瀛楄妭闀垮害
+ */
+dxstd.write = function (fd, buffer, offset, length) {
+    return os.write(fd, buffer, offset, length);
+}
+/**
+ * 鍒犻櫎鏂囦欢锛屾垚鍔熻繑鍥�0鍚﹀垯-errno
+ * @param {string} filename 鏂囦欢缁濆璺緞
+ */
+dxstd.remove = function (filename) {
+    return os.remove(filename)
+}
+/**
+ * 淇敼鏂囦欢鍚嶇О锛屾垚鍔熻繑鍥�0鍚﹀垯-errno
+ * @param {string} oldname 鏃ф枃浠剁粷瀵硅矾寰�
+ * @param {string} newname 鏂版枃浠剁粷瀵硅矾寰�
+ */
+dxstd.rename = function (oldname, newname) {
+    return os.rename(oldname, newname)
+}
+/**
+ * 杩斿洖 [str, err]锛屽叾涓� str 鏄綋鍓嶅伐浣滅洰褰曪紝err 鏄敊璇唬鐮�
+ */
+dxstd.getcwd = function () {
+    return os.getcwd()
+}
+/**
+ * 鏀瑰彉褰撳墠宸ヤ綔鐩綍
+ * @param {string} path 鐩綍,鏀寔缁濆鍜岀浉瀵硅矾寰� 
+ */
+dxstd.chdir = function (path) {
+    return os.chdir(path)
+}
+/**
+ * 鍒涘缓鐩綍,鎴愬姛杩斿洖0鍚﹀垯-errno
+ * @param {string} path 鐩綍缁濆璺緞 
+ */
+dxstd.mkdir = function (path) {
+    return os.mkdir(path)
+}
+dxstd.S_IFMT = os.S_IFMT
+dxstd.S_IFIFO = os.S_IFIFO
+dxstd.S_IFCHR = os.S_IFCHR
+dxstd.S_IFDIR = os.S_IFDIR
+dxstd.S_IFBLK = os.S_IFBLK
+dxstd.S_IFREG = os.S_IFREG
+dxstd.S_IFSOCK = os.S_IFSOCK
+dxstd.S_IFLNK = os.S_IFLNK
+dxstd.S_ISGID = os.S_ISGID
+dxstd.S_ISUID = os.S_ISUID
+/**
+ * 杩斿洖 [obj, err]锛屽叾涓� obj 鏄竴涓寘鍚矾寰刾ath鐨勬枃浠剁姸鎬佷俊鎭殑瀵硅薄銆�
+ * err 鏄敊璇唬鐮併�俹bj 涓畾涔変簡浠ヤ笅瀛楁锛歞ev銆乮no銆乵ode銆乶link銆乽id銆乬id銆乺dev銆乻ize銆乥locks銆乤time銆乵time銆乧time銆�
+ * 鏃堕棿浠ヨ嚜1970骞翠互鏉ョ殑姣涓哄崟浣嶆寚瀹氥��
+ * 鍏朵腑mode鐨勫�煎搴斾互涓嬫灇涓�,渚嬪锛屾鏌ヤ竴涓枃浠舵槸鍚︽槸鐩綍鍙互浣跨敤 (mode & S_IFMT) == S_IFDIR 鐨勬柟寮�:
+   S_IFMT锛氫綅鎺╃爜锛岀敤浜庢彁鍙栨枃浠剁被鍨嬮儴鍒嗙殑浣嶃�傝繖鏄竴涓敤浜庡睆钄芥枃浠剁被鍨嬩綅鐨勫父閲忋��
+   S_IFIFO锛氳〃绀篎IFO锛堝懡鍚嶇閬擄級銆�
+   S_IFCHR锛氳〃绀哄瓧绗﹁澶囥��
+   S_IFDIR锛氳〃绀虹洰褰曘��
+   S_IFBLK锛氳〃绀哄潡璁惧銆�
+   S_IFREG锛氳〃绀哄父瑙勬枃浠躲��
+   S_IFSOCK锛氳〃绀哄鎺ュ瓧銆�
+   S_IFLNK锛氳〃绀虹鍙烽摼鎺ャ��
+   S_ISGID锛氳缃粍ID浣嶃��
+   S_ISUID锛氳缃敤鎴稩D浣嶃��
+ * @param {string} path 鏂囦欢鎴栫洰褰曠粷瀵硅矾寰� 
+ */
+dxstd.stat = function (path) {
+    return os.stat(path)
+}
+/**
+ * lstat() 涓� stat() 鐩稿悓锛屽彧鏄畠杩斿洖鍏充簬閾炬帴鏈韩鐨勪俊鎭��
+ * @param {*} path 鏂囦欢鎴栫洰褰曠粷瀵硅矾寰� 
+ */
+dxstd.lstat = function (path) {
+    return os.lstat(path)
+}
+/**
+ * 杩斿洖 [array, err]锛屽叾涓� array 鏄寘鍚洰褰曡矾寰勪笅鐨勬枃浠跺悕鐨勫瓧绗︿覆鏁扮粍銆俥rr 鏄敊璇唬鐮併��
+ * @param {string} path 鐩綍缁濆璺緞 
+ */
+dxstd.readdir = function (path) {
+    return os.readdir(path)
+}
+export default dxstd
\ No newline at end of file
diff --git a/vf205_access/dxmodules/dxUart.js b/vf205_access/dxmodules/dxUart.js
new file mode 100644
index 0000000..8e01ebe
--- /dev/null
+++ b/vf205_access/dxmodules/dxUart.js
@@ -0,0 +1,242 @@
+//build: 20240715
+//鏁版嵁閫氫俊閫氶亾锛屽寘鎷覆鍙o紙Serial port锛夈�乁SB锛圲niversal Serial Bus锛夊拰闊︽牴锛圵iegand锛�
+//渚濊禆缁勪欢:dxDriver锛宒xStd锛宒xLogger锛宒xMap锛宒xEventBus,dxCommon
+import { channelClass } from './libvbar-m-dxchannel.so'
+import std from './dxStd.js'
+import dxMap from './dxMap.js'
+import dxCommon from './dxCommon.js'
+import bus from './dxEventBus.js'
+const uartObj = new channelClass();
+const map = dxMap.get('default')
+const uart = {}
+uart.TYPE = {
+	USBKBW: 1,//USB Keyboard Wedge閫氳繃USB鎺ュ彛杩炴帴閿洏锛屽苟浠ラ煢鏍瑰崗璁殑褰㈠紡浼犺緭鏁版嵁
+	USBHID: 2,//USB浜轰綋鎺ュ彛璁惧锛圲SB Human Interface Device锛夐�氶亾绫诲瀷
+	UART: 3,//琛ㄧずUART閫氶亾绫诲瀷锛屽嵆涓插彛閫氶亾
+	WIEGAND: 4//闊︽牴锛圵iegand锛夐�氶亾绫诲瀷
+}
+
+/* 鍚勭被閫氶亾 IO 鎺у埗鎿嶄綔鐨勮缃�夐」鏋氫妇 */
+uart.IOC_SET_CMD = {
+    /* 璁剧疆KBW閫氶亾鐨勯厤缃弬鏁� */
+    CHANNEL_IOC_SET_KBW_CONFIG      : 1,
+    /* 璁剧疆KBW閫氶亾鐨勪笂浣嶆満鍙傛暟 */
+    CHANNEL_IOC_SET_KBW_UPPER       : 2,
+    /* KBW涓婄嚎鏃堕棿 */
+    CHANNEL_IOC_SET_KBW_UPTIME      : 3,
+    /* KBW涓嬬嚎鏃堕棿 */
+    CHANNEL_IOC_SET_KBW_DOWNTIME    : 4,
+    /* 璁剧疆HID閫氶亾鐨勬姤鍛婇暱搴� */
+    CHANNEL_IOC_SET_HID_REPORT_LEN  : 5,
+    /* 璁剧疆UART閫氶亾鐨勫弬鏁� */
+    CHANNEL_IOC_SET_UART_PARAM      : 6,
+    /* 璁剧疆闊︽牴閫氶亾鐨勫伐浣滄ā寮� */
+    CHANNEL_IOC_SET_WIEGAND_MODE    : 7,
+    /* 璁剧疆闊︽牴閫氶亾鐨凣PIO閰嶇疆 */
+    CHANNEL_IOC_SET_WIEGAND_GPIO    : 8,
+    /* 璁剧疆闊︽牴閫氶亾鐨勫欢杩熸椂闂� */
+    CHANNEL_IOC_SET_WIEGAND_DELAY   : 9,
+    /* 璁剧疆闊︽牴閫氶亾鐨勬棩蹇楄褰曞姛鑳� */
+    CHANNEL_IOC_SET_WIEGAND_LOG     : 10
+
+};
+
+/* 闊︽牴閫氶亾鐨勪笉鍚屽伐浣滄ā寮� */
+uart.WIEGAND_MODE = {
+    /* 闊︽牴妯″紡鍒濆鍖栧�� */
+    WIEGAND_MODE_INIT      : 0,
+    /* 闊︽牴 26 浣嶆ā寮� */
+    WIEGAND_MODE_26		  : 1,
+    /* 闊︽牴 34 浣嶆ā寮� */
+    WIEGAND_MODE_34		  : 2,
+    /* 闊︽牴 128 浣嶆ā寮� */
+    WIEGAND_MODE_128       : 3,
+    /* 闊︽牴 256 浣嶆ā寮� */
+    WIEGAND_MODE_256       : 4,
+    /* 闊︽牴 2048 浣嶆ā寮� */
+    WIEGAND_MODE_2048      : 5,
+    /* 鑷畾涔夌殑闊︽牴妯″紡, 鏈�澶у彂閫� 6400 浣� */
+    WIEGAND_MODE_CUSTOM    : 6
+};
+
+/**
+ * 鎵撳紑淇¢亾
+ * @param {number} type 閫氶亾绫诲瀷锛屽弬鑰冩灇涓� TYPE锛屽繀濉�
+ * @param {string} path 涓嶅悓鐨勮澶囨垨鍚屼竴璁惧鐨勪笉鍚岀被鍨嬮�氶亾瀵瑰簲鐨刾ath涓嶄竴鏍凤紝姣斿DW200鐨�485瀵瑰簲鐨勫�兼槸"/dev/ttyS2"锛屽繀濉�
+ * @param {string} id 鍙ユ焺id锛岄潪蹇呭~锛堣嫢鎵撳紑澶氫釜瀹炰緥闇�瑕佷紶鍏ュ敮涓�id锛�
+ */
+uart.open = function (type, path, id) {
+	if (type === undefined || type === null) {
+		throw new Error("uart.open:'type' should not be null or empty")
+	}
+	if (path === undefined || path === null) {
+		throw new Error("uart.open:'path' should not be null or empty")
+	}
+
+	let pointer = uartObj.open(type, path);
+
+	if (pointer === undefined || pointer === null) {
+		throw new Error("uart.open: open failed")
+	}
+
+	dxCommon.handleId("uart", id, pointer)
+}
+
+/**
+ * 淇¢亾鏁版嵁鍙戦��
+ * @param {ArrayBuffer} buffer 瑕佸彂閫佺殑鏁版嵁锛屽繀濉�
+ * @param {string} id 鍙ユ焺id锛岄潪蹇呭~锛堥渶淇濇寔鍜宨nit涓殑id涓�鑷达級
+ * @returns true/false
+ */
+uart.send = function (buffer, id) {
+	if (buffer === undefined || buffer === null) {
+		throw new Error("uart.send: 'buffer' should not be null or empty")
+	}
+	let pointer = dxCommon.handleId("uart", id)
+
+	return uartObj.send(pointer, buffer);
+}
+
+/**
+ * 淇¢亾鏁版嵁鍙戦�侊紝浣跨敤寰厜閫氫俊鍗忚鏍煎紡
+ * @param {string/object} data 瑕佸彂閫佺殑鏁版嵁锛屽繀濉�
+ * @param {string} id 鍙ユ焺id锛岄潪蹇呭~锛堥渶淇濇寔鍜宨nit涓殑id涓�鑷达級
+ * @returns true/false
+ */
+uart.sendVg = function (data, id) {
+	if (!data) {
+        return
+    }
+    if (typeof data === 'string') {
+        uart.send(dxCommon.hexStringToArrayBuffer(data), id)
+        return
+    }
+    let pack = '55aa' + data.cmd
+    if (data.hasOwnProperty('result')) {
+        pack += data.result
+    }
+    pack += (data.length % 256).toString(16).padStart(2, '0')
+    pack += (Math.floor(data.length / 256)).toString(16).padStart(2, '0')
+    pack += data.data
+    let all = dxCommon.hexToArr(pack)
+    let bcc = dxCommon.calculateBcc(all)
+    all.push(bcc)
+    uart.send(new Uint8Array(all).buffer, id)
+}
+
+/**
+ * 鎺ユ敹鏁版嵁锛岄渶瑕佸湪绾跨▼閲岃疆璇㈠幓鑾峰彇,杩斿洖Uint8Array绫诲瀷
+ * 濡傛灉鎺ユ敹鍒扮殑鏁版嵁娌℃湁杈惧埌size闀垮害锛屼細缁х画绛夊緟鐩村埌鎺ユ敹鍒皊ize闀垮害锛屼絾鏄鏋渢imeout寰堢煭锛屽氨浼氭湁鍙兘娌℃敹瀹屽氨缁撴潫杩欎竴娆℃搷浣�
+ * @param {number} size 鎺ユ敹鏁版嵁鐨勫瓧鑺傛暟锛屽繀濉�
+ * @param {number} timeout 瓒呮椂鏃堕棿锛堟绉掞級杩欎釜鍑芥暟浼氶樆濉炵瓑寰呮渶澶氳繖涓椂闂村氨缁撴潫锛屽鏋滄彁鍓嶆帴鏀跺埌浜唖ize涓暟鎹篃浼氱粨鏉燂紝闈炲繀濉紝缂虹渷鏄�10ms
+ * @param {string} id 鍙ユ焺id锛岄潪蹇呭~锛堥渶淇濇寔鍜宨nit涓殑id涓�鑷达級
+ * @returns Uint8Array,杩斿洖鍊肩殑byteLength琛ㄧず鎺ユ敹鍒扮殑闀垮害锛屽鏋滀负0琛ㄧず娌℃湁鎺ユ敹鍒颁换浣曟暟鎹�
+ */
+uart.receive = function (size, timeout, id) {
+	if (size === undefined || size === null) {
+		throw new Error("uart.receive:'size' should not be null or empty")
+	}
+
+	if (timeout === undefined || timeout === null) {
+		timeout = 10
+	}
+
+	let pointer = dxCommon.handleId("uart", id)
+
+	let res = uartObj.receive(pointer, size, timeout)
+	if (res === null) {
+		return null
+	}
+	return new Uint8Array(res)
+}
+
+/**
+ * 璋冪敤淇¢亾鐗规畩IO鎺ュ彛
+ * @param {*} request 
+ * @param {*} arg 
+ * @param {string} id 鍙ユ焺id锛岄潪蹇呭~锛堥渶淇濇寔鍜宨nit涓殑id涓�鑷达級
+ * @returns true/false
+ */
+uart.ioctl = function (request, arg, id) {
+	let pointer = dxCommon.handleId("uart", id)
+
+	return uartObj.ioctl(pointer, request, arg)
+}
+
+/**
+ * 鍏抽棴淇¢亾
+ * @param {string} id 鍙ユ焺id锛岄潪蹇呭~锛堥渶淇濇寔鍜宨nit涓殑id涓�鑷达級
+ * @returns true/false
+ */
+uart.close = function (id) {
+	let pointer = dxCommon.handleId("uart", id)
+
+	return uartObj.close(pointer)
+}
+
+
+/**
+ * 鍒锋柊淇¢亾
+ * @param {number} queue_selector 蹇呭~
+ * @param {string} id 鍙ユ焺id锛岄潪蹇呭~锛堥渶淇濇寔鍜宨nit涓殑id涓�鑷达級
+ * @returns true/false
+ */
+uart.flush = function (queue_selector, id) {
+	if (queue_selector == null) {
+		throw new Error("queue_selector should not be null or empty")
+	}
+	let pointer = dxCommon.handleId("uart", id)
+
+	return uartObj.flush(pointer, queue_selector);
+}
+
+
+uart.VG = {
+	RECEIVE_MSG: '__uartvg__MsgReceive',
+}
+
+/**
+ * 绠�鍖栧井鍏夐�氫俊鍗忚鐨勪娇鐢紝
+ * 1. 鎺ュ彈鏁版嵁锛氭妸TLV鐨勪簩杩涘埗鐨勬暟鎹帴鍙楀埌鍚庤В鏋愭垚瀵硅薄锛屽苟浠ventbus鐨別vent鍙戦�佸嚭鍘�(uart.VG.RECEIVE_MSG+options.id)
+ * 杩斿洖鐨勫璞℃牸寮忥細{cmd:"2a",result:"01",length:7,data:"0a1acc320fee32",bcc:true}
+ * cmd: 1涓瓧鑺傜殑鍛戒护瀛楋紝16杩涘埗瀛楃涓�
+ * result:1涓瓧鑺傜殑鏍囪瘑瀛楋紝琛ㄧず鏁版嵁澶勭悊鐨勭粨鏋滐紝鎴愬姛鎴栧け璐ユ垨鍏朵粬鐘舵�併�傚彧鏈夊弽棣堟暟鎹墠鏈夋爣璇嗗瓧锛�16杩涘埗瀛楃涓�
+ * length锛氭暟鎹殑闀垮害锛屽湪TLV閲岀敤2涓瓧鑺傛潵瀹氫箟锛岃繖閲岀洿鎺ヨ浆鎴�10杩涘埗鐨勬暟瀛�
+ * data锛氬涓瓧鑺傜殑鏁版嵁鍩燂紝16杩涘埗瀛楃涓�
+ * bcc: bcc鏍¢獙鎴愬姛鎴栧け璐�
+ * 2. 鍙戦�佹暟鎹細鎶婂璞¤浆鎴怲LV鏍煎紡鐨勪簩杩涘埗鏁版嵁鍐嶅彂閫佸嚭鍘伙紝鍙互閫氳繃uart.sendVg('瑕佸彂閫佺殑鏁版嵁',id)锛屾暟鎹牸寮忓涓�
+ * 鍙戦�佺殑鏁版嵁鏍煎紡鏈変簩绉� 1.瀵硅薄鏍煎紡 锛歿cmd:"2a",result:"01",length:7,data:"0a1acc320fee32"} 2. 瀹屾暣鐨�16杩涘埗瀛楃涓�'55AA09000000F6'
+ * 3. 鍚屾牱鐨刬d锛屽娆¤皟鐢╮unvg涔熷彧浼氭墽琛屼竴娆�
+ * 
+ * @param {object} options 鍚姩鐨勫弬鏁�
+ *			@param {number} options.type 閫氶亾绫诲瀷锛屽弬鑰冩灇涓� TYPE锛屽繀濉�  锛堝吋瀹筓SBHID鍧椾紶杈擄紝榛樿1024姣忓潡锛�
+ *			@param {string} options.path 涓嶅悓鐨勮澶囨垨鍚屼竴璁惧鐨勪笉鍚岀被鍨嬮�氶亾瀵瑰簲鐨刾ath涓嶄竴鏍凤紝姣斿DW200鐨�485瀵瑰簲鐨勫�兼槸"/dev/ttyS2"锛屽繀濉�
+ *			@param {number} options.result 0鍜�1(缂虹渷鏄�0)锛屾爣璇嗘槸鎺ユ敹鐨勬暟鎹繕鏄彂閫佺殑鏁版嵁鍖呭惈鏍囪瘑瀛楄妭锛�0琛ㄧず鎺ュ彈鐨勬暟鎹笉鍖呮嫭鏍囪瘑瀛楋紝鍙戦�佺殑鏁版嵁鍖呮嫭锛�1鏄弽涔�
+ *			@param {number} options.passThrough passThrough涓簍rue鍒欐帴鏀剁殑鏁版嵁浣跨敤閫忎紶妯″紡锛岄潪蹇呭~
+ *          @param {string} options.id  鍙ユ焺id锛岄潪蹇呭~锛堣嫢鍒濆鍖栧涓疄渚嬮渶瑕佷紶鍏ュ敮涓�id锛�
+ */
+uart.runvg = function (options) {
+	if (options === undefined || options.length === 0) {
+		throw new Error("dxuart.runvg:'options' parameter should not be null or empty")
+	}
+	if (options.id === undefined || options.id === null || typeof options.id !== 'string') {
+        // 鍙ユ焺id
+        options.id = ""
+    }
+	if (options.type === undefined || options.type === null) {
+		throw new Error("dxuart.runvg:'type' should not be null or empty")
+	}
+	if (options.path === undefined || options.path === null) {
+		throw new Error("dxuart.runvg:'path' should not be null or empty")
+	}
+	let oldfilepre = '/app/code/dxmodules/vgUartWorker'
+	let content = std.loadFile(oldfilepre + '.js').replace("{{id}}", options.id)
+	let newfile = oldfilepre + options.id + '.js'
+	std.saveFile(newfile, content)
+	let init = map.get("__vguart__run_init" + options.id)
+	if (!init) {//纭繚鍙垵濮嬪寲涓�娆�
+		map.put("__vguart__run_init" + options.id, options)
+		bus.newWorker(options.id || "__uart",newfile)
+	}
+}
+export default uart;
\ No newline at end of file
diff --git a/vf205_access/dxmodules/dxUi.js b/vf205_access/dxmodules/dxUi.js
new file mode 100644
index 0000000..bae9902
--- /dev/null
+++ b/vf205_access/dxmodules/dxUi.js
@@ -0,0 +1,216 @@
+//build:20240724
+/**
+ * UI 鐨勫熀纭�缁勪欢锛岄渶瑕佸厛浜嗚В涓�浜涙蹇�
+ * 1. 鍥惧眰锛氳澶囧叿澶�2涓熀鏈浘灞傦紝涓诲浘灞傦紙main锛夊拰椤堕儴鍥惧眰锛坱op锛�
+      鍏朵腑TOP鍥惧眰姘歌繙鍦ㄤ富鍥惧眰涔嬩笂锛屼富鍥惧眰鍒囨崲椤甸潰涓嶄細鎸′綇TOP鍥惧眰锛孴OP鍥惧眰鐢ㄤ簬鏄剧ず涓�浜涚姸鎬佹爮鏄瘮杈冨悎閫傜殑銆�
+      鍏朵腑涓诲浘灞傚彲浠ラ鍏堝湪鍐呭瓨涓瀯閫犲涓〉闈紝鐒跺悗閫氳繃loadMain鏉ュ姞杞藉垏鎹笉鍚岀殑椤甸潰銆傝�孴OP鍥惧眰涓嶈兘鍒囨崲锛屽彧鑳借ui瀵硅薄闅愯棌鎴栧垹闄�
+
+ * 2. UI瀵硅薄锛氭湁寰堝绉嶇被鐨刄I瀵硅薄锛屽叾涓渶鍩虹鐨勬槸 'view' 瀵硅薄锛屼富鍥惧眰鍜岄《閮ㄥ浘灞傜殑鏍箄i瀵硅薄蹇呴』鏄� 'view'瀵硅薄锛屽墿涓嬬殑 ui 瀵硅薄閮芥槸鏌愪釜 ui 瀵硅薄鐨勫瓙ui銆�
+      ui瀵硅薄鍖呮嫭甯歌鐨� 'button'銆�'label'銆�'image'绛夌瓑锛屾墍鏈夊璞¢兘鏈変竴浜涢�氱敤鐨勫睘鎬э紝涔熸湁涓�浜涚嫭鐗圭殑灞炴��
+      鎵�鏈� ui 瀵硅薄閮芥湁鍏ㄥ眬鍞竴鐨� id 锛屼笉鑳介噸澶嶃�傞�氱敤鐨勫睘鎬ц繕鍖呮嫭
+      - type锛氳幏鍙杣i瀵硅薄鐨勭被鍨嬶紝瀛楃涓�
+      - parent锛氳幏鍙杣i瀵硅薄鐨勭埗鑺傜偣锛屽瓧绗︿覆
+      - children锛氳幏鍙杣i瀵硅薄鐨勬墍鏈夊瓙瀵硅薄鐨刬d锛屽瓧绗︿覆鏁扮粍
+
+ * 3. dxui鏂囦欢锛氫互.dxui涓烘墿灞曞悕鐨勬枃浠舵槸鍒╃敤鍙鍖栨嫋鎷藉伐鍏风敓鎴愮殑 ui 鏍�,宸ュ叿浼氳嚜鍔ㄧ敓鎴愬搴旂殑js鏂囦欢锛屽彲浠mport瀵瑰簲鐨刯s鏂囦欢鏉ユ搷浣�
+
+ */
+
+import logger from './dxLogger.js'
+import utils from './uiUtils.js'
+import button from './uiButton.js'
+import font from './uiFont.js'
+import image from './uiImage.js'
+import label from './uiLabel.js'
+import line from './uiLine.js'
+import list from './uiList.js'
+import dropdown from './uiDropdown.js'
+import checkbox from './uiCheckbox.js'
+import slider from './uiSlider.js'
+import _switch from './uiSwitch.js'
+import textarea from './uiTextarea.js'
+import keyboard from './uiKeyboard.js'
+import style from './uiStyle.js'
+import view from './uiView.js'
+import buttons from './uiButtons.js'
+
+const dxui = {}
+dxui.Button = button
+dxui.Font = font
+dxui.Image = image
+dxui.Label = label
+dxui.Line = line
+dxui.List = list
+dxui.Dropdown = dropdown
+dxui.Checkbox = checkbox
+dxui.Slider = slider
+dxui.Switch = _switch
+dxui.Textarea = textarea
+dxui.Keyboard = keyboard
+dxui.Style = style
+dxui.View = view
+dxui.Utils = utils
+dxui.Buttons = buttons
+let orientation = 1 //榛樿妯睆
+/**
+ * 鍒濆鍖栵紝蹇呴』鍦ㄤ唬鐮佹渶鍓嶉潰璋冪敤
+ * @param {object} options 鍒濆鍖栧弬鏁�
+ *        @param {number} options.orientation 灞忓箷鏂瑰悜 鍙互涓�0锛�1锛�2锛�3锛屽垎鍒〃绀虹珫灞忥紝灞忓箷鍦ㄥ乏锛涙í灞忥紝灞忓箷鍦ㄤ笂锛涚珫灞忥紝灞忓箷鍦ㄥ彸锛涙í鎵癸紝灞忓箷鍦ㄤ笅
+ * @param {object} context 涓婁笅鏂囷紝姣忎釜搴旂敤閮芥湁鍞竴鐨勪竴涓笂涓嬫枃鍙橀噺锛屼笉鍚岀殑js鍙互閮藉紩鐢╠xUi.js锛屼絾鏄痗ontext蹇呴』涓�鑷� 
+*/
+dxui.init = function (options, context = {}) {
+     this.initContext(context)
+     if (options && options.orientation != undefined && options.orientation != null && [0, 1, 2, 3].includes(options.orientation)) {
+          orientation = options.orientation
+     }
+     utils.GG.NativeDisp.lvDispSetRotation(orientation)
+}
+/**
+ * 鍒濆鍖栦笂涓嬫枃锛屾瘡涓簲鐢ㄩ兘鏈夊敮涓�鐨勪竴涓笂涓嬫枃鍙橀噺锛屼笉鍚岀殑js鍙互閮藉紩鐢╠xUi.js锛屼絾鏄痗ontext蹇呴』涓�鑷�
+ * 鍦ㄦ瀯寤簎i鍓嶉渶瑕佸垵濮嬪寲
+ * @param {object} context 鍒濆鏄竴涓┖瀵硅薄{}
+ */
+dxui.initContext = function (context) {
+     utils.validateObject(context)
+     dxui.all = context
+     dxui.Button.all = dxui.all
+     dxui.Image.all = dxui.all
+     dxui.Label.all = dxui.all
+     dxui.Line.all = dxui.all
+     dxui.List.all = dxui.all
+     dxui.Dropdown.all = dxui.all
+     dxui.Checkbox.all = dxui.all
+     dxui.Slider.all = dxui.all
+     dxui.Switch.all = dxui.all
+     dxui.Textarea.all = dxui.all
+     dxui.Keyboard.all = dxui.all
+     dxui.View.all = dxui.all
+     dxui.Buttons.all = dxui.all
+}
+/**
+ * 鏍规嵁id鑾峰彇宸茬粡鏋勫缓鐨剈i瀵硅薄
+ * @param {string} id 
+ * @returns 
+ */
+dxui.getUi = function (id) {
+     return dxui.all[id]
+}
+/**
+ * 澶栭儴寰幆闇�瑕佽皟鐢ㄦ鏂规硶
+ */
+dxui.handler = function () {
+     return utils.GG.NativeTimer.lvTimerHandler()
+}
+/**
+ * 鑾峰彇灞忓箷鏂瑰悜锛屼笉鍚岀殑灞忓箷鏂瑰悜鍙兘瑕佸姞杞戒笉鍚岀殑ui鎴栦笉鍚岀殑澶勭悊閫昏緫
+ * @returns 鍙互涓�0锛�1锛�2锛�3锛屽垎鍒〃绀虹珫灞忥紝灞忓箷鍦ㄥ乏锛涙í灞忥紝灞忓箷鍦ㄤ笂锛涚珫灞忥紝灞忓箷鍦ㄥ彸锛涙í鎵癸紝灞忓箷鍦ㄤ笅
+ */
+dxui.getOrientation = function () {
+     return orientation;
+}
+/**
+ * 鍒涘缓涓�涓畾鏃跺櫒锛屾瘡闅攎s姣鎵ц涓�娆″洖璋冨嚱鏁帮紝涓昏鐢ㄤ簬瀹氭椂鍒锋柊鏌愪釜ui瀵硅薄鐨勫��
+ * 鍙互鍦ㄥ洖璋冨嚱鏁伴噷鍒犻櫎瀹氭椂鍣�(clearInterval)鏉ュ疄鐜皊etTimeout鐨勬晥鏋�
+ * @param {string} id 瀹氭椂鍣ㄧ殑鍞竴鏍囪瘑 蹇呭~
+ * @param {function} callback 鍥炶皟鍑芥暟锛堝彲浠ユ槸鍖垮悕鍑芥暟锛�
+ * @param {number} ms 姣鏁�
+ * @param {object} user_data 鐢ㄦ埛鏁版嵁锛屼紶閫掔粰鍥炶皟鍙傛暟
+ * @returns 瀹氭椂鍣ㄥ彞鏌� 
+ */
+dxui.setInterval = function (id, callback, ms, user_data) {
+     if (utils.validateId(dxui.all, id))
+          if (!callback || (typeof callback != 'function') || !callback.name || callback.name === '') {
+               throw new Error('The callback should not be null and should be named function')
+          }
+     if (!ms || (typeof ms != 'number')) {
+          throw new Error('The interval should not be empty, and should be number')
+     }
+     if (!this.all.__interval) {
+          this.all.__interval = {}
+     }
+     this.all.__interval[id] = utils.GG.NativeTimer.lvTimerCreate(callback, ms, user_data)
+}
+/**
+ * 瀹氭椂鍣ㄤ笉鍐嶉渶瑕佸悗锛屽彲浠ュ垹闄よ繖涓畾鏃跺櫒
+ * @param {string} id 瀹氭椂鍣╥d 
+ */
+dxui.clearInterval = function (id) {
+     if (!dxui.all[id]) {
+          return
+     }
+     utils.GG.NativeTimer.lvTimerDel(dxui.all[id])
+     delete dxui.all.__interval[id]
+}
+/**
+ * 鑾峰彇ui瀵硅薄鐨勭埗瀵硅薄
+ * @param {Object} ui 
+ */
+dxui.getParent = function (ui) {
+     if (ui.parent) {
+          return dxui.getUi(ui.parent)
+     }
+     return null
+}
+/**
+ * 鍒犻櫎褰撳墠鑷韩ui瀵硅薄
+ */
+dxui.del = function (ui) {
+     function recursiveDelete(ui) {
+          // 濡傛灉瀵硅薄涓嶅瓨鍦紝鐩存帴杩斿洖
+          if (!dxui.all[ui.id]) {
+               return;
+          }
+
+          // 鍏堥�掑綊鍒犻櫎鎵�鏈夊瓙瀵硅薄
+          if (ui.children && Array.isArray(ui.children)) {
+               // 鍊掑簭閬嶅巻瀛愯妭鐐�
+               for (let i = ui.children.length - 1; i >= 0; i--) {
+                    const childId = ui.children[i];
+                    if (dxui.all[childId]) {
+                         recursiveDelete(dxui.all[childId]);
+                    }
+               }
+          }
+          // 浠庣埗瀵硅薄涓Щ闄ゅ綋鍓嶅璞�
+          if (ui.parent && dxui.all[ui.parent] && Array.isArray(dxui.all[ui.parent].children)) {
+               const children = dxui.all[ui.parent].children
+               let index = children.indexOf(ui.id);
+               if (index !== -1) {
+                    children.splice(index, 1);
+               }
+          }
+
+          // 鍒犻櫎褰撳墠瀵硅薄
+          ui.obj.lvObjDel();
+          delete dxui.all[ui.id];
+     }
+
+     // 寮�濮嬮�掑綊鍒犻櫎
+     recursiveDelete(ui);
+}
+/**
+ * 鍦ㄤ富鍥惧眰鍔犺浇锛堝垏鎹級宸茬粡鏋勫缓濂界殑 ui 瀵硅薄锛�
+ * @param {object} ui 浣跨敤build鍑芥暟鏋勫缓鐨� ui 瀵硅薄
+ */
+dxui.loadMain = function (ui) {
+     if (!ui || !ui.obj) {
+          throw new Error("dxui.loadMain:'ui' paramter should not be null")
+     }
+     // 鍔犺浇涓诲睆骞�
+     utils.GG.NativeDisp.lvScrLoad(ui.obj)
+}
+/**
+ * 浠庢渶鍚庝竴涓敤鎴锋椿鍔ㄦ樉绀�(濡傜偣鍑�)缁忚繃鐨勬椂闂�
+ * @returns 杩斿洖浠庢渶鍚庝竴涓椿鍔ㄥ紑濮嬬殑缁忚繃鏃堕棿(姣)
+ */
+dxui.getIdleDuration = function () {
+     return utils.GG.NativeDisp.lvDispGetInactiveTime()
+}
+/**
+ * 閲嶇疆鐢ㄦ埛娲诲姩鏄剧ず(濡傜偣鍑�)缁忚繃鐨勬椂闂�
+ */
+dxui.trigActivity = function () {
+     utils.GG.NativeDisp.lvDispTrigActivity()
+}
+
+export default dxui;
\ No newline at end of file
diff --git a/vf205_access/dxmodules/dxWatchdog.js b/vf205_access/dxmodules/dxWatchdog.js
new file mode 100644
index 0000000..963949b
--- /dev/null
+++ b/vf205_access/dxmodules/dxWatchdog.js
@@ -0,0 +1,123 @@
+//build 20240425
+//鐪嬮棬鐙楃粍浠讹紝鐢ㄤ簬鐩戞帶搴旂敤鏄惁鍗℃锛岃缃竴涓秴鏃舵椂闂达紝濡傛灉瓒呰繃杩欎釜鏃堕棿娌℃湁鍠傜嫍锛屼細鑷姩瑙﹀彂璁惧閲嶅惎
+//娉ㄦ剰浣跨敤鐪嬮棬鐙椾箣鍓嶅彲鑳介渶瑕佸厛鍒濆鍖杇pio
+//渚濊禆缁勪欢 dxDriver,dxLogger,dxCommon,dxMap,dxGpio
+import { watchdogClass } from './libvbar-b-dxwatchdog.so'
+import dxMap from './dxMap.js'
+import logger from './dxLogger.js'
+import dxCommon from './dxCommon.js'
+
+const map = dxMap.get("___watchdog")
+const watchdogObj = new watchdogClass();
+
+const watchdog = {}
+watchdog.last = new Date().getTime()
+/**
+ * 鎵撳紑鐪嬮棬鐙楄澶�
+ * @param {number} type 蹇呭~
+ * @param {string} id 鍙ユ焺id锛岄潪蹇呭~锛堣嫢鍒濆鍖栧涓疄渚嬮渶瑕佷紶鍏ュ敮涓�id锛�
+ */
+watchdog.open = function (type, id) {
+	let pointer = watchdogObj.open(type)
+	if (pointer === undefined || pointer === null) {
+		throw new Error("watchdog.open: open failed")
+	}
+	dxCommon.handleId("watchdog", id, pointer)
+}
+/**
+ * 鎺у埗鎸囧畾閫氶亾寮�鍏�
+ * @param {number} chan 閫氶亾id,蹇呭~
+ * @param {string} id 鍙ユ焺id锛岄潪蹇呭~锛堥渶淇濇寔鍜宨nit涓殑id涓�鑷达級
+ * @returns true/false
+ */
+watchdog.enable = function (chan, id) {
+	let pointer = dxCommon.handleId("watchdog", id)
+	return watchdogObj.enable(pointer, chan)
+}
+/**
+ * 寮�鍚湅闂ㄧ嫍鎬诲畾鏃跺櫒
+ * @param {*} timeout 蹇呭~
+ * @param {string} id 鍙ユ焺id锛岄潪蹇呭~锛堥渶淇濇寔鍜宨nit涓殑id涓�鑷达級
+ * @returns true/false
+ */
+watchdog.start = function (timeout, id) {
+	let pointer = dxCommon.handleId("watchdog", id)
+	return watchdogObj.start(pointer, timeout)
+}
+/**
+ * 鍒ゆ柇鏄惁鏄笂鐢靛浣嶏紝鐪嬮棬鐙楁槸鍚﹀凡缁忓惎鍔�
+ * @param {string} id 鍙ユ焺id锛岄潪蹇呭~锛堥渶淇濇寔鍜宨nit涓殑id涓�鑷达級
+ * @returns true/false
+ */
+watchdog.isPoweron = function (id) {
+	let pointer = dxCommon.handleId("watchdog", id)
+	return watchdogObj.isPoweron(pointer)
+}
+/**
+ * 鍠傜嫍鎸囧畾閫氶亾
+ * @param {*} chan 閫氶亾id锛屽繀濉�
+ * @param {string} id 鍙ユ焺id锛岄潪蹇呭~锛堥渶淇濇寔鍜宨nit涓殑id涓�鑷达級
+ * @returns true/false
+ */
+watchdog.restart = function (chan, id) {
+	let pointer = dxCommon.handleId("watchdog", id)
+	return watchdogObj.restart(pointer, chan)
+}
+/**
+ * 鍏抽棴鐪嬮棬鐙楁�诲畾鏃跺櫒
+ * @param {string} id 鍙ユ焺id锛岄潪蹇呭~锛堥渶淇濇寔鍜宨nit涓殑id涓�鑷达級
+ * @returns true/false
+ */
+watchdog.stop = function (id) {
+	let pointer = dxCommon.handleId("watchdog", id)
+	return watchdogObj.stop(pointer)
+}
+/**
+ * 鍏抽棴鐪嬮棬鐙楄澶�
+ * @param {string} id 鍙ユ焺id锛岄潪蹇呭~锛堥渶淇濇寔鍜宨nit涓殑id涓�鑷达級
+ * @returns true/false
+ */
+watchdog.close = function (id) {
+	let pointer = dxCommon.handleId("watchdog", id)
+	return watchdogObj.close(pointer)
+}
+/**
+ * 寰幆妫�鏌ユ瘡涓嚎绋嬬殑鍠傜嫍鎯呭喌锛屼换浣曚竴涓嚎绋嬫病鏈夊杺鐙楋紝鍒欎笉鍚姩restart
+ * @param {number} chan 閫氶亾id锛屽繀濉�
+ * @param {string} id 鍙ユ焺id锛岄潪蹇呭~锛堥渶淇濇寔鍜宨nit涓殑id涓�鑷达級
+ */
+watchdog.loop = function (chan, id) {
+	const now = new Date().getTime()
+	const minus = now - watchdog.last
+	if (minus > 3000 || minus < 0) {//姣�3绉掓鏌ヤ竴娆℃垨鑰呭皬浜�0浠h〃鎿嶄綔浜嗗線鍓嶆敼鏃堕棿
+		watchdog.last = now
+		let keys = map.keys()
+		let check = true
+		for (let i = 0; i < keys.length; i++) {
+			let key = keys[i]
+			let value = map.get(key)
+			const temp = now - value.now
+			if (temp > value.timeout * 1000 && temp < 1700000000) {
+				logger.error(`The worker ${key} did not feed the dog in time.`, temp)
+				check = false
+				break
+			}
+		}
+		if (check) {
+			this.restart(chan, id)
+		}
+	}
+}
+/**
+ * 涓嶅悓鐨勭嚎绋嬪杺鐙�
+ * @param {string} flag 绾跨▼鐨勬爣璇�,蹇呭~涓嶈兘涓虹┖ 
+ * @param {number} timeout 绾跨▼鍙互澶氶暱鏃堕棿涓嶅杺鐙楋紙绉掞級锛岀己鐪佹槸10绉�
+ */
+watchdog.feed = function (flag, timeout = 10) {
+	if (!flag || flag.length <= 0) {
+		return
+	}
+	map.put(flag, { now: new Date().getTime(), timeout: timeout })
+}
+
+export default watchdog;
diff --git a/vf205_access/dxmodules/dxWorkerPool.js b/vf205_access/dxmodules/dxWorkerPool.js
new file mode 100644
index 0000000..91cbf5d
--- /dev/null
+++ b/vf205_access/dxmodules/dxWorkerPool.js
@@ -0,0 +1,167 @@
+//build:20240717
+//绾跨▼姹狅紝閲岄潰鍔犺浇澶氫釜worker锛岀嚎绋嬫睜鎺ユ敹浠诲姟鎴栦簨鍔″悗鐒跺悗娲惧彂缁欑嚎绋嬫睜閲岄潰绌洪棽鐨剋orker鏉ユ墽琛屼换鍔★紝鐢ㄤ簬瑙e喅澶氫簨鍔″鐞嗙殑鐡堕
+//璁惧璧勬簮鏈夐檺锛岀嚎绋嬫暟閲忎笉瀹滃お澶氾紝鍙﹀涔熶笉鑰冭檻澶氫釜绾跨▼姹犵殑鎯呭喌锛屽叏灞�鍙竴涓�
+//缁勪欢渚濊禆 dxLogger,dxCommon锛宒xStd
+import std from './dxStd.js'
+import logger from './dxLogger.js'
+import * as os from "os";
+//-------------------------variable--------------------
+const pool = {}
+const isMain = (os.Worker.parent === undefined)
+let queueSize = 100
+const queue = []
+const all = {}
+pool.os = os
+/**
+ * 鍒濆鍖栫嚎绋嬫睜锛岃缃畐orker涓暟鍜岀紦瀛橀槦鍒楀ぇ灏忥紝鏈夊彲鑳藉涓獁orker閮芥病鏈夌┖闂诧紝缂撳瓨闃熷垪鍙互缂撳瓨鏉ヤ笉鍙婂鐞嗙殑浜嬪姟
+ * 鍥犱负worker鍙兘閫氳繃涓荤嚎绋嬪垱寤猴紝鎵�浠nit鍑芥暟涔熷彧鑳藉湪涓荤嚎绋嬮噷鎵ц
+ * 娉ㄦ剰: worker瀵瑰簲鐨勬枃浠堕噷涓嶈兘鍖呭惈while(true)杩欑姝诲惊鐜紝鍙互鐢╯etInteval鏉ュ疄鐜板惊鐜�
+ * @param {string} file worker瀵瑰簲鐨勬枃浠跺悕锛屽繀濉紝缁濆璺緞锛岄�氬父浠�'/app/code/src'寮�濮�
+ * @param {Object} bus EventBus瀵硅薄 蹇呭~
+ * @param {Array} topics 瑕佽闃呯殑涓婚缁� 蹇呭~
+ * @param {number} count 绾跨▼鐨勪釜鏁帮紝闈炲繀濉紝涓嶈兘灏忎簬1锛岀己鐪�2,
+ * @param {number} maxsize 浜嬪姟缂撳瓨鐨勫ぇ灏忥紝闈炲繀濉紝缂虹渷100锛屽鏋滆秴杩�100锛屾渶鑰佺殑浜嬪姟琚姏寮�
+ */
+pool.init = function (file, bus, topics, count = 2, maxsize = 100) {
+    if (!file) {
+        throw new Error("pool init:'file' should not be empty")
+    }
+    if (!bus) {
+        throw new Error("pool init:'bus' should not be empty")
+    }
+    if (!topics) {
+        throw new Error("pool init:'topics' should not be empty")
+    }
+    if (!isMain) {
+        throw new Error("pool init should be invoked in main thread")
+    }
+    if (!std.exist(file)) {
+        throw new Error("pool init: file not found:" + file)
+    }
+    queueSize = maxsize
+    if (count <= 1) {
+        count = 1
+    }
+    for (let i = 0; i < count; i++) {
+        const id = 'pool__id' + i
+        let content = std.loadFile(file) + `
+import __pool from '/app/code/dxmodules/dxWorkerPool.js'
+__pool.id = '${id}'
+const __parent = __pool.os.Worker.parent
+__parent.onmessage = function (e) {
+    if (!e.data) {
+        return
+    }
+    let fun = __pool.callbackFunc
+    if (fun) {
+        try {
+            fun(e.data)
+            __parent.postMessage({ id: __pool.id })//閫氱煡澶勭悊瀹屼簡idle
+        } catch (err) {
+            __parent.postMessage({ id: __pool.id, error: err.stack })//閫氱煡澶勭悊瀹屼簡idle,浣嗘槸澶辫触浜�    
+        }
+    }
+}
+            `
+        let newfile = file + '_' + id + '.js'
+        std.saveFile(newfile, content)
+        let worker = new os.Worker(newfile)
+        all[id] = { isIdle: true, worker: worker }
+        worker.onmessage = function (data) {
+            if (!data.data) {
+                return
+            }
+            const id = data.data.id
+            if (id) {//閫氱煡澶勭悊瀹屾垚鐨勬秷鎭�
+                all[id].isIdle = true
+                if (data.data.error) {
+                    logger.error(`worker ${id} callback error:${data.data.error}`)
+                }
+            } else {
+                const topic = data.data.topic
+                if (topic) {//bus.fire鍑烘潵鐨勬秷鎭�
+                    bus.fire(topic, data.data.data)
+                }
+            }
+        }
+    }
+    for (let topic of topics) {
+        bus.on(topic, function (d) {
+            push({ topic: topic, data: d })
+        })
+    }
+
+    std.setInterval(function () {
+        Object.keys(all).forEach(key => {
+            const obj = all[key]
+            if (obj.isIdle) {
+                let event = take()
+                if (event) {
+                    obj.isIdle = false
+                    obj.worker.postMessage(event)
+                }
+            }
+        });
+    }, 5)
+}
+/**
+ * 杩斿洖绾跨▼鐨勫敮涓�鏍囪瘑id
+ * @returns worker鍞竴鏍囪瘑
+ */
+pool.getWorkerId = function () {
+    if (isMain) {
+        return 'main'
+    } else {
+        return pool.id
+    }
+}
+/**
+ * 璁㈤槄EventBus 涓婄殑浜嬪姟涓婚锛屽彲浠ヨ闃呭涓富棰�,杩欎釜鍑芥暟涔熷彧鑳藉湪涓荤嚎绋嬮噷鎵ц
+ * @param {Object} bus EventBus瀵硅薄
+ * @param {Array} topics 瑕佽闃呯殑涓婚缁�
+ */
+pool.on = function (bus, topics) {
+    if (!bus) {
+        throw new Error("pool onEventBus:'bus' should not be empty")
+    }
+    if (!topics) {
+        throw new Error("pool onEventBus:'topics' should not be empty")
+    }
+    if (!isMain) {
+        throw new Error("pool onEventBus should be invoked in main thread")
+    }
+
+}
+
+pool.callbackFunc = null
+/**
+ * worker绾跨▼璁㈤槄绾跨▼姹犵殑浜嬩欢锛屼笉鐢ㄩ�夋嫨鐗瑰畾鐨勪富棰橈紝绾跨▼姹犲叧娉ㄧ殑鎵�鏈変簨浠堕兘浼氬鐞�,
+ * 杩欎釜鍑芥暟蹇呴』鍦╳orker绾跨▼閲屾墽琛岋紝涓嶈兘鍦ㄤ富绾跨▼鎵ц
+ * @param {function} cb 浜嬩欢澶勭悊鐨勫洖璋冨嚱鏁帮紝蹇呭~
+ */
+pool.callback = function (cb) {
+    if (!cb || (typeof cb) != 'function') {
+        throw new Error("pool on :The 'callback' should be a function");
+    }
+    if (isMain) {
+        throw new Error("pool on should not be invoked in main thread")
+    }
+    pool.callbackFunc = cb
+}
+
+function push(item) {
+    if (queue.length >= queueSize) {
+        const first = JSON.stringify(queue[0])
+        logger.error(`pool queue is full,removing oldest element: ${first}`)
+        queue.shift(); // 绉婚櫎鏈�鑰佺殑鍏冪礌
+    }
+    queue.push(item);
+}
+
+function take() {
+    if (queue.length === 0) {
+        return null; // 闃熷垪涓虹┖鏃惰繑鍥� null
+    }
+    return queue.shift(); // 绉婚櫎骞惰繑鍥炴渶鏃╂坊鍔犵殑鍏冪礌
+}
+export default pool
diff --git a/vf205_access/dxmodules/faceWorker.js b/vf205_access/dxmodules/faceWorker.js
new file mode 100644
index 0000000..9b0fbc2
--- /dev/null
+++ b/vf205_access/dxmodules/faceWorker.js
@@ -0,0 +1,23 @@
+//build:20240606
+//鐢ㄤ簬绠�鍖杅ace缁勪欢寰厜閫氫俊鍗忚鐨勪娇鐢紝鎶奻ace灏佽鍦ㄨ繖涓獁orker閲岋紝浣跨敤鑰呭彧闇�瑕佽闃卐ventbus鐨勪簨浠跺氨鍙互鐩戝惉face
+import log from './dxLogger.js'
+import face from './dxFace.js'
+import std from './dxStd.js'
+
+function run() {
+    face.worker.beforeLoop()
+    log.info('face start......')
+    std.setInterval (function() {
+        try {
+            face.worker.loop()
+        } catch (error) {
+            log.error(error)
+        }
+    },10)
+}
+
+try {
+    run()
+} catch (error) {
+    log.error(error)
+}
\ No newline at end of file
diff --git a/vf205_access/dxmodules/gpioKeyWorker.js b/vf205_access/dxmodules/gpioKeyWorker.js
new file mode 100644
index 0000000..8590a4e
--- /dev/null
+++ b/vf205_access/dxmodules/gpioKeyWorker.js
@@ -0,0 +1,23 @@
+//build:20240524
+//鐢ㄤ簬绠�鍖杇pioKey缁勪欢寰厜閫氫俊鍗忚鐨勪娇鐢紝鎶奼pioKey灏佽鍦ㄨ繖涓獁orker閲岋紝浣跨敤鑰呭彧闇�瑕佽闃卐ventbus鐨勪簨浠跺氨鍙互鐩戝惉gpioKey
+import log from './dxLogger.js'
+import gpioKey from './dxGpioKey.js'
+import * as os from "os";
+import std from './dxStd.js'
+function run() {
+    gpioKey.worker.beforeLoop()
+    log.info('gpioKey start......')
+    std.setInterval(() => {
+        try {
+            gpioKey.worker.loop()
+        } catch (error) {
+            log.error(error)
+        }
+    },10)
+}
+
+try {
+    run()
+} catch (error) {
+    log.error(error)
+}
\ No newline at end of file
diff --git a/vf205_access/dxmodules/libJLReader.so b/vf205_access/dxmodules/libJLReader.so
new file mode 100644
index 0000000..4a7005b
--- /dev/null
+++ b/vf205_access/dxmodules/libJLReader.so
Binary files differ
diff --git a/vf205_access/dxmodules/libalc.so b/vf205_access/dxmodules/libalc.so
new file mode 100644
index 0000000..262f603
--- /dev/null
+++ b/vf205_access/dxmodules/libalc.so
Binary files differ
diff --git a/vf205_access/dxmodules/libid_jpg.so b/vf205_access/dxmodules/libid_jpg.so
new file mode 100644
index 0000000..65fbe33
--- /dev/null
+++ b/vf205_access/dxmodules/libid_jpg.so
Binary files differ
diff --git a/vf205_access/dxmodules/libid_jpg_codec.so b/vf205_access/dxmodules/libid_jpg_codec.so
new file mode 100644
index 0000000..7925e2a
--- /dev/null
+++ b/vf205_access/dxmodules/libid_jpg_codec.so
Binary files differ
diff --git a/vf205_access/dxmodules/libie_jpg.so b/vf205_access/dxmodules/libie_jpg.so
new file mode 100644
index 0000000..5eb005d
--- /dev/null
+++ b/vf205_access/dxmodules/libie_jpg.so
Binary files differ
diff --git a/vf205_access/dxmodules/libie_jpg_codec.so b/vf205_access/dxmodules/libie_jpg_codec.so
new file mode 100644
index 0000000..1b29084
--- /dev/null
+++ b/vf205_access/dxmodules/libie_jpg_codec.so
Binary files differ
diff --git a/vf205_access/dxmodules/liblombo_jpeg.so b/vf205_access/dxmodules/liblombo_jpeg.so
new file mode 100644
index 0000000..ab37215
--- /dev/null
+++ b/vf205_access/dxmodules/liblombo_jpeg.so
Binary files differ
diff --git a/vf205_access/dxmodules/libvbar-b-dxface.so b/vf205_access/dxmodules/libvbar-b-dxface.so
new file mode 100644
index 0000000..5c54f77
--- /dev/null
+++ b/vf205_access/dxmodules/libvbar-b-dxface.so
Binary files differ
diff --git a/vf205_access/dxmodules/libvbar-b-dxgpio.so b/vf205_access/dxmodules/libvbar-b-dxgpio.so
new file mode 100644
index 0000000..fd44d48
--- /dev/null
+++ b/vf205_access/dxmodules/libvbar-b-dxgpio.so
Binary files differ
diff --git a/vf205_access/dxmodules/libvbar-b-dxpwm.so b/vf205_access/dxmodules/libvbar-b-dxpwm.so
new file mode 100644
index 0000000..16b5dc0
--- /dev/null
+++ b/vf205_access/dxmodules/libvbar-b-dxpwm.so
Binary files differ
diff --git a/vf205_access/dxmodules/libvbar-b-dxwatchdog.so b/vf205_access/dxmodules/libvbar-b-dxwatchdog.so
new file mode 100644
index 0000000..9aac1d5
--- /dev/null
+++ b/vf205_access/dxmodules/libvbar-b-dxwatchdog.so
Binary files differ
diff --git a/vf205_access/dxmodules/libvbar-drv-audio_gain.so b/vf205_access/dxmodules/libvbar-drv-audio_gain.so
new file mode 100644
index 0000000..21237bf
--- /dev/null
+++ b/vf205_access/dxmodules/libvbar-drv-audio_gain.so
Binary files differ
diff --git a/vf205_access/dxmodules/libvbar-drv-capturer.so b/vf205_access/dxmodules/libvbar-drv-capturer.so
new file mode 100644
index 0000000..e15739d
--- /dev/null
+++ b/vf205_access/dxmodules/libvbar-drv-capturer.so
Binary files differ
diff --git a/vf205_access/dxmodules/libvbar-drv-capturer_calibration.so b/vf205_access/dxmodules/libvbar-drv-capturer_calibration.so
new file mode 100644
index 0000000..3b9d040
--- /dev/null
+++ b/vf205_access/dxmodules/libvbar-drv-capturer_calibration.so
Binary files differ
diff --git a/vf205_access/dxmodules/libvbar-drv-display.so b/vf205_access/dxmodules/libvbar-drv-display.so
new file mode 100644
index 0000000..e2a01dd
--- /dev/null
+++ b/vf205_access/dxmodules/libvbar-drv-display.so
Binary files differ
diff --git a/vf205_access/dxmodules/libvbar-drv-face.so b/vf205_access/dxmodules/libvbar-drv-face.so
new file mode 100644
index 0000000..203c6ce
--- /dev/null
+++ b/vf205_access/dxmodules/libvbar-drv-face.so
Binary files differ
diff --git a/vf205_access/dxmodules/libvbar-drv-gpio.so b/vf205_access/dxmodules/libvbar-drv-gpio.so
new file mode 100644
index 0000000..ef802b0
--- /dev/null
+++ b/vf205_access/dxmodules/libvbar-drv-gpio.so
Binary files differ
diff --git a/vf205_access/dxmodules/libvbar-drv-memory.so b/vf205_access/dxmodules/libvbar-drv-memory.so
new file mode 100644
index 0000000..338b6f6
--- /dev/null
+++ b/vf205_access/dxmodules/libvbar-drv-memory.so
Binary files differ
diff --git a/vf205_access/dxmodules/libvbar-drv-pwm.so b/vf205_access/dxmodules/libvbar-drv-pwm.so
new file mode 100644
index 0000000..9355d70
--- /dev/null
+++ b/vf205_access/dxmodules/libvbar-drv-pwm.so
Binary files differ
diff --git a/vf205_access/dxmodules/libvbar-drv-soc.so b/vf205_access/dxmodules/libvbar-drv-soc.so
new file mode 100644
index 0000000..62887bb
--- /dev/null
+++ b/vf205_access/dxmodules/libvbar-drv-soc.so
Binary files differ
diff --git a/vf205_access/dxmodules/libvbar-drv-tts.so b/vf205_access/dxmodules/libvbar-drv-tts.so
new file mode 100644
index 0000000..14480c3
--- /dev/null
+++ b/vf205_access/dxmodules/libvbar-drv-tts.so
Binary files differ
diff --git a/vf205_access/dxmodules/libvbar-drv-watchdog.so b/vf205_access/dxmodules/libvbar-drv-watchdog.so
new file mode 100644
index 0000000..34bce9a
--- /dev/null
+++ b/vf205_access/dxmodules/libvbar-drv-watchdog.so
Binary files differ
diff --git a/vf205_access/dxmodules/libvbar-m-alsa.so b/vf205_access/dxmodules/libvbar-m-alsa.so
new file mode 100644
index 0000000..44a6231
--- /dev/null
+++ b/vf205_access/dxmodules/libvbar-m-alsa.so
Binary files differ
diff --git a/vf205_access/dxmodules/libvbar-m-capturer.so b/vf205_access/dxmodules/libvbar-m-capturer.so
new file mode 100644
index 0000000..512f3b8
--- /dev/null
+++ b/vf205_access/dxmodules/libvbar-m-capturer.so
Binary files differ
diff --git a/vf205_access/dxmodules/libvbar-m-channel.so b/vf205_access/dxmodules/libvbar-m-channel.so
new file mode 100644
index 0000000..8d7c7c6
--- /dev/null
+++ b/vf205_access/dxmodules/libvbar-m-channel.so
Binary files differ
diff --git a/vf205_access/dxmodules/libvbar-m-common.so b/vf205_access/dxmodules/libvbar-m-common.so
new file mode 100644
index 0000000..a70db84
--- /dev/null
+++ b/vf205_access/dxmodules/libvbar-m-common.so
Binary files differ
diff --git a/vf205_access/dxmodules/libvbar-m-dxalsa.so b/vf205_access/dxmodules/libvbar-m-dxalsa.so
new file mode 100644
index 0000000..17f78fc
--- /dev/null
+++ b/vf205_access/dxmodules/libvbar-m-dxalsa.so
Binary files differ
diff --git a/vf205_access/dxmodules/libvbar-m-dxcapturer.so b/vf205_access/dxmodules/libvbar-m-dxcapturer.so
new file mode 100644
index 0000000..e63f0a9
--- /dev/null
+++ b/vf205_access/dxmodules/libvbar-m-dxcapturer.so
Binary files differ
diff --git a/vf205_access/dxmodules/libvbar-m-dxcapturer_calibration.so b/vf205_access/dxmodules/libvbar-m-dxcapturer_calibration.so
new file mode 100644
index 0000000..3dacb09
--- /dev/null
+++ b/vf205_access/dxmodules/libvbar-m-dxcapturer_calibration.so
Binary files differ
diff --git a/vf205_access/dxmodules/libvbar-m-dxchannel.so b/vf205_access/dxmodules/libvbar-m-dxchannel.so
new file mode 100644
index 0000000..55987ca
--- /dev/null
+++ b/vf205_access/dxmodules/libvbar-m-dxchannel.so
Binary files differ
diff --git a/vf205_access/dxmodules/libvbar-m-dxcommon.so b/vf205_access/dxmodules/libvbar-m-dxcommon.so
new file mode 100644
index 0000000..4c9f580
--- /dev/null
+++ b/vf205_access/dxmodules/libvbar-m-dxcommon.so
Binary files differ
diff --git a/vf205_access/dxmodules/libvbar-m-dxeid.so b/vf205_access/dxmodules/libvbar-m-dxeid.so
new file mode 100644
index 0000000..0ec5c15
--- /dev/null
+++ b/vf205_access/dxmodules/libvbar-m-dxeid.so
Binary files differ
diff --git a/vf205_access/dxmodules/libvbar-m-dxhttp.so b/vf205_access/dxmodules/libvbar-m-dxhttp.so
new file mode 100644
index 0000000..a654c8f
--- /dev/null
+++ b/vf205_access/dxmodules/libvbar-m-dxhttp.so
Binary files differ
diff --git a/vf205_access/dxmodules/libvbar-m-dxkey.so b/vf205_access/dxmodules/libvbar-m-dxkey.so
new file mode 100644
index 0000000..4dda42a
--- /dev/null
+++ b/vf205_access/dxmodules/libvbar-m-dxkey.so
Binary files differ
diff --git a/vf205_access/dxmodules/libvbar-m-dxmap.so b/vf205_access/dxmodules/libvbar-m-dxmap.so
new file mode 100644
index 0000000..66e69da
--- /dev/null
+++ b/vf205_access/dxmodules/libvbar-m-dxmap.so
Binary files differ
diff --git a/vf205_access/dxmodules/libvbar-m-dxmqtt.so b/vf205_access/dxmodules/libvbar-m-dxmqtt.so
new file mode 100644
index 0000000..50d60bd
--- /dev/null
+++ b/vf205_access/dxmodules/libvbar-m-dxmqtt.so
Binary files differ
diff --git a/vf205_access/dxmodules/libvbar-m-dxnet.so b/vf205_access/dxmodules/libvbar-m-dxnet.so
new file mode 100644
index 0000000..9971437
--- /dev/null
+++ b/vf205_access/dxmodules/libvbar-m-dxnet.so
Binary files differ
diff --git a/vf205_access/dxmodules/libvbar-m-dxsqlite.so b/vf205_access/dxmodules/libvbar-m-dxsqlite.so
new file mode 100644
index 0000000..95f8f56
--- /dev/null
+++ b/vf205_access/dxmodules/libvbar-m-dxsqlite.so
Binary files differ
diff --git a/vf205_access/dxmodules/libvbar-m-dxui.so b/vf205_access/dxmodules/libvbar-m-dxui.so
new file mode 100644
index 0000000..c2cd72b
--- /dev/null
+++ b/vf205_access/dxmodules/libvbar-m-dxui.so
Binary files differ
diff --git a/vf205_access/dxmodules/libvbar-m-eid.so b/vf205_access/dxmodules/libvbar-m-eid.so
new file mode 100644
index 0000000..c53fbcd
--- /dev/null
+++ b/vf205_access/dxmodules/libvbar-m-eid.so
Binary files differ
diff --git a/vf205_access/dxmodules/libvbar-m-key.so b/vf205_access/dxmodules/libvbar-m-key.so
new file mode 100644
index 0000000..db06fca
--- /dev/null
+++ b/vf205_access/dxmodules/libvbar-m-key.so
Binary files differ
diff --git a/vf205_access/dxmodules/libvbar-m-net.so b/vf205_access/dxmodules/libvbar-m-net.so
new file mode 100644
index 0000000..3e01601
--- /dev/null
+++ b/vf205_access/dxmodules/libvbar-m-net.so
Binary files differ
diff --git a/vf205_access/dxmodules/libvbar-m-vgmqtt.so b/vf205_access/dxmodules/libvbar-m-vgmqtt.so
new file mode 100644
index 0000000..ea8ae21
--- /dev/null
+++ b/vf205_access/dxmodules/libvbar-m-vgmqtt.so
Binary files differ
diff --git a/vf205_access/dxmodules/libvbar-p-dxnfc.so b/vf205_access/dxmodules/libvbar-p-dxnfc.so
new file mode 100644
index 0000000..f3561a4
--- /dev/null
+++ b/vf205_access/dxmodules/libvbar-p-dxnfc.so
Binary files differ
diff --git a/vf205_access/dxmodules/libvbar-p-nfc.so b/vf205_access/dxmodules/libvbar-p-nfc.so
new file mode 100644
index 0000000..d341cdf
--- /dev/null
+++ b/vf205_access/dxmodules/libvbar-p-nfc.so
Binary files differ
diff --git a/vf205_access/dxmodules/libvccore.so b/vf205_access/dxmodules/libvccore.so
new file mode 100644
index 0000000..3b40d88
--- /dev/null
+++ b/vf205_access/dxmodules/libvccore.so
Binary files differ
diff --git a/vf205_access/dxmodules/libyuv.so b/vf205_access/dxmodules/libyuv.so
new file mode 100644
index 0000000..1ed6931
--- /dev/null
+++ b/vf205_access/dxmodules/libyuv.so
Binary files differ
diff --git a/vf205_access/dxmodules/mqttWorker.js b/vf205_access/dxmodules/mqttWorker.js
new file mode 100644
index 0000000..bf2083d
--- /dev/null
+++ b/vf205_access/dxmodules/mqttWorker.js
@@ -0,0 +1,64 @@
+//build:20240524
+//鐢ㄤ簬绠�鍖杕qtt缁勪欢寰厜閫氫俊鍗忚鐨勪娇鐢紝鎶妋qtt灏佽鍦ㄨ繖涓獁orker閲岋紝浣跨敤鑰呭彧闇�瑕佽闃卐ventcenter鐨勪簨浠跺氨鍙互鐩戝惉mqtt
+import log from './dxLogger.js'
+import net from './dxNet.js'
+import mqtt from './dxMqtt.js'
+import dxMap from './dxMap.js'
+import std from './dxStd.js'
+import * as os from "os";
+const map = dxMap.get('default')
+const id = "{{id}}"
+const options = map.get("__mqtt__run_init" + id)
+let connected = false
+function run() {
+    mqtt.init(options.mqttAddr, options.clientId, options.username, options.password, options.prefix, options.qos, options.willTopic, options.willMessage, options.id)
+    log.info('mqtt start......,id =', id)
+    os.sleep(2000)//绛夊緟2绉�
+
+    __bus.on(mqtt.RECONNECT, (options) => {
+        mqtt.destroy(options.id)
+        mqtt.init(options.mqttAddr, options.clientId, options.username, options.password, options.prefix, options.qos, options.willTopic, options.willMessage, options.id)
+    })
+
+    std.setInterval(() => {
+        try {
+            if (mqtt.isConnected(options.id) && net.getStatus().connected) {
+                if (!connected) {
+                    _fireChange(true)
+                    if (options.subs) {
+                        mqtt.subscribes(options.subs, options.qos, options.id)
+                    }
+                }
+            } else {
+                if (connected) {
+                    _fireChange(false)
+                }
+                // 閲嶈繛
+                mqtt.reconnect(options.willTopic, options.willMessage, options.id)
+                os.sleep(2000)//閲嶈繛鍚庣瓑寰�2绉�
+            }
+        } catch (error) {
+            log.error(error)
+        }
+    }, 3000)
+    std.setInterval(() => {
+        // 杩炴帴鎴愬姛鍚庤繘鍏ユ秷鎭洃鍚�
+        if (connected) {
+            if (!mqtt.msgIsEmpty(options.id)) {
+                let msg = mqtt.receive(options.id)
+                __bus.fire(mqtt.RECEIVE_MSG + options.id, msg)//bus.newworker鐨勬椂鍊欎細import eventbus as __bus
+            }
+        }
+    }, 10);
+}
+
+try {
+    run()
+} catch (error) {
+    log.error(error)
+}
+
+function _fireChange(status) {
+    __bus.fire(mqtt.CONNECTED_CHANGED + options.id, status ? 'connected' : 'disconnected')//bus.newworker鐨勬椂鍊欎細import eventbus as __bus
+    connected = status
+}
diff --git a/vf205_access/dxmodules/netWorker.js b/vf205_access/dxmodules/netWorker.js
new file mode 100644
index 0000000..8b77c79
--- /dev/null
+++ b/vf205_access/dxmodules/netWorker.js
@@ -0,0 +1,25 @@
+//build:20240525
+//鐢ㄤ簬绠�鍖杗et缁勪欢寰厜閫氫俊鍗忚鐨勪娇鐢紝鎶妌et灏佽鍦ㄨ繖涓獁orker閲岋紝浣跨敤鑰呭彧闇�瑕佽闃卐ventcenter鐨勪簨浠跺氨鍙互鐩戝惉net
+import log from './dxLogger.js'
+import net from './dxNet.js'
+import dxMap from './dxMap.js'
+import std from './dxStd.js'
+const map = dxMap.get('default')
+const options = map.get("__net__run_init")
+
+function run() {
+    net.worker.beforeLoop(options)
+    log.info('net worker start......')
+    std.setInterval (function() {
+        try {
+            net.worker.loop()
+        } catch (error) {
+            log.error(error)
+        }
+    },100)
+}
+try {
+    run()
+} catch (error) {
+    log.error(error)
+}
diff --git a/vf205_access/dxmodules/nfcWorker.js b/vf205_access/dxmodules/nfcWorker.js
new file mode 100644
index 0000000..c824cac
--- /dev/null
+++ b/vf205_access/dxmodules/nfcWorker.js
@@ -0,0 +1,27 @@
+//build:20240524
+//鐢ㄤ簬绠�鍖杗fc缁勪欢寰厜閫氫俊鍗忚鐨勪娇鐢紝鎶妌fc灏佽鍦ㄨ繖涓獁orker閲岋紝浣跨敤鑰呭彧闇�瑕佽闃卐ventcenter鐨勪簨浠跺氨鍙互鐩戝惉nfc
+import log from './dxLogger.js'
+import nfc from './dxNfc.js'
+import dxMap from './dxMap.js'
+import std from './dxStd.js'
+import * as os from "os";
+const map = dxMap.get('default')
+const options = map.get("__nfc__run_init")
+
+function run() {
+    nfc.worker.beforeLoop(options)
+    log.info('nfc start......')
+    std.setInterval(() => {
+        try {
+            nfc.worker.loop(options)
+        } catch (error) {
+            log.error(error)
+        }
+    }, 10)
+}
+
+try {
+    run()
+} catch (error) {
+    log.error(error)
+}
\ No newline at end of file
diff --git a/vf205_access/dxmodules/uiBase.js b/vf205_access/dxmodules/uiBase.js
new file mode 100644
index 0000000..4b2514c
--- /dev/null
+++ b/vf205_access/dxmodules/uiBase.js
@@ -0,0 +1,582 @@
+//build:20240524
+/**
+ * UI鐨勫熀绫伙紝鍏跺畠鎺т欢閮戒細缁ф壙锛屽瓙绫讳笉鍏佽淇敼瀵瑰簲鐨勫嚱鏁拌涓�,杩欎釜js涓嶉渶瑕佺洿鎺ュ紩鐢ㄥ拰浣跨敤
+ */
+import utils from "./uiUtils.js"
+import logger from './dxLogger.js'
+import * as os from "os"
+const uibase = {}
+/**
+* 淇敼鎴栬幏鍙栨帶浠剁殑瀹藉害
+* @param {number} w 闈炲繀濉紝濡傛灉涓嶅~鏄幏鍙栧搴︼紝鍚﹀垯灏辨槸淇敼瀹藉害 
+*/
+uibase.width = function (w) {
+     if (!utils.validateNumber(w)) {
+          return this.obj.getWidth()
+     }
+     this.obj.lvObjSetWidth(w)
+}
+/**
+* 淇敼鎴栬幏鍙栨帶浠剁殑楂樺害
+* @param {number} h 闈炲繀濉紝濡傛灉涓嶅~灏辨槸鑾峰彇楂樺害锛屽惁鍒欏氨鏄慨鏀归珮搴� 
+*/
+uibase.height = function (h) {
+     if (!utils.validateNumber(h)) {
+          return this.obj.getHeight()
+     }
+     this.obj.lvObjSetHeight(h)
+}
+/**
+ * 鑾峰彇鍘婚櫎杈规銆佸唴杈硅窛鐨勫搴�
+ * @returns 
+ */
+uibase.contentWidth = function () {
+     return this.obj.lvObjGetContentWidth()
+}
+/**
+ * 鑾峰彇鍘婚櫎杈规銆佸唴杈硅窛鐨勯珮搴�
+ * @returns 
+ */
+uibase.contentHeight = function () {
+     return this.obj.lvObjGetContentHeight()
+}
+/**
+ * 鑾峰彇涓婃柟婊氬姩璺濈
+ * @returns 
+ */
+uibase.scrollTop = function () {
+     return this.obj.getScrollTop()
+}
+/**
+ * 鑾峰彇涓嬫柟婊氬姩璺濈
+ * @returns 
+ */
+uibase.scrollBottom = function () {
+     return this.obj.getScrollBottom()
+}
+/**
+ * 鑾峰彇宸︽柟婊氬姩璺濈
+ * @returns 
+ */
+uibase.scrollLeft = function () {
+     return this.obj.getScrollLeft()
+}
+/**
+ * 鑾峰彇鍙虫柟婊氬姩璺濈
+ * @returns 
+ */
+uibase.scrollRight = function () {
+     return this.obj.getScrollRight()
+}
+/**
+* 淇敼鎺т欢鐨勫搴﹀拰楂樺害
+* @param {number} w 蹇呭~ 
+* @param {number} h 蹇呭~ 
+*/
+uibase.setSize = function (w, h) {
+     let err = 'dxui.setSize: width or height should not be empty'
+     utils.validateNumber(w, err)
+     utils.validateNumber(h, err)
+     this.obj.lvObjSetSize(w, h)
+}
+/**
+* 淇敼鎴栬幏鍙栨帶浠剁浉褰撲簬鐖跺璞$殑x鍧愭爣
+* @param {number} x 闈炲繀濉紝濡傛灉涓嶅~灏辨槸鑾峰彇x鍧愭爣锛屽惁鍒欏氨鏄慨鏀箈鍧愭爣 
+*/
+uibase.x = function (x) {
+     if (!utils.validateNumber(x)) {
+          return this.obj.getX()
+     }
+     this.obj.lvObjSetX(x)
+}
+/**
+* 淇敼鎴栬幏鍙栨帶浠剁浉褰撲簬鐖跺璞$殑x鍧愭爣
+* @param {number} y 闈炲繀濉紝濡傛灉涓嶅~灏辨槸鑾峰彇y鍧愭爣锛屽惁鍒欏氨鏄慨鏀箉鍧愭爣 
+*/
+uibase.y = function (y) {
+     if (!utils.validateNumber(y)) {
+          return this.obj.getY()
+     }
+     this.obj.lvObjSetY(y)
+}
+/**
+* 淇敼鎺т欢鐩稿鐖跺璞$殑x鍜寉鍧愭爣
+* @param {number} x 蹇呭~ 
+* @param {number} y 蹇呭~ 
+*/
+uibase.setPos = function (x, y) {
+     let err = 'dxui.setPos: x or y should not be empty'
+     utils.validateNumber(x, err)
+     utils.validateNumber(y, err)
+     this.obj.lvObjSetPos(x, y)
+}
+/**
+ * 鎶婃帶浠剁Щ鍔ㄥ埌鏈�涓婂眰锛岀浉褰撲簬鐖跺璞℃渶鍚庝竴涓垱寤虹殑瀛愭帶浠讹紝浼氳鐩栧叾瀹冩墍鏈夊瓙鎺т欢
+ */
+uibase.moveForeground = function () {
+     this.obj.moveForeground()
+}
+/**
+ * 鎶婃帶浠剁Щ鍔ㄥ埌鏈�搴曞眰锛岀浉褰撲簬鐖跺璞$涓�涓垱寤虹殑瀛愭帶浠讹紝浼氳鍏跺畠鎵�鏈夊瓙鎺т欢瑕嗙洊
+ */
+uibase.moveBackground = function () {
+     this.obj.moveBackground()
+}
+/**
+ * 璁㈤槄浜嬩欢锛屾敮鎸佺殑浜嬩欢绫诲瀷鍙傝�僽tils.EVENT
+ * @param {number} type 鏋氫妇utils.EVENT,姣斿鐐瑰嚮銆侀暱鎸夌瓑
+ * @param {function} cb 浜嬩欢瑙﹀彂鐨勫洖璋冨嚱鏁帮紙涓嶈兘鏄尶鍚嶅嚱鏁帮級
+ * @param {object} ud 鐢ㄦ埛鏁版嵁
+ */
+uibase.on = function (type, cb, ud) {
+     this.obj.addEventCb(() => {
+          if (cb) {
+               cb({ target: this, ud: ud })
+          }
+     }, type)
+}
+/**
+ * 鍙戦�佷簨浠讹紝姣斿妯℃嫙鐐瑰嚮鎸夐挳锛屽彲浠ョ粰鎸夐挳鍙戦�丆LICK浜嬩欢
+ * @param {number} type 鏋氫妇utils.EVENT,姣斿鐐瑰嚮銆侀暱鎸夌瓑
+ */
+uibase.send = function (type) {
+     NativeObject.APP.NativeComponents.NativeEvent.lvEventSend(this.obj, type)
+}
+/**
+ * 闅愯棌ui瀵硅薄
+ */
+uibase.hide = function () {
+     if (!this.obj.hasFlag(1)) {
+          this.obj.lvObjAddFlag(1);
+     }
+}
+/**
+ * 鍒ゆ柇鏄惁闅愯棌
+ * @returns 
+ */
+uibase.isHide = function () {
+     return this.obj.hasFlag(1);
+}
+/**
+ * 鏄剧ず宸茬粡闅愯棌鐨剈i瀵硅薄
+ */
+uibase.show = function () {
+     if (this.obj.hasFlag(1)) {
+          this.obj.lvObjClearFlag(1);
+     }
+}
+/**
+ * 绂佸惎鐢ㄥ璞�
+ * @param {*} en false/true锛宼rue鏄鐢紝false鏄惎鐢�
+ */
+uibase.disable = function (en) {
+     if (en) {
+          this.obj.addState(utils.STATE.DISABLED)
+     } else {
+          this.obj.clearState(utils.STATE.DISABLED)
+     }
+}
+/**
+ * 鏄惁鍙偣鍑诲璞�
+ * @param {*} en false/true锛宼rue鏄彲鐐瑰嚮锛宖alse鏄笉鍙偣鍑�
+ */
+uibase.clickable = function (en) {
+     if (en) {
+          this.obj.lvObjAddFlag(utils.OBJ_FLAG.CLICKABLE)
+     } else {
+          this.obj.lvObjClearFlag(utils.OBJ_FLAG.CLICKABLE)
+     }
+}
+/**
+ * 鍒ゆ柇鏄惁绂佸惎鐢�
+ * @returns true鏄凡绂佺敤锛宖alse鏄凡鍚敤
+ */
+uibase.isDisable = function () {
+     return this.obj.hasState(utils.STATE.DISABLED)
+}
+/**
+ * 鑱氱劍瀵硅薄
+ * @param {*} en false/true锛宼rue鏄仛鐒︼紝false鏄彇娑堣仛鐒�
+ */
+uibase.focus = function (en) {
+     if (en) {
+          this.obj.addState(utils.STATE.FOCUSED)
+     } else {
+          this.obj.clearState(utils.STATE.FOCUSED)
+     }
+}
+/**
+ * 鍒ゆ柇鏄惁鑱氱劍
+ * @returns true鏄凡鑱氱劍锛宖alse鏄病鑱氱劍
+ */
+uibase.isFocus = function () {
+     return this.obj.hasState(utils.STATE.FOCUSED)
+}
+
+/**
+ * 璁剧疆ui鐨勬牱寮忥紝鍙互閫氳繃涓�涓釜鏍峰紡鍗曠嫭璁剧疆锛屼篃鍙互鍏堝畾涔夋牱寮忓璞★紝鐒跺悗鍜寀i瀵硅薄缁戝畾
+ * 缁檜i瀵硅薄鍜屾牱寮忓璞$粦瀹氾紝鍙互缁戝畾鍒颁笉鍚岀殑閮ㄥ垎鎴栦笉鍚岀殑鐘舵��
+ * @param {object} style  style.js build鍑芥暟杩斿洖鐨勫璞�
+ * @param {number} type  鍙傝�僽tils.STYLE 闈炲繀濉紝缂虹渷鏄拰瀵硅薄鑷韩缁戝畾
+ */
+uibase.addStyle = function (style, type) {
+     if (!style || !style.obj) {
+          throw new Error('dxui.addStyle: style should not be null')
+     }
+     if (!utils.validateNumber(type)) {
+          type = 0
+     }
+     this.obj.lvObjAddStyle(style.obj, type);
+}
+/**
+* 璁剧疆宸﹀彸涓婁笅鐨勫唴杈硅窛閮戒负涓�涓��
+* @param {number} pad 杈硅窛鍊�
+* @param {number} type  鍙傝�僽tils.STYLE 闈炲繀濉紝缂虹渷鏄拰瀵硅薄鑷韩缁戝畾
+*/
+uibase.padAll = function (pad, type) {
+     if (!utils.validateNumber(type)) {
+          type = 0
+     }
+     this.obj.lvObjSetStylePadAll(pad, type)
+}
+/**
+ * 璁剧疆/鑾峰彇鍙冲唴杈硅窛閮戒负涓�涓��
+ * @param {number} pad 杈硅窛鍊�
+ * @param {number} type  鍙傝�僽tils.STYLE 闈炲繀濉紝缂虹渷鏄拰瀵硅薄鑷韩缁戝畾
+ */
+uibase.padRight = function (pad, type) {
+     if (!utils.validateNumber(type)) {
+          type = 0
+     }
+     if (!utils.validateNumber(pad)) {
+          return this.obj.getStylePadRight(type)
+     }
+     this.obj.setStylePadRight(pad, type)
+}
+/**
+  * 璁剧疆/鑾峰彇宸﹀唴杈硅窛閮戒负涓�涓��
+  * @param {number} pad 杈硅窛鍊�
+  * @param {number} type  鍙傝�僽tils.STYLE 闈炲繀濉紝缂虹渷鏄拰瀵硅薄鑷韩缁戝畾
+  */
+uibase.padLeft = function (pad, type) {
+     if (!utils.validateNumber(type)) {
+          type = 0
+     }
+     if (!utils.validateNumber(pad)) {
+          return this.obj.getStylePadLeft(type)
+     }
+     this.obj.setStylePadLeft(pad, type)
+}
+/**
+  * 璁剧疆/鑾峰彇涓婂唴杈硅窛閮戒负涓�涓��
+  * @param {number} pad 杈硅窛鍊�
+  * @param {number} type  鍙傝�僽tils.STYLE 闈炲繀濉紝缂虹渷鏄拰瀵硅薄鑷韩缁戝畾
+  */
+uibase.padTop = function (pad, type) {
+     if (!utils.validateNumber(type)) {
+          type = 0
+     }
+     if (!utils.validateNumber(pad)) {
+          return this.obj.getStylePadTop(type)
+     }
+     this.obj.setStylePadTop(pad, type)
+}
+/**
+  * 璁剧疆/鑾峰彇涓嬪唴杈硅窛閮戒负涓�涓��
+  * @param {number} pad 杈硅窛鍊�
+  * @param {number} type  鍙傝�僽tils.STYLE 闈炲繀濉紝缂虹渷鏄拰瀵硅薄鑷韩缁戝畾
+  */
+uibase.padBottom = function (pad, type) {
+     if (!utils.validateNumber(type)) {
+          type = 0
+     }
+     if (!utils.validateNumber(pad)) {
+          return this.obj.getStylePadBottom(type)
+     }
+     this.obj.setStylePadBottom(pad, type)
+}
+/**
+ * 璁剧疆/鑾峰彇杈规瀹藉害
+ * @param {number} w 
+ * @param {number} type  鍙傝�僽tils.STYLE 闈炲繀濉紝缂虹渷鏄拰瀵硅薄鑷韩缁戝畾
+ */
+uibase.borderWidth = function (w, type) {
+     if (!utils.validateNumber(type)) {
+          type = 0
+     }
+     if (!utils.validateNumber(w)) {
+          return this.obj.lvObjGetStyleBorderWidth(type)
+     }
+     this.obj.lvObjSetStyleBorderWidth(w, type)
+}
+/**
+ * 璁剧疆杈规棰滆壊
+ * @param {number} color  鏀寔鏁板瓧绫诲瀷锛氭瘮濡�0x34ffaa锛涘瓧绗︿覆绫诲瀷(#寮�澶�),姣斿:'#34ffaa'
+ * @param {number} type  鍙傝�僽tils.STYLE 闈炲繀濉紝缂虹渷鏄拰瀵硅薄鑷韩缁戝畾
+ */
+uibase.setBorderColor = function (color, type) {
+     if (!utils.validateNumber(type)) {
+          type = 0
+     }
+     this.obj.setStyleBorderColor(utils.colorParse(color), type)
+}
+/**
+ * 璁剧疆杈瑰渾瑙�
+ * @param {number} r 
+ * @param {number} type  鍙傝�僽tils.STYLE 闈炲繀濉紝缂虹渷鏄拰瀵硅薄鑷韩缁戝畾
+ */
+uibase.radius = function (r, type) {
+     if (!utils.validateNumber(type)) {
+          type = 0
+     }
+     this.obj.lvObjSetStyleRadius(r, type)
+}
+/**
+ * 璁剧疆鑳屾櫙閫忔槑搴︼紝鍊艰寖鍥存槸0-100锛屽�艰秺灏忚秺濂�
+ * @param {number} opa 蹇呴』鏄�0-100
+ * @param {number} type  鍙傝�僽tils.STYLE 闈炲繀濉紝缂虹渷鏄拰瀵硅薄鑷韩缁戝畾
+ */
+uibase.bgOpa = function (opa, type) {
+     if (!utils.validateNumber(type)) {
+          type = 0
+     }
+     this.obj.lvObjSetStyleBgOpa(utils.OPA_MAPPING(opa), type)
+}
+/**
+ * 璁剧疆鑳屾櫙棰滆壊
+ * @param {any} color 鏀寔鏁板瓧绫诲瀷锛氭瘮濡�0x34ffaa锛涘瓧绗︿覆绫诲瀷(#寮�澶�),姣斿:'#34ffaa'
+ * @param {number} type  鍙傝�僽tils.STYLE 闈炲繀濉紝缂虹渷鏄拰瀵硅薄鑷韩缁戝畾
+ */
+uibase.bgColor = function (color, type) {
+     if (!utils.validateNumber(type)) {
+          type = 0
+     }
+     this.obj.lvObjSetStyleBgColor(utils.colorParse(color), type)
+}
+/**
+ * 璁剧疆闃村奖
+ * @param {number} width 闃村奖瀹藉害
+ * @param {number} x 姘村钩鍋忕Щ
+ * @param {number} y 鍨傜洿鍋忕Щ
+ * @param {number} spread 鎵╂暎璺濈
+ * @param {number} color 棰滆壊
+ * @param {number} opa 閫忔槑搴︼紝蹇呴』鏄�0-100
+ * @param {number} type 鍙傝�僽tils.STYLE 闈炲繀濉紝缂虹渷鏄拰瀵硅薄鑷韩缁戝畾
+ */
+uibase.shadow = function (width, x, y, spread, color, opa, type) {
+     if (!utils.validateNumber(type)) {
+          type = 0
+     }
+     this.obj.lvObjSetStyleShadowWidth(width, type)
+     this.obj.lvObjSetStyleShadowOfsX(x, type)
+     this.obj.lvObjSetStyleShadowOfsY(y, type)
+     this.obj.lvObjSetStyleShadowSpread(spread, type)
+     this.obj.setStyleShadowColor(color, type)
+     this.obj.setStyleShadowOpa(utils.OPA_MAPPING(opa), type)
+}
+/**
+ * 璁剧疆鏂囨湰棰滆壊
+ * @param {any} color  鏀寔鏁板瓧绫诲瀷锛氭瘮濡�0x34ffaa锛涘瓧绗︿覆绫诲瀷(#寮�澶�),姣斿:'#34ffaa'
+ * @param {number} type  鍙傝�僽tils.STYLE 闈炲繀濉紝缂虹渷鏄拰瀵硅薄鑷韩缁戝畾
+ */
+uibase.textColor = function (color, type) {
+     if (!utils.validateNumber(type)) {
+          type = 0
+     }
+     this.obj.lvObjSetStyleTextColor(utils.colorParse(color), type)
+}
+/**
+ * 璁剧疆鏂囨湰瀵归綈鏂瑰紡
+ * @param {number} align  鍙傝�僽tils.TEXT_ALIGN
+ * @param {number} type  鍙傝�僽tils.STYLE 闈炲繀濉紝缂虹渷鏄拰瀵硅薄鑷韩缁戝畾
+ */
+uibase.textAlign = function (align, type) {
+     if (!utils.validateNumber(type)) {
+          type = 0
+     }
+     this.obj.lvObjSetStyleTextAlign(align, type)
+}
+/**
+ * 璁剧疆鏂囨湰瀛椾綋
+ * @param {object} font font.js閲宐uild杩斿洖鐨勫璞� 
+ * @param {number} type  鍙傝�僽tils.STYLE 闈炲繀濉紝缂虹渷鏄拰瀵硅薄鑷韩缁戝畾
+ */
+uibase.textFont = function (font, type) {
+     if (!utils.validateNumber(type)) {
+          type = 0
+     }
+     if (!font || !font.obj) {
+          throw new Error("dxui.textFont: 'font' parameter should not be null")
+     }
+     this.obj.lvObjSetStyleTextFont(font.obj, type)
+}
+/**
+ * 璁剧疆绾垮璞�(line)棰滆壊
+ * @param {any} color  鏀寔鏁板瓧绫诲瀷锛氭瘮濡�0x34ffaa锛涘瓧绗︿覆绫诲瀷(#寮�澶�),姣斿:'#34ffaa'
+ * @param {number} type  鍙傝�僽tils.STYLE 闈炲繀濉紝缂虹渷鏄拰瀵硅薄鑷韩缁戝畾
+ */
+uibase.lineColor = function (color, type) {
+     if (!utils.validateNumber(type)) {
+          type = 0
+     }
+     this.obj.lvObjSetStyleLineColor(utils.colorParse(color), type)
+}
+/**
+ * 璁剧疆绾垮璞�(line)瀹藉害
+ * @param {number} w 
+ * @param {number} type  鍙傝�僽tils.STYLE 闈炲繀濉紝缂虹渷鏄拰瀵硅薄鑷韩缁戝畾
+ */
+uibase.lineWidth = function (w, type) {
+     if (!utils.validateNumber(type)) {
+          type = 0
+     }
+     this.obj.lvObjSetStyleLineWidth(w, type)
+}
+/**
+ * 璁剧疆绾垮璞�(line)鍦嗚
+ * @param {boolean} enable true/false
+ */
+uibase.lineRound = function (enable) {
+     this.obj.lvObjSetStyleLineRounded(enable)
+}
+/**
+ * 璁剧疆ui瀵硅薄鐨勬粴鍔ㄦ潯鏄剧ず鏂瑰紡
+ * @param {boolean} state ture/false 
+ */
+uibase.scrollbarMode = function (state) {
+     this.obj.lvObjSetScrollbarMode(state)
+}
+/**
+ * 璁剧疆ui瀵硅薄鏄惁鏀寔婊氬姩
+ * @param {boolean} state 
+ */
+uibase.scroll = function (state) {
+     if (state) {
+          this.obj.lvObjAddFlag(16)
+     } else {
+          this.obj.lvObjClearFlag(16)
+     }
+}
+/**
+ * 灏嗗璞′笌鍏跺畠鍙傜収瀵硅薄瀵归綈
+ * @param {object} ref 鍙傜収瀵硅薄
+ * @param {number} type 瀵归綈鐨勬柟鍚戯紝鍙傝�僤xui.Utils.ALIGN鏋氫妇
+ * @param {number} x 鍋忕Щ鐨剎
+ * @param {number} y 鍋忕Щ鐨剏
+ */
+uibase.alignTo = function (ref, type, x, y) {
+     if (!ref || !ref.obj) {
+          throw new Error("dxui.alignto: 'ref' parameter should not be null")
+     }
+     this.obj.lvObjAlignTo(ref.obj, type, x, y)
+}
+/**
+ * 灏嗗璞′笌鐖跺璞″榻�
+ * @param {number} type 瀵归綈鐨勬柟鍚戯紝鍙傝�僤xui.Utils.ALIGN鏋氫妇
+ * @param {number} x 鍋忕Щ鐨剎
+ * @param {number} y 鍋忕Щ鐨剏
+ */
+uibase.align = function (type, x, y) {
+     this.obj.lvObjAlign(type, x, y)
+}
+/**
+ * 浼哥缉鐩掑竷灞�锛屽彲浠ユ洿鍔犵伒娲诲緱瀹氫綅銆佹帓鍒楀拰鍒嗗竷鍏冪礌锛屼娇寰楀垱寤哄搷搴斿紡鍜屽彲浼哥缉鐨勫竷灞�鍙樺緱鏇村姞瀹规槗銆�
+ * 瀹冨熀浜庝竴涓鍣紝鍜屽唴閮ㄧ殑涓�浜涘脊鎬ч」鐩紝涓嬮潰鏄娇鐢ㄨ繖绉嶅竷灞�鐨勪竴浜涙蹇碉細
+ * 1銆佸鍣細瀹瑰櫒鍖呭惈浜嗗唴閮ㄧ殑寮规�ч」鐩紝鍙互浣块噷闈㈤」鐩粠宸﹀悜鍙虫垨浠庡彸鍚戝乏绛夎鍒欐帓鍒椼��
+ * 2銆佷富杞村拰渚ц酱锛氫富杞达紝鏄鍣ㄤ腑椤圭洰鐨勪富瑕佹帓鍒楁柟寮忥紝閫氬父鏄按骞虫柟鍚戞垨鍨傜洿鏂瑰悜锛屽彲浠ヨ椤圭洰浠按骞虫帓鍒楁垨绾靛悜鎺掑垪銆�
+ *   渚ц酱锛屼笌涓昏酱鍨傜洿鐨勮酱鍚戯紝鍙互瑙勫畾椤圭洰浠湪渚ц酱涓婄殑鎺掑垪鏂瑰紡銆�
+ *   涓昏酱鍜屼晶杞寸敱flexFlow()璁剧疆锛屼富瑕佹湁ROW锛堟按骞虫柟鍚戯級銆丆OLUMN锛堝瀭鐩存柟鍚戯級涓ょ锛屽甫鏈塛RAP鍚庣紑鐨勫湪椤圭洰浠秴鍑哄鍣ㄦ椂鑷姩鎹㈣锛屽甫鏈塕EVERSE鍚庣紑鐨勪笌榛樿鎺掑垪鏂瑰悜鐩稿弽锛屽嵆涓轰粠鍙冲埌宸︽帓鍒楋紙鑻ヤ富杞存槸鍨傜洿鏂瑰悜鍒欎负浠庝笅鍒颁笂鎺掑垪锛夈��
+ * 3銆佷富杞村榻愭柟寮忥細START锛堥粯璁や富杞撮『搴忥級銆丒ND锛堥粯璁や富杞撮『搴忕浉鍙嶏級銆丆ENTER锛堝湪涓昏酱鏂瑰悜涓婂眳涓級銆丼PACE_EVENLY锛堝湪涓昏酱涓婂潎鍖�鍒嗗竷锛屼袱涓や箣闂磋窛绂荤浉绛夛級銆丼PACE_AROUND锛堝湪涓昏酱涓婂潎鍖�鍒嗗竷锛屾瘡涓」鐩钩鍒嗕富杞翠笂鐨勮窛绂伙級銆丼PACE_BETWEEN锛堜袱绔《鏍硷紝涓棿鍧囧垎锛夛紝鐢眆lexAlign()璁剧疆銆�
+ * 4銆佷晶杞村榻愭柟寮忥細灏嗘瘡涓�琛屾垨姣忎竴鍒楃湅浣滀竴涓」鐩紝鍦ㄤ晶杞存柟鍚戜笂瀵归綈锛屽榻愭柟寮忓悓涓昏酱锛岀敱flexAlign()璁剧疆銆�
+ * 5銆佹暣浣撳榻愭柟寮忥細灏嗗鍣ㄥ唴鎵�鏈夐」鐩湅浣滀竴涓暣浣擄紝鍦ㄥ鍣ㄤ腑瀵归綈锛屽榻愭柟寮忓悓涓昏酱锛岀敱flexAlign()璁剧疆銆�
+ * @param {number} type 涓昏酱鍜屼晶杞寸殑璁剧疆
+ */
+uibase.flexFlow = function (type) {
+     this.obj.lvObjSetFlexFlow(type)
+}
+/**
+ * 
+ * @param {number} main 瀛愬厓绱犳寜涓昏酱鏂瑰悜鐨勫榻愭柟寮�
+ * @param {number} cross 瀛愬厓绱犳寜渚ц酱鏂瑰悜鐨勫榻愭柟寮�
+ * @param {number} track 鎵�鏈夊瓙鍏冪礌瀵逛簬瀹瑰櫒鐨勫榻愭柟寮�
+ */
+uibase.flexAlign = function (main, cross, track) {
+     this.obj.lvObjSetFlexAlign(main, cross, track)
+}
+/**
+ * 鏇存柊涓�涓帶浠剁殑灏哄锛屽綋鑾峰彇涓�涓帶浠剁殑灏哄涓�0鏃跺彲浠ュ厛璋冪敤锛岀浉褰撲簬鏇存柊鏄剧ず缂撳瓨銆�
+ */
+uibase.update = function () {
+     this.obj.lvObjUpdateLayout()
+}
+/**
+ * 娣诲姞涓�涓帶浠剁殑鐘舵��
+ * @param {number} state 鐘舵�佹灇涓�
+ */
+uibase.addState = function (state) {
+     this.obj.addState(state)
+}
+/**
+ * 鍒犻櫎涓�涓帶浠剁殑鐘舵�侊紝濡傛灉鎯宠涓�涓仛鐒﹁緭鍏ユ澶辩劍锛屽彲浠ヨ皟鐢ㄦ鏂规硶鍒犻櫎FOCUSED鐘舵��
+ * @param {number} state 鐘舵�佹灇涓�
+ */
+uibase.clearState = function (state) {
+     this.obj.clearState(state)
+}
+/**
+ * 鍒ゆ柇涓�涓帶浠舵槸鍚︽嫢鏈夌姸鎬侊紝鎯冲垽鏂竴涓緭鍏ユ鏄惁琚仛鐒︿簡锛屽彲浠ヤ娇鐢ㄦ鏂规硶骞朵紶鍏OCUSED鍙傛暟
+ * @param {number} state 鐘舵�佹灇涓�
+ * @returns true/false
+ */
+uibase.hasState = function (state) {
+     return this.obj.hasState(state)
+}
+/**
+ * 閲嶇粯涓�涓帶浠讹紝寮哄埗鍒锋柊鎺т欢鐨勭紦瀛橈紝鍙互寮哄埗瑙e喅鑺卞睆鐨勯棶棰橈紝浣嗘槸濡傛灉姝诲惊鐜腑璋冪敤浼氶檷浣庢�ц兘
+ */
+uibase.invalidate = function () {
+     this.obj.invalidate()
+}
+/**
+ * 婊氬姩鏌愪釜瀛愭帶浠剁洿鑷虫樉绀哄嚭鏉ワ紝濡傛灉鎯冲皢涓�涓婊氬姩鑷冲鍣ㄥ瀵艰嚧鐪嬩笉瑙佺殑椤圭洰婊氬姩鑷宠兘琚湅瑙佺殑浣嶇疆锛岃皟鐢ㄦ鏂规硶銆�
+ * @param {boolean} en 鏄惁寮�鍚姩鐢伙紝寮�鍚細缂撴參婊氬姩鍑烘潵锛屽叧闂垯鐩存帴璺冲嚭銆�
+ * @param {boolean} notRecursive 榛樿閫掑綊锛岄�傜敤浜庝竴鑸粴鍔ㄥ拰婊氬姩宓屽鎺т欢
+ */
+uibase.scrollToView = function (en, isRecursive) {
+     if (isRecursive) {
+          this.obj.scrollToView(en)
+     } else {
+          this.obj.scrollToViewRecursive(en)
+     }
+}
+/**
+ * 婊氬姩涓�涓帶浠剁殑x鏂瑰悜
+ * @param {number} x 婊氬姩x杞磋窛绂�
+ * @param {boolean} en 鏄惁寮�鍚姩鐢�
+ */
+uibase.scrollToX = function (x, en) {
+     this.obj.scrollToX(x, en)
+}
+/**
+ * 婊氬姩涓�涓帶浠剁殑y鏂瑰悜
+ * @param {number} y 婊氬姩y杞磋窛绂�
+ * @param {boolean} en 鏄惁寮�鍚姩鐢�
+ */
+uibase.scrollToY = function (y, en) {
+     this.obj.scrollToY(y, en)
+}
+/**
+ * 鍏冪礌蹇収锛堝叾瀹炲氨鏄埅鍥撅紝濡傛灉鎯充繚瀛樺叏灞忔埅鍥撅紝鍙互瀵瑰睆骞曞璞′娇鐢ㄦ鏂规硶锛�
+ * @param {string} fileName 蹇呭~锛屼繚瀛樺揩鐓х殑鏂囦欢鍚嶏紙娉ㄦ剰鍚庣紑搴斾笌鏍煎紡瀵瑰簲锛�
+ * @param {number} type 闈炲繀濉紝缂虹渷png锛屽揩鐓ф牸寮� 0:bmp/1:png/2:jpg(jpeg)
+ * @param {number} cf 闈炲繀濉紝涓�绉峈GB棰滆壊瀛樺偍鏍煎紡
+ */
+uibase.snapshot = function (fileName, type = 1, cf = NativeObject.APP.NativeComponents.NativeEnum.LV_IMG_CF_TRUE_COLOR_ALPHA) {
+     if (!fileName) {
+          return
+     }
+     // 榛樿瀛樺偍鍦�/app/data/snapshot浣嶇疆
+     os.mkdir("/app/data/snapshot/")
+     this.obj.lvSnapshotTake(cf, "/app/data/snapshot/" + fileName, type)
+}
+export default uibase;
\ No newline at end of file
diff --git a/vf205_access/dxmodules/uiButton.js b/vf205_access/dxmodules/uiButton.js
new file mode 100644
index 0000000..b60fc4d
--- /dev/null
+++ b/vf205_access/dxmodules/uiButton.js
@@ -0,0 +1,16 @@
+//build锛�20240311
+//button鎺т欢 鐩稿鍩虹被娌℃湁鏂板姛鑳�
+import utils from "./uiUtils.js"
+import base from "./uiBase.js"
+let button = {}
+
+button.build = function (id, parent) {
+    let temp = utils.validateBuild(button.all, id, parent, 'button')
+    let my = { type: 'button' }
+    my.obj = new utils.GG.NativeButton({ uid: id }, temp)
+    my.id = id
+    let comp = Object.assign(my, base);
+    utils.setParent(this.all, comp, parent)
+    return comp;
+}
+export default button;
\ No newline at end of file
diff --git a/vf205_access/dxmodules/uiButtons.js b/vf205_access/dxmodules/uiButtons.js
new file mode 100644
index 0000000..f1ff13f
--- /dev/null
+++ b/vf205_access/dxmodules/uiButtons.js
@@ -0,0 +1,107 @@
+//build锛�20240314
+//鎸夐挳缁勬帶浠�
+import utils from "./uiUtils.js"
+import base from "./uiBase.js"
+let buttons = {}
+
+buttons.build = function (id, parent) {
+    let temp = utils.validateBuild(buttons.all, id, parent, 'buttons')
+    let my = {type: 'buttons'}
+    my.obj = new utils.GG.NativeBtnmatrix({ uid: id }, temp)
+    my.id = id
+    /**
+     * 璁剧疆button缁勫搴旂殑鏁版嵁锛屽繀椤绘槸鏁扮粍鏍煎紡锛岀ず渚嬪涓嬶細琛ㄧず涓夎鎸夐挳锛屾�诲叡12涓寜閽�
+     * ["1", "2", "3", "0", "\n",
+     * "4", "5", "6", "鍙栨秷", "\n",
+     *  "7", "8", "9", "纭", ""]
+     * @param {array} d 闈炲繀濉紝濡傛灉娌℃湁濉垨鑰呬笉鏄痮bject绫诲瀷灏辨槸鑾峰彇鏁版嵁
+     */
+    my.data = function (d) {
+        if (utils.validateObject(d)) {
+            this.obj.lvBtnmatrixSetMap(d)
+        } else {
+            return this.obj.lvBtnmatrixGetMap()
+        }
+    }
+    /**
+     * 鐐瑰嚮鎸夐挳缁勯噷浠讳綍涓�涓寜閽紝璋冪敤selectedData鏉ヨ幏鍙栫偣鍑绘寜閽殑id鍜屾枃鏈�
+     * 杩斿洖绀轰緥: {id:11,text:'鍙栨秷'}
+     */
+    my.clickedButton = function () {
+        let id = this.obj.lvBtnmatrixGetSelectedBtn();
+        if (id == 0xFFFF) {
+            // 鐐瑰嚮鎸夐挳缁勮竟鐣屼細鍑虹幇0xFFFF闈炴硶鍊硷紝杩斿洖绌�
+            return { id: null, text: null }
+        }
+        let txt = this.obj.lvBtnmatrixGetBtnText(id);
+        return { id: id, text: txt }
+    }
+    /**
+     * 璁剧疆鎸夐挳缁勯噷鏌愪竴涓壒瀹氭寜閽殑鐘舵�侊紝鍙互鏀规垚閫変腑锛屼笉鍙敤涔嬬被鐨�
+     * @param {number} id 鎸夐挳鐨勭储寮曪紝浠�0寮�濮嬩粠宸﹀埌鍙充粠涓婂埌涓嬶紝涔熸槸鐐瑰嚮鎸夐挳clickedButton杩斿洖鐨刬d
+     * @param {number} state 鍙傝�僤xui.Utils.BUTTONS_STATE 
+     */
+    my.setState = function (id, state) {
+        this.obj.lvBtnmatrixSetBtnCtrl(id, state)
+    }
+    /**
+     * 娓呴櫎鎸夐挳缁勯噷鏌愪竴涓壒瀹氭寜閽殑宸茬粡璁剧疆濂界殑鐘舵��
+     * @param {number} id 鎸夐挳鐨勭储寮曪紝浠�0寮�濮嬩粠宸﹀埌鍙充粠涓婂埌涓嬶紝涔熸槸鐐瑰嚮鎸夐挳clickedButton杩斿洖鐨刬d
+     * @param {number} state 鍙傝�僤xui.Utils.BUTTONS_STATE 
+     */
+    my.clearState = function (id, state) {
+        this.obj.lvBtnmatrixClearBtnCtrl(id, state)
+    }
+    /**
+     * 璁剧疆鎸夐挳缁勯噷鎵�鏈夋寜閽殑鐘舵�侊紝鍙互鏀规垚閫変腑锛屼笉鍙敤涔嬬被鐨�
+     * @param {number} state 鍙傝�僤xui.Utils.BUTTONS_STATE 
+     */
+    my.setAllState = function (state) {
+        this.obj.lvBtnmatrixSetBtnCtrlAll(state)
+    }
+    /**
+     * 娓呴櫎鎸夐挳缁勯噷鎵�鏈夋寜閽殑宸茬粡璁剧疆濂界殑鐘舵��
+     * @param {number} state 鍙傝�僤xui.Utils.BUTTONS_STATE 
+     */
+    my.clearAllState = function (state) {
+        this.obj.lvBtnmatrixClearBtnCtrlAll(state)
+    }
+    /**
+     * 璁剧疆鏌愪釜id鐨勬寜閽搴﹀崰鐢ㄥ嚑鏍�
+     * @param {number} id 鎸夐挳搴忓彿锛屼粠0寮�濮嬬紪鍙�
+     * @param {number} width 瀹藉害璺ㄨ秺鏍煎瓙鏁伴噺
+     */
+    my.setBtnWidth = function (id, width) {
+        this.obj.lvBtnmatrixSetBtnWidth(id, width)
+    }
+    /**
+     * 璁剧疆鏌愪釜id鐨勬寜閽浘鏍�
+     * @param {number} id 鎸夐挳搴忓彿锛屼粠0寮�濮嬬紪鍙�
+     * @param {string} src 鍥炬爣鏂囦欢璺緞
+     */
+    my.setBtnIcon = function (id, src) {
+        this.obj.addEventCb((e) => {
+            // 鑾峰彇缁樺埗鎺т欢瀵硅薄
+            let dsc = e.lvEventGetDrawPartDsc()
+            // 濡傛灉鏄粯鍒剁id涓寜閽�
+            if (dsc.type == utils.ENUM.LV_BTNMATRIX_DRAW_PART_BTN && dsc.id == id) {
+                // 鑾峰彇鍥剧墖淇℃伅
+                let header = utils.GG.NativeDraw.lvImgDecoderGetInfo(src)
+                // 瀹氫箟涓�鍧楀尯鍩燂紝灞呬腑鏄剧ず锛屾敞鎰忥細灏哄杞琣rea闇�瑕�-1锛宎rea杞昂瀵搁渶瑕�+1
+                let x1 = dsc.draw_area.x1 + (dsc.draw_area.x2 - dsc.draw_area.x1 + 1 - header.w) / 2;
+                let y1 = dsc.draw_area.y1 + (dsc.draw_area.y2 - dsc.draw_area.y1 + 1 - header.h) / 2;
+                let x2 = x1 + header.w - 1;
+                let y2 = y1 + header.h - 1;
+                let area = utils.GG.NativeArea.lvAreaSet(x1, y1, x2, y2)
+                // 缁樺埗鍥剧墖淇℃伅
+                let img_draw_dsc = utils.GG.NativeDraw.lvDrawImgDscInit()
+                // 缁樺埗鍥剧墖
+                utils.GG.NativeDraw.lvDrawImg(dsc.dsc, img_draw_dsc, area, src)
+            }
+        }, utils.ENUM.LV_EVENT_DRAW_PART_END)
+    }
+    let comp = Object.assign(my, base);
+    utils.setParent(this.all,comp,parent)
+    return comp;
+}
+export default buttons;
\ No newline at end of file
diff --git a/vf205_access/dxmodules/uiCheckbox.js b/vf205_access/dxmodules/uiCheckbox.js
new file mode 100644
index 0000000..f08dac2
--- /dev/null
+++ b/vf205_access/dxmodules/uiCheckbox.js
@@ -0,0 +1,48 @@
+//build锛�20240329
+//checkbox鎺т欢
+import utils from "./uiUtils.js"
+import base from "./uiBase.js"
+let checkbox = {}
+
+checkbox.build = function (id, parent) {
+    let temp = utils.validateBuild(checkbox.all, id, parent, 'checkbox')
+    let my = { type: 'checkbox' }
+    my.obj = new utils.GG.NativeCheckbox({ uid: id }, temp)
+    my.id = id
+    /**
+     * 鑾峰彇/璁剧疆鏂囧瓧
+     * @param {string} text 璁剧疆鏂囧瓧
+     * @returns 鑾峰彇鏂囧瓧
+     */
+    my.text = function (text) {
+        if (text == null || text == undefined) {
+            return this.obj.getText()
+        } else {
+            this.obj.setText(text)
+        }
+    }
+    /**
+     * 閫変腑鎴栦笉閫変腑
+     * @param {boolean} en true/false
+     */
+    my.select = function (en) {
+        if (en) {
+            if (!my.obj.hasState(utils.STATE.CHECKED)) {
+                my.obj.addState(utils.STATE.CHECKED)
+            }
+        } else {
+            my.obj.clearState(utils.STATE.CHECKED)
+        }
+    }
+    /**
+     * 鍒ゆ柇鏄惁閫変腑
+     * @returns 杩斿洖true/false
+     */
+    my.isSelect = function () {
+        return my.obj.hasState(utils.STATE.CHECKED)
+    }
+    let comp = Object.assign(my, base);
+    utils.setParent(this.all, comp, parent)
+    return comp;
+}
+export default checkbox;
\ No newline at end of file
diff --git a/vf205_access/dxmodules/uiDropdown.js b/vf205_access/dxmodules/uiDropdown.js
new file mode 100644
index 0000000..d517613
--- /dev/null
+++ b/vf205_access/dxmodules/uiDropdown.js
@@ -0,0 +1,53 @@
+//build锛�20240329
+//dropdown鎺т欢
+import utils from "./uiUtils.js"
+import base from "./uiBase.js"
+let dropdown = {}
+
+dropdown.build = function (id, parent) {
+    let temp = utils.validateBuild(dropdown.all, id, parent, 'dropdown')
+    let my = {type: 'dropdown'}
+    my.obj = new utils.GG.NativeDropdown({ uid: id }, temp)
+    my.id = id
+    /**
+     * 璁剧疆涓嬫媺閫夐」鍐呭
+     * @param {array} arr 閫夐」鍐呭锛屾槸涓瓧绗︿覆鏁扮粍锛屾瘡涓�椤逛负涓�涓�夐」
+     */
+    my.setOptions = function (arr) {
+        this.obj.setOptions(arr.join('\n'))
+    }
+    /**
+     * 鑾峰彇涓嬫媺閫夐」鍒楄〃
+     * @returns 杩斿洖鍒楄〃瀵硅薄锛屾槸涓�涓熀绫诲璞★紝鍙互鍗曠嫭璁剧疆瀹冪殑瀛椾綋
+     */
+    my.getList = function () {
+        let res = {}
+        res.obj = this.obj.getList()
+        return Object.assign(res, base)
+    }
+    /**
+     * 璁剧疆閫変腑椤癸紝榛樿浼氶�変腑杩欎釜
+     * @param {number} index 閫変腑椤圭储寮�
+     */
+    my.setSelected = function (index) {
+        this.obj.setSelected(index)
+    }
+    /**
+     * 鑾峰彇閫変腑椤圭储寮�
+     * @returns 杩斿洖褰撳墠閫変腑鐨勭储寮�
+     */
+    my.getSelected = function () {
+        return this.obj.getSelected()
+    }
+    /**
+     * 璁剧疆涓嬫媺妗嗛檮灞炲浘鏍囷紝榛樿鏄釜鏈濅笅鐨勭澶�
+     * @param {string} icon 鍥炬爣鍦板潃
+     */
+    my.setSymbol = function (icon) {
+        this.obj.setSymbol(icon)
+    }
+    let comp = Object.assign(my, base);
+    utils.setParent(this.all, comp, parent)
+    return comp;
+}
+export default dropdown;
\ No newline at end of file
diff --git a/vf205_access/dxmodules/uiFont.js b/vf205_access/dxmodules/uiFont.js
new file mode 100644
index 0000000..bea8251
--- /dev/null
+++ b/vf205_access/dxmodules/uiFont.js
@@ -0,0 +1,18 @@
+//build锛�20240311
+//瀛椾綋瀵硅薄(瑕佹敮鎸佷腑鏂囷紝闇�瑕佷娇鐢ㄦ敮鎸佷腑鏂囩殑瀛椾綋ttf鏂囦欢)
+import utils from "./uiUtils.js"
+let font = {}
+/**
+ * 鏋勫缓瀛椾綋
+ * @param {string} ttf 瀛椾綋ttf鏂囦欢鐨勫畬鏁磋矾寰� 
+ * @param {number} size 瀛椾綋澶у皬
+ * @param {number} style 瀛椾綋鏍峰紡锛屽弬鑰僽tils.FONT_STYLE
+ * @returns 
+ */
+font.build = function (ttf, size, style) {
+    let comp = {}
+    comp.obj = utils.GG.NativeFont.lvFontInit(ttf, size, style)
+    return comp;
+}
+
+export default font;
\ No newline at end of file
diff --git a/vf205_access/dxmodules/uiImage.js b/vf205_access/dxmodules/uiImage.js
new file mode 100644
index 0000000..3111257
--- /dev/null
+++ b/vf205_access/dxmodules/uiImage.js
@@ -0,0 +1,27 @@
+//build锛�20240311
+//image鎺т欢 
+import utils from "./uiUtils.js"
+import base from "./uiBase.js"
+let image = {}
+
+image.build = function (id, parent) {
+    let temp = utils.validateBuild(image.all, id, parent, 'image')
+    let my = {type: 'image'}
+    my.obj = new utils.GG.NativeImage({ uid: id }, temp)
+    my.id = id
+    /**
+     * 璁剧疆image鐨勬潵婧愭垨鑾峰彇鏉ユ簮
+     * @param {string} path 闈炲繀濉紝鍥剧墖鏂囦欢鐨勭粷瀵硅矾寰勶紝濡傛灉娌℃湁濉垨鑰呬笉鏄痵tring绫诲瀷灏辨槸鑾峰彇
+     */
+    my.source = function (path) {
+        if (utils.validateString(path)) {
+            this.obj.lvImgSetSrc(path)
+        } else {
+            return this.obj.lvImgGetSrc()
+        }
+    }
+    let comp = Object.assign(my, base);
+    utils.setParent(this.all, comp, parent)
+    return comp;
+}
+export default image;
\ No newline at end of file
diff --git a/vf205_access/dxmodules/uiKeyboard.js b/vf205_access/dxmodules/uiKeyboard.js
new file mode 100644
index 0000000..5f50b27
--- /dev/null
+++ b/vf205_access/dxmodules/uiKeyboard.js
@@ -0,0 +1,102 @@
+//build锛�20240329
+//keyboard鎺т欢
+import utils from "./uiUtils.js"
+import base from "./uiBase.js"
+let keyboard = {}
+
+keyboard.build = function (id, parent) {
+    let temp = utils.validateBuild(keyboard.all, id, parent, 'keyboard')
+    let my = {type: 'keyboard'}
+    my.obj = new utils.GG.NativeKeyboard({ uid: id }, temp)
+
+    // 鎷奸煶杈撳叆娉曚細鑾峰緱涓�涓柊瀵硅薄锛屼笌褰撳墠閿洏缁戝畾锛屼互澧炲己閿洏鍔熻兘锛屽9閿瓑锛岀敤鎴蜂娇鐢ㄦ椂涓嶇敤鍏冲績锛屽彧瑕佹搷浣滄渶鍒濆垱寤虹殑閭d釜閿洏瀵硅薄
+    let pinyin = {}
+    pinyin.obj = my.obj.lvImePinyinCreate()
+    my.obj.lvImePinyinSetKeyboard(pinyin.obj)
+    my["__obj"] = Object.assign(pinyin, base)
+    my.__mode = "K26"
+
+    my.id = id
+    /**
+     * 璁剧疆鍏宠仈鏂囨湰妗嗭紝閿洏杈撳嚭鐨勫唴瀹逛細鏄剧ず鍦ㄨ繖閲�
+     * @param {object} textarea 鏂囨湰妗嗘帶浠跺璞�
+     */
+    my.setTextarea = function (textarea) {
+        this.obj.lvKeyboardSetTextarea(textarea.obj)
+        my.textarea = textarea
+    }
+    /**
+     * 璁剧疆/鑾峰彇妯″紡锛岀函鏁板瓧閿洏鎴栧叾浠栨ā寮�
+     * @param {any} mode 妯″紡锛屽弬鐓ф灇涓�
+     * @returns 杩斿洖褰撳墠妯″紡
+     */
+    my.mode = function (mode) {
+        if (!mode) {
+            return my.__mode
+        }
+        if (mode == "K26" || mode == "K9") {
+            this.obj.lvImePinyinSetMode(my["__obj"].obj, mode == "K26" ? 0 : 1)
+        } else {
+            if (mode == utils.KEYBOARD.NUMBER) {
+                this.obj.lvImePinyinSetMode(my["__obj"].obj, 2)
+            }
+            this.obj.lvKeyboardSetMode(mode)
+        }
+        my.__mode = mode
+    }
+    /**
+     * 璁剧疆鎷奸煶瀛椾綋锛屽拰閿洏涓嶅悓锛岃繖閲岃缃殑鏄�欓�夊瓧瀛椾綋
+     * @param {object} font font.js閲宐uild杩斿洖鐨勫璞� 
+     * @param {number} type  鍙傝�僽tils.STYLE 闈炲繀濉紝缂虹渷鏄拰瀵硅薄鑷韩缁戝畾
+     */
+    my.chFont = function (font, type) {
+        if (!utils.validateNumber(type)) {
+            type = 0
+        }
+        if (!font || !font.obj) {
+            throw new Error("dxui.textFont: 'font' parameter should not be null")
+        }
+        my.obj.lvImePinyinGetCandPanel(my["__obj"].obj).lvObjSetStyleTextFont(font.obj, type)
+    }
+    /**
+     * 鎸変笅鏃跺湪寮瑰嚭绐楀彛涓樉绀烘寜閽爣棰橈紝鍗宠緟鍔╂樉绀虹殑涓婁綅妗嗐��
+     * @param {boolean} en true/false
+     */
+    my.setPopovers = function (en) {
+        this.obj.lvKeyboardSetPopovers(en)
+    }
+    /**
+     * 璁剧疆璇嶅簱
+     * @param {object} dict 璇嶅簱锛屾牸寮忓锛歿"a": "鍟�", "ai": "鐖�",...,"zu":"缁�"},26涓瓧姣嶉兘瑕佹湁锛屾病鏈夊�欓�夊瓧灏卞啓""
+     * @returns 
+     */
+    my.dict = function (dict) {
+        if (!dict) {
+            return my.obj.lvImePinyinGetDict(my["__obj"].obj)
+        } else {
+            my.obj.lvImePinyinSetDict(my["__obj"].obj, dict)
+        }
+    }
+    let comp = Object.assign(my, base);
+    // 閲嶅啓鏂规硶
+    // 淇濈暀鍘熷鐨勬柟娉�
+    const super_hide = my.hide;
+    const super_show = my.show;
+    my.hide = function () {
+        super_hide.call(this)
+        my.obj.lvImePinyinGetCandPanel(my["__obj"].obj).lvObjAddFlag(1);
+        if (my.textarea.text() && my.textarea.text().length > 0) {
+            my.obj.lvImePinyinClearData(my["__obj"].obj)
+        }
+    }
+    my.show = function () {
+        super_show.call(this)
+        if (my.obj.lvImePinyinGetCandNum(my["__obj"].obj) > 0) {
+            my.obj.lvImePinyinGetCandPanel(my["__obj"].obj).lvObjClearFlag(1);
+        }
+        my.obj.lvImePinyinGetCandPanel(my["__obj"].obj).lvObjAlignTo(my.obj, utils.ALIGN.OUT_TOP_MID, 0, 0)
+    }
+    utils.setParent(this.all, comp, parent)
+    return comp;
+}
+export default keyboard;
\ No newline at end of file
diff --git a/vf205_access/dxmodules/uiLabel.js b/vf205_access/dxmodules/uiLabel.js
new file mode 100644
index 0000000..0e4b6ea
--- /dev/null
+++ b/vf205_access/dxmodules/uiLabel.js
@@ -0,0 +1,34 @@
+//build锛�20240311
+//label鎺т欢
+import utils from "./uiUtils.js"
+import base from "./uiBase.js"
+let label = {}
+
+label.build = function (id, parent) {
+    let temp = utils.validateBuild(label.all, id, parent, 'label')
+    let my = {type: 'label'}
+    my.obj = new utils.GG.NativeLabel({ uid: id }, temp)
+    my.id = id
+    /**
+     * 璁剧疆label鐨勬枃鏈垨鑾峰彇鏂囨湰鍐呭
+     * @param {string} t 闈炲繀濉紝濡傛灉娌℃湁濉垨鑰呬笉鏄痵tring绫诲瀷灏辨槸鑾峰彇鏂囨湰
+     */
+    my.text = function (t) {
+        if (utils.validateString(t)) {
+            this.obj.lvLabelSetText(t)
+        } else {
+            return this.obj.lvLabelGetText()
+        }
+    }
+    /**
+     * 璁剧疆鏂囨湰瓒呴暱鍚庢樉绀虹殑妯″紡锛屾瘮濡傛粴鍔ㄦ樉绀烘垨鎴柇鎴�...绛�
+     * @param {number} mode 鏋氫妇鍙傝�僽tils.LABEL_LONG_MODE 
+     */
+    my.longMode = function (mode) {
+        this.obj.lvLabelSetLongMode(mode)
+    }
+    let comp = Object.assign(my, base);
+    utils.setParent(this.all, comp, parent)
+    return comp;
+}
+export default label;
\ No newline at end of file
diff --git a/vf205_access/dxmodules/uiLine.js b/vf205_access/dxmodules/uiLine.js
new file mode 100644
index 0000000..9639b84
--- /dev/null
+++ b/vf205_access/dxmodules/uiLine.js
@@ -0,0 +1,24 @@
+//build锛�20240311
+//line鎺т欢
+import utils from "./uiUtils.js"
+import base from "./uiBase.js"
+let line = {}
+
+line.build = function (id, parent) {
+    let temp = utils.validateBuild(line.all, id, parent, 'line')
+    let my = {type: 'line'}
+    my.obj = new utils.GG.NativeLine({ uid: id }, temp)
+    my.id = id
+    /**
+     * 璁剧疆line鐨勬墍鏈夌偣鐨勫潗鏍�
+     * @param {Array} points 蹇呭~锛屾墍鏈夌殑鐐圭粍鎴愮殑鏁扮粍锛屾瘮濡俒[x1,y1],[x2,y2]]
+     * @param {number} count 蹇呭~锛岃缁樺埗鐨勭偣鐨勪釜鏁帮紝娉ㄦ剰杩欎釜鍊煎彲浠ュ皬浜巔oints鐨勯暱搴�
+     */
+    my.setPoints = function (points, count) {
+        this.obj.lvLineSetPoints(points, count)
+    }
+    let comp = Object.assign(my, base);
+    utils.setParent(this.all, comp, parent)
+    return comp;
+}
+export default line;
\ No newline at end of file
diff --git a/vf205_access/dxmodules/uiList.js b/vf205_access/dxmodules/uiList.js
new file mode 100644
index 0000000..de1316a
--- /dev/null
+++ b/vf205_access/dxmodules/uiList.js
@@ -0,0 +1,45 @@
+//build锛�20240329
+//list鎺т欢
+import utils from "./uiUtils.js"
+import base from "./uiBase.js"
+let list = {}
+
+list.build = function (id, parent) {
+    let temp = utils.validateBuild(list.all, id, parent, 'list')
+    let my = {type: 'list'}
+    my.obj = new utils.GG.NativeList({ uid: id }, temp)
+    my.id = id
+    /**
+     * 娣诲姞鍗曚釜鏂囨湰椤�
+     * @param {string} text 椤圭殑鏂囨湰鍐呭
+     * @returns 椤硅嚜韬殑base瀵硅薄
+     */
+    my.addText = function (text) {
+        let res = {}
+        res.obj = this.obj.lvListAddText(text)
+        return Object.assign(res, base)
+    }
+    /**
+     * 娣诲姞鍗曚釜鎸夐挳椤�
+     * @param {string} src 椤瑰墠闈㈢殑鍥炬爣璺緞
+     * @param {string} text 椤圭殑鏂囨湰鍐呭
+     * @returns 椤硅嚜韬殑base瀵硅薄
+     */
+    my.addBtn = function (src, text) {
+        let res = {}
+        res.obj = this.obj.lvListAddBtn(src, text)
+        return Object.assign(res, base)
+    }
+    /**
+     * 鑾峰彇鎸夐挳椤圭殑鏂囨湰鍐呭
+     * @param {string} btn 鎸夐挳椤�
+     * @returns 鎸夐挳椤圭殑鏂囨湰鍐呭
+     */
+    my.getBtnText = function (btn) {
+        return this.obj.lvListGetBtnText(btn.obj)
+    }
+    let comp = Object.assign(my, base);
+    utils.setParent(this.all, comp, parent)
+    return comp;
+}
+export default list;
\ No newline at end of file
diff --git a/vf205_access/dxmodules/uiSlider.js b/vf205_access/dxmodules/uiSlider.js
new file mode 100644
index 0000000..e67d877
--- /dev/null
+++ b/vf205_access/dxmodules/uiSlider.js
@@ -0,0 +1,42 @@
+//build锛�20240329
+//slider鎺т欢
+import utils from "./uiUtils.js"
+import base from "./uiBase.js"
+let slider = {}
+
+slider.build = function (id, parent) {
+    let temp = utils.validateBuild(slider.all, id, parent, 'slider')
+    let my = {type: 'slider'}
+    my.obj = new utils.GG.NativeSlider({ uid: id }, temp)
+    my.id = id
+
+    /**
+     * 鑾峰彇/璁剧疆鍊�
+     * @param {number} v 璁剧疆鍊�
+     * @param {boolean} en 璁剧疆鍊兼椂鏄惁寮�鍚姩鐢伙紝鍗崇紦鍔ㄦ晥鏋�
+     * @returns 鑾峰彇鍊�
+     */
+    my.value = function (v, en) {
+        if (v == null || v == undefined) {
+            return this.obj.lvSliderGetValue()
+        } else {
+            if (!utils.validateNumber(en)) {
+                en = false
+            }
+            this.obj.lvSliderSetValue(v, en)
+        }
+    }
+    /**
+     * 璁剧疆鑼冨洿
+     * @param {number} min 鏈�灏忓��
+     * @param {number} max 鏈�澶у��
+     */
+    my.range = function (min, max) {
+        this.obj.lvSliderSetRange(min, max)
+    }
+
+    let comp = Object.assign(my, base);
+    utils.setParent(this.all, comp, parent)
+    return comp;
+}
+export default slider;
\ No newline at end of file
diff --git a/vf205_access/dxmodules/uiStyle.js b/vf205_access/dxmodules/uiStyle.js
new file mode 100644
index 0000000..0e4f845
--- /dev/null
+++ b/vf205_access/dxmodules/uiStyle.js
@@ -0,0 +1,149 @@
+//build锛�20240315
+//鎺т欢鏍峰紡 姣忎釜鎺т欢鍙互缁戝畾鏍峰紡瀵硅薄锛岃缃绉嶆牱寮�
+import utils from "./uiUtils.js"
+
+let style = {}
+style.build = function () {
+    let comp = {}
+    comp.obj = new utils.GG.NativeStyle()
+    comp.obj.lvStyleInit()
+    /**
+     * 璁剧疆宸﹀彸涓婁笅鐨勫唴杈硅窛閮戒负涓�涓��
+     * @param {number} pad 杈硅窛鍊�
+     */
+    comp.padAll = function (pad) {
+        this.obj.lvStyleSetPadAll(pad)
+    }
+    /**
+     * 璁剧疆鍙冲唴杈硅窛閮戒负涓�涓��
+     * @param {number} pad 杈硅窛鍊�
+     */
+    comp.padRight = function (pad) {
+        this.obj.lvStyleSetPadRight(pad)
+    }
+    /**
+     * 璁剧疆宸﹀唴杈硅窛閮戒负涓�涓��
+     * @param {number} pad 杈硅窛鍊�
+     */
+    comp.padLeft = function (pad) {
+        this.obj.lvStyleSetPadLeft(pad)
+    }
+    /**
+     * 璁剧疆涓婂唴杈硅窛閮戒负涓�涓��
+     * @param {number} pad 杈硅窛鍊�
+     */
+    comp.padTop = function (pad) {
+        this.obj.lvStyleSetPadTop(pad)
+    }
+    /**
+     * 璁剧疆涓嬪唴杈硅窛閮戒负涓�涓��
+     * @param {number} pad 杈硅窛鍊�
+     */
+    comp.padBottom = function (pad) {
+        this.obj.lvStyleSetPadBottom(pad)
+    }
+    /**
+     * 璁剧疆鍒椾笌鍒椾箣闂寸殑杈硅窛閮戒负涓�涓��
+     * @param {number} pad 杈硅窛鍊�
+     */
+    comp.padColumn = function (pad) {
+        this.obj.lvStyleSetPadColumn(pad)
+    }
+    /**
+     * 璁剧疆琛屼笌琛屼箣闂寸殑杈硅窛閮戒负涓�涓��
+     * @param {number} pad 杈硅窛鍊�
+     */
+    comp.padRow = function (pad) {
+        this.obj.lvStyleSetPadRow(pad)
+    }
+    /**
+     * 璁剧疆杈规瀹藉害
+     * @param {number} w 
+     */
+    comp.borderWidth = function (w) {
+        this.obj.lvStyleSetBorderWidth(w)
+    }
+    /**
+     * 璁剧疆杈瑰渾瑙�
+     * @param {number} r 
+     */
+    comp.radius = function (r) {
+        this.obj.lvStyleSetRadius(r)
+    }
+    /**
+     * 璁剧疆鑳屾櫙閫忔槑搴︼紝鍊艰寖鍥存槸0-100锛屽�艰秺灏忚秺濂�
+     * @param {number} opa 蹇呴』鏄�0-100
+     */
+    comp.bgOpa = function (opa) {
+        this.obj.lvStyleSetBgOpa(utils.OPA_MAPPING(opa))
+    }
+    /**
+     * 璁剧疆鑷韩閫忔槑搴︼紝鍊艰寖鍥存槸0-100锛屽�艰秺灏忚秺濂�
+     * @param {number} opa 蹇呴』鏄�0-100
+     */
+    comp.opa = function (opa) {
+        this.obj.lvStyleSetOpa(utils.OPA_MAPPING(opa))
+    }
+    /**
+     * 璁剧疆鑳屾櫙棰滆壊
+     * @param {any} color 鏀寔鏁板瓧绫诲瀷锛氭瘮濡�0x34ffaa锛涘瓧绗︿覆绫诲瀷(#寮�澶�),姣斿:'#34ffaa'
+     */
+    comp.bgColor = function (color) {
+        this.obj.lvStyleSetBgColor(utils.colorParse(color))
+    }
+    /**
+     * 璁剧疆鏂囨湰棰滆壊
+     * @param {any} color  鏀寔鏁板瓧绫诲瀷锛氭瘮濡�0x34ffaa锛涘瓧绗︿覆绫诲瀷(#寮�澶�),姣斿:'#34ffaa'
+     */
+    comp.textColor = function (color) {
+        this.obj.lvStyleSetTextColor(utils.colorParse(color))
+    }
+    /**
+     * 璁剧疆鏂囨湰瀵归綈鏂瑰紡
+     * @param {number} type  鍙傝�僽tils.TEXT_ALIGN
+     */
+    comp.textAlign = function (type) {
+        this.obj.lvStyleSetTextAlign(type)
+    }
+    /**
+     * 璁剧疆鏂囨湰瀛椾綋
+     * @param {object} font font.js閲宐uild杩斿洖鐨勫璞� 
+     */
+    comp.textFont = function (font) {
+        if (!font || !font.obj) {
+            throw new Error("style.textFont: 'font' parameter should not be null")
+        }
+        this.obj.lvStyleSetTextFont(font.obj)
+    }
+    /**
+     * 璁剧疆娓愬彉鑹�
+     * @param {number} color 娓愬彉鑹诧紝渚嬪:0xffffff
+     */
+    comp.bgGradColor = function (color) {
+        this.obj.lvStyleSetBgGradColor(color)
+    }
+    /**
+     * 璁剧疆娓愬彉鑹叉柟鍚�
+     * @param {number} dir 鏂瑰悜锛岀洰鍓嶅彧鏀寔姘村钩鍜屽瀭鐩�
+     */
+    comp.bgGradDir = function (dir) {
+        this.obj.lvStyleSetBgGradDir(dir)
+    }
+    /**
+     * 鑳屾櫙鑹茬殑缁撴潫浣嶇疆(0-255)
+     * @param {number} value 璺濈锛屼粠宸︾寮�濮嬭绠�
+     */
+    comp.bgMainStop = function (value) {
+        this.obj.lvStyleSetBgMainStop(value)
+    }
+    /**
+     * 娓愬彉鑹茬殑璺濈(0-255)
+     * @param {number} value 璺濈锛屼粠鑳屾櫙鑹茬殑缁撴潫浣嶇疆寮�濮嬭绠�
+     */
+    comp.bgGradStop = function (value) {
+        this.obj.lvStyleSetBgGradStop(value)
+    }
+    return comp;
+}
+
+export default style;
\ No newline at end of file
diff --git a/vf205_access/dxmodules/uiSwitch.js b/vf205_access/dxmodules/uiSwitch.js
new file mode 100644
index 0000000..bfa4376
--- /dev/null
+++ b/vf205_access/dxmodules/uiSwitch.js
@@ -0,0 +1,49 @@
+//build锛�20240329
+//_switch鎺т欢
+import utils from "./uiUtils.js"
+import base from "./uiBase.js"
+let _switch = {}
+
+_switch.build = function (id, parent) {
+    let temp = utils.validateBuild(_switch.all, id, parent, '_switch')
+    let my = {type: 'switch'}
+    my.obj = new utils.GG.NativeSwitch({ uid: id }, temp)
+    my.id = id
+
+    /**
+     * 鑾峰彇/璁剧疆鏂囧瓧
+     * @param {string} text 璁剧疆鏂囧瓧
+     * @returns 鑾峰彇鏂囧瓧
+     */
+    my.text = function (text) {
+        if (text == null || text == undefined) {
+            return this.obj.getText()
+        } else {
+            this.obj.setText(text)
+        }
+    }
+    /**
+     * 閫変腑鎴栦笉閫変腑
+     * @param {boolean} en true/false
+     */
+    my.select = function (en) {
+        if (en) {
+            if (!my.obj.hasState(utils.STATE.CHECKED)) {
+                my.obj.addState(utils.STATE.CHECKED)
+            }
+        } else {
+            my.obj.clearState(utils.STATE.CHECKED)
+        }
+    }
+    /**
+     * 鍒ゆ柇鏄惁閫変腑
+     * @returns 杩斿洖true/false
+     */
+    my.isSelect = function () {
+        return my.obj.hasState(utils.STATE.CHECKED)
+    }
+    let comp = Object.assign(my, base);
+    utils.setParent(this.all, comp, parent)
+    return comp;
+}
+export default _switch;
\ No newline at end of file
diff --git a/vf205_access/dxmodules/uiTextarea.js b/vf205_access/dxmodules/uiTextarea.js
new file mode 100644
index 0000000..5ff82d0
--- /dev/null
+++ b/vf205_access/dxmodules/uiTextarea.js
@@ -0,0 +1,76 @@
+//build锛�20240330
+//textarea鎺т欢
+import utils from "./uiUtils.js"
+import base from "./uiBase.js"
+let textarea = {}
+
+textarea.build = function (id, parent) {
+    let temp = utils.validateBuild(textarea.all, id, parent, 'textarea')
+    let my = {type: 'textarea'}
+    my.obj = new utils.GG.NativeTextarea({ uid: id }, temp)
+    my.id = id
+    /**
+     * 璁剧疆鍗曡妯″紡锛屼笉鑳芥崲琛�
+     * @param {boolean} en true/false
+     */
+    my.setOneLine = function (en) {
+        this.obj.lvTextareaSetOneLine(en)
+    }
+    /**
+     * 璁剧疆瀵嗙爜妯″紡锛屽唴瀹规樉绀轰负路鍙�
+     * @param {boolean} en true/false
+     */
+    my.setPasswordMode = function (en) {
+        this.obj.lvTextareaSetPasswordMode(en)
+    }
+    /**
+     * 璁剧疆鍐呭瀵归綈鏂瑰紡锛屽眳涓潬宸﹂潬鍙崇瓑
+     * @param {number} align 瀵归綈鏂瑰紡鏋氫妇
+     */
+    my.setAlign = function (align) {
+        this.obj.lvTextareaSetAlign(align)
+    }
+    /**
+     * 璁剧疆鍐呭鏈�澶ч暱搴︼紝瀛楃鏁伴檺鍒�
+     * @param {number} length 闀垮害
+     */
+    my.setMaxLength = function (length) {
+        this.obj.lvTextareaSetMaxLength(length)
+    }
+    /**
+     * 璁剧疆鏄惁鍚敤鍏夋爣瀹氫綅锛屾槸鍚︽樉绀簗
+     * @param {boolean} en true/false
+     */
+    my.setCursorClickPos = function (en) {
+        this.obj.lvTextareaSetCursorClickPos(en)
+    }
+    /**
+     * 鍦ㄥ綋鍓嶅厜鏍囦綅缃彃鍏ユ枃鏈�
+     * @param {string} txt 鏂囨湰鍐呭
+     */
+    my.lvTextareaAddText = function (txt) {
+        this.obj.lvTextareaAddText(txt)
+    }
+    /**
+     * 浠庡綋鍓嶅厜鏍囦綅缃垹闄ゅ乏杈圭殑瀛楃
+     */
+    my.lvTextareaDelChar = function () {
+        this.obj.lvTextareaDelChar()
+    }
+    /**
+     * 鑾峰彇/璁剧疆鏂囨湰鍐呭
+     * @param {string} text 璁剧疆鏂囨湰鍐呭
+     * @returns 鑾峰彇鏂囨湰鍐呭
+     */
+    my.text = function (text) {
+        if (text == null || text == undefined) {
+            return this.obj.lvTextareaGetText()
+        } else {
+            this.obj.lvTextareaSetText(text)
+        }
+    }
+    let comp = Object.assign(my, base);
+    utils.setParent(this.all, comp, parent)
+    return comp;
+}
+export default textarea;
\ No newline at end of file
diff --git a/vf205_access/dxmodules/uiUtils.js b/vf205_access/dxmodules/uiUtils.js
new file mode 100644
index 0000000..eae2a07
--- /dev/null
+++ b/vf205_access/dxmodules/uiUtils.js
@@ -0,0 +1,292 @@
+//build锛�20240315
+//鍏敤鐨勪竴浜涘嚱鏁般�佸父閲忋�佹灇涓剧瓑
+import { uiClass } from '../dxmodules/libvbar-m-dxui.so'
+import logger from './dxLogger.js'
+const ui = new uiClass();
+// 鍒濆鍖杣i缁勪欢
+ui.init()
+
+let utils = {}
+utils.GG = NativeObject.APP.NativeComponents
+utils.ENUM = utils.GG.NativeEnum
+utils.LAYER = {
+    "MAIN": 0,
+    "SYS": 1,
+    "TOP": 2
+}
+utils.EVENT = {
+    "CLICK": 7,
+    "LONG_PRESSED": 5,
+    "SHORT_PRESSED": 4,
+    "PRESSING": utils.ENUM.LV_EVENT_PRESSING,
+    "FOCUSED": utils.ENUM.LV_EVENT_FOCUSED,
+    "DEFOCUSED": utils.ENUM.LV_EVENT_DEFOCUSED,
+    "VALUE_CHANGED": utils.ENUM.LV_EVENT_VALUE_CHANGED,
+    "INSERT": utils.ENUM.LV_EVENT_INSERT,
+    "REFRESH": utils.ENUM.LV_EVENT_REFRESH,
+    "READY": utils.ENUM.LV_EVENT_READY,
+    "CANCEL": utils.ENUM.LV_EVENT_CANCEL,
+}
+utils.TEXT_ALIGN = {
+    "AUTO": 0,
+    "LEFT": 1,
+    "CENTER": 2,
+    "RIGHT": 3
+}
+utils.STATE = {
+    "DEFAULT": utils.ENUM.LV_STATE_DEFAULT,
+    "CHECKED": utils.ENUM.LV_STATE_CHECKED,
+    "FOCUSED": utils.ENUM.LV_STATE_FOCUSED,
+    "FOCUS_KEY": utils.ENUM.LV_STATE_FOCUS_KEY,
+    "EDITED": utils.ENUM.LV_STATE_EDITED,
+    "HOVERED": utils.ENUM.LV_STATE_HOVERED,
+    "PRESSED": utils.ENUM.LV_STATE_PRESSED,
+    "SCROLLED": utils.ENUM.LV_STATE_SCROLLED,
+    "DISABLED": utils.ENUM.LV_STATE_DISABLED,
+}
+utils.OBJ_FLAG = {
+    "CLICKABLE": utils.ENUM.LV_OBJ_FLAG_CLICKABLE,
+}
+utils.ALIGN = {//鐩稿鍙傜収瀵硅薄鐨勪綅缃紝甯� OUT 鐨勫湪鍙傜収瀵硅薄鐨勮竟鐣屽
+    "OUT_TOP_LEFT": utils.ENUM.LV_ALIGN_OUT_TOP_LEFT,
+    "OUT_TOP_MID": utils.ENUM.LV_ALIGN_OUT_TOP_MID,
+    "OUT_TOP_RIGHT": utils.ENUM.LV_ALIGN_OUT_TOP_RIGHT,
+    "OUT_BOTTOM_LEFT": utils.ENUM.LV_ALIGN_OUT_BOTTOM_LEFT,
+    "OUT_BOTTOM_MID": utils.ENUM.LV_ALIGN_OUT_BOTTOM_MID,
+    "OUT_BOTTOM_RIGHT": utils.ENUM.LV_ALIGN_OUT_BOTTOM_RIGHT,
+    "OUT_LEFT_TOP": utils.ENUM.LV_ALIGN_OUT_LEFT_TOP,
+    "OUT_LEFT_MID": utils.ENUM.LV_ALIGN_OUT_LEFT_MID,
+    "OUT_LEFT_BOTTOM": utils.ENUM.LV_ALIGN_OUT_LEFT_BOTTOM,
+    "OUT_RIGHT_TOP": utils.ENUM.LV_ALIGN_OUT_RIGHT_TOP,
+    "OUT_RIGHT_MID": utils.ENUM.LV_ALIGN_OUT_RIGHT_MID,
+    "OUT_RIGHT_BOTTOM": utils.ENUM.LV_ALIGN_OUT_RIGHT_BOTTOM,
+    "TOP_LEFT": utils.ENUM.LV_ALIGN_TOP_LEFT,
+    "TOP_MID": utils.ENUM.LV_ALIGN_TOP_MID,
+    "TOP_RIGHT": utils.ENUM.LV_ALIGN_TOP_RIGHT,
+    "BOTTOM_LEFT": utils.ENUM.LV_ALIGN_BOTTOM_LEFT,
+    "BOTTOM_MID": utils.ENUM.LV_ALIGN_BOTTOM_MID,
+    "BOTTOM_RIGHT": utils.ENUM.LV_ALIGN_BOTTOM_RIGHT,
+    "LEFT_MID": utils.ENUM.LV_ALIGN_LEFT_MID,
+    "RIGHT_MID": utils.ENUM.LV_ALIGN_RIGHT_MID,
+    "CENTER": utils.ENUM.LV_ALIGN_CENTER,
+    "DEFAULT": utils.ENUM.LV_ALIGN_DEFAULT
+}
+utils.FLEX_ALIGN = {//flex甯冨眬锛屽榻愭柟寮�
+    "START": utils.ENUM.LV_FLEX_ALIGN_START,
+    "END": utils.ENUM.LV_FLEX_ALIGN_END,
+    "CENTER": utils.ENUM.LV_FLEX_ALIGN_CENTER,
+    "SPACE_EVENLY": utils.ENUM.LV_FLEX_ALIGN_SPACE_EVENLY,
+    "SPACE_AROUND": utils.ENUM.LV_FLEX_ALIGN_SPACE_AROUND,
+    "SPACE_BETWEEN": utils.ENUM.LV_FLEX_ALIGN_SPACE_BETWEEN,
+}
+utils.FLEX_FLOW = {//flex甯冨眬锛屼富渚ц酱
+    "ROW": utils.ENUM.LV_FLEX_FLOW_ROW,
+    "COLUMN": utils.ENUM.LV_FLEX_FLOW_COLUMN,
+    "ROW_WRAP": utils.ENUM.LV_FLEX_FLOW_ROW_WRAP,
+    "ROW_REVERSE": utils.ENUM.LV_FLEX_FLOW_ROW_REVERSE,
+    "ROW_WRAP_REVERSE": utils.ENUM.LV_FLEX_FLOW_ROW_WRAP_REVERSE,
+    "COLUMN_WRAP": utils.ENUM.LV_FLEX_FLOW_COLUMN_WRAP,
+    "COLUMN_REVERSE": utils.ENUM.LV_FLEX_FLOW_COLUMN_REVERSE,
+    "COLUMN_WRAP_REVERSE": utils.ENUM.LV_FLEX_FLOW_COLUMN_WRAP_REVERSE,
+}
+utils.GRAD = {//娓愬彉鑹叉柟鍚�
+    "NONE": utils.ENUM.LV_GRAD_DIR_NONE,
+    "VER": utils.ENUM.LV_GRAD_DIR_VER,
+    "HOR": utils.ENUM.LV_GRAD_DIR_HOR,
+}
+utils.KEYBOARD = {//閿洏妯″紡
+    "TEXT_LOWER": utils.ENUM.LV_KEYBOARD_MODE_TEXT_LOWER,
+    "TEXT_UPPER": utils.ENUM.LV_KEYBOARD_MODE_TEXT_UPPER,
+    "SPECIAL": utils.ENUM.LV_KEYBOARD_MODE_SPECIAL,
+    "NUMBER": utils.ENUM.LV_KEYBOARD_MODE_NUMBER,
+    "K26": "K26",
+    "K9": "K9",
+}
+utils.FONT_STYLE = {
+    "NORMAL": utils.ENUM.FT_FONT_STYLE_NORMAL,
+    "ITALIC": utils.ENUM.FT_FONT_STYLE_ITALIC,
+    "BOLD": utils.ENUM.FT_FONT_STYLE_BOLD,
+}
+utils.BUTTONS_STATE = {
+    "HIDDEN": utils.ENUM.LV_BTNMATRIX_CTRL_HIDDEN,//鎸夐挳鐭╅樀涓殑鏌愪釜鎸夐挳鏄惁闅愯棌
+    "NO_REPEAT": utils.ENUM.LV_BTNMATRIX_CTRL_NO_REPEAT,//鎸夐挳鐭╅樀涓殑鎸夐挳鏄惁鍙互閲嶅鎸変笅,涓嶄細閲嶅瑙﹀彂鎸夐敭浜嬩欢
+    "DISABLED": utils.ENUM.LV_BTNMATRIX_CTRL_DISABLED,//鎸夐挳鐭╅樀涓殑鏌愪釜鎸夐挳鏄惁绂佺敤
+    "CHECKABLE": utils.ENUM.LV_BTNMATRIX_CTRL_CHECKABLE,//鎸夐挳鐭╅樀涓殑鎸夐挳鏄惁鍙�変腑
+    "CHECKED": utils.ENUM.LV_BTNMATRIX_CTRL_CHECKED,//鎸夐挳鐭╅樀涓殑鏌愪釜鎸夐挳鏄惁宸茶閫変腑,鍦ㄧ晫闈笂鍛堢幇涓鸿閫変腑鐘舵��
+    "CLICK_TRIG": utils.ENUM.LV_BTNMATRIX_CTRL_CLICK_TRIG,//鎸夐挳鐭╅樀涓殑鎸夐挳鏄惁鍙互閫氳繃鐐瑰嚮瑙﹀彂
+    "POPOVER": utils.ENUM.LV_BTNMATRIX_CTRL_POPOVER,//鐭╅樀涓殑鏌愪釜鎸夐挳鏄惁寮瑰嚭,琚偣鍑诲悗浼氭樉绀烘洿澶氱殑閫夐」鎴栧唴瀹�
+    "RECOLOR": utils.ENUM.LV_BTNMATRIX_CTRL_RECOLOR//鐭╅樀涓殑鎸夐挳鏄惁鍙噸鏂扮潃鑹�
+}
+//鏍峰紡璧蜂綔鐢ㄧ殑閮ㄥ垎
+utils.STYLE_PART = {
+    "MAIN": 0, //瀵硅薄褰撳墠鏍峰紡璧蜂綔鐢�
+    "ITEMS": 327680//瀵硅薄鍐呴儴瀛愰」璧蜂綔鐢紝姣斿buttonMatrix閲岀殑鎸夐挳缁�
+}
+//鏂囨湰瓒呭嚭鎺т欢鏄剧ず鐨勬ā寮�
+utils.LABEL_LONG_MODE = {
+    "WRAP": utils.ENUM.LV_LABEL_LONG_WRAP,//鏂囨湰闀跨殑鏃跺�欐崲琛�
+    "DOT": utils.ENUM.LV_LABEL_LONG_DOT,//鏂囨湰闀跨殑鏃跺�欑敤...鏇夸唬
+    "SCROLL": utils.ENUM.LV_LABEL_LONG_SCROLL,//鏂囨湰闀跨殑鏃跺�欒嚜鍔ㄦ粴鍔�
+    "SCROLL_CIRCULAR": utils.ENUM.LV_LABEL_LONG_SCROLL_CIRCULAR,//鏂囨湰闀跨殑鏃跺�欏惊鐜粴鍔�
+    "CLIP": utils.ENUM.LV_LABEL_LONG_CLIP,//鏂囨湰闀跨殑鏃跺�欒嚜鍔ㄦ埅鏂�
+}
+// 瀹炵幇0-100鏄犲皠涓�0-255
+utils.OPA_MAPPING = function (value) {
+    return Math.round((value / 100) * 255);
+}
+/**
+* 鏍¢獙鏁板瓧鏄惁涓虹┖锛屾槸鍚︿负number
+* @param {number} n 蹇呭~
+* @param {err} 閿欒淇℃伅锛岄潪蹇呭~锛屽~浜嗕細鎶涘嚭Error
+*/
+utils.validateNumber = function (n, err) {
+    return _valid(n, 'number', err)
+}
+/**
+* 鏍¢獙瀵硅薄鏄惁涓虹┖锛屾槸鍚︿负object
+* @param {object} o 蹇呭~
+* @param {err} 閿欒淇℃伅锛岄潪蹇呭~锛屽~浜嗕細鎶涘嚭Error
+*/
+utils.validateObject = function (o, err) {
+    return _valid(o, 'object', err)
+}
+/**
+ * 鏍¢獙ui瀵硅薄鐨勬瀯寤哄弬鏁�
+ * @param {array} all 蹇呭~,鎵�鏈夊璞″紩鐢�
+ * @param {string} id 涓嶈兘涓虹┖锛屽繀濉�
+ * @param {object} parent 闈炲繀濉紝缂虹渷鏄�0
+ */
+utils.validateBuild = function (all, id, parent, type) {
+    this.validateId(all, id)
+    if (parent === 0 || parent === 1 || parent === 2) {
+        return parent
+    }
+    if (!parent || !parent.obj) {
+        throw new Error(type + ".build: 'parent' paramter should not be null")
+    }
+    return parent.obj
+}
+/**
+ * 鏍¢獙鎵�鏈塽i鎺т欢鐨刬d锛屼笉鑳介噸澶�
+ * @param {array} all 
+ * @param {string} id 
+ */
+utils.validateId = function (all, id) {
+    this.validateString(id, "The 'id' parameter should not be null.")
+    if (all[id]) {
+        throw new Error("The id(" + id + ") already exists. Please set a different id value.")
+    }
+}
+/**
+* 鏍¢獙瀛楃涓叉槸鍚︿负绌�
+* @param {string} s 蹇呭~
+* @param {err} 閿欒淇℃伅锛岄潪蹇呭~锛屽~浜嗕細鎶涘嚭Error
+*/
+utils.validateString = function (s, err) {
+    let res = _valid(s, 'string', err)
+    if (!res) {
+        return false
+    }
+    if (s.length <= 0) {
+        if (err) {
+            throw new Error(err)
+        }
+        return false
+    }
+    return true
+}
+/**
+ * 瑙f瀽涓嶅悓绫诲瀷鐨勯鑹插��
+ * @param {any} value 鏀寔鏁板瓧绫诲瀷锛�0x34ffaa锛屽瓧绗︿覆绫诲瀷:'0x34ffaa',瀛楃涓茬被鍨�:'#34ffaa'
+ * @returns 
+ */
+utils.colorParse = function (value) {
+    if (typeof value == 'string') {
+        value = value.replace('#', '0x')
+        value = parseInt(value, 16)
+    }
+    return value
+}
+/**
+ * 鑾峰彇瑙︽懜鐐圭殑鍧愭爣
+ * @returns {x:妯潗鏍�,y:绾靛潗鏍噠
+ */
+utils.getTouchPoint = function () {
+    let point = NativeObject.APP.NativeComponents.NativeIndev.lvIndevGetPoint()
+    return point
+}
+/**
+ * 鎻愪緵鍔ㄧ敾
+ * @param {object} obj 鍔ㄧ敾鎿嶄綔瀵硅薄锛屽彲浠ユ槸浠绘剰瀵硅薄锛屽洖璋冨弬鏁拌幏鍙�
+ * @param {number} start 鍖洪棿寮�濮嬪�硷紝涓�鑸拰end鎼厤浣跨敤锛屽洖璋冨弬鏁拌幏鍙栵紝start鍦ㄥ姩鐢昏繃绋嬪彉鍖栧埌end
+ * @param {number} end 鍖洪棿缁撴潫鍊�
+ * @param {function} cb 鍥炶皟鍑芥暟(obj, v)=>{},obj鍗冲姩鐢绘搷浣滃璞★紝鍖洪棿鍊硷紙start-end锛�
+ * @param {number} duration 鍔ㄧ敾鎸佺画鏃堕棿锛屾绉�
+ * @param {number} backDuration 鍙�夛紝鍔ㄧ敾鍥炴斁鏃堕棿锛屾绉掞紝缂虹渷涓嶅洖鏀�
+ * @param {number} repeat 鍙�夛紝鍔ㄧ敾閲嶅娆℃暟锛岀己鐪�1娆�
+ * @param {string} mode 閫熺巼鏇茬嚎锛屽彲閫夛紝缂虹渷linear锛屽唴缃姛鑳斤細linear,ease_in,ease_out,ease_in_out,overshoot,bounce,step
+ *  linear 绾挎�у姩鐢�
+    step 鍦ㄦ渶鍚庝竴姝ユ洿鏀�
+    ease_in 寮�濮嬬紦鎱�
+    ease_out 鏈�鍚庣紦鎱�
+    ease_in_out 鍦ㄥ紑濮嬪拰缁撴潫鏃堕兘寰堢紦鎱�
+    overshoot 瓒呭嚭鏈�缁堝��
+    bounce 浠庢渶缁堝�煎弽寮逛竴鐐癸紙姣斿鎾炲埌澧欙級
+ * @returns 鍔ㄧ敾瀹炰緥锛屼竴瀹氬緱淇濆瓨鍒板叏灞�
+ */
+utils.anime = function (obj, start, end, cb, duration, backDuration, repeat, mode) {
+    // 1銆佸垵濮嬪寲鍔ㄧ敾
+    let anim = NativeObject.APP.NativeComponents.NativeAnim.lvAnimInit()
+    // 2銆佽缃姩鐢诲璞�
+    anim.lvAnimSetVar(obj)
+    // 3銆佽缃捣濮嬪拰缁撴潫鍊�
+    anim.lvAnimSetValues(start, end)
+    //4銆佽缃姩鐢诲洖璋冨嚱鏁�
+    anim.lvAnimSetExecCb(cb)
+    // 5銆佽缃姩鐢绘椂闂�
+    anim.lvAnimSetTime(duration)
+    // 鍙�夛紝璁剧疆鍔ㄧ敾鍥炴斁鏃堕棿锛屼笉璁剧疆灏变笉鍥炴斁
+    if (backDuration) {
+        anim.lvAnimSetPlaybackTime(backDuration)
+    }
+    // 鍙�夛紝璁剧疆鍔ㄧ敾閲嶅娆℃暟
+    if (repeat) {
+        anim.lvAnimSetRepeatCount(repeat)
+    }
+    // 鍙�夛紝璁剧疆鍔ㄧ敾閫熺巼鏇茬嚎
+    if (mode) {
+        anim.lvAnimSetPathCb(mode)
+    }
+    // 6銆佽繍琛屽姩鐢�
+    anim.lvAnimStart()
+    return anim
+}
+//姣忎釜瀵硅薄璁剧疆parent鍜宑hildren
+utils.setParent = function (all, child, parent) {
+    if (!all || parent == null || parent == undefined || !child) {
+        return
+    }
+    if((typeof parent)=='number'){
+
+    }
+    const parentId = ((typeof parent)=='number')?'' + parent:parent.id//鎶�0锛�1锛�2杞垚瀛楃涓�
+    if (!all[parentId]) {
+        all[parentId] = { id: parentId }//鏍硅妭鐐�0,1,2
+    }
+    if (!all[parentId].children) {
+        all[parentId].children = []
+    }
+    all[parentId].children.push(child.id)
+    child.parent = parentId
+    all[child.id] = child
+}
+function _valid(n, type, err) {
+    if (n === undefined || n === null || (typeof n) != type) {
+        if (err) {
+            throw new Error(err)
+        }
+        return false
+    }
+    return true
+}
+export default utils
\ No newline at end of file
diff --git a/vf205_access/dxmodules/uiView.js b/vf205_access/dxmodules/uiView.js
new file mode 100644
index 0000000..9f66a80
--- /dev/null
+++ b/vf205_access/dxmodules/uiView.js
@@ -0,0 +1,27 @@
+//build锛�20240314
+//鍩虹鐭╁舰瀵硅薄 绫讳技div鍙互鍔犺浇浠讳綍鍏跺畠鎺т欢
+import utils from "./uiUtils.js"
+import base from "./uiBase.js"
+let view = {}
+/**
+ * 鍒涘缓涓�涓獀iew鍔犺浇鍦ㄧ埗鎺т欢瀵硅薄涓�
+ * @param {string} id 鎺т欢id锛屽繀濉�
+ * @param {object} parent 鐖跺璞�
+ * @returns 鍒涘缓瀹岀殑view瀵硅薄
+ */
+view.build = function (id, parent) {
+    let temp = utils.validateBuild(view.all, id, parent, 'view')
+    let my = {type: 'view'}
+    if (temp === 0 || temp === 1 || temp === 2) {
+        my.obj = new utils.GG.NativeBasicComponent({ uid: id }, null, temp)
+    }
+    else {
+        my.obj = new utils.GG.NativeBasicComponent({ uid: id }, temp)
+    }
+    my.id = id
+    let comp = Object.assign(my, base);
+    utils.setParent(this.all,comp,parent)
+    return comp;
+}
+
+export default view;
\ No newline at end of file
diff --git a/vf205_access/dxmodules/vgUartWorker.js b/vf205_access/dxmodules/vgUartWorker.js
new file mode 100644
index 0000000..62adb8c
--- /dev/null
+++ b/vf205_access/dxmodules/vgUartWorker.js
@@ -0,0 +1,166 @@
+//build:20240715
+//鐢ㄤ簬绠�鍖杣art缁勪欢寰厜閫氫俊鍗忚鐨勪娇鐢紝鎶妘art灏佽鍦ㄨ繖涓獁orker閲岋紝浣跨敤鑰呭彧闇�瑕佽闃卐ventcenter鐨勪簨浠跺氨鍙互鐩戝惉uart
+import log from './dxLogger.js'
+import uart from './dxUart.js'
+import common from './dxCommon.js';
+import dxMap from './dxMap.js'
+import * as os from "os";
+import std from './dxStd.js'
+const map = dxMap.get('default')
+const id = "{{id}}"
+const options = map.get("__vguart__run_init" + id)
+const timeout = 100
+const longTimeout = 500
+
+function run() {
+    uart.open(options.type, options.path, options.id)
+    log.info('vg uart start......,id =', id)
+    std.setInterval(() => {
+        try {
+            // 鎺ユ敹鏁版嵁妯″紡
+            if (options.passThrough) {
+                // 閫忎紶妯″紡锛岄�傞厤闊︽牴涔嬬被
+                passThrough()
+            }
+            if(options.type == uart.TYPE.USBHID){
+                receiveUsb() 
+            } else {
+                // 寰厜閫氫俊鍗忚妯″紡
+                receive()
+            }
+        } catch (error) {
+            log.error(error)
+        }
+    }, 10)
+}
+
+// 閫忎紶妯″紡
+function passThrough() {
+    let pack = [];
+    let buffer = readOne()
+    while (buffer !== null) {
+        pack.push(buffer)
+        os.sleep(10)
+        buffer = readOne()
+    }
+    if (pack.length !== 0) {
+        __bus.fire(uart.VG.RECEIVE_MSG + options.id, pack)//bus.newworker鐨勬椂鍊欎細import eventbus as __bus
+    }
+}
+
+function receive() {
+    //鍓�2涓瓧鑺傚繀椤绘槸55aa
+    let buffer = readOne()
+    if (buffer === null) {
+        return;
+    }
+    if (buffer == 85) {//0x55
+        buffer = readOne()
+        if (buffer != 170) {//0xaa
+            return;
+        }
+    } else {
+        return;
+    }
+    let pack = {};
+    // 璇诲彇鍛戒护瀛楋紙鍗犵敤1Byte锛�
+    buffer = readOne()
+    if (buffer === null) {
+        return;
+    }
+    pack.cmd = buffer
+    if (options.result) {
+        // 璇诲彇缁撴灉瀛楋紙鍗犵敤1Byte锛�
+        buffer = readOne()
+        if (buffer === null) {
+            return;
+        }
+        pack.result = buffer;
+    } else {
+        pack.result = 0//0涓嶅奖鍝峛cc鐨勮绠楃粨鏋�
+    }
+    // 鍛戒护澶村凡瑙f瀽瀹岋紝璇诲彇闀垮害瀛楋紙鍗犵敤2Byte锛�
+    let len1 = readOne()
+    if (len1 === null) {
+        return;
+    }
+    let len2 = readOne()
+    if (len2 === null) {
+        return;
+    }
+    // 瑙f瀽闀垮害瀛楋紝鑾峰彇鏁版嵁鍩熼暱搴�
+    let len = len1 + len2 * 256
+    // 鏍规嵁闀垮害瀛楄鍙栨寚瀹氭暟鎹暱搴�
+    pack.length = len
+    if (len > 0) {
+        buffer = uart.receive(len, longTimeout, options.id)
+        if (buffer === null) {
+            return;
+        }
+        pack.data = Array.from(buffer);
+    } else {
+        pack.data = 0
+    }
+    // 璇诲彇1Byte鐨勬牎楠屼綅
+    buffer = readOne()
+    if (buffer === null) {
+        return;
+    }
+    let bcc = valid(pack, buffer)
+    let res = { cmd: int2hex(pack.cmd), length: pack.length, bcc: bcc }
+    if (pack.length > 0) {
+        res.data = common.arrToHex(pack.data)
+    }
+    if (options.result) {
+        res.result = int2hex(pack.result)
+    }
+    __bus.fire(uart.VG.RECEIVE_MSG + options.id, res)//bus.newworker鐨勬椂鍊欎細import eventbus as __bus
+}
+
+
+function receiveUsb() {
+    let arr = uart.receive(1024, 100, options.id)
+    if (arr && arr[0] == 0x55 && arr[1] == 0xAA) {
+        let cmd = arr[2]
+        let dlen = arr[4] * 256 + arr[3]
+        if (dlen > (1024 - 6)) {
+            let tempLen = dlen - 1024 + 5 
+            while(tempLen >= 0){
+                let tempArr = uart.receive(1024, 100, options.id)
+                tempLen = tempLen - tempArr.length
+                let newArr = new Uint8Array(arr.length + tempArr.length)
+                newArr.set(arr)
+                newArr.set(tempArr, arr.length)
+                arr = newArr
+            }
+        }
+        let data = (dlen == 0 ? [] : Object.values(arr.slice(5, 5 + dlen)))
+        let bcc = common.calculateBcc([0x55, 0xAA, arr[2], arr[3], arr[4]].concat(data))
+        data = data.map(v => v.toString(16).padStart(2, '0')).join('')
+        if (bcc == arr[5 + dlen]) {
+            let res = { "cmd": cmd.toString(16).padStart(2, '0'), "length": dlen, "data": data, "bcc": true }
+            __bus.fire(uart.VG.RECEIVE_MSG + options.id, res)//bus.newworker鐨勬椂鍊欎細import eventbus as __bus
+        }
+    }
+}
+
+function valid(pack, bcc) {
+    let temp = common.calculateBcc([0x55, 0xaa, pack.cmd, pack.result, pack.length % 256, Math.floor(pack.length / 256)].concat(pack.data))
+    return temp === bcc
+}
+function readOne() {
+    let buffer = uart.receive(1, timeout, options.id)
+    if (buffer) {
+        return parseInt(buffer);
+    }
+    return null
+}
+function int2hex(num) {
+    return num.toString(16).padStart(2, '0')
+}
+
+try {
+    run()
+} catch (error) {
+    log.error(error, error.stack)
+}
\ No newline at end of file
diff --git a/vf205_access/resource/CN/wav/access_f.wav b/vf205_access/resource/CN/wav/access_f.wav
new file mode 100644
index 0000000..be7cdf6
--- /dev/null
+++ b/vf205_access/resource/CN/wav/access_f.wav
Binary files differ
diff --git a/vf205_access/resource/CN/wav/access_s.wav b/vf205_access/resource/CN/wav/access_s.wav
new file mode 100644
index 0000000..fdd6ec4
--- /dev/null
+++ b/vf205_access/resource/CN/wav/access_s.wav
Binary files differ
diff --git a/vf205_access/resource/CN/wav/btn11.wav b/vf205_access/resource/CN/wav/btn11.wav
new file mode 100644
index 0000000..b92f478
--- /dev/null
+++ b/vf205_access/resource/CN/wav/btn11.wav
Binary files differ
diff --git a/vf205_access/resource/CN/wav/btn12.wav b/vf205_access/resource/CN/wav/btn12.wav
new file mode 100644
index 0000000..b304efe
--- /dev/null
+++ b/vf205_access/resource/CN/wav/btn12.wav
Binary files differ
diff --git a/vf205_access/resource/CN/wav/btn13.wav b/vf205_access/resource/CN/wav/btn13.wav
new file mode 100644
index 0000000..197a085
--- /dev/null
+++ b/vf205_access/resource/CN/wav/btn13.wav
Binary files differ
diff --git a/vf205_access/resource/CN/wav/btn21.wav b/vf205_access/resource/CN/wav/btn21.wav
new file mode 100644
index 0000000..3f1cb3a
--- /dev/null
+++ b/vf205_access/resource/CN/wav/btn21.wav
Binary files differ
diff --git a/vf205_access/resource/CN/wav/btn22.wav b/vf205_access/resource/CN/wav/btn22.wav
new file mode 100644
index 0000000..f0b0eb1
--- /dev/null
+++ b/vf205_access/resource/CN/wav/btn22.wav
Binary files differ
diff --git a/vf205_access/resource/CN/wav/btn23.wav b/vf205_access/resource/CN/wav/btn23.wav
new file mode 100644
index 0000000..5e58697
--- /dev/null
+++ b/vf205_access/resource/CN/wav/btn23.wav
Binary files differ
diff --git a/vf205_access/resource/CN/wav/btn31.wav b/vf205_access/resource/CN/wav/btn31.wav
new file mode 100644
index 0000000..f600140
--- /dev/null
+++ b/vf205_access/resource/CN/wav/btn31.wav
Binary files differ
diff --git a/vf205_access/resource/CN/wav/btn32.wav b/vf205_access/resource/CN/wav/btn32.wav
new file mode 100644
index 0000000..641d760
--- /dev/null
+++ b/vf205_access/resource/CN/wav/btn32.wav
Binary files differ
diff --git a/vf205_access/resource/CN/wav/btn33.wav b/vf205_access/resource/CN/wav/btn33.wav
new file mode 100644
index 0000000..197a085
--- /dev/null
+++ b/vf205_access/resource/CN/wav/btn33.wav
Binary files differ
diff --git a/vf205_access/resource/CN/wav/calibration_s.wav b/vf205_access/resource/CN/wav/calibration_s.wav
new file mode 100644
index 0000000..a4bff16
--- /dev/null
+++ b/vf205_access/resource/CN/wav/calibration_s.wav
Binary files differ
diff --git a/vf205_access/resource/CN/wav/control_f.wav b/vf205_access/resource/CN/wav/control_f.wav
new file mode 100644
index 0000000..747e2c0
--- /dev/null
+++ b/vf205_access/resource/CN/wav/control_f.wav
Binary files differ
diff --git a/vf205_access/resource/CN/wav/door_close.wav b/vf205_access/resource/CN/wav/door_close.wav
new file mode 100644
index 0000000..5cceeaa
--- /dev/null
+++ b/vf205_access/resource/CN/wav/door_close.wav
Binary files differ
diff --git a/vf205_access/resource/CN/wav/door_open.wav b/vf205_access/resource/CN/wav/door_open.wav
new file mode 100644
index 0000000..a0c86f4
--- /dev/null
+++ b/vf205_access/resource/CN/wav/door_open.wav
Binary files differ
diff --git a/vf205_access/resource/CN/wav/emergency.wav b/vf205_access/resource/CN/wav/emergency.wav
new file mode 100644
index 0000000..aa78e67
--- /dev/null
+++ b/vf205_access/resource/CN/wav/emergency.wav
Binary files differ
diff --git a/vf205_access/resource/CN/wav/emergency_f.wav b/vf205_access/resource/CN/wav/emergency_f.wav
new file mode 100644
index 0000000..630d23b
--- /dev/null
+++ b/vf205_access/resource/CN/wav/emergency_f.wav
Binary files differ
diff --git a/vf205_access/resource/CN/wav/emergency_s.wav b/vf205_access/resource/CN/wav/emergency_s.wav
new file mode 100644
index 0000000..6f5ed36
--- /dev/null
+++ b/vf205_access/resource/CN/wav/emergency_s.wav
Binary files differ
diff --git a/vf205_access/resource/CN/wav/failed.wav b/vf205_access/resource/CN/wav/failed.wav
new file mode 100644
index 0000000..e47d4eb
--- /dev/null
+++ b/vf205_access/resource/CN/wav/failed.wav
Binary files differ
diff --git a/vf205_access/resource/CN/wav/light_close.wav b/vf205_access/resource/CN/wav/light_close.wav
new file mode 100644
index 0000000..f474245
--- /dev/null
+++ b/vf205_access/resource/CN/wav/light_close.wav
Binary files differ
diff --git a/vf205_access/resource/CN/wav/light_open.wav b/vf205_access/resource/CN/wav/light_open.wav
new file mode 100644
index 0000000..ee0428a
--- /dev/null
+++ b/vf205_access/resource/CN/wav/light_open.wav
Binary files differ
diff --git a/vf205_access/resource/CN/wav/network.wav b/vf205_access/resource/CN/wav/network.wav
new file mode 100644
index 0000000..41a063a
--- /dev/null
+++ b/vf205_access/resource/CN/wav/network.wav
Binary files differ
diff --git a/vf205_access/resource/CN/wav/read.wav b/vf205_access/resource/CN/wav/read.wav
new file mode 100644
index 0000000..5d43586
--- /dev/null
+++ b/vf205_access/resource/CN/wav/read.wav
Binary files differ
diff --git a/vf205_access/resource/CN/wav/recg_f.wav b/vf205_access/resource/CN/wav/recg_f.wav
new file mode 100644
index 0000000..357972f
--- /dev/null
+++ b/vf205_access/resource/CN/wav/recg_f.wav
Binary files differ
diff --git a/vf205_access/resource/CN/wav/recg_s.wav b/vf205_access/resource/CN/wav/recg_s.wav
new file mode 100644
index 0000000..9258bae
--- /dev/null
+++ b/vf205_access/resource/CN/wav/recg_s.wav
Binary files differ
diff --git a/vf205_access/resource/CN/wav/recognition.wav b/vf205_access/resource/CN/wav/recognition.wav
new file mode 100644
index 0000000..dac63a3
--- /dev/null
+++ b/vf205_access/resource/CN/wav/recognition.wav
Binary files differ
diff --git a/vf205_access/resource/CN/wav/recognition_s.wav b/vf205_access/resource/CN/wav/recognition_s.wav
new file mode 100644
index 0000000..e5c5772
--- /dev/null
+++ b/vf205_access/resource/CN/wav/recognition_s.wav
Binary files differ
diff --git a/vf205_access/resource/CN/wav/register.wav b/vf205_access/resource/CN/wav/register.wav
new file mode 100644
index 0000000..c76cd83
--- /dev/null
+++ b/vf205_access/resource/CN/wav/register.wav
Binary files differ
diff --git a/vf205_access/resource/CN/wav/stranger.wav b/vf205_access/resource/CN/wav/stranger.wav
new file mode 100644
index 0000000..9f08f3a
--- /dev/null
+++ b/vf205_access/resource/CN/wav/stranger.wav
Binary files differ
diff --git a/vf205_access/resource/CN/wav/user2.wav b/vf205_access/resource/CN/wav/user2.wav
new file mode 100644
index 0000000..96a9f09
--- /dev/null
+++ b/vf205_access/resource/CN/wav/user2.wav
Binary files differ
diff --git a/vf205_access/resource/CN/wav/user2_s.wav b/vf205_access/resource/CN/wav/user2_s.wav
new file mode 100644
index 0000000..611fd82
--- /dev/null
+++ b/vf205_access/resource/CN/wav/user2_s.wav
Binary files differ
diff --git a/vf205_access/resource/CN/wav/verify.wav b/vf205_access/resource/CN/wav/verify.wav
new file mode 100644
index 0000000..3a7555c
--- /dev/null
+++ b/vf205_access/resource/CN/wav/verify.wav
Binary files differ
diff --git a/vf205_access/resource/CN/wav/verify_10x_f.wav b/vf205_access/resource/CN/wav/verify_10x_f.wav
new file mode 100644
index 0000000..72c6d99
--- /dev/null
+++ b/vf205_access/resource/CN/wav/verify_10x_f.wav
Binary files differ
diff --git a/vf205_access/resource/CN/wav/verify_10x_s.wav b/vf205_access/resource/CN/wav/verify_10x_s.wav
new file mode 100644
index 0000000..deef22e
--- /dev/null
+++ b/vf205_access/resource/CN/wav/verify_10x_s.wav
Binary files differ
diff --git a/vf205_access/resource/CN/wav/verify_200_f.wav b/vf205_access/resource/CN/wav/verify_200_f.wav
new file mode 100644
index 0000000..357c4c4
--- /dev/null
+++ b/vf205_access/resource/CN/wav/verify_200_f.wav
Binary files differ
diff --git a/vf205_access/resource/CN/wav/verify_200_s.wav b/vf205_access/resource/CN/wav/verify_200_s.wav
new file mode 100644
index 0000000..52c66b5
--- /dev/null
+++ b/vf205_access/resource/CN/wav/verify_200_s.wav
Binary files differ
diff --git a/vf205_access/resource/CN/wav/verify_300_f.wav b/vf205_access/resource/CN/wav/verify_300_f.wav
new file mode 100644
index 0000000..fae609d
--- /dev/null
+++ b/vf205_access/resource/CN/wav/verify_300_f.wav
Binary files differ
diff --git a/vf205_access/resource/CN/wav/verify_300_s.wav b/vf205_access/resource/CN/wav/verify_300_s.wav
new file mode 100644
index 0000000..92b9958
--- /dev/null
+++ b/vf205_access/resource/CN/wav/verify_300_s.wav
Binary files differ
diff --git a/vf205_access/resource/CN/wav/verify_400_f.wav b/vf205_access/resource/CN/wav/verify_400_f.wav
new file mode 100644
index 0000000..5752539
--- /dev/null
+++ b/vf205_access/resource/CN/wav/verify_400_f.wav
Binary files differ
diff --git a/vf205_access/resource/CN/wav/verify_400_s.wav b/vf205_access/resource/CN/wav/verify_400_s.wav
new file mode 100644
index 0000000..876a228
--- /dev/null
+++ b/vf205_access/resource/CN/wav/verify_400_s.wav
Binary files differ
diff --git a/vf205_access/resource/EN/wav/calibration_s.wav b/vf205_access/resource/EN/wav/calibration_s.wav
new file mode 100644
index 0000000..5d8ba54
--- /dev/null
+++ b/vf205_access/resource/EN/wav/calibration_s.wav
Binary files differ
diff --git a/vf205_access/resource/EN/wav/network.wav b/vf205_access/resource/EN/wav/network.wav
new file mode 100644
index 0000000..f866c59
--- /dev/null
+++ b/vf205_access/resource/EN/wav/network.wav
Binary files differ
diff --git a/vf205_access/resource/EN/wav/read.wav b/vf205_access/resource/EN/wav/read.wav
new file mode 100644
index 0000000..7b40b0b
--- /dev/null
+++ b/vf205_access/resource/EN/wav/read.wav
Binary files differ
diff --git a/vf205_access/resource/EN/wav/recg_f.wav b/vf205_access/resource/EN/wav/recg_f.wav
new file mode 100644
index 0000000..bc4258f
--- /dev/null
+++ b/vf205_access/resource/EN/wav/recg_f.wav
Binary files differ
diff --git a/vf205_access/resource/EN/wav/recg_s.wav b/vf205_access/resource/EN/wav/recg_s.wav
new file mode 100644
index 0000000..054cdb6
--- /dev/null
+++ b/vf205_access/resource/EN/wav/recg_s.wav
Binary files differ
diff --git a/vf205_access/resource/EN/wav/recognition.wav b/vf205_access/resource/EN/wav/recognition.wav
new file mode 100644
index 0000000..1394a09
--- /dev/null
+++ b/vf205_access/resource/EN/wav/recognition.wav
Binary files differ
diff --git a/vf205_access/resource/EN/wav/recognition_s.wav b/vf205_access/resource/EN/wav/recognition_s.wav
new file mode 100644
index 0000000..b096125
--- /dev/null
+++ b/vf205_access/resource/EN/wav/recognition_s.wav
Binary files differ
diff --git a/vf205_access/resource/EN/wav/register.wav b/vf205_access/resource/EN/wav/register.wav
new file mode 100644
index 0000000..324688a
--- /dev/null
+++ b/vf205_access/resource/EN/wav/register.wav
Binary files differ
diff --git a/vf205_access/resource/EN/wav/stranger.wav b/vf205_access/resource/EN/wav/stranger.wav
new file mode 100644
index 0000000..6ba2568
--- /dev/null
+++ b/vf205_access/resource/EN/wav/stranger.wav
Binary files differ
diff --git a/vf205_access/resource/EN/wav/verify.wav b/vf205_access/resource/EN/wav/verify.wav
new file mode 100644
index 0000000..f95f56c
--- /dev/null
+++ b/vf205_access/resource/EN/wav/verify.wav
Binary files differ
diff --git a/vf205_access/resource/EN/wav/verify_10x_f.wav b/vf205_access/resource/EN/wav/verify_10x_f.wav
new file mode 100644
index 0000000..f787a39
--- /dev/null
+++ b/vf205_access/resource/EN/wav/verify_10x_f.wav
Binary files differ
diff --git a/vf205_access/resource/EN/wav/verify_10x_s.wav b/vf205_access/resource/EN/wav/verify_10x_s.wav
new file mode 100644
index 0000000..b00d806
--- /dev/null
+++ b/vf205_access/resource/EN/wav/verify_10x_s.wav
Binary files differ
diff --git a/vf205_access/resource/EN/wav/verify_200_f.wav b/vf205_access/resource/EN/wav/verify_200_f.wav
new file mode 100644
index 0000000..acacbcf
--- /dev/null
+++ b/vf205_access/resource/EN/wav/verify_200_f.wav
Binary files differ
diff --git a/vf205_access/resource/EN/wav/verify_200_s.wav b/vf205_access/resource/EN/wav/verify_200_s.wav
new file mode 100644
index 0000000..c85a71b
--- /dev/null
+++ b/vf205_access/resource/EN/wav/verify_200_s.wav
Binary files differ
diff --git a/vf205_access/resource/EN/wav/verify_300_f.wav b/vf205_access/resource/EN/wav/verify_300_f.wav
new file mode 100644
index 0000000..eb7a0d4
--- /dev/null
+++ b/vf205_access/resource/EN/wav/verify_300_f.wav
Binary files differ
diff --git a/vf205_access/resource/EN/wav/verify_300_s.wav b/vf205_access/resource/EN/wav/verify_300_s.wav
new file mode 100644
index 0000000..ec178b7
--- /dev/null
+++ b/vf205_access/resource/EN/wav/verify_300_s.wav
Binary files differ
diff --git a/vf205_access/resource/EN/wav/verify_400_f.wav b/vf205_access/resource/EN/wav/verify_400_f.wav
new file mode 100644
index 0000000..16aa712
--- /dev/null
+++ b/vf205_access/resource/EN/wav/verify_400_f.wav
Binary files differ
diff --git a/vf205_access/resource/EN/wav/verify_400_s.wav b/vf205_access/resource/EN/wav/verify_400_s.wav
new file mode 100644
index 0000000..e4914b2
--- /dev/null
+++ b/vf205_access/resource/EN/wav/verify_400_s.wav
Binary files differ
diff --git a/vf205_access/resource/font/AlibabaPuHuiTi-2-65-Medium.ttf b/vf205_access/resource/font/AlibabaPuHuiTi-2-65-Medium.ttf
new file mode 100644
index 0000000..588a02d
--- /dev/null
+++ b/vf205_access/resource/font/AlibabaPuHuiTi-2-65-Medium.ttf
Binary files differ
diff --git a/vf205_access/resource/image/4g.png b/vf205_access/resource/image/4g.png
new file mode 100644
index 0000000..5404f82
--- /dev/null
+++ b/vf205_access/resource/image/4g.png
Binary files differ
diff --git a/vf205_access/resource/image/4g_dark.png b/vf205_access/resource/image/4g_dark.png
new file mode 100644
index 0000000..c531e9a
--- /dev/null
+++ b/vf205_access/resource/image/4g_dark.png
Binary files differ
diff --git a/vf205_access/resource/image/accessCtrl.png b/vf205_access/resource/image/accessCtrl.png
new file mode 100644
index 0000000..bd73f79
--- /dev/null
+++ b/vf205_access/resource/image/accessCtrl.png
Binary files differ
diff --git a/vf205_access/resource/image/add.png b/vf205_access/resource/image/add.png
new file mode 100644
index 0000000..3e4c4b0
--- /dev/null
+++ b/vf205_access/resource/image/add.png
Binary files differ
diff --git a/vf205_access/resource/image/advance.png b/vf205_access/resource/image/advance.png
new file mode 100644
index 0000000..5f6ae29
--- /dev/null
+++ b/vf205_access/resource/image/advance.png
Binary files differ
diff --git a/vf205_access/resource/image/app.png b/vf205_access/resource/image/app.png
new file mode 100644
index 0000000..17d3e3c
--- /dev/null
+++ b/vf205_access/resource/image/app.png
Binary files differ
diff --git a/vf205_access/resource/image/app_btn.png b/vf205_access/resource/image/app_btn.png
new file mode 100644
index 0000000..86494be
--- /dev/null
+++ b/vf205_access/resource/image/app_btn.png
Binary files differ
diff --git a/vf205_access/resource/image/app_qrcode.png b/vf205_access/resource/image/app_qrcode.png
new file mode 100644
index 0000000..5172bfb
--- /dev/null
+++ b/vf205_access/resource/image/app_qrcode.png
Binary files differ
diff --git a/vf205_access/resource/image/arrow_right.png b/vf205_access/resource/image/arrow_right.png
new file mode 100644
index 0000000..f30bb36
--- /dev/null
+++ b/vf205_access/resource/image/arrow_right.png
Binary files differ
diff --git a/vf205_access/resource/image/back.png b/vf205_access/resource/image/back.png
new file mode 100644
index 0000000..b8fd21b
--- /dev/null
+++ b/vf205_access/resource/image/back.png
Binary files differ
diff --git a/vf205_access/resource/image/back_2.png b/vf205_access/resource/image/back_2.png
new file mode 100644
index 0000000..c7343d6
--- /dev/null
+++ b/vf205_access/resource/image/back_2.png
Binary files differ
diff --git a/vf205_access/resource/image/background.jpg b/vf205_access/resource/image/background.jpg
new file mode 100644
index 0000000..64adab6
--- /dev/null
+++ b/vf205_access/resource/image/background.jpg
Binary files differ
diff --git a/vf205_access/resource/image/backspace.png b/vf205_access/resource/image/backspace.png
new file mode 100644
index 0000000..51dcd8f
--- /dev/null
+++ b/vf205_access/resource/image/backspace.png
Binary files differ
diff --git a/vf205_access/resource/image/basic.png b/vf205_access/resource/image/basic.png
new file mode 100644
index 0000000..9582177
--- /dev/null
+++ b/vf205_access/resource/image/basic.png
Binary files differ
diff --git a/vf205_access/resource/image/black_btn.png b/vf205_access/resource/image/black_btn.png
new file mode 100644
index 0000000..28dfe8c
--- /dev/null
+++ b/vf205_access/resource/image/black_btn.png
Binary files differ
diff --git a/vf205_access/resource/image/card.png b/vf205_access/resource/image/card.png
new file mode 100644
index 0000000..9931f21
--- /dev/null
+++ b/vf205_access/resource/image/card.png
Binary files differ
diff --git a/vf205_access/resource/image/close.png b/vf205_access/resource/image/close.png
new file mode 100644
index 0000000..4f3a4a1
--- /dev/null
+++ b/vf205_access/resource/image/close.png
Binary files differ
diff --git a/vf205_access/resource/image/close_small.png b/vf205_access/resource/image/close_small.png
new file mode 100644
index 0000000..f5e815b
--- /dev/null
+++ b/vf205_access/resource/image/close_small.png
Binary files differ
diff --git a/vf205_access/resource/image/cloudCert.png b/vf205_access/resource/image/cloudCert.png
new file mode 100644
index 0000000..5d3fffe
--- /dev/null
+++ b/vf205_access/resource/image/cloudCert.png
Binary files differ
diff --git a/vf205_access/resource/image/co2_f.png b/vf205_access/resource/image/co2_f.png
new file mode 100644
index 0000000..89fb8db
--- /dev/null
+++ b/vf205_access/resource/image/co2_f.png
Binary files differ
diff --git a/vf205_access/resource/image/co2_s.png b/vf205_access/resource/image/co2_s.png
new file mode 100644
index 0000000..c88502f
--- /dev/null
+++ b/vf205_access/resource/image/co2_s.png
Binary files differ
diff --git a/vf205_access/resource/image/commMgmt.png b/vf205_access/resource/image/commMgmt.png
new file mode 100644
index 0000000..0b0be70
--- /dev/null
+++ b/vf205_access/resource/image/commMgmt.png
Binary files differ
diff --git a/vf205_access/resource/image/config.png b/vf205_access/resource/image/config.png
new file mode 100644
index 0000000..0a5b62b
--- /dev/null
+++ b/vf205_access/resource/image/config.png
Binary files differ
diff --git a/vf205_access/resource/image/config_btn.png b/vf205_access/resource/image/config_btn.png
new file mode 100644
index 0000000..d9e899b
--- /dev/null
+++ b/vf205_access/resource/image/config_btn.png
Binary files differ
diff --git a/vf205_access/resource/image/delete.png b/vf205_access/resource/image/delete.png
new file mode 100644
index 0000000..5ddd206
--- /dev/null
+++ b/vf205_access/resource/image/delete.png
Binary files differ
diff --git a/vf205_access/resource/image/delete_fill.png b/vf205_access/resource/image/delete_fill.png
new file mode 100644
index 0000000..6378e4e
--- /dev/null
+++ b/vf205_access/resource/image/delete_fill.png
Binary files differ
diff --git a/vf205_access/resource/image/devInfo.png b/vf205_access/resource/image/devInfo.png
new file mode 100644
index 0000000..2b3b8ef
--- /dev/null
+++ b/vf205_access/resource/image/devInfo.png
Binary files differ
diff --git a/vf205_access/resource/image/deviceInfo.png b/vf205_access/resource/image/deviceInfo.png
new file mode 100644
index 0000000..e1fa5cb
--- /dev/null
+++ b/vf205_access/resource/image/deviceInfo.png
Binary files differ
diff --git a/vf205_access/resource/image/doorControl.png b/vf205_access/resource/image/doorControl.png
new file mode 100644
index 0000000..ce3d59b
--- /dev/null
+++ b/vf205_access/resource/image/doorControl.png
Binary files differ
diff --git a/vf205_access/resource/image/down.png b/vf205_access/resource/image/down.png
new file mode 100644
index 0000000..2715cf0
--- /dev/null
+++ b/vf205_access/resource/image/down.png
Binary files differ
diff --git a/vf205_access/resource/image/emergencyOpen.png b/vf205_access/resource/image/emergencyOpen.png
new file mode 100644
index 0000000..0b89c97
--- /dev/null
+++ b/vf205_access/resource/image/emergencyOpen.png
Binary files differ
diff --git a/vf205_access/resource/image/empty.png b/vf205_access/resource/image/empty.png
new file mode 100644
index 0000000..8dac448
--- /dev/null
+++ b/vf205_access/resource/image/empty.png
Binary files differ
diff --git a/vf205_access/resource/image/enter.png b/vf205_access/resource/image/enter.png
new file mode 100644
index 0000000..0d59c8e
--- /dev/null
+++ b/vf205_access/resource/image/enter.png
Binary files differ
diff --git a/vf205_access/resource/image/enter_b.png b/vf205_access/resource/image/enter_b.png
new file mode 100644
index 0000000..2b68ac9
--- /dev/null
+++ b/vf205_access/resource/image/enter_b.png
Binary files differ
diff --git a/vf205_access/resource/image/eth_disable.png b/vf205_access/resource/image/eth_disable.png
new file mode 100644
index 0000000..d54411f
--- /dev/null
+++ b/vf205_access/resource/image/eth_disable.png
Binary files differ
diff --git a/vf205_access/resource/image/eth_enable.png b/vf205_access/resource/image/eth_enable.png
new file mode 100644
index 0000000..cd2c35c
--- /dev/null
+++ b/vf205_access/resource/image/eth_enable.png
Binary files differ
diff --git a/vf205_access/resource/image/ethernet.png b/vf205_access/resource/image/ethernet.png
new file mode 100644
index 0000000..9a5e4ab
--- /dev/null
+++ b/vf205_access/resource/image/ethernet.png
Binary files differ
diff --git a/vf205_access/resource/image/ethernet_dark.png b/vf205_access/resource/image/ethernet_dark.png
new file mode 100644
index 0000000..accc200
--- /dev/null
+++ b/vf205_access/resource/image/ethernet_dark.png
Binary files differ
diff --git a/vf205_access/resource/image/eye-fill.png b/vf205_access/resource/image/eye-fill.png
new file mode 100644
index 0000000..af3db1c
--- /dev/null
+++ b/vf205_access/resource/image/eye-fill.png
Binary files differ
diff --git a/vf205_access/resource/image/eye-off.png b/vf205_access/resource/image/eye-off.png
new file mode 100644
index 0000000..3e5798b
--- /dev/null
+++ b/vf205_access/resource/image/eye-off.png
Binary files differ
diff --git a/vf205_access/resource/image/eye_fill.png b/vf205_access/resource/image/eye_fill.png
new file mode 100644
index 0000000..0d2db7f
--- /dev/null
+++ b/vf205_access/resource/image/eye_fill.png
Binary files differ
diff --git a/vf205_access/resource/image/eye_fill_show.png b/vf205_access/resource/image/eye_fill_show.png
new file mode 100644
index 0000000..df86b59
--- /dev/null
+++ b/vf205_access/resource/image/eye_fill_show.png
Binary files differ
diff --git a/vf205_access/resource/image/face.png b/vf205_access/resource/image/face.png
new file mode 100644
index 0000000..5a8312b
--- /dev/null
+++ b/vf205_access/resource/image/face.png
Binary files differ
diff --git a/vf205_access/resource/image/faceAdd.png b/vf205_access/resource/image/faceAdd.png
new file mode 100644
index 0000000..01c4128
--- /dev/null
+++ b/vf205_access/resource/image/faceAdd.png
Binary files differ
diff --git a/vf205_access/resource/image/faceEmpty.png b/vf205_access/resource/image/faceEmpty.png
new file mode 100644
index 0000000..5672597
--- /dev/null
+++ b/vf205_access/resource/image/faceEmpty.png
Binary files differ
diff --git a/vf205_access/resource/image/faceError.png b/vf205_access/resource/image/faceError.png
new file mode 100644
index 0000000..d88383d
--- /dev/null
+++ b/vf205_access/resource/image/faceError.png
Binary files differ
diff --git a/vf205_access/resource/image/faceRec.png b/vf205_access/resource/image/faceRec.png
new file mode 100644
index 0000000..995137c
--- /dev/null
+++ b/vf205_access/resource/image/faceRec.png
Binary files differ
diff --git a/vf205_access/resource/image/faceRec2.png b/vf205_access/resource/image/faceRec2.png
new file mode 100644
index 0000000..07a0def
--- /dev/null
+++ b/vf205_access/resource/image/faceRec2.png
Binary files differ
diff --git a/vf205_access/resource/image/factoryTest.png b/vf205_access/resource/image/factoryTest.png
new file mode 100644
index 0000000..9256b1d
--- /dev/null
+++ b/vf205_access/resource/image/factoryTest.png
Binary files differ
diff --git a/vf205_access/resource/image/failBg.png b/vf205_access/resource/image/failBg.png
new file mode 100644
index 0000000..7988953
--- /dev/null
+++ b/vf205_access/resource/image/failBg.png
Binary files differ
diff --git a/vf205_access/resource/image/grey_btn.png b/vf205_access/resource/image/grey_btn.png
new file mode 100644
index 0000000..4643664
--- /dev/null
+++ b/vf205_access/resource/image/grey_btn.png
Binary files differ
diff --git a/vf205_access/resource/image/help.png b/vf205_access/resource/image/help.png
new file mode 100644
index 0000000..460396e
--- /dev/null
+++ b/vf205_access/resource/image/help.png
Binary files differ
diff --git a/vf205_access/resource/image/idleImage.jpg b/vf205_access/resource/image/idleImage.jpg
new file mode 100644
index 0000000..64adab6
--- /dev/null
+++ b/vf205_access/resource/image/idleImage.jpg
Binary files differ
diff --git a/vf205_access/resource/image/input_bg.png b/vf205_access/resource/image/input_bg.png
new file mode 100644
index 0000000..bc3528f
--- /dev/null
+++ b/vf205_access/resource/image/input_bg.png
Binary files differ
diff --git a/vf205_access/resource/image/light_close.png b/vf205_access/resource/image/light_close.png
new file mode 100644
index 0000000..2ab29cd
--- /dev/null
+++ b/vf205_access/resource/image/light_close.png
Binary files differ
diff --git a/vf205_access/resource/image/light_open.png b/vf205_access/resource/image/light_open.png
new file mode 100644
index 0000000..960b6a4
--- /dev/null
+++ b/vf205_access/resource/image/light_open.png
Binary files differ
diff --git a/vf205_access/resource/image/localUser.png b/vf205_access/resource/image/localUser.png
new file mode 100644
index 0000000..757907e
--- /dev/null
+++ b/vf205_access/resource/image/localUser.png
Binary files differ
diff --git a/vf205_access/resource/image/lock.png b/vf205_access/resource/image/lock.png
new file mode 100644
index 0000000..5bd2b25
--- /dev/null
+++ b/vf205_access/resource/image/lock.png
Binary files differ
diff --git a/vf205_access/resource/image/logo.png b/vf205_access/resource/image/logo.png
new file mode 100644
index 0000000..150a6be
--- /dev/null
+++ b/vf205_access/resource/image/logo.png
Binary files differ
diff --git a/vf205_access/resource/image/menu_btn.png b/vf205_access/resource/image/menu_btn.png
new file mode 100644
index 0000000..b562b86
--- /dev/null
+++ b/vf205_access/resource/image/menu_btn.png
Binary files differ
diff --git a/vf205_access/resource/image/mini_app.png b/vf205_access/resource/image/mini_app.png
new file mode 100644
index 0000000..fd1cabe
--- /dev/null
+++ b/vf205_access/resource/image/mini_app.png
Binary files differ
diff --git a/vf205_access/resource/image/mini_background.png b/vf205_access/resource/image/mini_background.png
new file mode 100644
index 0000000..6036302
--- /dev/null
+++ b/vf205_access/resource/image/mini_background.png
Binary files differ
diff --git a/vf205_access/resource/image/mini_config.png b/vf205_access/resource/image/mini_config.png
new file mode 100644
index 0000000..4da2b0e
--- /dev/null
+++ b/vf205_access/resource/image/mini_config.png
Binary files differ
diff --git a/vf205_access/resource/image/mini_password.png b/vf205_access/resource/image/mini_password.png
new file mode 100644
index 0000000..9e20fec
--- /dev/null
+++ b/vf205_access/resource/image/mini_password.png
Binary files differ
diff --git a/vf205_access/resource/image/mqtt.png b/vf205_access/resource/image/mqtt.png
new file mode 100644
index 0000000..4c55959
--- /dev/null
+++ b/vf205_access/resource/image/mqtt.png
Binary files differ
diff --git a/vf205_access/resource/image/mqtt_dark.png b/vf205_access/resource/image/mqtt_dark.png
new file mode 100644
index 0000000..becda23
--- /dev/null
+++ b/vf205_access/resource/image/mqtt_dark.png
Binary files differ
diff --git a/vf205_access/resource/image/mqtt_enable.png b/vf205_access/resource/image/mqtt_enable.png
new file mode 100644
index 0000000..5d0a993
--- /dev/null
+++ b/vf205_access/resource/image/mqtt_enable.png
Binary files differ
diff --git a/vf205_access/resource/image/network.png b/vf205_access/resource/image/network.png
new file mode 100644
index 0000000..356d7f1
--- /dev/null
+++ b/vf205_access/resource/image/network.png
Binary files differ
diff --git a/vf205_access/resource/image/networkSetting.png b/vf205_access/resource/image/networkSetting.png
new file mode 100644
index 0000000..8932fce
--- /dev/null
+++ b/vf205_access/resource/image/networkSetting.png
Binary files differ
diff --git a/vf205_access/resource/image/network_dark.png b/vf205_access/resource/image/network_dark.png
new file mode 100644
index 0000000..6ddbf4e
--- /dev/null
+++ b/vf205_access/resource/image/network_dark.png
Binary files differ
diff --git a/vf205_access/resource/image/o2_f.png b/vf205_access/resource/image/o2_f.png
new file mode 100644
index 0000000..41ada63
--- /dev/null
+++ b/vf205_access/resource/image/o2_f.png
Binary files differ
diff --git a/vf205_access/resource/image/o2_s.png b/vf205_access/resource/image/o2_s.png
new file mode 100644
index 0000000..b7d4924
--- /dev/null
+++ b/vf205_access/resource/image/o2_s.png
Binary files differ
diff --git a/vf205_access/resource/image/ph3_f.png b/vf205_access/resource/image/ph3_f.png
new file mode 100644
index 0000000..286e61a
--- /dev/null
+++ b/vf205_access/resource/image/ph3_f.png
Binary files differ
diff --git a/vf205_access/resource/image/ph3_s.png b/vf205_access/resource/image/ph3_s.png
new file mode 100644
index 0000000..19dc6b5
--- /dev/null
+++ b/vf205_access/resource/image/ph3_s.png
Binary files differ
diff --git a/vf205_access/resource/image/pwd_btn.png b/vf205_access/resource/image/pwd_btn.png
new file mode 100644
index 0000000..4f6bdc7
--- /dev/null
+++ b/vf205_access/resource/image/pwd_btn.png
Binary files differ
diff --git a/vf205_access/resource/image/qrcode_small.png b/vf205_access/resource/image/qrcode_small.png
new file mode 100644
index 0000000..b33c3dd
--- /dev/null
+++ b/vf205_access/resource/image/qrcode_small.png
Binary files differ
diff --git a/vf205_access/resource/image/recQuery.png b/vf205_access/resource/image/recQuery.png
new file mode 100644
index 0000000..33e2702
--- /dev/null
+++ b/vf205_access/resource/image/recQuery.png
Binary files differ
diff --git a/vf205_access/resource/image/recordQuery.png b/vf205_access/resource/image/recordQuery.png
new file mode 100644
index 0000000..bb83bfd
--- /dev/null
+++ b/vf205_access/resource/image/recordQuery.png
Binary files differ
diff --git a/vf205_access/resource/image/rectangle.png b/vf205_access/resource/image/rectangle.png
new file mode 100644
index 0000000..615c1e6
--- /dev/null
+++ b/vf205_access/resource/image/rectangle.png
Binary files differ
diff --git a/vf205_access/resource/image/register.png b/vf205_access/resource/image/register.png
new file mode 100644
index 0000000..aaea4f7
--- /dev/null
+++ b/vf205_access/resource/image/register.png
Binary files differ
diff --git a/vf205_access/resource/image/right.png b/vf205_access/resource/image/right.png
new file mode 100644
index 0000000..27ce040
--- /dev/null
+++ b/vf205_access/resource/image/right.png
Binary files differ
diff --git a/vf205_access/resource/image/select_arrow.png b/vf205_access/resource/image/select_arrow.png
new file mode 100644
index 0000000..b1f4612
--- /dev/null
+++ b/vf205_access/resource/image/select_arrow.png
Binary files differ
diff --git a/vf205_access/resource/image/setting.png b/vf205_access/resource/image/setting.png
new file mode 100644
index 0000000..dd0d549
--- /dev/null
+++ b/vf205_access/resource/image/setting.png
Binary files differ
diff --git a/vf205_access/resource/image/setting32.png b/vf205_access/resource/image/setting32.png
new file mode 100644
index 0000000..ebb535c
--- /dev/null
+++ b/vf205_access/resource/image/setting32.png
Binary files differ
diff --git a/vf205_access/resource/image/space.png b/vf205_access/resource/image/space.png
new file mode 100644
index 0000000..3df41f6
--- /dev/null
+++ b/vf205_access/resource/image/space.png
Binary files differ
diff --git a/vf205_access/resource/image/successBg.png b/vf205_access/resource/image/successBg.png
new file mode 100644
index 0000000..ca6bb9e
--- /dev/null
+++ b/vf205_access/resource/image/successBg.png
Binary files differ
diff --git a/vf205_access/resource/image/success_fill.png b/vf205_access/resource/image/success_fill.png
new file mode 100644
index 0000000..d8c21d0
--- /dev/null
+++ b/vf205_access/resource/image/success_fill.png
Binary files differ
diff --git a/vf205_access/resource/image/sysSettings.png b/vf205_access/resource/image/sysSettings.png
new file mode 100644
index 0000000..ab9707a
--- /dev/null
+++ b/vf205_access/resource/image/sysSettings.png
Binary files differ
diff --git a/vf205_access/resource/image/sys_info.png b/vf205_access/resource/image/sys_info.png
new file mode 100644
index 0000000..24643b4
--- /dev/null
+++ b/vf205_access/resource/image/sys_info.png
Binary files differ
diff --git a/vf205_access/resource/image/systemSetting.png b/vf205_access/resource/image/systemSetting.png
new file mode 100644
index 0000000..eeff386
--- /dev/null
+++ b/vf205_access/resource/image/systemSetting.png
Binary files differ
diff --git a/vf205_access/resource/image/title_bg.png b/vf205_access/resource/image/title_bg.png
new file mode 100644
index 0000000..c4c7c8e
--- /dev/null
+++ b/vf205_access/resource/image/title_bg.png
Binary files differ
diff --git a/vf205_access/resource/image/trackFace.png b/vf205_access/resource/image/trackFace.png
new file mode 100644
index 0000000..d1bb520
--- /dev/null
+++ b/vf205_access/resource/image/trackFace.png
Binary files differ
diff --git a/vf205_access/resource/image/unlock.png b/vf205_access/resource/image/unlock.png
new file mode 100644
index 0000000..7450bf6
--- /dev/null
+++ b/vf205_access/resource/image/unlock.png
Binary files differ
diff --git a/vf205_access/resource/image/user.png b/vf205_access/resource/image/user.png
new file mode 100644
index 0000000..757907e
--- /dev/null
+++ b/vf205_access/resource/image/user.png
Binary files differ
diff --git a/vf205_access/resource/image/userGuide.png b/vf205_access/resource/image/userGuide.png
new file mode 100644
index 0000000..ccf6102
--- /dev/null
+++ b/vf205_access/resource/image/userGuide.png
Binary files differ
diff --git a/vf205_access/resource/image/userMgmt.png b/vf205_access/resource/image/userMgmt.png
new file mode 100644
index 0000000..58e2457
--- /dev/null
+++ b/vf205_access/resource/image/userMgmt.png
Binary files differ
diff --git a/vf205_access/resource/image/user_1.png b/vf205_access/resource/image/user_1.png
new file mode 100644
index 0000000..c29ea5e
--- /dev/null
+++ b/vf205_access/resource/image/user_1.png
Binary files differ
diff --git a/vf205_access/resource/image/user_f.png b/vf205_access/resource/image/user_f.png
new file mode 100644
index 0000000..98f99dd
--- /dev/null
+++ b/vf205_access/resource/image/user_f.png
Binary files differ
diff --git a/vf205_access/resource/image/user_s.png b/vf205_access/resource/image/user_s.png
new file mode 100644
index 0000000..7eb46a8
--- /dev/null
+++ b/vf205_access/resource/image/user_s.png
Binary files differ
diff --git a/vf205_access/resource/image/user_w.png b/vf205_access/resource/image/user_w.png
new file mode 100644
index 0000000..7404530
--- /dev/null
+++ b/vf205_access/resource/image/user_w.png
Binary files differ
diff --git a/vf205_access/resource/image/view_f.png b/vf205_access/resource/image/view_f.png
new file mode 100644
index 0000000..c963060
--- /dev/null
+++ b/vf205_access/resource/image/view_f.png
Binary files differ
diff --git a/vf205_access/resource/image/view_s.png b/vf205_access/resource/image/view_s.png
new file mode 100644
index 0000000..4ed96d2
--- /dev/null
+++ b/vf205_access/resource/image/view_s.png
Binary files differ
diff --git a/vf205_access/resource/image/vip.png b/vf205_access/resource/image/vip.png
new file mode 100644
index 0000000..0d73f58
--- /dev/null
+++ b/vf205_access/resource/image/vip.png
Binary files differ
diff --git a/vf205_access/resource/image/voiceBroadcast.png b/vf205_access/resource/image/voiceBroadcast.png
new file mode 100644
index 0000000..91de4a9
--- /dev/null
+++ b/vf205_access/resource/image/voiceBroadcast.png
Binary files differ
diff --git a/vf205_access/resource/image/wifi.png b/vf205_access/resource/image/wifi.png
new file mode 100644
index 0000000..61d7ccf
--- /dev/null
+++ b/vf205_access/resource/image/wifi.png
Binary files differ
diff --git a/vf205_access/resource/image/wifi_dark.png b/vf205_access/resource/image/wifi_dark.png
new file mode 100644
index 0000000..32deff1
--- /dev/null
+++ b/vf205_access/resource/image/wifi_dark.png
Binary files differ
diff --git a/vf205_access/resource/langPack.js b/vf205_access/resource/langPack.js
new file mode 100644
index 0000000..3a63542
--- /dev/null
+++ b/vf205_access/resource/langPack.js
@@ -0,0 +1,664 @@
+// 璇█鍖�
+const messages = {
+  CN: {
+    mainView: {
+      config: "閰嶇疆",
+      pwd: "瀵嗙爜",
+      app: "灏忕▼搴忕爜",
+      success: "閫氳鎴愬姛",
+      fail: "閫氳澶辫触",
+      passwordDisabled: "瀵嗙爜宸茬鐢�",
+    },
+    idleView: {
+      week: {
+        0: "鍛ㄦ棩",
+        1: "鍛ㄤ竴",
+        2: "鍛ㄤ簩",
+        3: "鍛ㄤ笁",
+        4: "鍛ㄥ洓",
+        5: "鍛ㄤ簲",
+        6: "鍛ㄥ叚",
+      },
+    },
+    appView: {
+      knowed: "鎴戝凡鐭ユ檽",
+      appQrcodeLbl: "浣跨敤灏忕▼搴忎究鎹风鐞�",
+    },
+    pwdView: {
+      title: "瀵嗙爜閫氳",
+      pwd: "璇疯緭鍏ュ瘑鐮�",
+      pwdAccess: "纭",
+      success: "瀵嗙爜閫氳鎴愬姛",
+      fail: "瀵嗙爜閫氳澶辫触",
+    },
+    newPwdView: {
+      title: "璁剧疆绠$悊瀵嗙爜",
+      pwdAccess: "纭",
+      pwd: "璇疯緭鍏ュ瘑鐮�",
+      confirmPwd: "璇峰啀娆¤緭鍏ュ瘑鐮�",
+      pwdAccess: "纭",
+      tip: "娉ㄦ剰锛氭偍璁剧疆鐨勫瘑鐮佷綅鏁板簲澶т簬鎴栫瓑浜� 8 浣嶏紝濡傝烦杩囪缃紝璁惧灏嗛噰鐢ㄩ粯璁ゅ瘑鐮併��",
+      skip: "璺宠繃锛屼互鍚庤缃�",
+      success: "瀵嗙爜璁剧疆鎴愬姛",
+      fail: "瀵嗙爜璁剧疆澶辫触",
+      pwdNotMatch: "涓ゆ杈撳叆瀵嗙爜涓嶄竴鑷�",
+    },
+    identityVerificationView: {
+      title: "韬唤楠岃瘉",
+      pwd: "璇疯緭鍏ョ鐞嗗瘑鐮�",
+      pwdAccess: "纭",
+      success: "浜鸿劯楠岃瘉鎴愬姛",
+      fail: "浜鸿劯楠岃瘉澶辫触",
+      pwdLog: "瀵嗙爜鐧诲綍",
+      faceLog: "浜鸿劯鐧诲綍",
+      pwdFail: "瀵嗙爜閿欒",
+    },
+    configView: {
+      title: "璁剧疆鑿滃崟",
+      localUser: "鏈湴鐢ㄦ埛",
+      networkSetting: "缃戠粶璁剧疆",
+      doorControl: "闂ㄧ绠$悊",
+      systemSetting: "绯荤粺璁剧疆",
+      deviceInfo: "璁惧淇℃伅",
+      recordQuery: "璁板綍鏌ヨ",
+      voiceBroadcast: "璇煶鎾姤",
+      cloudCert: "浜戣瘉鍔熻兘",
+      factoryTest: "宸ュ巶娴嬭瘯",
+      help: "浣跨敤甯姪",
+      confirmExit: "纭閫�鍑�",
+      confirmExitContent: "鏄惁纭閫�鍑鸿缃彍鍗曪紵",
+    },
+    cloudCertView: {
+      title: "浜戣瘉鍔熻兘",
+      cloudCertActive: "浜戣瘉婵�娲�",
+      inputKey: "璇疯緭鍏ュ瘑閽�",
+      key: "瀵嗛挜",
+      tip: "娉ㄦ剰锛氫簯璇佸彲浠ラ�氳繃鎵嬭緭瀵嗛挜鎴栨壂鎻廫n涓撶敤浜岀淮鐮佹縺娲伙紝璇︽儏璇疯仈绯诲鏈嶃��",
+      save: "淇濆瓨",
+    },
+    doorControlView: {
+      title: "闂ㄧ绠$悊",
+      save: "淇濆瓨",
+      openDoorRelayDelay: "寮�闂ㄧ户鐢靛櫒寤舵椂",
+      antiTamperAlarm: "闃叉媶鎶ヨ",
+      input: "璇疯緭鍏�",
+      success: "淇濆瓨鎴愬姛",
+      fail: "淇濆瓨澶辫触",
+      mqttAddr: "MQTT鍦板潃",
+      mqttUser: "MQTT璐﹀彿",
+      mqttPwd: "MQTT瀵嗙爜",
+      onlineChecking: "鍦ㄧ嚎楠岃瘉",
+      onlineCheckingTimeout: "鍦ㄧ嚎楠岃瘉瓒呮椂",
+      ms: "姣"
+    },
+    helpView: {
+      title: "浣跨敤甯姪",
+      scanCode: "鎵爜璁块棶瀹樻柟鏁欑▼",
+    },
+    networkSettingView: {
+      title: "缃戠粶璁剧疆",
+      type: "缃戠粶绫诲瀷",
+      ip: "IP",
+      dhcp: "DHCP",
+      mask: "瀛愮綉鎺╃爜",
+      gateway: "缃戝叧",
+      dns: "DNS1",
+      dns2: "DNS2",
+      mac: "MAC",
+      status: "缃戠粶鐘舵��",
+      save: "淇濆瓨",
+      input: "璇疯緭鍏�",
+      ethernet: "浠ュお缃�",
+      wifi: "WiFi",
+      _4G: "4G",
+      networkUnconnected: "缃戠粶鏈繛鎺�",
+      networkConnected: "缃戠粶宸茶繛鎺�",
+      wifiName: "WiFi鍚嶇О",
+      wifiPwd: "WiFi瀵嗙爜",
+      wifiList: "WiFi鍒楄〃",
+      close: "鍏抽棴",
+      confirm: "纭",
+      fail: "淇濆瓨澶辫触",
+      success: "淇濆瓨鎴愬姛",
+    },
+    systemSettingView: {
+      title: "绯荤粺璁剧疆",
+      displaySetting: "鏄剧ず鐣岄潰璁剧疆",
+      faceRecognitionSetting: "浜鸿劯璇嗗埆璁剧疆",
+      swipeCardRecognitionSetting: "鍒峰崱璇嗗埆璁剧疆",
+      passLogSetting: "閫氳鏃ュ織璁剧疆",
+      passwordOpenDoorSetting: "瀵嗙爜寮�闂ㄨ缃�",
+      passwordManagement: "瀵嗙爜绠$悊",
+      timeSetting: "鏃堕棿璁剧疆",
+      restartDevice: "閲嶅惎璁惧",
+      restoreDefaultConfig: "鎭㈠榛樿閰嶇疆",
+      resetDevice: "閲嶇疆璁惧",
+      restart: "閲嶅惎",
+      restoreDefault: "鎭㈠",
+      reset: "閲嶇疆",
+      autoAdjustScreenBrightness: "鑷姩璋冭妭灞忓箷浜害",
+      screenBrightness: "灞忓箷浜害",
+      autoTurnOffScreen: "鑷姩鐔勫睆",
+      autoTurnOffScreenTime: "鑷姩鐔勫睆鏃堕棿",
+      autoScreenSaver: "鑷姩灞忎繚",
+      autoScreenSaverTime: "鑷姩灞忎繚鏃堕棿",
+      displayIp: "鏄剧ずIP鍦板潃",
+      displayDeviceSn: "鏄剧ず璁惧SN",
+      language: "璇█",
+      displayCode: "鏄剧ず灏忕▼搴忕爜",
+      themeMode: "宸ヤ綔涓婚",
+      save: "淇濆瓨",
+      input: "璇疯緭鍏�",
+      faceSimilarityThreshold: "浜鸿劯鐩镐技搴﹂槇鍊�",
+      livenessDetectionFunction: "娲讳綋妫�娴嬪姛鑳�",
+      livenessDetectionThreshold: "娲讳綋妫�娴嬮槇鍊�",
+      infraredImageDisplay: "绾㈠鍥惧儚鏄剧ず",
+      maskRecognition: "鍙g僵璇嗗埆",
+      maskRecognitionThreshold: "鍙g僵璇嗗埆闃堝��",
+      recognitionDistance: "璇嗗埆璺濈",
+      imageSaveType: "鍥惧儚淇濆瓨绫诲瀷",
+      saveStrangerImage: "淇濆瓨闄岀敓浜哄浘鍍�",
+      fullView: "鍏ㄦ櫙",
+      face: "浜鸿劯",
+      swipeCardRecognition: "鍒峰崱鏍搁獙",
+      passwordOpenDoor: "瀵嗙爜寮�闂�",
+      inputOriginalPassword: "璇疯緭鍏ュ師绠$悊瀵嗙爜",
+      inputNewPassword: "璇疯緭鍏ユ柊瀵嗙爜",
+      inputRepeatNewPassword: "璇烽噸澶嶆柊瀵嗙爜",
+      syncMode: "鏃跺尯",
+      ntpAddress: "NTP鍦板潃",
+      timeSyncSuccess: "鏃堕棿涓庢湇鍔″櫒鍚屾鎴愬姛",
+      success: "淇濆瓨鎴愬姛",
+      fail: "淇濆瓨澶辫触",
+      appMode: "APP妯″紡",
+      confirmation: "纭",
+      confirmRestart: "纭閲嶅惎鍚楋紵",
+      confirmRecoveryConfiguration: "纭鎭㈠榛樿閰嶇疆鍚楋紵",
+      confirmReset: "纭閲嶇疆鍚楋紵",
+      min: "鍒嗛挓"
+    },
+    deviceInfoView: {
+      title: "璁惧淇℃伅",
+      systemInfo: "绯荤粺淇℃伅",
+      dataCapacityInfo: "鏁版嵁瀹归噺淇℃伅",
+      deviceQrCode: "璁惧浜岀淮鐮�",
+      miniProgramCode: "灏忕▼搴忕爜",
+      deviceSN: "璁惧SN鍙�",
+      firmwareVersion: "鍥轰欢鐗堟湰鍙�",
+      firmwareReleaseDate: "鍥轰欢鍙戝竷鏃ユ湡",
+      deviceTotalSpace: "璁惧鎬荤┖闂�",
+      deviceUsedSpace: "宸茬敤绌洪棿",
+      deviceRemainingSpace: "鍓╀綑绌洪棿",
+      registeredPersonNum: "娉ㄥ唽浜烘暟",
+      localFaceWhiteListNum: "鏈湴浜鸿劯鐧藉悕鍗曟暟閲�",
+      localPasswordWhiteListNum: "鏈湴瀵嗙爜鐧藉悕鍗曟暟閲�",
+      localSwipeCardWhiteListNum: "鏈湴鍒峰崱鐧藉悕鍗曟暟閲�",
+      passLogTotalNum: "閫氳璁板綍鎬绘暟",
+      updateDevice: "鏇存柊璁惧",
+      currentVersion: "褰撳墠宸茬粡鏄渶鏂扮増鏈紝鏃犻渶鏇存柊鍥轰欢",
+      deviceFreeSpace: "璁惧绌洪棽绌洪棿",
+    },
+    factoryTestView: {
+      title: "宸ュ巶娴嬭瘯",
+      calibration: "鎽勫儚澶存爣瀹�",
+    },
+    localUserView: {
+      title: "鏈湴鐢ㄦ埛",
+      empty: "鏈湴灏氭湭娣诲姞浜哄憳锛�",
+      add: "鏂板浜哄憳",
+      sync: "鍚屾鏈湴浜哄憳鑷冲皬绋嬪簭",
+      search: "濮撳悕鎴朓D",
+      searchBtn: "鎼滅储",
+      edit: "缂栬緫",
+      attention: "娉ㄦ剰",
+      attentionContent:
+        "1銆佽澶囧皢鍚屾璁惧鏈湴鐨勪汉鍛樹俊鎭痋n鑷冲皬绋嬪簭鐨勫鎵瑰垪琛ㄤ腑锛屾墽琛屾垚鍔焅n鍚庤澶囩灏嗘竻闄ゅ凡缁忓綍鍏ョ殑浜哄憳淇n鎭�� \n2銆佷綔涓虹鐞嗗憳锛屾偍鍙互鍦ㄥ皬绋嬪簭涓璡n瀵规湰鍦板悓姝ョ殑浜哄憳杩涜瀹℃壒銆傚鎵筡n閫氳繃骞惰ˉ鍏呭畬蹇呰鐨勫瓧娈靛悗锛岀粍缁嘰n鍐呯殑鍏ㄩ儴璁惧锛屽皢鎷ユ湁姝ゆ鍚屾浜篭n鍛樼殑閫氳鏉冮檺銆俓n姝ゆ搷浣滄棤娉曟挙閿�锛岃闂偍纭畾瑕佸悓\n姝ュ悧锛�",
+      tip: "鎻愮ず",
+      tipContent: "璁惧灏氭湭杩炴帴缃戠粶锛岃鍏堥厤缃綉缁滐紒",
+    },
+    recordQueryView: {
+      title: "璁板綍鏌ヨ",
+      code: "浜哄憳缂栧彿",
+      time: "閫氳鏃堕棿",
+      result: "閫氳缁撴灉",
+      stranger: "闄岀敓浜�",
+      face: "浜鸿劯",
+      card: "鍒峰崱",
+      password: "瀵嗙爜",
+      qrcode: "鎵爜",
+      success: "閫氳鎴愬姛",
+      fail: "閫氳澶辫触",
+    },
+    recordQueryDetailView: {
+      title: "閫氳璁板綍璇︽儏",
+      id: "绗竴鐢ㄦ埛缂栧彿",
+      name: "绗竴鐢ㄦ埛濮撳悕",
+      idCard: "绗竴鐢ㄦ埛韬唤璇佸彿",
+      face: "绗竴鐢ㄦ埛浜鸿劯鎶撴媿",
+      secondId: "绗簩鐢ㄦ埛缂栧彿",
+      secondName: "绗簩鐢ㄦ埛濮撳悕",
+      secondIdCard: "绗簩鐢ㄦ埛韬唤璇佸彿",
+      secondFace: "绗簩鐢ㄦ埛浜鸿劯鎶撴媿",
+      time: "閫氳鏃堕棿",
+      result: "閫氳缁撴灉",
+    },
+    voiceBroadcastView: {
+      title: "璇煶鎾姤",
+      save: "淇濆瓨",
+      strangerVoice: "闄岀敓浜鸿闊�",
+      voiceMode: "璇煶妯″紡",
+      volume: "闊抽噺",
+      success: "淇濆瓨鎴愬姛",
+      fail: "淇濆瓨澶辫触",
+    },
+    confirm: {
+      ok: "纭",
+      no: "鍙栨秷",
+      upgrade: "璁惧鍗囩骇",
+      upgrading: "姝e湪鍗囩骇",
+      upgradeSuccess: "鍗囩骇鎴愬姛",
+      upgradeFail: "鍗囩骇澶辫触",
+      cloudCertActive: "浜戣瘉婵�娲�",
+      cloudCertActiveSuccess: "婵�娲绘垚鍔�",
+      cloudCertActiveFail: "婵�娲诲け璐�",
+      restartDevice: "閲嶅惎璁惧",
+      restartDeviceDis: "閰嶇疆宸叉洿鏂帮紝璁惧鍗冲皢閲嶅惎",
+    },
+    localUserAddView: {
+      title: "鐢ㄦ埛鏂板",
+      title2: "鐢ㄦ埛缂栬緫",
+      save: "淇濆瓨",
+      id: "ID",
+      name: "浜哄憳濮撳悕",
+      idCard: "韬唤璇佸彿",
+      face: "浜鸿劯鍑瘉",
+      pwd: "瀵嗙爜鍑瘉",
+      card: "鍗$墖鍑瘉",
+      type: "浜哄憳绫诲瀷",
+      input: "璇疯緭鍏�",
+      enter: "褰曞叆",
+      generate: "鐢熸垚",
+      edit: "淇敼",
+      reset: "閲嶈",
+      confirm: "纭",
+      confirmDelete: "纭鍒犻櫎",
+      confirmDeleteContent: "鏄惁纭鍒犻櫎",
+      confirmFace: "纭鍒犻櫎浜鸿劯鍑瘉鍚楋紵",
+      confirmPwd: "纭鍒犻櫎瀵嗙爜鍑瘉鍚楋紵",
+      confirmCard: "纭鍒犻櫎鍗$墖鍑瘉鍚楋紵",
+      pwdBoxLbl: "瀵嗙爜鐢熸垚涓�",
+      pwdBoxSaveBtnLbl: "鎹竴涓�",
+      pwdBoxConfirmBtnLbl: "纭畾",
+      cardBoxResetBtnLbl: "閲嶇疆",
+      cardBoxSaveBtnLbl: "淇濆瓨",
+      cardBoxLbl: "璇诲彇鍗$墖涓�",
+      cardBoxInput: "璇峰~鍐欑敤鎴峰崱鍙�",
+      delete: "鍒犻櫎",
+      success: "鎴愬姛",
+      fail: "澶辫触",
+      requiredInfo: "璇峰厛濉啓蹇呭~淇℃伅",
+      preview: "棰勮",
+      failRepeat: "澶辫触锛岀敤鎴稩D閲嶅",
+      failSimilarity: "澶辫触锛屼汉鑴哥浉浼煎害杩囬珮",
+      failCardRepeat: "澶辫触锛屽崱鐗囬噸澶�",
+      failPwdRepeat: "澶辫触锛屽瘑鐮侀噸澶�",
+    },
+    faceEnterView: {
+      title: "浜鸿劯褰曞叆",
+      faceAdd: "浜鸿劯褰曞叆涓紝璇锋瑙嗘憚鍍忓ご",
+      recogFace: "璇嗗埆鍒颁汉鑴�",
+      recogSuccess: "璇嗗埆鎴愬姛",
+      faceError: "瓒呮椂鏈幏鍙�",
+    },
+    faceService: {
+      contrastFailure: "瀵规瘮澶辫触",
+      scalingFailure: "缂╂斁澶辫触",
+      failedToSavePicture: "瀛樺偍鍥剧墖澶辫触",
+      convertToBase64Failed: "鐗瑰緛鍊艰浆base64澶辫触",
+      base64DecodingFailed: "base64瑙g爜澶辫触",
+      similarityOverheight: "鐩镐技搴﹁繃楂�",
+      fileDoesNotExist: "鏂囦欢涓嶅瓨鍦�",
+      theImageFormatIsNotSupported: "鍥剧墖鏍煎紡涓嶆敮鎸�",
+      pictureReadFailure: "鍥剧墖璇诲彇澶辫触",
+      thePictureSizeDoesNotMatch: "鍥剧墖灏哄涓嶇",
+      imageParsingFailure: "鍥剧墖瑙f瀽澶辫触",
+      imageYUVProcessingFailed: "鍥剧墖YUV澶勭悊澶辫触",
+      failedToConvertJpegToImage: "jpeg杞琲mage澶辫触",
+      faceInformationExtractionFailed: "浜鸿劯淇℃伅鎻愬彇澶辫触",
+      theFaceIsNotUnique: "鍥剧墖涓汉鑴镐俊鎭笉鍞竴",
+    }
+  },
+  EN: {
+    mainView: {
+      config: "Settings",
+      pwd: "Password",
+      app: "Mini Program Code",//灞忚斀灏忕▼搴忕爜
+      success: "Access Granted",
+      fail: "Access Denied",
+      passwordDisabled: "Password Access Disabled",
+    },
+    idleView: {
+      week: {
+        0: "Sun",
+        1: "Mon",
+        2: "Tue",
+        3: "Wed",
+        4: "Thu",
+        5: "Fri",
+        6: "Sat",
+      },
+    },
+    appView: {
+      knowed: "Got it",
+      appQrcodeLbl: "Manage with Mini Program",
+    },
+    pwdView: {
+      title: "Password Access",
+      pwd: "Enter Password",
+      pwdAccess: "Confirm",
+      success: "Access Granted",
+      fail: "Access Denied",
+    },
+    newPwdView: {
+      title: "Set Admin Password",
+      pwdAccess: "Confirm",
+      pwd: "Enter Password",
+      confirmPwd: "Confirm Password",
+      pwdAccess: "Confirm",
+      tip: "Note: Password must be at least 8 characters long. Default password will be used if skipped.",
+      skip: "Skip for Now",
+      success: "Password Set Successfully",
+      fail: "Failed to Set Password",
+      pwdNotMatch: "Passwords Don't Match",
+    },
+    identityVerificationView: {
+      title: "Identity Verification",
+      pwd: "Enter Admin Password",
+      pwdAccess: "Confirm",
+      success: "Face Verification Successful",
+      fail: "Face Verification Failed",
+      pwdLog: "Password Login",
+      faceLog: "Face Login",
+      pwdFail: "Wrong Password",
+    },
+    configView: {
+      title: "Settings",
+      localUser: "Local Users",
+      networkSetting: "Network",
+      doorControl: "Access Control",
+      systemSetting: "System",
+      deviceInfo: "Device Info",
+      recordQuery: "Access Logs",
+      voiceBroadcast: "Voice Settings",
+      cloudCert: "Cloud Certificate",
+      factoryTest: "Factory Test",
+      help: "Help",
+      confirmExit: "Exit Settings",
+      confirmExitContent: "Are you sure you want to exit Settings?",
+    },
+    cloudCertView: {
+      title: "Cloud Certificate",
+      cloudCertActive: "Activate Certificate",
+      inputKey: "Enter Key",
+      key: "Key",
+      tip: "Note: Activate using key or QR code scan. Contact support for details.",
+      save: "Save",
+    },
+    doorControlView: {
+      title: "Access Control",
+      save: "Save",
+      openDoorRelayDelay: "Door Release Delay",
+      antiTamperAlarm: "Tamper Alarm",
+      input: "Enter",
+      success: "Saved",
+      fail: "Save Failed",
+      mqttAddr: "MQTT Server",
+      mqttUser: "MQTT Username",
+      mqttPwd: "MQTT Password",
+      onlineChecking: "Online Verification",
+      onlineCheckingTimeout: "Verification Timeout",
+      ms: "ms"
+    },
+    helpView: {
+      title: "Help",
+      scanCode: "Scan for Tutorial",
+    },
+    networkSettingView: {
+      title: "Network",
+      type: "Connection Type",
+      ip: "IP Address",
+      dhcp: "DHCP",
+      mask: "Subnet Mask",
+      gateway: "Gateway",
+      dns: "Primary DNS",
+      dns2: "Secondary DNS",
+      mac: "MAC Address",
+      status: "Status",
+      save: "Save",
+      input: "Enter",
+      ethernet: "Ethernet",
+      wifi: "Wi-Fi",
+      _4G: "4G",
+      networkUnconnected: "Disconnected",
+      networkConnected: "Connected",
+      wifiName: "Network Name",
+      wifiPwd: "Password",
+      wifiList: "Available Networks",
+      close: "Close",
+      confirm: "Confirm",
+      fail: "Save Failed",
+      success: "Saved",
+    },
+    systemSettingView: {
+      title: "System Settings",
+      displaySetting: "Display",
+      faceRecognitionSetting: "Face Recognition",
+      swipeCardRecognitionSetting: "Card Access",
+      passLogSetting: "Access Logs",
+      passwordOpenDoorSetting: "Password Access",
+      passwordManagement: "Password Management",
+      timeSetting: "Date & Time",
+      restartDevice: "Restart",
+      restoreDefaultConfig: "Reset to Default",
+      resetDevice: "Factory Reset",
+      restart: "Restart",
+      restoreDefault: "Reset",
+      reset: "Reset",
+      autoAdjustScreenBrightness: "Auto Brightness",
+      screenBrightness: "Brightness",
+      autoTurnOffScreen: "Auto Screen Off",
+      autoTurnOffScreenTime: "Screen Off Timer",
+      autoScreenSaver: "Screen Saver",
+      autoScreenSaverTime: "Screen Saver Timer",
+      displayIp: "Show IP Address",
+      displayDeviceSn: "Show Device SN",
+      language: "Language",
+      displayCode: "Show Program Code",
+      themeMode: "Work Theme",
+      save: "Save",
+      input: "Enter",
+      faceSimilarityThreshold: "Face Match Threshold",
+      livenessDetectionFunction: "Liveness Detection",
+      livenessDetectionThreshold: "Liveness Threshold",
+      infraredImageDisplay: "IR Display",
+      maskRecognition: "Mask Detection",
+      maskRecognitionThreshold: "Mask Detection Threshold",
+      recognitionDistance: "Detection Range",
+      imageSaveType: "Image Storage Type",
+      saveStrangerImage: "Save Stranger Photos",
+      fullView: "Full View",
+      face: "Face Only",
+      swipeCardRecognition: "Card Verification",
+      passwordOpenDoor: "Password Access",
+      inputOriginalPassword: "Enter Current Password",
+      inputNewPassword: "Enter New Password",
+      inputRepeatNewPassword: "Confirm New Password",
+      syncMode: "Time Zone",
+      ntpAddress: "NTP Server",
+      timeSyncSuccess: "Time Synced Successfully",
+      success: "Saved",
+      fail: "Failed",
+      confirmation: "Confirm",
+      confirmRestart: "Confirm Restart?",
+      confirmRecoveryConfiguration: "Reset to Default Settings?",
+      confirmReset: "Confirm Factory Reset?",
+      min: "min"
+    },
+    deviceInfoView: {
+      title: "Device Info",
+      systemInfo: "System Info",
+      dataCapacityInfo: "Storage Info",
+      deviceQrCode: "Device QR Code",
+      miniProgramCode: "Mini Program Code",
+      deviceSN: "Serial Number",
+      firmwareVersion: "Firmware Version",
+      firmwareReleaseDate: "Release Date",
+      deviceTotalSpace: "Total Storage",
+      deviceUsedSpace: "Used Storage",
+      deviceRemainingSpace: "Available Storage",
+      registeredPersonNum: "Registered Users",
+      localFaceWhiteListNum: "Face Whitelist Count",
+      localPasswordWhiteListNum: "Password Whitelist Count",
+      localSwipeCardWhiteListNum: "Card Whitelist Count",
+      passLogTotalNum: "Total Access Logs",
+      updateDevice: "Update Device",
+      currentVersion: "Device is up to date",
+      deviceFreeSpace: "Free Space",
+    },
+    factoryTestView: {
+      title: "Factory Test",
+      calibration: "Camera Calibration",
+      appMode: "APP Mode",
+    },
+    localUserView: {
+      title: "Local Users",
+      empty: "No Users Added",
+      add: "Add User",
+      sync: "Sync to Mini Program",
+      search: "Search by Name or ID",
+      searchBtn: "Search",
+      edit: "Edit",
+      attention: "Notice",
+      attentionContent:
+        "1. Local user data will be synced to the Mini Program approval list. After successful sync, local user data will be cleared.\n2. As an admin, you can approve synced users in the Mini Program. Once approved and required fields are completed, users will have access to all organization devices.\nThis action cannot be undone. Continue?",
+      tip: "Note",
+      tipContent: "Please connect to network first",
+    },
+    recordQueryView: {
+      title: "Access Logs",
+      code: "User ID",
+      time: "Time",
+      result: "Result",
+      stranger: "Unknown",
+      face: "Face",
+      card: "Card",
+      password: "Password",
+      success: "Granted",
+      fail: "Denied",
+    },
+    recordQueryDetailView: {
+      title: "Access Log Details",
+      id: "User ID",
+      name: "Name",
+      idCard: "ID Number",
+      face: "First Face Photo",
+      secondId: "Second User ID",
+      secondName: "Second Name",
+      secondIdCard: "Second ID Number",
+      secondFace: "Second Face Photo",
+      time: "Access Time",
+      result: "Result",
+    },
+    voiceBroadcastView: {
+      title: "Voice Settings",
+      save: "Save",
+      strangerVoice: "Stranger Alert",
+      voiceMode: "Voice Mode",
+      volume: "Volume",
+      success: "Saved",
+      fail: "Save Failed",
+    },
+    confirm: {
+      ok: "OK",
+      no: "Cancel",
+      upgrade: "Update Device",
+      upgrading: "Updating...",
+      upgradeSuccess: "Update Complete",
+      upgradeFail: "Update Failed",
+      cloudCertActive: "Activate Certificate",
+      cloudCertActiveSuccess: "Activate Success",
+      cloudCertActiveFail: "Activate Failed",
+      restartDevice: "Restart Device",
+      restartDeviceDis: "Configuration updated, device will restart",
+    },
+    localUserAddView: {
+      title: "Add User",
+      title2: "Edit User",
+      save: "Save",
+      id: "ID",
+      name: "Name",
+      idCard: "ID Number",
+      face: "Face ID",
+      pwd: "Password",
+      card: "Access Card",
+      type: "User Type",
+      input: "Enter",
+      enter: "Add",
+      generate: "Generate",
+      edit: "Edit",
+      reset: "Reset",
+      confirm: "Confirm",
+      confirmDelete: "Confirm Delete",
+      confirmDeleteContent: "Delete this item?",
+      confirmFace: "Delete Face ID?",
+      confirmPwd: "Delete Password?",
+      confirmCard: "Delete Access Card?",
+      pwdBoxLbl: "Generating...",
+      pwdBoxSaveBtnLbl: "Generate New",
+      pwdBoxConfirmBtnLbl: "OK",
+      cardBoxResetBtnLbl: "Reset",
+      cardBoxSaveBtnLbl: "Save",
+      cardBoxLbl: "Reading Card...",
+      cardBoxInput: "Enter Card Number",
+      delete: "Delete",
+      success: "Success",
+      fail: "Failed",
+      requiredInfo: "Required Fields Missing",
+      preview: "Preview",
+      failRepeat: "ID Already Exists",
+      failSimilarity: "Face Too Similar",
+      failCardRepeat: "Card Already Exists",
+      failPwdRepeat: "Password Already Exists",
+    },
+    faceEnterView: {
+      title: "Face Enrollment",
+      faceAdd: "Look at Camera",
+      recogFace: "Face Detected",
+      recogSuccess: "Enrollment Complete",
+      faceError: "No Face Detected",
+    },
+    calibrationView: {
+      firstCalibration: "Initial Calibration",
+      secondCalibration: "Secondary Calibration"
+    },
+    faceService: {
+      contrastFailure: "Comparison Failed",
+      scalingFailure: "Scaling Failed",
+      failedToSavePicture: "Failed to Save Image",
+      convertToBase64Failed: "Base64 Conversion Failed",
+      base64DecodingFailed: "Base64 Decode Failed",
+      similarityOverheight: "Face Too Similar",
+      fileDoesNotExist: "File Not Found",
+      theImageFormatIsNotSupported: "Unsupported Image Format",
+      pictureReadFailure: "Failed to Read Image",
+      thePictureSizeDoesNotMatch: "the picture size does not match",
+      imageParsingFailure: "image parsing failure",
+      imageYUVProcessingFailed: "image yuv processing failed",
+      failedToConvertJpegToImage: "failed to convert jpeg to image",
+      faceInformationExtractionFailed: "face information extraction failed",
+      theFaceIsNotUnique: "the face is not unique",
+    }
+  },
+};
+
+export default messages;
diff --git a/vf205_access/resource/wav/alarm.wav b/vf205_access/resource/wav/alarm.wav
new file mode 100644
index 0000000..b8fd962
--- /dev/null
+++ b/vf205_access/resource/wav/alarm.wav
Binary files differ
diff --git a/vf205_access/src/common/consts/configConst.js b/vf205_access/src/common/consts/configConst.js
new file mode 100644
index 0000000..3c22fc4
--- /dev/null
+++ b/vf205_access/src/common/consts/configConst.js
@@ -0,0 +1,99 @@
+
+/**
+ * 閰嶇疆甯搁噺鏂囦欢
+ * 瀹氫箟绯荤粺涓墍鏈夐厤缃」鐨勯敭鍊兼槧灏�
+ * 鐢ㄤ簬缁熶竴绠$悊閰嶇疆椤圭殑璺緞锛屾柟渚垮湪绯荤粺涓紩鐢�
+ */
+const configConst = {}
+
+/**
+ * 閰嶇疆椤规槧灏勮〃
+ * 鍖呭惈绯荤粺鎵�鏈夊彲閰嶇疆椤圭殑閿�煎
+ * 閿负閰嶇疆椤瑰悕绉帮紝鍊间负閰嶇疆椤瑰湪閰嶇疆鏂囦欢涓殑璺緞
+ */
+configConst.setConfig = {
+    // 鍩虹閰嶇疆
+    language: "base.language",           // 璇█璁剧疆锛欳N/EN
+    password: "base.password",           // 绠$悊鍛樺瘑鐮�
+    screenOff: "base.screenOff",         // 鐔勫睆鏃堕棿锛屽崟浣嶅垎閽燂紝0琛ㄧず浠庝笉
+    screensaver: "base.screensaver",     // 灞忓箷淇濇姢锛屽崟浣嶅垎閽燂紝0琛ㄧず浠庝笉
+    brightness: "base.brightness",       // 灞忓箷浜害
+    brightnessAuto: "base.brightnessAuto", // 鑷姩浜害寮�鍏�
+    volume: "base.volume",               // 闊抽噺璁剧疆
+    showIp: "base.showIp",               // 鏄惁鏄剧ずIP鍦板潃
+    showSn: "base.showSn",               // 鏄惁鏄剧ず搴忓垪鍙�
+    showProgramCode: "base.showProgramCode", // 鏄惁鏄剧ず绋嬪簭浠g爜
+    showIdentityCard: "base.showIdentityCard", // 鏄惁鏄剧ず韬唤璇佷俊鎭�
+    appMode: "base.appMode",             // 搴旂敤妯″紡
+    luminanceWhite: "base.luminanceWhite", // 鐧藉厜浜害
+    luminanceNir: "base.luminanceNir",   // 绾㈠鍏変寒搴�
+    
+    // 浜鸿劯璇嗗埆閰嶇疆
+    similarity: "face.similarity",       // 浜鸿劯璇嗗埆鐩镐技搴﹂槇鍊�
+    livenessOff: "face.livenessOff",     // 娲讳綋妫�娴嬪紑鍏�
+    livenessVal: "face.livenessVal",     // 娲讳綋妫�娴嬮槇鍊�
+    showNir: "face.showNir",             // 鏄惁鏄剧ず绾㈠鍥惧儚
+    detectMask: "face.detectMask",       // 鏄惁妫�娴嬪彛缃�
+    stranger: "face.stranger",           // 闄岀敓浜鸿闊虫彁绀猴細["鏃犺闊�", "鎾斁璇峰厛娉ㄥ唽", "鎾斁闄岀敓浜轰綘濂�"]
+    voiceMode: "face.voiceMode",         // 璇煶妯″紡锛歔"鏃犺闊�", "鎾斁鍚嶅瓧", "鎾斁闂�欒"]
+    voiceModeDate: "face.voiceModeDate", // 璇煶妯″紡鏃ユ湡璁剧疆
+    
+    // MQTT閰嶇疆
+    addr: "mqtt.addr",                   // MQTT鏈嶅姟鍣ㄥ湴鍧�
+    mqttclientId: "mqtt.clientId",       // MQTT瀹㈡埛绔疘D
+    mqttusername: "mqtt.username",       // MQTT鐢ㄦ埛鍚�
+    mqttpassword: "mqtt.password",       // MQTT瀵嗙爜
+    mqttqos: "mqtt.qos",                 // MQTT QoS绾у埆
+    mqttprefix: "mqtt.prefix",           // MQTT涓婚鍓嶇紑
+    onlinecheck: "mqtt.onlinecheck",     // 鍦ㄧ嚎妫�鏌ュ紑鍏�
+    timeout: "mqtt.timeout",             // MQTT杩炴帴瓒呮椂
+    willTopic: "mqtt.willTopic",         // MQTT閬楀槺涓婚
+    
+    // 缃戠粶閰嶇疆
+    type: "net.type",                    // 缃戠粶绫诲瀷
+    ssid: "net.ssid",                    // WiFi SSID
+    psk: "net.psk",                      // WiFi瀵嗙爜
+    dhcp: "net.dhcp",                    // DHCP寮�鍏�
+    ip: "net.ip",                        // IP鍦板潃
+    gateway: "net.gateway",              // 缃戝叧鍦板潃
+    mask: "net.mask",                    // 瀛愮綉鎺╃爜
+    dns: "net.dns",                      // DNS鏈嶅姟鍣�
+    mac: "net.mac",                      // MAC鍦板潃
+    
+    // NTP鏃堕棿鍚屾閰嶇疆
+    ntp: "ntp.ntp",                      // NTP寮�鍏�
+    server: "ntp.server",                // NTP鏈嶅姟鍣ㄥ湴鍧�
+    ntpInterval: "ntp.interval",         // NTP鍚屾闂撮殧
+    gmt: "ntp.gmt",                      // GMT鏃跺尯璁剧疆
+    
+    // 绯荤粺閰嶇疆
+    version: "sys.version",              // 绯荤粺鐗堟湰
+    appVersion: "sys.appVersion",        // 搴旂敤鐗堟湰
+    releaseTime: "sys.releaseTime",      // 鍙戝竷鏃堕棿
+    heart_en: "sys.heart_en",            // 蹇冭烦寮�鍏筹細1寮� 0鍏�
+    heart_time: "sys.heart_time",        // 蹇冭烦闂撮殧
+    nfc: "sys.nfc",                      // 鍒峰崱寮�鍏筹細1寮� 0鍏�
+    pwd: "sys.pwd",                      // 瀵嗙爜寮�闂ㄥ紑鍏筹細1寮� 0鍏�
+    emergencyPwd: "sys.emergencyPwd",        // 搴旀�ュ紑浠撳瘑鐮�
+    interval: "sys.interval",            // 绯荤粺闂撮殧璁剧疆
+    strangerImage: "sys.strangerImage",  // 闄岀敓浜轰繚瀛樺浘鐗囧紑鍏筹細1寮� 0鍏�
+    accessImageType: "sys.accessImageType", // 閫氳鍥剧墖绫诲瀷锛�1浜鸿劯 0鍏ㄦ櫙
+    com_passwd: "sys.com_passwd",        // 閰嶇疆鐮佸瘑鐮佹牎楠�
+    nfcIdentityCardEnable: "sys.nfcIdentityCardEnable", // 浜戣瘉寮�鍏筹細3浜戣瘉鑾峰彇 1鐗╃悊鍗″彿
+    
+    // 闂ㄧ閰嶇疆
+    offlineAccessNum: "access.offlineAccessNum", // 绂荤嚎寮�闂ㄦ鏁�
+    relayTime: "access.relayTime",       // 缁х數鍣ㄥ姩浣滄椂闂�
+    tamperAlarm: "access.tamperAlarm"    // 闃叉媶鎶ヨ寮�鍏�
+}
+
+/**
+ * 鏍规嵁閿幏鍙栭厤缃」璺緞
+ * @param {string} key - 閰嶇疆椤瑰悕绉�
+ * @returns {string|undefined} 閰嶇疆椤瑰湪閰嶇疆鏂囦欢涓殑璺緞锛屽鏋滀笉瀛樺湪鍒欒繑鍥瀠ndefined
+ */
+configConst.getValueByKey = function (key) {
+    return this.setConfig[key] || undefined;
+}
+
+export default configConst
\ No newline at end of file
diff --git a/vf205_access/src/common/utils/utils.js b/vf205_access/src/common/utils/utils.js
new file mode 100644
index 0000000..efb1810
--- /dev/null
+++ b/vf205_access/src/common/utils/utils.js
@@ -0,0 +1,132 @@
+/**
+ * 宸ュ叿鍑芥暟妯″潡
+ * 鎻愪緵绯荤粺甯哥敤鐨勫伐鍏峰嚱鏁帮紝鍖呮嫭鏂囦欢涓嬭浇銆佸瓧绗︿覆澶勭悊銆佺郴缁熸搷浣滅瓑
+ */
+import * as os from "os"
+import common from '../../../dxmodules/dxCommon.js'
+import logger from "../../../dxmodules/dxLogger.js"
+const utils = {}
+
+/**
+ * 鑾峰彇URL鏂囦欢鐨勪笅杞藉ぇ灏忥紙瀛楄妭鏁帮級
+ * @param {string} url - 鏂囦欢鐨刄RL鍦板潃
+ * @returns {number} 鏂囦欢澶у皬锛堝瓧鑺傦級锛屽鏋滆幏鍙栧け璐ュ垯杩斿洖0
+ */
+utils.getUrlFileSize = function (url) {
+    // 浣跨敤wget鍛戒护鑾峰彇鏂囦欢澶у皬淇℃伅
+    let actualSize = common.systemWithRes(`wget --spider -S ${url} 2>&1 | grep 'Length' | awk '{print $2}'`, 100).match(/\d+/g)
+    return actualSize ? parseInt(actualSize) : 0
+}
+
+/**
+ * 鍒ゆ柇鍊兼槸鍚︿负绌猴紙绌哄瓧绗︿覆銆乶ull鎴杣ndefined锛�
+ * @param {*} str - 瑕佸垽鏂殑鍊�
+ * @returns {boolean} 濡傛灉鍊间负绌哄垯杩斿洖true锛屽惁鍒欒繑鍥瀎alse
+ */
+utils.isEmpty = function (str) {
+    return (str === "" || str === null || str === undefined)
+}
+
+/**
+ * 瑙f瀽瀛楃涓蹭负JSON瀵硅薄
+ * 娉ㄦ剰锛歷alue鍐呬笉鑳芥湁"鍙�
+ * @param {string} inputString - 瑕佽В鏋愮殑瀛楃涓诧紝鏍煎紡涓簕key1=value1, key2=value2}
+ * @returns {Object} 瑙f瀽鍚庣殑JSON瀵硅薄
+ */
+utils.parseString = function (inputString) {
+    // 鑾峰彇{}鍙婂叾涔嬮棿鐨勫唴瀹�
+    inputString = inputString.slice(inputString.indexOf("{"), inputString.lastIndexOf("}") + 1)
+    // key=value姝e垯锛宬ey鏄痋w+锛堝瓧姣嶆暟瀛椾笅鍒掔嚎锛屽尯鍒ぇ灏忓啓锛夛紝=涓よ竟鍙湁绌烘牸锛寁alue鏄痋w+鎴栫浉閭讳袱涓�"涔嬮棿鐨勫唴瀹癸紙鍖呭惈"锛�
+    const keyValueRegex = /(\w+)\s*=\s*("[^"]*"|\w+(\.\w+)?)/g;
+    let jsonObject = {};
+    let match;
+    
+    // 閬嶅巻鍖归厤缁撴灉锛屾瀯寤篔SON瀵硅薄
+    while ((match = keyValueRegex.exec(inputString)) !== null) {
+        let key = match[1];
+        let value = match[2]
+        
+        // 鏍规嵁鍊肩殑绫诲瀷杩涜杞崲
+        if (/^\d+$/.test(value)) {
+            // 鏁板瓧绫诲瀷
+            value = parseInt(value)
+        } else if (/^\d+\.\d+$/.test(value)) {
+            // 灏忔暟绫诲瀷
+            value = parseFloat(value)
+        } else if (value == 'true') {
+            // 甯冨皵鍊紅rue
+            value = true
+        } else if (value == 'false') {
+            // 甯冨皵鍊糵alse
+            value = false
+        } else {
+            // 瀛楃涓茬被鍨嬶紝鍘婚櫎寮曞彿鍜岀┖鏍�
+            value = value.replace(/"/g, '').trim()
+        }
+        
+        jsonObject[key] = value;
+    }
+    
+    return jsonObject;
+}
+
+/**
+ * 绛夊緟鏂囦欢涓嬭浇瀹屾垚骞惰繘琛孧D5鏍¢獙
+ * 娉ㄦ剰锛氳秴鏃舵椂闂翠笉寰楄秴杩囧杺鐙楁椂闂达紝鍚﹀垯涓嬭浇鎱細瀵艰嚧绯荤粺閲嶅惎
+ * @param {string} update_addr - 涓嬭浇鍦板潃
+ * @param {string} downloadPath - 瀛樺偍璺緞
+ * @param {number} timeout - 瓒呮椂鏃堕棿锛堟绉掞級
+ * @param {string} update_md5 - MD5鏍¢獙鍊�
+ * @param {number} fileSize - 鏂囦欢澶у皬锛堝瓧鑺傦級
+ * @returns {boolean} 涓嬭浇缁撴灉锛歵rue琛ㄧず鎴愬姛锛宖alse琛ㄧず澶辫触
+ */
+utils.waitDownload = function (update_addr, downloadPath, timeout, update_md5, fileSize) {
+    // 鍒犻櫎鍘熸枃浠�
+    common.systemBrief(`rm -rf "${downloadPath}"`)
+    
+    // 寮傛涓嬭浇鏂囦欢
+    common.systemBrief(`wget -c "${update_addr}" -O "${downloadPath}" &`)
+    
+    let startTime = new Date().getTime()
+    
+    // 寰幆妫�鏌ヤ笅杞借繘搴�
+    while (true) {
+        // 璁$畻宸蹭笅杞界殑鏂囦欢澶у皬
+        let size = parseInt(common.systemWithRes(`file="${downloadPath}"; [ -e "$file" ] && wc -c "$file" | awk '{print $1}' || echo "0"`, 100).split(/\s/g)[0])
+        
+        // 濡傛灉鏂囦欢澶у皬杈惧埌棰勬湡锛岃繘琛孧D5鏍¢獙
+        if (size == fileSize) {
+            let ret = common.md5HashFile(downloadPath)
+            if (ret) {
+                let md5 = ret.map(v => v.toString(16).padStart(2, '0')).join('')
+                if (md5 == update_md5) {
+                    // MD5鏍¢獙鎴愬姛
+                    return true
+                }
+            }
+            // MD5鏍¢獙澶辫触锛屽垹闄ゆ枃浠�
+            common.systemBrief(`rm -rf "${downloadPath}"`)
+            return false
+        }
+        // 濡傛灉涓嬭浇瓒呮椂锛屽垹闄や笅杞界殑鏂囦欢骞朵笖閲嶅惎锛屽仠姝㈠紓姝ョ户缁笅杞�
+        if (new Date().getTime() - startTime > timeout) {
+            vf203.pwm.fail()
+            common.systemBrief(`rm -rf "${downloadPath}"`)
+            // 绔嬪嵆閲嶅惎
+            this.restart()
+            return false
+        }
+        
+        // 鏆傚仠100姣鍚庣户缁鏌�
+        os.sleep(100)
+    }
+}
+
+/**
+ * 绔嬪嵆閲嶅惎
+ */
+utils.restart = function () {
+    common.systemBrief("reboot -f")
+}
+
+export default utils
diff --git a/vf205_access/src/config.json b/vf205_access/src/config.json
new file mode 100644
index 0000000..933977d
--- /dev/null
+++ b/vf205_access/src/config.json
@@ -0,0 +1,115 @@
+{
+    // CN/EN
+    "base.language": "CN",
+    // 绠$悊鍛樺瘑鐮�
+    "base.password": "1",
+    //鏄惁绗竴娆$櫥褰曞悗鍙� 0 鏈櫥褰� 1 宸茬櫥褰�
+    "base.firstLogin": 0,
+    // 浜鸿劯璇嗗埆鐩镐技搴�
+    "face.similarity": 0.6,
+    // 娲讳綋妫�娴�
+    "face.livenessOff": 0,
+    // 娲讳綋妫�娴嬮槇鍊硷紙0-100锛�
+    "face.livenessVal": 0,
+    "face.showNir": 0,
+    "face.detectMask": 0,
+    // ["鏃犺闊�", "鎾斁璇峰厛娉ㄥ唽", "鎾斁闄岀敓浜轰綘濂�"]
+    "face.stranger": 1,
+    // ["鏃犺闊�", "鎾斁鍚嶅瓧", "鎾斁闂�欒"]
+    "face.voiceMode": 1,
+    "face.voiceModeDate": "娆㈣繋鍏変复",
+    "mqtt.addr": "192.168.1.78:1883",
+    "mqtt.clientId": "",
+    "mqtt.username": "admin",
+    "mqtt.password": "123456",
+    "mqtt.qos": 1,
+    "mqtt.prefix": "",
+    "mqtt.onlinecheck": 0,
+    "mqtt.timeout": 5000,
+    "mqtt.willTopic": "access_device/v2/event/offline",
+    "net.type": 2,
+    "net.ssid": "",
+    "net.psk": "Fzzy@#$432..K",
+    "net.dhcp": 1,
+    "net.ip": "192.168.1.188",
+    "net.gateway": "192.168.1.1",
+    "net.mask": "255.255.255.0",
+    "net.dns": "218.4.4.4,218.2.2.2",
+    "net.mac": "",
+    // 0鍏抽棴锛�1瀹氭椂鍚屾
+    "ntp.ntp": 2,
+    "ntp.server": "192.168.1.78",
+    // 瀹氭椂鍚屾锛�24灏忔椂鍒�
+    "ntp.hour": 3,
+    "ntp.gmt": 8,
+     // mac鍦板潃
+    "sys.mac": "",
+    "sys.uuid": "",
+    "sys.sn": "",
+    "sys.model": "vf105",
+    "sys.version": "",
+    "sys.appVersion": "vf105_v11_access_2.0.0",
+    "sys.releaseTime": "2024-09-13 09:52:00",
+    "sys.heart_en": 0, //蹇冭烦1寮� 0 鍏�
+    "sys.heart_time": 30,
+    "sys.nfc": 1, //1寮� 0 鍏�    鍒峰崱寮�鍏�
+    "sys.pwd": 1, //1寮� 0 鍏�    瀵嗙爜寮�闂ㄥ紑鍏�
+    "sys.strangerImage": 1, //1寮� 0 鍏�   闄岀敓浜轰繚瀛樺浘鐗囧紑鍏�
+    "sys.accessImageType": 1, //1浜鸿劯 0 鍏ㄦ櫙   閫氳鍥剧墖绫诲瀷
+    "sys.com_passwd": "1234567887654321", // 閰嶇疆鐮佸瘑鐮佹牎楠�
+    //浜戣瘉寮�鍏� 3:浜戣瘉鑾峰彇 1:鐗╃悊鍗″彿
+    "sys.nfcIdentityCardEnable": 1,
+    "sys.interval": 1000, //鎵爜闂撮殧妯″紡闂撮殧鏃堕棿
+    "access.offlineAccessNum": 2000,
+    "access.relayTime": 2000,
+    "access.tamperAlarm": 1,
+    // 鐔勫睆鏃堕棿锛屽崟浣嶅垎閽燂紝0浠庝笉
+    "base.screenOff": 5,
+    // 灞忓箷淇濇姢锛屽崟浣嶅垎閽燂紝0浠庝笉
+    "base.screensaver": 5,
+    //灞忓箷浜害
+    "base.brightness": 70,
+    //鑷姩璋冭妭浜害  1 鑷姩璋冭妭
+    "base.brightnessAuto": 1,
+    //闊抽噺
+    "base.volume": 80,
+    // ip 鏄剧ず  1 鏄剧ず 0 闅愯棌
+    "base.showIp": 0,
+    // sn 鏄剧ず  1 鏄剧ず 0 闅愯棌
+    "base.showSn": 0,
+    //灏忕▼搴忕爜 鏄剧ず  1 鏄剧ず 0 闅愯棌
+    "base.showProgramCode": 0,
+    //浜戣瘉鍔熻兘鑿滃崟 鏄剧ず  1 鏄剧ず 0 闅愯棌
+    "base.showIdentityCard": 0,
+    // 0: 鏍囧噯妯″紡 1: 绠�绾︽ā寮�
+    "base.appMode": 1,
+    // 鐧借壊琛ュ厜鐏寒搴�
+    "base.luminanceWhite": 80,
+    // 绾㈠琛ュ厜鐏寒搴�
+    "base.luminanceNir": 80,
+    // 0:wifi 鐗堟湰  1:4G鐗堟湰  2:浠ュお缃戠増鏈� 榛樿 3鏈鍙栫姸鎬�
+    "sys.devType": 0,
+    // 涓氬姟缂栫爜瀹氫箟锛團unctionId锛�
+    "functionId": {
+        "gasDetection": "1000",
+        "safeInputControl": "2000",
+        "lightControl": "3000"
+    },
+    // 鎺ュ彛杩斿洖缂栫爜锛坮espCode锛�
+    "respCode": {
+        "success": "200",
+        "badRequest": "400",
+        "unauthorized": "401",
+        "forbidden": "403",
+        "notFound": "404",
+        "serverError": "500"
+    },
+    // 浠撳粧鍚嶇О
+    "houseName": "01鍙蜂粨",
+    // 搴撳尯鍚嶇О
+    "GranaryName": "涓ぎ鍌ㄥ绮煇鏌愮洿灞炲簱",
+    // HTTP鎺ュ彛璺緞
+    "http": {
+        "safeInputAccess": "http://192.168.1.119:80/cgi-bin/safeInputAccess"
+    }
+}
\ No newline at end of file
diff --git a/vf205_access/src/controller.js b/vf205_access/src/controller.js
new file mode 100644
index 0000000..ddb7fee
--- /dev/null
+++ b/vf205_access/src/controller.js
@@ -0,0 +1,66 @@
+/**
+ * 鎺у埗鍣ㄦ枃浠�
+ * 璐熻矗瀹氭湡鎵ц绯荤粺鍚勯┍鍔ㄧ殑寰幆鎿嶄綔锛岀‘淇濈郴缁熸甯歌繍琛�
+ */
+import log from '../dxmodules/dxLogger.js'
+import std from '../dxmodules/dxStd.js'
+import face from '../dxmodules/dxFace.js'
+import bus from '../dxmodules/dxEventBus.js'
+import driver from './driver.js'
+
+/**
+ * 杩愯鎺у埗鍣�
+ * 璁剧疆澶氫釜瀹氭椂鍣紝瀹氭湡鎵ц涓嶅悓鐨勫惊鐜换鍔�
+ */
+function run() {
+    // 姣�5ms鎵ц涓�娆′富寰幆
+    std.setInterval(() => {
+        try {
+            driver.watchdog.feed("controller", 30) // 鍠傜嫍锛岃缃�30绉掕秴鏃�
+            loop() // 鎵ц涓诲惊鐜�
+        } catch (error) {
+            log.error(error) // 璁板綍閿欒
+        }
+    }, 5)
+
+    // 姣�500ms鎵ц涓�娆$綉缁滃惊鐜�
+    std.setInterval(() => {
+        try {
+            driver.watchdog.feed("controller1", 30) // 鍠傜嫍锛岃缃�30绉掕秴鏃�
+            driver.net.loop() // 鎵ц缃戠粶寰幆
+        } catch (error) {
+            log.error(error) // 璁板綍閿欒
+        }
+    }, 500)
+
+    // 姣�1000ms鎵ц涓�娆TP寰幆
+    std.setInterval(() => {
+        try {
+            driver.watchdog.feed("controller2", 30) // 鍠傜嫍锛岃缃�30绉掕秴鏃�
+            driver.ntp.loop() // 鎵цNTP寰幆
+        } catch (error) {
+            log.error(error) // 璁板綍閿欒
+        }
+    }, 1000)
+}
+
+/**
+ * 鍚姩鎺у埗鍣�
+ */
+try {
+    run()
+} catch (error) {
+    log.error(error)
+}
+
+/**
+ * 涓诲惊鐜嚱鏁�
+ * 鎵ц鍚勯┍鍔ㄧ殑寰幆鎿嶄綔
+ */
+function loop() {
+    driver.capturer.loop()      // 鎵ц鎽勫儚澶村惊鐜�
+    driver.face.loop()          // 鎵ц浜鸿劯璇嗗埆寰幆
+    driver.nfc.loop()           // 鎵цNFC寰幆
+    driver.mqtt.heartbeat()     // 鎵цMQTT蹇冭烦
+    driver.gpiokey.loop()       // 鎵цGPIO鎸夐敭寰幆
+}
diff --git a/vf205_access/src/driver.js b/vf205_access/src/driver.js
new file mode 100644
index 0000000..bda4f7c
--- /dev/null
+++ b/vf205_access/src/driver.js
@@ -0,0 +1,1226 @@
+/**
+ * 椹卞姩妯″潡鏂囦欢
+ * 鍖呭惈绯荤粺鎵�鏈夌‖浠堕┍鍔ㄧ殑鍒濆鍖栧拰鎿嶄綔鏂规硶锛屾槸绯荤粺涓庣‖浠朵氦浜掔殑鏍稿績妯″潡
+ */
+import * as os from "os"
+import capturer from '../dxmodules/dxCapturer.js'
+import cameraCalibration from '../dxmodules/dxCameraCalibration.js'
+import face from '../dxmodules/dxFace.js'
+import std from '../dxmodules/dxStd.js'
+import common from '../dxmodules/dxCommon.js'
+import utils from './common/utils/utils.js'
+import alsa from '../dxmodules/dxAlsa.js'
+import config from '../dxmodules/dxConfig.js'
+import pwm from '../dxmodules/dxPwm.js'
+import net from '../dxmodules/dxNet.js'
+import ntp from '../dxmodules/dxNtp.js'
+import mqtt from '../dxmodules/dxMqtt.js'
+import dxMap from '../dxmodules/dxMap.js'
+import logger from '../dxmodules/dxLogger.js'
+import sqliteService from "./service/sqliteService.js"
+import mqttService from "./service/mqttService.js"
+import gpio from "../dxmodules/dxGpio.js"
+import map from "../dxmodules/dxMap.js"
+import eid from "../dxmodules/dxEid.js"
+import nfc from "../dxmodules/dxNfc.js"
+import bus from "../dxmodules/dxEventBus.js"
+import dxUart from "../dxmodules/dxUart.js"
+import watchdog from "../dxmodules/dxWatchdog.js"
+import base64 from "../dxmodules/dxBase64.js"
+import dxGpioKey from "../dxmodules/dxGpioKey.js"
+import dxDriver from "../dxmodules/dxDriver.js"
+const driver = {}
+
+/**
+ * 闊抽椹卞姩妯″潡
+ * 璐熻矗闊抽鎾斁鍜岃闊冲悎鎴�
+ */
+driver.alsa = alsa
+
+/**
+ * 閰嶇疆椹卞姩妯″潡
+ * 璐熻矗鍒濆鍖栫郴缁熼厤缃紝璁剧疆绯荤粺鍩烘湰淇℃伅
+ */
+driver.config = {
+    /**
+     * 鍒濆鍖栭厤缃�
+     * 鍒濆鍖栭厤缃ā鍧楋紝璁剧疆绯荤粺MAC銆乁UID銆丼N绛夊熀鏈俊鎭�
+     */
+    init: function () {
+        config.init()
+        let mac = common.getUuid2mac(19)
+        let uuid = common.getSn(19)
+        if (!config.get('sys.mac') && mac) {
+            config.set('sys.mac', mac)
+        }
+        if (!config.get('sys.uuid') && uuid) {
+            config.set('sys.uuid', uuid)
+        }
+        //濡傛灉 sn 涓虹┖鍏堢敤璁惧 uuid
+        if (!config.get('sys.sn') && uuid) {
+            config.set('sys.sn', uuid)
+        }
+        if (!config.get('mqtt.clientId') && uuid) {
+            config.set('mqtt.clientId', uuid)
+        }
+        config.save()
+    }
+}
+/**
+ * 灞忓箷椹卞姩妯″潡
+ * 璐熻矗灞忓箷鐩稿叧鐨勪簨浠惰Е鍙戝拰鎿嶄綔
+ */
+driver.screen = {
+    /**
+     * 閫氳澶辫触
+     * 瑙﹀彂閫氳澶辫触浜嬩欢
+     */
+    accessFail: function () {
+        bus.fire('accessRes', false)
+    },
+    
+    /**
+     * 閫氳鎴愬姛
+     * 瑙﹀彂閫氳鎴愬姛浜嬩欢
+     */
+    accessSuccess: function () {
+        bus.fire('accessRes', true)
+    },
+    
+    /**
+     * 鍗囩骇
+     * 瑙﹀彂鍗囩骇浜嬩欢
+     * @param {object} data - 鍗囩骇鏁版嵁
+     */
+    upgrade: function (data) {
+        bus.fire('upgrade', data)
+    },
+    
+    /**
+     * 鑾峰彇鍗$墖
+     * 鎾斁璇诲崱澹伴煶骞惰Е鍙戣幏鍙栧崱鐗囦簨浠�
+     * @param {string} card - 鍗$墖淇℃伅
+     */
+    getCard: function (card) {
+        driver.alsa.play(`/app/code/resource/${config.get("base.language") == "CN" ? "CN" : "EN"}/wav/read.wav`)
+        bus.fire('getCard', card)
+    },
+    
+    /**
+     * 闅愯棌SN
+     * 瑙﹀彂闅愯棌SN浜嬩欢
+     * @param {object} data - 浜嬩欢鏁版嵁
+     */
+    hideSn: function (data) {
+        bus.fire('hideSn', data)
+    },
+    
+    /**
+     * 搴旂敤妯″紡
+     * 瑙﹀彂搴旂敤妯″紡浜嬩欢
+     * @param {object} data - 妯″紡鏁版嵁
+     */
+    appMode: function (data) {
+        bus.fire('appMode', data)
+    },
+    
+    /**
+     * 闅愯棌IP
+     * 瑙﹀彂闅愯棌IP浜嬩欢
+     * @param {object} data - 浜嬩欢鏁版嵁
+     */
+    hideIp: function (data) {
+        bus.fire('hideIp', data)
+    },
+    
+    /**
+     * 鍒囨崲璇█
+     * 瑙﹀彂璇█鍒囨崲浜嬩欢
+     */
+    changeLanguage: function () {
+        bus.fire('changeLanguage')
+    }
+}
+/**
+ * SQLite椹卞姩妯″潡
+ * 璐熻矗鏁版嵁搴撳垵濮嬪寲鍜岀鐞�
+ */
+driver.sqlite = {
+    /**
+     * 鍒濆鍖栨暟鎹簱
+     * 纭繚鏁版嵁搴撹矾寰勫瓨鍦ㄥ苟鍒濆鍖朣QLite鏈嶅姟
+     */
+    init: function () {
+        std.ensurePathExists('/app/data/db/app.db')
+        sqliteService.init('/app/data/db/app.db')
+    }
+}
+
+/**
+ * PWM椹卞姩妯″潡
+ * 璐熻矗鎺у埗琛ュ厜鐏殑浜害
+ */
+driver.pwm = {
+    /**
+     * 鍒濆鍖朠WM
+     * 鍒濆鍖栫櫧鑹茶ˉ鍏夌伅鍜岀孩澶栬ˉ鍏夌伅鐨凱WM閫氶亾
+     */
+    init: function () {
+        // 鐧界伅
+        let luminanceWhite = config.get('base.luminanceWhite') ?? 80
+        pwm.request(dxDriver.PWM.WHITE_SUPPLEMENT_CHANNEL);
+        pwm.setPeriodByChannel(dxDriver.PWM.WHITE_SUPPLEMENT_CHANNEL, dxDriver.PWM.WHITE_SUPPLEMENT_PERIOD_NS)
+        pwm.enable(dxDriver.PWM.WHITE_SUPPLEMENT_CHANNEL, true);
+        pwm.setDutyByChannel(dxDriver.PWM.WHITE_SUPPLEMENT_CHANNEL, dxDriver.PWM.WHITE_SUPPLEMENT_PERIOD_NS - (dxDriver.PWM.WHITE_SUPPLEMENT_PERIOD_NS * (luminanceWhite / 100)))
+        // 绾㈠
+        let luminanceNir = config.get('base.luminanceNir') ?? 80
+        pwm.request(dxDriver.PWM.NIR_SUPPLEMENT_CHANNEL);
+        pwm.setPeriodByChannel(dxDriver.PWM.NIR_SUPPLEMENT_CHANNEL, dxDriver.PWM.NIR_SUPPLEMENT_PERIOD_NS)
+        pwm.enable(dxDriver.PWM.NIR_SUPPLEMENT_CHANNEL, true);
+        pwm.setDutyByChannel(dxDriver.PWM.NIR_SUPPLEMENT_CHANNEL, dxDriver.PWM.NIR_SUPPLEMENT_PERIOD_NS - (dxDriver.PWM.NIR_SUPPLEMENT_PERIOD_NS * (luminanceNir / 100)))
+    },
+    
+    /**
+     * 璋冭妭鐧借壊琛ュ厜鐏寒搴�
+     * @param {number} value - 浜害鍊硷紝鑼冨洿0-100
+     */
+    luminanceWhite: function (value) {
+        if (value < 0 || value > 100) {
+            logger.error("[driver.pwm]: value should be between 0 and 100")
+            return
+        }
+        pwm.setDutyByChannel(dxDriver.PWM.WHITE_SUPPLEMENT_CHANNEL, dxDriver.PWM.WHITE_SUPPLEMENT_PERIOD_NS - (dxDriver.PWM.WHITE_SUPPLEMENT_PERIOD_NS * (value / 100)))
+    },
+    
+    /**
+     * 璋冭妭绾㈠琛ュ厜鐏寒搴�
+     * @param {number} value - 浜害鍊硷紝鑼冨洿0-100
+     */
+    luminanceNir: function (value) {
+        if (value < 0 || value > 100) {
+            logger.error("[driver.pwm]: value should be between 0 and 100")
+            return
+        }
+        pwm.setDutyByChannel(dxDriver.PWM.NIR_SUPPLEMENT_CHANNEL, dxDriver.PWM.NIR_SUPPLEMENT_PERIOD_NS - (dxDriver.PWM.NIR_SUPPLEMENT_PERIOD_NS * (value / 100)))
+    }
+}
+
+/**
+ * ALSA椹卞姩妯″潡
+ * 璐熻矗闊抽鎾斁鍜岄煶閲忔帶鍒�
+ */
+driver.alsa = {
+    /**
+     * 鍒濆鍖栭煶棰�
+     * 鍒濆鍖朅LSA闊抽妯″潡骞惰缃煶閲�
+     */
+    init: function () {
+        alsa.init()
+        this.volume(config.get("base.volume"))
+    },
+    
+    /**
+     * 鎾斁闊抽鏂囦欢
+     * @param {string} src - 闊抽鏂囦欢璺緞
+     */
+    play: function (src) {
+        alsa.play(src)
+    },
+    
+    /**
+     * 鏂囨湰杞闊虫挱鏀�
+     * @param {string} text - 瑕佹挱鏀剧殑鏂囨湰
+     */
+    ttsPlay: function (text) {
+        alsa.ttsPlay(text)
+    },
+    
+    /**
+     * 鑾峰彇鎴栬缃煶閲�
+     * @param {number} [volume] - 闊抽噺鍊硷紝鑼冨洿1-100
+     * @returns {number} 褰撳墠闊抽噺鍊硷紙褰撴湭鎻愪緵鍙傛暟鏃讹級
+     */
+    volume: function (volume) {
+        if (volume === undefined || volume === null) {
+            return alsa.getVolume()
+        } else {
+            function mapScore(input) {
+                // 纭繚杈撳叆鍊煎湪1-100涔嬮棿
+                if (input < 1 || input > 100) {
+                    throw new Error('杈撳叆鍊煎繀椤诲湪1鍒�100涔嬮棿');
+                }
+                if (input < 60 && input > 30) {
+                    input = input * 1.2
+                }
+                if (input < 30 && input > 1) {
+                    input = input * 2
+                }
+                return input
+            }
+            alsa.setVolume(mapScore(volume))
+        }
+    }
+}
+
+/**
+ * 鎽勫儚澶撮┍鍔ㄦā鍧�
+ * 璐熻矗鎽勫儚澶寸殑鍒濆鍖栧拰鎿嶄綔锛屽寘鎷僵鑹叉憚鍍忓ご鍜岀孩澶栨憚鍍忓ご
+ */
+driver.capturer = {
+    /**
+     * 褰╄壊鎽勫儚澶撮厤缃�
+     */
+    options1: {
+        id: "rgb",
+        path: dxDriver.CAPTURER.RGB_PATH,
+        width: dxDriver.CAPTURER.RGB_WIDTH,
+        height: dxDriver.CAPTURER.RGB_HEIGHT,
+        preview_width: dxDriver.CAPTURER.RGB_HEIGHT,
+        preview_height: dxDriver.CAPTURER.RGB_WIDTH,
+        preview_mode: 2,
+        preview_screen_index: 0 // 鍏堝悗椤哄簭锛屾暟瀛楄秺澶ц秺鍦ㄥ墠闈�
+    },
+    
+    /**
+     * 绾㈠鎽勫儚澶撮厤缃�
+     */
+    options2: {
+        id: "nir",
+        path: dxDriver.CAPTURER.NIR_PATH,
+        width: dxDriver.CAPTURER.NIR_WIDTH,
+        height: dxDriver.CAPTURER.NIR_HEIGHT,
+        preview_width: 150,
+        preview_height: 200,
+        preview_mode: 1,
+        preview_left: 605,
+        preview_top: 80,
+        preview_screen_index: 1 // 鍏堝悗椤哄簭锛屾暟瀛楄秺澶ц秺鍦ㄥ墠闈�
+    },
+
+    /**
+     * 鍒濆鍖栨憚鍍忓ご
+     * 鍒濆鍖栧僵鑹叉憚鍍忓ご鍜岀孩澶栨憚鍍忓ご
+     */
+    init: function () {
+        capturer.worker.beforeLoop(this.options1)
+        capturer.worker.beforeLoop(this.options2)
+
+        this.showNir(config.get("face.showNir"))
+    },
+    
+    /**
+     * 鏄剧ず鎴栭殣钘忕孩澶栨憚鍍忓ご棰勮
+     * @param {boolean} enable - 鏄惁鍚敤绾㈠鎽勫儚澶撮瑙�
+     */
+    showNir: function (enable) {
+        capturer.capturerEnable(enable, this.options2.id)
+    },
+    
+    /**
+     * 灏嗗浘鐗囨暟鎹浆鎹负鍥惧儚
+     * @param {string} base64Data - Base64缂栫爜鐨勫浘鐗囨暟鎹�
+     * @returns {number} 鍥惧儚ID
+     */
+    pictureDataToImage: function (base64Data) {
+        return capturer.pictureDataToImage(base64Data, base64Data.length, 1)
+    },
+    
+    /**
+     * 灏嗗浘鍍忎繚瀛樹负鏂囦欢
+     * @param {number} imageId - 鍥惧儚ID
+     * @param {string} savePath - 淇濆瓨璺緞
+     * @returns {boolean} 鏄惁淇濆瓨鎴愬姛
+     */
+    imageToPictureFile: function (imageId, savePath) {
+        return capturer.imageToPictureFile(imageId, 1, 0, 24, savePath)
+    },
+    
+    /**
+     * 灏嗗浘鍍忎繚瀛樹负鏂囦欢锛堥珮璐ㄩ噺锛�
+     * @param {number} imageId - 鍥惧儚ID
+     * @param {string} savePath - 淇濆瓨璺緞
+     * @returns {boolean} 鏄惁淇濆瓨鎴愬姛
+     */
+    imageToPictureFile2: function (imageId, savePath) {
+        return capturer.imageToPictureFile(imageId, 1, 0, 100, savePath)
+    },
+    
+    /**
+     * 璋冩暣鍥惧儚鍒嗚鲸鐜�
+     * @param {number} imageId - 鍥惧儚ID
+     * @param {number} width - 鐩爣瀹藉害
+     * @param {number} height - 鐩爣楂樺害
+     * @returns {number} 璋冩暣鍚庣殑鍥惧儚ID
+     */
+    imageResizeResolution: function (imageId, width, height) {
+        return capturer.imageResizeResolution(imageId, width, height, 0)
+    },
+    
+    /**
+     * 鎽勫儚澶村惊鐜�
+     * 鎵ц鎽勫儚澶寸殑寰幆鎿嶄綔
+     */
+    loop: function () {
+        capturer.worker.loop(this.options1)
+        capturer.worker.loop(this.options2)
+    }
+}
+/**
+ * NFC椹卞姩妯″潡
+ * 璐熻矗NFC鍗$墖鐨勮鍙栧拰澶勭悊
+ */
+driver.nfc = {
+    /**
+     * NFC閰嶇疆閫夐」
+     */
+    options: { m1: true, psam: false },
+    
+    /**
+     * 鍒濆鍖朜FC
+     * 鍒濆鍖朜FC妯″潡锛屾牴鎹厤缃喅瀹氭槸鍚﹀惎鐢�
+     */
+    init: function () {
+        if (!config.get('sys.nfc')) {
+            logger.debug("鍒峰崱宸插叧闂�")
+            return
+        }
+        this.options.useEid = config.get("sys.nfcIdentityCardEnable") == 3 ? 1 : 0
+        nfc.worker.beforeLoop(this.options)
+    },
+    
+    /**
+     * 鍒濆鍖朎ID锛堢數瀛愯韩浠借瘉锛�
+     * 鏇存柊EID閰嶇疆
+     */
+    eidInit: function () {
+        if (!config.get('sys.nfc')) {
+            return
+        }
+        if (config.get("sys.nfcIdentityCardEnable") == 3) {
+            nfc.eidUpdateConfig({ appid: "1621503", sn: config.get("sys.sn"), device_model: config.get("sys.appVersion") })
+        }
+    },
+    
+    /**
+     * NFC寰幆
+     * 鎵цNFC鐨勫惊鐜搷浣滐紝鏍规嵁閰嶇疆鍐冲畾鏄惁鍚敤
+     */
+    loop: function () {
+        if (!config.get('sys.nfc')) {
+            this.loop = () => { }
+        } else {
+            this.loop = () => nfc.worker.loop(this.options)
+        }
+    }
+}
+/**
+ * 浜鸿劯璇嗗埆椹卞姩妯″潡
+ * 璐熻矗浜鸿劯璇嗗埆銆佹敞鍐屽拰鐩稿叧鍔熻兘鐨勭鐞�
+ */
+driver.face = {
+    /**
+     * 鍒濆鍖栦汉鑴歌瘑鍒�
+     * 鍒濆鍖栦汉鑴告ā鍧楋紝璁剧疆鐩稿叧鍙傛暟鍜岄厤缃�
+     */
+    init: function () {
+        common.systemBrief('mkdir -p /app/data/user/temp/')
+        let options = {
+            dbPath: "/app/data/db/face.db",
+            rgbPath: "/dev/video3",
+            nirPath: "/dev/video0",
+            capturerRgbId: "rgb",
+            capturerNirId: "nir",
+            dbMax: 5000, //浜鸿劯娉ㄥ唽涓婇檺
+            score: config.get("face.similarity"),
+            picPath: "/app/data/user/temp",
+            gThumbnailHeight: 1280 / 6,
+            gThumbnailWidth: 800 / 6,
+            // 鏄惁寮�鍚噸妫�
+            recgFaceattrEnable: 1,
+            // 娲讳綋寮�鍏�
+            livingCheckEnable: config.get("face.livenessOff"),
+            // 娲讳綋妫�娴嬮槇鍊�
+            livingScore: config.get("face.livenessVal"),
+            // 鍙g僵妫�娴嬪紑鍏�
+            detectMaskEnable: config.get("face.detectMask"),
+            // 閲嶆闂撮殧
+            recheckIntervalTime: 5000,
+            // 妫�娴嬭秴鏃�
+            detectTimeoutTime: 1000
+        }
+        face.worker.beforeLoop(options)
+
+        // 榛樿涓轰汉鑴歌瘑鍒ā寮�
+        this.mode(0)
+        // 鍏抽棴鎵�鏈変汉鑴稿姛鑳�
+        this.status(false)
+
+        // 灞忓箷浜害
+        this.setDisplayBacklight(config.get("base.brightness"))
+
+        this.screenStatus(1)
+        
+        // 琛ュ厜鐏姸鎬佽窡韪�
+        let isLightOn = true
+
+        // 灞忓箷浜害鑷姩璋冭妭
+        std.setInterval(() => {
+            // 鐔勫睆鍒ゆ柇
+            let screenOff = map.get("screenOff")
+            if (screenOff.get("status") == 1) {
+                this.setDisplayBacklight(0)
+                this.screenStatus(0)
+                // 鍏抽棴琛ュ厜鐏紙浠呭綋琛ュ厜鐏綋鍓嶆槸寮�鍚姸鎬佹椂锛�
+                if (isLightOn) {
+                    driver.pwm.luminanceWhite(0)
+                    driver.pwm.luminanceNir(0)
+                    logger.info("[driver.face]: 鐔勫睆锛屽叧闂ˉ鍏夌伅")
+                    isLightOn = false
+                }
+            }
+
+            // 鍋滄鐔勫睆
+            if (screenOff.get("status") != 1) {
+                if (config.get("base.brightnessAuto") == 1) {
+                    // 鑷姩璋冭妭灞忓箷浜害
+                    let brightness = Math.floor(face.getEnvBrightness() / 10)
+                    brightness = brightness > 100 ? 100 : brightness
+                    this.setDisplayBacklight(brightness)
+                } else {
+                    this.setDisplayBacklight(config.get("base.brightness"))
+                }
+                // 寮�鍚ˉ鍏夌伅锛堜粎褰撹ˉ鍏夌伅褰撳墠鏄叧闂姸鎬佹椂锛�
+                if (!isLightOn) {
+                    let luminanceWhite = config.get('base.luminanceWhite') ?? 80
+                    let luminanceNir = config.get('base.luminanceNir') ?? 80
+                    driver.pwm.luminanceWhite(luminanceWhite)
+                    driver.pwm.luminanceNir(luminanceNir)
+                    logger.info(`[driver.face]: 閫�鍑虹唲灞忥紝寮�鍚ˉ鍏夌伅锛堢櫧鐏�: ${luminanceWhite}%, 绾㈠: ${luminanceNir}%锛塦)
+                    isLightOn = true
+                }
+            }
+        }, 1000)
+    },
+    
+    /**
+     * 鑾峰彇浜鸿劯璺熻釜妗�
+     * @returns {object} 璺熻釜妗嗕俊鎭�
+     */
+    getTrackingBox: function () {
+        return face.getTrackingBox()
+    },
+    
+    /**
+     * 浜鸿劯璇嗗埆寰幆
+     * 鎵ц浜鸿劯璇嗗埆鐨勫惊鐜搷浣�
+     */
+    loop: function () {
+        // 妫�鏌ュ睆骞曟槸鍚﹀浜庣唲灞忕姸鎬�
+        let screenOff = map.get("screenOff")
+        if (screenOff && screenOff.get("status") == 1) {
+            // 鐔勫睆鐘舵�佷笅涓嶈繘琛屼汉鑴歌瘑鍒�
+            return
+        }
+        face.worker.loop()
+    },
+    
+    /**
+     * 浜鸿劯绾跨▼鍚敤寮�鍏�
+     * @param {boolean} flag - 鏄惁鍚敤浜鸿劯妫�娴�
+     */
+    status: function (flag) {
+        console.log('---浜鸿劯妫�娴�' + (flag ? '寮�鍚�' : '鏆傚仠') + '---');
+        face.faceSetEnable(flag)
+    },
+    
+    /**
+     * 璁剧疆浜鸿劯璇嗗埆妯″紡
+     * @param {number} value - 妯″紡鍊硷紝0涓鸿瘑鍒ā寮忥紝1涓烘敞鍐屾ā寮�
+     */
+    mode: function (value) {
+        console.log('---浜鸿劯' + (value ? '娉ㄥ唽' : '璇嗗埆') + '妯″紡---');
+        face.setRecgMode(value)
+    },
+    
+    /**
+     * 浜鸿劯娉ㄥ唽
+     * @param {string} id - 鐢ㄦ埛ID
+     * @param {string} feature - 浜鸿劯鐗瑰緛
+     * @returns {boolean} 鏄惁娉ㄥ唽鎴愬姛
+     */
+    reg: function (id, feature) {
+        return face.addFaceFeatures(id, feature);
+    },
+    
+    /**
+     * 鏇存柊浜鸿劯閰嶇疆
+     * @param {object} options - 閰嶇疆閫夐」
+     */
+    faceUpdateConfig: function (options) {
+        console.log("鏇存柊浜鸿劯閰嶇疆", JSON.stringify(options));
+        face.faceUpdateConfig(options)
+    },
+    
+    /**
+     * 璁剧疆灞忓箷浜害
+     * @param {number} brightness - 浜害鍊�
+     */
+    setDisplayBacklight: function (brightness) {
+        brightness = brightness < 2 ? 2 : brightness
+        face.setDisplayBacklight(brightness)
+    },
+    
+    /**
+     * 閫氳繃鍥剧墖鏂囦欢娉ㄥ唽浜鸿劯
+     * @param {string} userId - 鐢ㄦ埛ID
+     * @param {string} picPath - 鍥剧墖璺緞
+     * @returns {boolean} 鏄惁娉ㄥ唽鎴愬姛
+     */
+    registerFaceByPicFile: function (userId, picPath) {
+        return face.registerFaceByPicFile(userId, picPath)
+    },
+    
+    /**
+     * 娓呯┖浜鸿劯鏁版嵁
+     * @returns {boolean} 鏄惁娓呯┖鎴愬姛
+     */
+    clean: function () {
+        // 娓呯┖浜鸿劯锛岄渶瑕佸湪鍒濆鍖栦汉鑴哥粍浠朵箣鍓嶆墠鑳芥墽琛岋紝鍚﹀垯鎶ラ敊
+        face.faceFeaturesClean()
+        common.systemBrief("rm -rf /app/data/db/face.db")
+        return !std.exist("/app/data/db/face.db")
+    },
+    
+    /**
+     * 鍒犻櫎鎸囧畾鐢ㄦ埛鐨勪汉鑴告暟鎹�
+     * @param {string} userId - 鐢ㄦ埛ID
+     * @returns {boolean} 鏄惁鍒犻櫎鎴愬姛
+     */
+    delete: function (userId) {
+        return face.deleteFaceFeatures(userId)
+    },
+    
+    /**
+     * 璁剧疆灞忓箷鐘舵��
+     * @param {boolean} status - 鏄惁鍚敤灞忓箷
+     */
+    screenStatus: function (status) {
+        if (status) {
+            face.setPowerMode(0)
+        } else {
+            face.setPowerMode(1)
+        }
+        face.setEnableStatus(status)
+    },
+    
+    /**
+     * 灏嗘枃浠惰浆鎹负base64缂栫爜
+     * @param {string} filePath - 鏂囦欢璺緞
+     * @returns {string} Base64缂栫爜鐨勬枃浠跺唴瀹�
+     */
+    fileToBase64: function (filePath) {
+        function fileToUint8Array(filename) {
+            // 璇诲彇鏂囦欢
+            const file = std.open(filename, "rb");
+            if (!file) {
+                throw new Error("鏃犳硶鎵撳紑鏂囦欢");
+            }
+
+            // 鑾峰彇鏂囦欢澶у皬
+            const size = std.seek(file, 0, std.SEEK_END)
+            std.seek(file, 0, std.SEEK_SET)
+            
+            // 妫�鏌ユ枃浠跺ぇ灏忔槸鍚︽湁鏁�
+            if (size <= 0) {
+                std.close(file);
+                throw new Error("鏂囦欢澶у皬鏃犳晥");
+            }
+            
+            // 鍒涘缓 ArrayBuffer 骞惰鍙栨枃浠跺唴瀹�
+            const buffer = new ArrayBuffer(size);
+            const array = new Uint8Array(buffer);
+            std.read(file, array.buffer, 0, size);
+
+            std.close(file);
+
+            return array;
+        }
+
+        try {
+            // 妫�鏌ユ枃浠惰矾寰勬槸鍚﹀瓨鍦�
+            if (!filePath) {
+                throw new Error("鏂囦欢璺緞涓虹┖");
+            }
+            const data = fileToUint8Array(filePath);
+            return base64.fromUint8Array(data);
+        } catch (error) {
+            logger.info("鏂囦欢杞珺ase64澶辫触: " + error.message);
+            return "";
+        }
+    }
+}
+
+/**
+ * 缃戠粶椹卞姩妯″潡
+ * 璐熻矗缃戠粶杩炴帴鍜岀鐞�
+ */
+driver.net = {
+    /**
+     * 鍒濆鍖栫綉缁�
+     * 鍒濆鍖栫綉缁滄ā鍧楋紝璁剧疆缃戠粶閰嶇疆
+     */
+    init: function () {
+        let dns = config.get("net.dns").split(",")
+        let option = {
+            type: config.get("net.type"),
+            dhcp: config.get("net.dhcp"),
+            ip: config.get("net.ip"),
+            gateway: config.get("net.gateway"),
+            netmask: config.get("net.mask"),
+            dns0: dns[0],
+            dns1: dns[1],
+            macAddr: common.getUuid2mac()
+        }
+        logger.info("鏇存柊鑱旂綉閰嶇疆锛�", JSON.stringify(option));
+        net.worker.beforeLoop(option)
+        config.set("net.mac", common.getUuid2mac())
+        if (config.get("net.type") == 2) {
+            //wifi鍙栭厤缃枃浠跺幓杩炴帴
+            let ssid = utils.isEmpty(config.get('net.ssid')) ? "ssid" : config.get('net.ssid')
+            let psk = utils.isEmpty(config.get('net.psk')) ? "psk" : config.get('net.psk')
+            driver.net.netConnectWifiSsid(ssid, psk)
+        }
+        // 瑙e喅缃戠粶鍒囨崲鐘舵�佷笉瀵�
+        std.setInterval(() => {
+            let status = net.getStatus()
+            if (status.status != map.get("NET").get("status")) {
+                status.type = config.get("net.type")
+                bus.fire(net.STATUS_CHANGE, status)
+            }
+        }, 1000)
+    },
+    
+    /**
+     * 鍒囨崲缃戠粶绫诲瀷
+     * 鍒囨崲缃戠粶绫诲瀷骞堕厤缃浉搴旂殑缃戠粶鍙傛暟
+     */
+    changeNetType: function () {
+        // 鍔犻攣
+        if (map.get("NET").get("changeType") == "Y") {
+            return
+        }
+        map.get("NET").put("changeType", "Y")
+        let type = config.get("net.type")
+        logger.info("鍒囨崲缃戠粶", type);
+        [1, 2, 4].filter(v => v != type).forEach(v => {
+            logger.info("鍏抽棴缃戝崱", v, net.cardEnable(v, false));
+        })
+        logger.info("璁剧疆涓荤綉鍗�", type, net.setMasterCard(type));
+        logger.info("寮�鍚綉鍗�", type, net.cardEnable(type, true));
+        if (type == 2) {
+            //wifi鍙栭厤缃枃浠跺幓杩炴帴
+            let ssid = utils.isEmpty(config.get('net.ssid')) ? "ssid" : config.get('net.ssid')
+            let psk = utils.isEmpty(config.get('net.psk')) ? "psk" : config.get('net.psk')
+            logger.info("杩炴帴wifi", ssid, psk);
+            net.netConnectWifiSsid(ssid, psk)
+            
+            // 绛夊緟WiFi杩炴帴鎴愬姛鍚庡啀璁剧疆缃戠粶妯″紡
+            std.setTimeout(() => {
+                let dns = config.get("net.dns").split(",")
+                net.setModeByCard(type, config.get("net.dhcp"), config.get("net.dhcp") == 1 ? {
+                    ip: config.get("net.ip"),
+                    gateway: config.get("net.gateway"),
+                    netmask: config.get("net.mask"),
+                    dns0: dns[0],
+                    dns1: dns[1],
+                } : undefined)
+            }, 3000); // 绛夊緟3绉掕WiFi杩炴帴鎴愬姛
+        } else if (type == 1) {
+            // 浠ュお缃戠洿鎺ヨ缃綉缁滄ā寮�
+            let dns = config.get("net.dns").split(",")
+            net.setModeByCard(type, config.get("net.dhcp"), config.get("net.dhcp") == 1 ? {
+                ip: config.get("net.ip"),
+                gateway: config.get("net.gateway"),
+                netmask: config.get("net.mask"),
+                dns0: dns[0],
+                dns1: dns[1],
+            } : undefined)
+        }
+        map.get("NET").del("changeType")
+    },
+    
+    /**
+     * 鍒濆鍖朎ID缃戠粶
+     * 閫�鍑虹綉缁滃苟閲嶅惎鐩稿叧鏈嶅姟
+     */
+    eidInit: function () {
+        net.exit();
+        common.systemWithRes(`pkill -9 -f 'wpa_supplicant|udhcpc'`, 5)
+    },
+    
+    /**
+     * 鑾峰彇缃戠粶鐘舵��
+     * @returns {boolean} 鏄惁杩炴帴鎴愬姛
+     */
+    getStatus: function () {
+        let status = net.getStatus()
+        if (status.connected == true && status.status == 4) {
+            return true
+        } else {
+            return false
+        }
+
+    },
+    
+    /**
+     * 杩炴帴WiFi
+     * @param {string} ssid - WiFi鍚嶇О
+     * @param {string} psk - WiFi瀵嗙爜
+     */
+    netConnectWifiSsid: function (ssid, psk) {
+        net.netConnectWifiSsid(ssid, psk, "")
+    },
+    
+    /**
+     * 鑾峰彇WiFi鍒楄〃
+     * @returns {array} WiFi鍒楄〃
+     */
+    netGetWifiSsidList: function () {
+        if (!driver.net.getStatus()) {
+            //濡傛灉 wifi 杩炴帴澶辫触  鑾峰彇鍒楄〃浼氬け璐ラ渶瑕佸厛閿�姣�
+            net.netDisconnetWifi()
+        }
+        let result = net.netGetWifiSsidList(1000, 5)
+        if (!result || !result.results || result.results.length === 0) {
+            return [];
+        }
+        let wifiList = []; // 鍒濆鍖杦ifiList涓烘暟缁�
+        result.results.forEach(element => wifiList.push(element.ssid)); // 浣跨敤push鏂规硶娣诲姞ssid鍒版暟缁�
+        return wifiList;
+    },
+    
+    /**
+     * 閲嶇疆缃戝崱
+     */
+    cardReset: function () {
+        // net.netCardReset(2,1)
+    },
+    
+    /**
+     * 缃戠粶寰幆
+     * 鎵ц缃戠粶鐨勫惊鐜搷浣�
+     */
+    loop: function () {
+        net.worker.loop()
+    }
+}
+
+/**
+ * NTP椹卞姩妯″潡
+ * 璐熻矗缃戠粶鏃堕棿鍚屾
+ */
+driver.ntp = {
+    /**
+     * NTP寰幆
+     * 鍒濆鍖朜TP妯″潡骞舵墽琛屾椂闂村悓姝ユ搷浣�
+     */
+    loop: function () {
+        // 姣忕閽熷垽鏂椂闂达紝濡傛灉鏃跺樊澶т簬2绉掑垯杩涜浜嗗鏃�
+        let last = new Date().getTime()
+        dxMap.get("NTP_SYNC").put("syncTime", last)
+        std.setInterval(() => {
+            let now = new Date().getTime()
+            let diff = now - last
+            if (diff > 2000) {
+                dxMap.get("NTP_SYNC").put("syncTime", now)
+                last = now
+            }
+        }, 1000)
+
+        ntp.beforeLoop(config.get("ntp.server"), 9999999999999)
+        this.ntpHour = config.get('ntp.hour')
+        this.flag = true
+        driver.ntp.loop = () => {
+            if (config.get("ntp.ntp")) {
+                ntp.loop()
+                if (new Date().getHours() == this.ntpHour && this.flag) {
+                    // 瀹氭椂鍚屾锛岀珛鍗冲悓姝ヤ竴娆℃椂闂�
+                    ntp.syncnow = true
+                    this.flag = false
+                }
+                if (new Date().getHours() != this.ntpHour) {
+                    // 绛夎繃浜嗚繖涓皬鏃跺啀娆″厑璁稿鏃�
+                    this.flag = true
+                }
+            }
+        }
+    }
+}
+/**
+ * 鍚屾椹卞姩妯″潡
+ * 鎻愪緵寮傛杞悓姝ョ殑瀹炵幇
+ */
+driver.sync = {
+    /**
+     * 寮傛杞悓姝ヨ姹�
+     * @param {string} topic - 涓婚
+     * @param {number} timeout - 瓒呮椂鏃堕棿锛堟绉掞級
+     * @returns {any} 鍝嶅簲鏁版嵁
+     */
+    request: function (topic, timeout) {
+        let map = dxMap.get("SYNC")
+        let count = 0
+        let data = map.get(topic)
+        while (utils.isEmpty(data) && count * 10 < timeout) {
+            data = map.get(topic)
+            std.sleep(10)
+            count += 1
+        }
+        let res = map.get(topic)
+        map.del(topic)
+        return res
+    },
+    
+    /**
+     * 鍚屾鍝嶅簲
+     * @param {string} topic - 涓婚
+     * @param {any} data - 鍝嶅簲鏁版嵁
+     */
+    response: function (topic, data) {
+        let map = dxMap.get("SYNC")
+        map.put(topic, data)
+    }
+}
+/**
+ * MQTT椹卞姩妯″潡
+ * 璐熻矗MQTT閫氫俊鍜屾秷鎭鐞�
+ */
+driver.mqtt = {
+    /**
+     * 鍒濆鍖朚QTT
+     * 鍒濆鍖朚QTT妯″潡锛岃缃繛鎺ュ弬鏁�
+     */
+    init: function () {
+        mqtt.run({ mqttAddr: config.get("mqtt.addr"), clientId: config.get('mqtt.clientId'), subs: mqttService.getTopics(), username: config.get("mqtt.username"), password: config.get("mqtt.password"), qos: config.get("mqtt.qos"), willTopic: config.get("mqtt.willTopic"), willMessage: JSON.stringify({ "uuid": config.get("sys.uuid") }) })
+    },
+    
+    /**
+     * 鍒濆鍖朎ID鐨凪QTT
+     * 閿�姣丮QTT杩炴帴
+     */
+    eidInit: function () {
+        mqtt.destroy()
+    },
+    
+    /**
+     * 鍙戦�丮QTT娑堟伅
+     * @param {string} topic - 娑堟伅涓婚
+     * @param {any} payload - 娑堟伅杞借嵎
+     */
+    send: function (topic, payload,) {
+        logger.info("[driver.mqtt] send :", topic)
+        mqtt.send(topic, payload)
+    },
+    
+    /**
+     * 鑾峰彇鍦ㄧ嚎妫�鏌�
+     * @returns {any} 鍦ㄧ嚎妫�鏌ョ粨鏋�
+     */
+    getOnlinecheck: function () {
+        let timeout = config.get("mqtt.timeout")
+        timeout = utils.isEmpty(timeout) ? 2000 : timeout
+        return driver.sync.request("mqtt.getOnlinecheck", timeout)
+    },
+    
+    /**
+     * 鍦ㄧ嚎妫�鏌ュ洖澶�
+     * @param {any} data - 鍥炲鏁版嵁
+     */
+    getOnlinecheckReply: function (data) {
+        driver.sync.response("mqtt.getOnlinecheck", data)
+    },
+    
+    /**
+     * 鑾峰彇MQTT杩炴帴鐘舵��
+     * @returns {boolean} 鏄惁杩炴帴鎴愬姛
+     */
+    getStatus: function () {
+        return mqtt.isConnected()
+    },
+    
+    /**
+     * MQTT蹇冭烦
+     * 鍙戦�佸績璺虫秷鎭紝淇濇寔杩炴帴
+     */
+    heartbeat: function () {
+        if (utils.isEmpty(this.heart_en)) {
+            let heart_en = config.get('sys.heart_en')
+            this.heart_en = utils.isEmpty(heart_en) ? 0 : heart_en
+            let heart_time = config.get('sys.heart_time')
+            this.heart_time = utils.isEmpty(heart_time) ? 30 : heart_time < 30 ? 30 : heart_time
+        }
+        if (utils.isEmpty(this.lastHeartbeat)) {
+            this.lastHeartbeat = 0
+        }
+        if (this.heart_en === 1 && (new Date().getTime() - this.lastHeartbeat >= (this.heart_time * 1000))) {
+            this.lastHeartbeat = new Date().getTime()
+            driver.mqtt.send("access_device/v2/event/heartbeat", JSON.stringify(mqttService.mqttReply(std.genRandomStr(10), undefined, mqttService.CODE.S_000)))
+        }
+    }
+}
+
+/**
+ * GPIO椹卞姩妯″潡
+ * 璐熻矗GPIO璁惧鐨勬帶鍒讹紝涓昏鏄户鐢靛櫒鎺у埗
+ */
+driver.gpio = {
+    /**
+     * 鍒濆鍖朑PIO
+     * 鍒濆鍖朑PIO妯″潡骞惰姹傜户鐢靛櫒寮曡剼
+     */
+    init: function () {
+        gpio.init()
+        gpio.request(dxDriver.GPIO.RELAY0)
+    },
+    
+    /**
+     * 鎵撳紑缁х數鍣�
+     * 鎵撳紑缁х數鍣ㄥ苟鍦ㄦ寚瀹氭椂闂村悗鑷姩鍏抽棴
+     */
+    open: function () {
+        logger.info("[GPIO]: 鎵撳紑缁х數鍣�")
+        let result = gpio.setValue(dxDriver.GPIO.RELAY0, 1);
+        logger.info("[GPIO]: 鎵撳紑缁х數鍣ㄧ粨鏋�: " + result)
+
+        let relayTime = config.get("access.relayTime")
+
+        std.setTimeout(() => {
+            logger.info("[GPIO]: 鍏抽棴缁х數鍣�")
+            let closeResult = gpio.setValue(dxDriver.GPIO.RELAY0, 0);
+            logger.info("[GPIO]: 鍏抽棴缁х數鍣ㄧ粨鏋�: " + closeResult)
+        }, relayTime)
+    },
+    
+    /**
+     * 鍏抽棴缁х數鍣�
+     * 绔嬪嵆鍏抽棴缁х數鍣�
+     */
+    close: function () {
+        gpio.setValue(dxDriver.GPIO.RELAY0, 0)
+    }
+}
+
+/**
+ * UART485椹卞姩妯″潡
+ * 璐熻矗UART485閫氫俊
+ */
+driver.uart485 = {
+    /**
+     * UART485 ID
+     */
+    id: 'uart485',
+    
+    /**
+     * 鍒濆鍖朥ART485
+     * 鍒濆鍖朥ART485妯″潡骞惰缃�氫俊鍙傛暟
+     */
+    init: function () {
+        dxUart.runvg({ id: this.id, type: dxUart.TYPE.UART, path: '/dev/ttySLB2', result: 0, passThrough: false })
+        std.sleep(2000)
+        dxUart.ioctl(6, '115200-8-N-1', this.id)
+    },
+    
+    /**
+     * 鎺у埗UART485
+     * @param {string} data - 鎺у埗鏁版嵁
+     */
+    ioctl: function (data) {
+        dxUart.ioctl(6, data, this.id)
+    },
+    
+    /**
+     * 鍙戦�佹暟鎹�
+     * @param {string} data - 瑕佸彂閫佺殑鏁版嵁
+     */
+    send: function (data) {
+        dxUart.send(data, this.id)
+    },
+    
+    /**
+     * 鍙戦�乂G鏁版嵁
+     * @param {object|string} data - 瑕佸彂閫佺殑鏁版嵁
+     */
+    sendVg: function (data) {
+        if (typeof data == 'object') {
+            data.length = data.length ? data.length : (data.data ? data.data.length / 2 : 0)
+        }
+        dxUart.sendVg(data, this.id)
+    }
+}
+
+/**
+ * UARTCode椹卞姩妯″潡
+ * 璐熻矗UART鏉$爜鎵弿閫氫俊
+ */
+driver.uartCode = {
+    /**
+     * UARTCode ID
+     */
+    id: 'uartCode',
+    
+    /**
+     * 鍒濆鍖朥ARTCode
+     * 鍒濆鍖朥ARTCode妯″潡骞惰缃�氫俊鍙傛暟
+     */
+    init: function () {
+        dxUart.runvg({ id: this.id, type: dxUart.TYPE.UART, path: '/dev/ttySLB1', result: 0, passThrough: false })
+        std.sleep(500)
+        dxUart.ioctl(6, '115200-8-N-1', this.id)
+    },
+    
+    /**
+     * 鎺у埗UARTCode
+     * @param {string} data - 鎺у埗鏁版嵁
+     */
+    ioctl: function (data) {
+        dxUart.ioctl(6, data, this.id)
+    },
+    
+    /**
+     * 鍙戦�佹暟鎹�
+     * @param {string} data - 瑕佸彂閫佺殑鏁版嵁
+     */
+    send: function (data) {
+        dxUart.send(data, this.id)
+    },
+    
+    /**
+     * 鍙戦�乂G鏁版嵁
+     * @param {object|string} data - 瑕佸彂閫佺殑鏁版嵁
+     */
+    sendVg: function (data) {
+        if (typeof data == 'object') {
+            data.length = data.length ? data.length : (data.data ? data.data.length / 2 : 0)
+        }
+        dxUart.sendVg(data, this.id)
+    },
+}
+
+/**
+ * EID椹卞姩妯″潡
+ * 璐熻矗鐢靛瓙韬唤璇佺浉鍏虫搷浣�
+ */
+driver.eid = {
+    /**
+     * EID ID
+     */
+    id: "eid",
+    
+    /**
+     * 婵�娲籈ID
+     * @param {string} sn - 璁惧SN
+     * @param {string} version - 鐗堟湰鍙�
+     * @param {string} mac - MAC鍦板潃
+     * @param {string} codeMsg - 婵�娲荤爜
+     * @returns {boolean} 鏄惁婵�娲绘垚鍔�
+     */
+    active: function (sn, version, mac, codeMsg) {
+        return eid.active(sn, version, mac, codeMsg)
+    },
+    
+    /**
+     * 鑾峰彇EID鐗堟湰
+     * @returns {string} EID鐗堟湰
+     */
+    getVerion: function () {
+        return eid.getVersion()
+    }
+}
+/**
+ * GPIO鎸夐敭椹卞姩妯″潡
+ * 璐熻矗GPIO鎸夐敭鐨勫垵濮嬪寲鍜屽惊鐜鐞�
+ */
+driver.gpiokey = {
+    /**
+     * 鍒濆鍖朑PIO鎸夐敭
+     * 鍒濆鍖朑PIO鎸夐敭妯″潡
+     */
+    init: function () {
+        dxGpioKey.worker.beforeLoop()
+    },
+    
+    /**
+     * GPIO鎸夐敭寰幆
+     * 鎵цGPIO鎸夐敭鐨勫惊鐜搷浣�
+     */
+    loop: function () {
+        dxGpioKey.worker.loop()
+    },
+}
+/**
+ * 鐪嬮棬鐙楅┍鍔ㄦā鍧�
+ * 璐熻矗绯荤粺鐪嬮棬鐙楃殑鍒濆鍖栧拰鍠傜嫍鎿嶄綔
+ */
+driver.watchdog = {
+    /**
+     * 鍒濆鍖栫湅闂ㄧ嫍
+     * 鍒濆鍖栫湅闂ㄧ嫍妯″潡
+     */
+    init: function () {
+        // watchdog.open(1)
+        // watchdog.enable(1)
+        // watchdog.start(20000)
+    },
+    
+    /**
+     * 鐪嬮棬鐙楀惊鐜�
+     * 鎵ц鐪嬮棬鐙楃殑寰幆鎿嶄綔
+     */
+    loop: function () {
+        // watchdog.loop(1)
+    },
+    
+    /**
+     * 鍠傜嫍
+     * 鍚戠湅闂ㄧ嫍鍙戦�佸杺鐙椾俊鍙凤紝闃叉绯荤粺閲嶅惎
+     * @param {string} flag - 鍠傜嫍鏍囧織
+     * @param {number} timeout - 瓒呮椂鏃堕棿
+     */
+    feed: function (flag, timeout) {
+        // if (utils.isEmpty(this["feedTime" + flag]) || new Date().getTime() - this["feedTime" + flag] > 2000) {
+        //     // 闄嶄綆鍠傜嫍棰戠巼锛岄棿闅�2绉掑杺涓�娆�
+        //     this["feedTime" + flag] = new Date().getTime()
+        //     watchdog.feed(flag, timeout)
+        // }
+    }
+}
+
+/**
+ * 鑷姩閲嶅惎椹卞姩妯″潡
+ * 璐熻矗绯荤粺鐨勮嚜鍔ㄩ噸鍚姛鑳�
+ */
+driver.autoRestart = {
+    /**
+     * 涓婃閲嶅惎妫�鏌ョ殑灏忔椂鏁�
+     */
+    lastRestartCheck: new Date().getHours(),  // 鍒濆鍖栦负褰撳墠灏忔椂鏁帮紝鑰屼笉鏄�0
+    
+    /**
+     * 鍒濆鍖栬嚜鍔ㄩ噸鍚�
+     * 鍒濆鍖栬嚜鍔ㄩ噸鍚ā鍧楋紝璁剧疆瀹氭椂閲嶅惎鍔熻兘
+     */
+    init: function () {
+        // std.setInterval(() => {        // 妫�鏌ユ槸鍚﹂渶瑕佹暣鐐归噸鍚�
+        //     const now = new Date()
+        //     const currentHour = now.getHours()
+        //     // 鍙湁褰撳皬鏃舵暟绛変簬璁惧畾鍊硷紝涓斾笉鏄笂娆℃鏌ヨ繃鐨勫皬鏃舵椂鎵嶆墽琛�
+        //     if (currentHour === 3 && currentHour !== this.lastRestartCheck && now.getMinutes() === 0) {
+        //         common.systemBrief('reboot')
+        //     }
+        //     // 鏇存柊涓婃妫�鏌ョ殑灏忔椂鏁�
+        //     this.lastRestartCheck = currentHour
+        // }, 60000)
+    }
+}
+
+export default driver
diff --git a/vf205_access/src/main.js b/vf205_access/src/main.js
new file mode 100644
index 0000000..a4b9565
--- /dev/null
+++ b/vf205_access/src/main.js
@@ -0,0 +1,78 @@
+/**
+ * 搴旂敤涓诲叆鍙f枃浠�
+ * 璐熻矗鍒濆鍖栫郴缁熷悇缁勪欢銆侀┍鍔ㄥ拰鏈嶅姟锛屽惎鍔ㄥ簲鐢ㄧ▼搴�
+ */
+import log from '../dxmodules/dxLogger.js'
+import std from '../dxmodules/dxStd.js'
+import bus from '../dxmodules/dxEventBus.js'
+import screen from './screen.js'
+import driver from './driver.js'
+import pool from '../dxmodules/dxWorkerPool.js'
+import config from '../dxmodules/dxConfig.js'
+import face from '../dxmodules/dxFace.js'
+import net from '../dxmodules/dxNet.js'
+import mqtt from '../dxmodules/dxMqtt.js'
+import dxNfc from '../dxmodules/dxNfc.js'
+import dxUart from '../dxmodules/dxUart.js'
+import dxGpioKey from '../dxmodules/dxGpioKey.js'
+
+/**
+ * 浜嬩欢鎬荤嚎涓婚鍒楄〃
+ * 鍖呭惈绯荤粺涓墍鏈夐渶瑕佺洃鍚殑浜嬩欢涓婚
+ */
+let topics = ["getCode", face.RECEIVE_MSG, dxGpioKey.RECEIVE_MSG, "netGetWifiSsidList", "switchNetworkType", "access", "setConfig", dxNfc.RECEIVE_MSG, net.STATUS_CHANGE, mqtt.CONNECTED_CHANGED, mqtt.RECEIVE_MSG, dxUart.VG.RECEIVE_MSG + driver.uart485.id, dxUart.VG.RECEIVE_MSG + driver.uartCode.id, "trackResult"]
+
+/**
+ * 鍒濆鍖栨帶鍒跺櫒
+ * 鍒濆鍖栫郴缁熸墍鏈夐┍鍔ㄦā鍧�
+ */
+function initController() {
+    driver.gpio.init()         // 鍒濆鍖朑PIO
+    driver.watchdog.init()     // 鍒濆鍖栫湅闂ㄧ嫍
+    driver.config.init()       // 鍒濆鍖栭厤缃�
+    driver.gpiokey.init()      // 鍒濆鍖朑PIO鎸夐敭
+    driver.net.init()          // 鍒濆鍖栫綉缁�
+    driver.sqlite.init()       // 鍒濆鍖栨暟鎹簱
+    driver.alsa.init()         // 鍒濆鍖栭煶棰�
+    driver.nfc.init()          // 鍒濆鍖朜FC
+    driver.nfc.eidInit()       // 鍒濆鍖朎ID锛堢數瀛愯韩浠借瘉锛�
+    driver.uart485.init()      // 鍒濆鍖朥ART485
+    driver.uartCode.init()     // 鍒濆鍖朥ART鐮�
+    driver.capturer.init()     // 鍒濆鍖栨憚鍍忓ご
+    std.sleep(100)             // 绛夊緟100ms
+    driver.face.init()         // 鍒濆鍖栦汉鑴歌瘑鍒�
+    std.sleep(100)             // 绛夊緟100ms
+    driver.pwm.init()          // 鍒濆鍖朠WM
+    std.sleep(100)             // 绛夊緟100ms
+    driver.mqtt.init()         // 鍒濆鍖朚QTT
+    driver.autoRestart.init()  // 鍒濆鍖栬嚜鍔ㄩ噸鍚�
+}
+
+/**
+ * 搴旂敤绋嬪簭鍚姩鍑芥暟
+ * 鍒濆鍖栨帶鍒跺櫒銆佸睆骞曘�佸垱寤哄伐浣滅嚎绋嬪拰鏈嶅姟姹�
+ */
+(function () {
+    initController()                      // 鍒濆鍖栨帶鍒跺櫒
+    screen.init()                         // 鍒濆鍖栧睆骞�
+    bus.newWorker('controller', '/app/code/src/controller.js')  // 鍒涘缓鎺у埗鍣ㄥ伐浣滅嚎绋�
+    pool.init('/app/code/src/services.js', bus, topics, 5, 100) // 鍒濆鍖栨湇鍔℃睜
+    const appVersion = 'vf105_v12_access_2.0.1.1'  // 搴旂敤鐗堟湰鍙�
+    config.setAndSave('sys.version', appVersion)    // 淇濆瓨鐗堟湰鍙峰埌閰嶇疆
+    config.setAndSave('sys.appVersion', appVersion) // 淇濆瓨搴旂敤鐗堟湰鍙峰埌閰嶇疆
+    log.info("=================== version:" + appVersion + " ====================")
+})();
+
+/**
+ * 涓诲惊鐜�
+ * 瀹氭湡鍠傜嫍銆佹墽琛岀湅闂ㄧ嫍寰幆鍜屽睆骞曞惊鐜�
+ */
+std.setInterval(() => {
+    try {
+        driver.watchdog.feed("main", 30) // 鍠傜嫍锛岃缃�30绉掕秴鏃�
+        driver.watchdog.loop()           // 鎵ц鐪嬮棬鐙楀惊鐜�
+        screen.loop()                    // 鎵ц灞忓箷寰幆
+    } catch (error) {
+        log.error(error)                 // 璁板綍閿欒
+    }
+}, 5) // 姣�5ms鎵ц涓�娆�
\ No newline at end of file
diff --git a/vf205_access/src/screen.js b/vf205_access/src/screen.js
new file mode 100644
index 0000000..1227934
--- /dev/null
+++ b/vf205_access/src/screen.js
@@ -0,0 +1,1470 @@
+/**
+ * 灞忓箷绠$悊妯″潡
+ * 璐熻矗灞忓箷鏄剧ず銆乁I鎺у埗銆佺敤鎴风晫闈㈢鐞嗙瓑鍔熻兘
+ */
+import dxui from '../dxmodules/dxUi.js'
+import dxMap from '../dxmodules/dxMap.js'
+import log from '../dxmodules/dxLogger.js'
+import net from '../dxmodules/dxNet.js'
+import viewUtils from './view/viewUtils.js'
+import i18n from './view/i18n.js'
+import grainService from './service/grainService.js'
+import sqliteService from './service/sqliteService.js'
+import pinyin from './view/pinyin/pinyin.js'
+import mainView from './view/mainView.js'
+import idleView from './view/idleView.js'
+import topView from './view/topView.js'
+import appView from './view/appView.js'
+import pwdView from './view/pwdView.js'
+import emergencyPwdView from './view/emergencyPwdView.js'
+import newPwdView from './view/config/newPwdView.js'
+import identityVerificationView from './view/config/identityVerificationView.js'
+import configView from './view/config/configView.js'
+import cloudCertView from './view/config/menu/cloudCertView.js'
+import doorControlView from './view/config/menu/doorControlView.js'
+import helpView from './view/config/menu/helpView.js'
+import networkSettingView from './view/config/menu/networkSettingView.js'
+import systemSettingView from './view/config/menu/systemSettingView.js'
+import deviceInfoView from './view/config/menu/deviceInfoView.js'
+import factoryTestView from './view/config/menu/factoryTestView.js'
+import localUserView from './view/config/menu/localUserView.js'
+import recordQueryView from './view/config/menu/recordQueryView.js'
+import voiceBroadcastView from './view/config/menu/voiceBroadcastView.js'
+import dockingSettingView from './view/config/menu/dockingSetting.js'
+import localUserAddView from './view/config/menu/localUser/localUserAddView.js'
+import faceEnterView from './view/config/menu/localUser/faceEnterView.js'
+import displaySettingView from './view/config/menu/systemSetting/displaySettingView.js'
+import faceRecognitionSettingView from './view/config/menu/systemSetting/faceRecognitionSettingView.js'
+import swipeCardRecognitionSettingView from './view/config/menu/systemSetting/swipeCardRecognitionSettingView.js'
+import passLogSettingView from './view/config/menu/systemSetting/passLogSettingView.js'
+import passwordOpenDoorSettingView from './view/config/menu/systemSetting/passwordOpenDoorSettingView.js'
+import passwordManagementView from './view/config/menu/systemSetting/passwordManagementView.js'
+import timeSettingView from './view/config/menu/systemSetting/timeSettingView.js'
+import systemInfoView from './view/config/menu/deviceInfo/systemInfoView.js'
+import dataCapacityInfoView from './view/config/menu/deviceInfo/dataCapacityInfoView.js'
+import recordQueryDetailView from './view/config/menu/recordQuery/recordQueryDetailView.js'
+import std from '../dxmodules/dxStd.js'
+import bus from '../dxmodules/dxEventBus.js'
+import driver from './driver.js'
+import config from '../dxmodules/dxConfig.js'
+import common from '../dxmodules/dxCommon.js'
+import configService from './service/configService.js'
+import codeService from './service/codeService.js'
+import face from '../dxmodules/dxFace.js'
+import faceService from './service/faceService.js'
+
+/**
+ * 灞忓箷绠$悊瀵硅薄
+ */
+const screen = {}
+
+/**
+ * 灞忓箷灏哄閰嶇疆
+ */
+screen.screenSize = {
+    width: 800,
+    height: 1280
+}
+
+/**
+ * UI涓婁笅鏂�
+ */
+const context = {}
+
+/**
+ * 鍒濆鍖栧睆骞曠鐞嗘ā鍧�
+ * 鍒濆鍖栨墍鏈塙I缁勪欢銆佽缃瑷�銆佸惎鍔ㄥ睆淇濊鏃跺櫒绛�
+ * 娉ㄦ剰锛氬湪main.js涓皟鐢紝鍙厑璁歌皟鐢ㄤ竴娆�
+ */
+screen.init = function () {
+    const loadMethod = dxui.loadMain
+    dxui.loadMain = function (view) {
+        if (screen.screenNow && screen.screenNow.id == view.id) {
+            return
+        }
+        screen.screenNow = view
+        pinyin.hide(true)
+        loadMethod.call(dxui, view)
+    }
+
+    dxui.init({ orientation: 0 }, context);
+    // 鍒濆鍖栨墍鏈夌粍浠�
+    pinyin.init(800, 400)
+
+    viewUtils.confirmInit()
+
+    mainView.init()
+    idleView.init()
+    topView.init()
+    appView.init()
+    pwdView.init()
+    emergencyPwdView.init()
+    newPwdView.init()
+    identityVerificationView.init()
+    configView.init()
+
+    cloudCertView.init()
+    doorControlView.init()
+    helpView.init()
+    networkSettingView.init()
+    systemSettingView.init()
+    deviceInfoView.init()
+    factoryTestView.init()
+    localUserView.init()
+    recordQueryView.init()
+    voiceBroadcastView.init()
+    dockingSettingView.init()
+
+    localUserAddView.init()
+    faceEnterView.init()
+
+    displaySettingView.init()
+    faceRecognitionSettingView.init()
+    swipeCardRecognitionSettingView.init()
+    passLogSettingView.init()
+
+
+    passwordOpenDoorSettingView.init()
+    passwordManagementView.init()
+    timeSettingView.init()
+
+    systemInfoView.init()
+    dataCapacityInfoView.init()
+    recordQueryDetailView.init()
+
+    // 璁剧疆璇█
+    // i18n.setLanguage("en-US")
+    i18n.setLanguage(config.get("base.language"))
+
+    dxui.loadMain(mainView.screenMain)
+    // dxui.loadMain(networkSettingView.screenMain)
+
+    // 鍚姩灞忎繚璁℃椂鍣�
+    idleTimerStart()
+
+    // bus浜嬩欢
+    busEvents()
+
+    // 瀹炴椂鑾峰彇鐐瑰嚮鍧愭爣
+    getClickPoint()
+
+    // 闅愯棌閿洏
+    hidePinyin()
+
+    // 浜鸿劯璺熻釜妗�
+    faceTrackingBox()
+}
+
+/**
+ * 浜鸿劯璺熻釜妗嗗鐞�
+ * 瀹氭湡鑾峰彇浜鸿劯璺熻釜鏁版嵁骞舵洿鏂拌窡韪鏄剧ず
+ */
+function faceTrackingBox() {
+    std.setInterval(() => {
+        let data = driver.face.getTrackingBox()
+        try {
+            if (data && typeof data === 'string') {
+                // 妫�鏌ユ暟鎹槸鍚︽槸鏈夋晥鐨凧SON瀛楃涓�
+                try {
+                    data = JSON.parse(data)
+                    // 鏈�澶�10涓汉
+                    if (data.type == "track" && data.faces && data.faces.length <= 10) {
+                        for (let i = 0; i < data.faces.length; i++) {
+                            let item = data.faces[i]
+                            if (item && item.rect_render && item.rect_render.length === 4) {
+                                screen.trackUpdate({ w: item.rect_render[2] - item.rect_render[0], h: item.rect_render[3] - item.rect_render[1], x: item.rect_render[0], y: item.rect_render[1] }, item.id, item.is_living)
+                            }
+                        }
+                    }
+                } catch (parseError) {
+                    log.info('screen.faceTrackingBox: 鏃犳晥鐨凧SON鏁版嵁:', data);
+                    log.error("screen.faceTrackingBox: JSON瑙f瀽閿欒:", parseError)
+                }
+            }
+        } catch (error) {
+            log.info('screen.faceTrackingBox:', data);
+            log.error("screen.faceTrackingBox:", error)
+        }
+    }, 110)
+}
+
+/**
+ * 鐐瑰嚮鍧愭爣鍙樺寲鏍囪
+ */
+let changedClickPoint
+
+/**
+ * 涓婃鐐瑰嚮鍧愭爣
+ */
+let lastClickPoint = { x: 0, y: 0 }
+
+/**
+ * 褰撳墠鐐瑰嚮鍧愭爣
+ */
+let clickPoint
+
+/**
+ * 瀹炴椂鑾峰彇鐐瑰嚮鍧愭爣
+ * 瀹氭湡鑾峰彇鐢ㄦ埛瑙︽懜灞忓箷鐨勫潗鏍囦綅缃�
+ */
+function getClickPoint() {
+    const indev = NativeObject.APP.NativeComponents.NativeIndev
+    std.setInterval(() => {
+        clickPoint = {
+            x: Math.abs(800 - indev.lvIndevGetPointVg().x),
+            y: indev.lvIndevGetPointVg().y
+        }
+
+        if (lastClickPoint.x != clickPoint.x || lastClickPoint.y != clickPoint.y) {
+            changedClickPoint = clickPoint
+        } else {
+            changedClickPoint = null
+        }
+
+        lastClickPoint = clickPoint
+    }, 5)
+}
+
+/**
+ * 闅愯棌鎷奸煶閿洏
+ * 澶勭悊鎷奸煶閿洏鐨勬樉绀哄拰闅愯棌閫昏緫锛屽綋鐢ㄦ埛鐐瑰嚮灞忓箷鍏朵粬鍖哄煙鏃惰嚜鍔ㄩ殣钘忛敭鐩�
+ */
+function hidePinyin() {
+    /**
+     * 閿洏鏄剧ず鏃剁殑鐐瑰嚮鍧愭爣
+     */
+    let showPoint
+    
+    /**
+     * 鍘熷鐨勯殣钘忔柟娉�
+     */
+    const hideMethod = pinyin.hide
+    
+    /**
+     * 鍘熷鐨勬樉绀烘柟娉�
+     */
+    const showMethod = pinyin.show
+    
+    /**
+     * 閿佸畾鏍囧織锛岄槻姝㈤噸澶嶆搷浣�
+     */
+    let lock = false
+    
+    // 閲嶅啓闅愯棌鏂规硶
+    pinyin.hide = function (isForce) {
+        if (isForce) {
+            hideMethod.call(pinyin)
+            lock = false
+            return
+        }
+        if (lock) {
+            return
+        }
+        lock = true
+        hideMethod.call(pinyin)
+        lock = false
+    }
+    
+    // 閲嶅啓鏄剧ず鏂规硶
+    pinyin.show = function (...args) {
+        if (lock) {
+            return
+        }
+        lock = true
+        showMethod.call(pinyin, ...args)
+        showPoint = clickPoint
+        lock = false
+    }
+    
+    // 瀹氭湡妫�鏌ユ槸鍚﹂渶瑕侀殣钘忛敭鐩�
+    std.setInterval(() => {
+        if (showPoint && (Math.abs(showPoint.x - clickPoint.x) > 5 && Math.abs(showPoint.y - clickPoint.y) > 5)) {
+            if (clickPoint.y < (1280 - (pinyin.getMode() == 1 ? 400 + 70 : 400))) {
+                let defocus = dxMap.get("INPUT_KEYBOARD").get("defocus")
+                if (defocus == "defocus") {
+                    dxMap.get("INPUT_KEYBOARD").del("defocus")
+                    showPoint = null
+                    pinyin.hide()
+                }
+            }
+        }
+    }, 5)
+}
+
+/**
+ * 灞忓箷绠$悊鍣ㄧ被
+ * 璐熻矗灞忓箷鐘舵�佺鐞嗭紝鍖呮嫭灞忎繚鍜岀唲灞忓姛鑳�
+ */
+class ScreenManager {
+    /**
+     * 鏋勯�犲嚱鏁�
+     * @param {object} callbacks - 鍥炶皟鍑芥暟瀵硅薄
+     */
+    constructor(callbacks = {}) {
+        /**
+         * 瀹氭椂鍣ㄥ璞�
+         */
+        this.timers = {
+            screenSaver: null, // 灞忎繚瀹氭椂鍣�
+            screenOff: null    // 鐔勫睆瀹氭椂鍣�
+        };
+
+        /**
+         * 閰嶇疆瀵硅薄
+         */
+        this.config = {
+            screenSaverDelay: 0, // 灞忎繚寤惰繜锛堟绉掞級
+            screenOffDelay: 0    // 鐔勫睆寤惰繜锛堟绉掞級
+        };
+
+        /**
+         * 鍥炶皟鍑芥暟
+         */
+        this.callbacks = {
+            onScreenSaverStart: callbacks.onScreenSaverStart || (() => { }),
+            onScreenSaverEnd: callbacks.onScreenSaverEnd || (() => { }),
+            onScreenOff: callbacks.onScreenOff || (() => { }),
+            onScreenOn: callbacks.onScreenOn || (() => { })
+        };
+
+        this.resetTimers = this.resetTimers.bind(this);
+    }
+
+    /**
+     * 閰嶇疆鏃堕棿
+     * @param {number} screenSaverDelay - 灞忎繚寤惰繜锛堟绉掞級
+     * @param {number} screenOffDelay - 鐔勫睆寤惰繜锛堟绉掞級
+     */
+    configure({ screenSaverDelay = 0, screenOffDelay = 0 }) {
+        this.config.screenSaverDelay = screenSaverDelay;
+        this.config.screenOffDelay = screenOffDelay;
+        this.resetTimers();
+    }
+
+    /**
+     * 閲嶇疆瀹氭椂鍣�
+     * 娓呴櫎鐜版湁瀹氭椂鍣ㄥ苟璁剧疆鏂扮殑瀹氭椂鍣�
+     */
+    resetTimers() {
+        // 娓呴櫎鐜版湁瀹氭椂鍣�
+        if (this.timers.screenSaver) {
+            std.clearTimeout(this.timers.screenSaver);
+        }
+        if (this.timers.screenOff) {
+            std.clearTimeout(this.timers.screenOff);
+        }
+
+        // 閫�鍑哄綋鍓嶇姸鎬�
+        this.exitScreenStates();
+
+        // 璁剧疆鏂扮殑瀹氭椂鍣�
+        if (this.config.screenOffDelay > 0) {
+            this.timers.screenOff = std.setTimeout(() => {
+                this.enterScreenOff();
+            }, this.config.screenOffDelay);
+        }
+
+        // 鍙湁褰撶唲灞忔椂闂村ぇ浜庡睆淇濇椂闂存椂鎵嶈缃睆淇濆畾鏃跺櫒
+        if (this.config.screenSaverDelay > 0 &&
+            (this.config.screenSaverDelay < this.config.screenOffDelay || this.config.screenOffDelay == 0)) {
+            this.timers.screenSaver = std.setTimeout(() => {
+                this.enterScreenSaver();
+            }, this.config.screenSaverDelay);
+        }
+    }
+
+    /**
+     * 杩涘叆灞忎繚鐘舵��
+     */
+    enterScreenSaver() {
+        const mapUI = dxMap.get("UI")
+        if (!mapUI.get("isScreenOff")) {
+            mapUI.put("isScreenSaver", true)
+            this.callbacks.onScreenSaverStart();
+        }
+    }
+
+    /**
+     * 杩涘叆鐔勫睆鐘舵��
+     */
+    enterScreenOff() {
+        const mapUI = dxMap.get("UI")
+        mapUI.put("isScreenOff", true)
+        mapUI.put("isScreenSaver", false)
+        this.callbacks.onScreenOff();
+    }
+
+    /**
+     * 閫�鍑烘墍鏈夊睆骞曠姸鎬�
+     */
+    exitScreenStates() {
+        const mapUI = dxMap.get("UI")
+        const previousState = { isScreenOff: mapUI.get("isScreenOff"), isScreenSaver: mapUI.get("isScreenSaver") };
+        mapUI.put("isScreenOff", false)
+        mapUI.put("isScreenSaver", false)
+        // 濡傛灉鐘舵�佸彂鐢熸敼鍙橈紝瑙﹀彂鐩稿簲鍥炶皟
+        if (previousState.isScreenSaver) {
+            this.callbacks.onScreenSaverEnd();
+        }
+        if (previousState.isScreenOff) {
+            this.callbacks.onScreenOn();
+        }
+    }
+
+    /**
+     * 鑾峰彇褰撳墠鐘舵��
+     * @returns {object} 褰撳墠灞忓箷鐘舵��
+     */
+    getState() {
+        const mapUI = dxMap.get("UI")
+        return { isScreenOff: mapUI.get("isScreenOff"), isScreenSaver: mapUI.get("isScreenSaver") };
+    }
+
+    /**
+     * 娓呯悊璧勬簮
+     * 娓呴櫎鎵�鏈夊畾鏃跺櫒
+     */
+    destroy() {
+        if (this.timers.screenSaver) {
+            std.clearTimeout(this.timers.screenSaver);
+        }
+        if (this.timers.screenOff) {
+            std.clearTimeout(this.timers.screenOff);
+        }
+    }
+}
+
+/**
+ * 灞忓箷绠$悊鍣ㄥ疄渚�
+ */
+let screenManager
+
+/**
+ * 鍚姩灞忎繚璁℃椂鍣�
+ * 鍒濆鍖栧睆骞曠鐞嗗櫒锛岃缃睆淇濆拰鐔勫睆鏃堕棿锛屾娴嬬敤鎴疯Е鎽�
+ */
+function idleTimerStart() {
+    // 鍒涘缓瀹炰緥锛屼紶鍏ュ洖璋冨嚱鏁�
+    screenManager = new ScreenManager({
+        /**
+         * 灞忎繚寮�濮嬪洖璋�
+         */
+        onScreenSaverStart: () => {
+            screen.enterIdle()
+        },
+        
+        /**
+         * 灞忎繚缁撴潫鍥炶皟
+         */
+        onScreenSaverEnd: () => {
+            screen.exitIdle(true)
+        },
+        
+        /**
+         * 鐔勫睆鍥炶皟
+         */
+        onScreenOff: () => {
+            dxMap.get("screenOff").put("status", 1)
+            // 鍋滄浜鸿劯璇嗗埆
+            driver.face.status(false)
+            screen.screenNow.hide()
+            topView.screenMain.hide()
+        },
+        
+        /**
+         * 浜睆鍥炶皟
+         */
+        onScreenOn: () => {
+            screen.exitIdle(true)
+            dxMap.get("screenOff").put("status", 0)
+            // 鎭㈠浜鸿劯璇嗗埆
+            driver.face.status(true)
+            screen.screenNow.show()
+            topView.screenMain.show()
+            
+            // 閫�鍑虹唲灞忔椂鑾峰彇骞舵洿鏂版皵浣撴祿搴﹀拰鐘舵�佷俊鎭�
+            try {
+                log.info('[screen]: 閫�鍑虹唲灞忥紝鑾峰彇姘斾綋娴撳害鍜岀姸鎬佷俊鎭�')
+                grainService.checkGasConcentration()
+                grainService.checkDevConcentration()
+            } catch (error) {
+                log.error(`[screen]: 鑾峰彇姘斾綋娴撳害鍜岀姸鎬佷俊鎭敊璇�: ${error.message}`)
+            }
+        }
+    });
+
+    // 閰嶇疆鏃堕棿锛堟绉掞級
+    screenManager.configure({
+        // screenSaverDelay: 10000,  // 灞忎繚
+        // screenOffDelay: 5000     // 鐔勫睆
+        screenSaverDelay: config.get("base.screensaver") * 60 * 1000,  // 灞忎繚
+        screenOffDelay: config.get("base.screenOff") * 60 * 1000     // 鐔勫睆
+    });
+
+    // 妫�娴嬬敤鎴疯Е鎽�
+    let touchCount = 0
+    std.setInterval(() => {
+        let count = dxui.Utils.GG.NativeDisp.lvDispGetInactiveTime()
+        if (count < touchCount) {
+            screenManager.resetTimers();
+        }
+        touchCount = count
+    }, 100);
+}
+
+/**
+ * 鍒锋柊灞忓箷绠$悊鍣ㄩ厤缃�
+ * 鏇存柊灞忎繚鍜岀唲灞忔椂闂撮厤缃�
+ */
+screen.screenManagerRefresh = function () {
+    screenManager.configure({
+        screenSaverDelay: config.get("base.screensaver") * 60 * 1000,  // 灞忎繚
+        screenOffDelay: config.get("base.screenOff") * 60 * 1000     // 鐔勫睆
+    });
+    screenManager.resetTimers();
+}
+
+/**
+ * 杩涘叆灞忎繚瀹氭椂鍣�
+ */
+let enterIdleTimer
+
+/**
+ * 杩涘叆灞忎繚
+ * 鏄剧ず灞忎繚鐣岄潰
+ */
+screen.enterIdle = function () {
+    // 寤惰繜1绉掞紝闃叉杩涘叆灞忎繚鍜岄��鍑哄睆淇濆悓鏃惰Е鍙戯紝1绉掑唴娌℃湁瑙﹀彂閫�鍑哄睆淇濓紝鍒欒涓鸿繘鍏ュ睆淇�
+    enterIdleTimer = std.setTimeout(() => {
+        if (idleView.screenMain.isHide()) {
+            viewUtils.confirmClose()
+            dxui.loadMain(mainView.screenMain)
+            idleView.screenMain.show()
+            topView.changeTheme(false)
+        }
+    }, 1000)
+}
+
+/**
+ * 閫�鍑哄睆淇�
+ * 闅愯棌灞忎繚鐣岄潰
+ * @param {boolean} isSelf - 鏄惁鐢辩郴缁熻嚜韬Е鍙�
+ */
+screen.exitIdle = function (isSelf) {
+    if (enterIdleTimer) {
+        std.clearTimeout(enterIdleTimer)
+        enterIdleTimer = null
+    }
+    if (!isSelf) {
+        screenManager.resetTimers();
+    }
+    if (!idleView.screenMain.isHide()) {
+        idleView.screenMain.hide()
+    }
+}
+
+/**
+ * 灞忓箷寰幆澶勭悊
+ * 澶勭悊UI浜嬩欢
+ * @returns {boolean} 澶勭悊缁撴灉
+ */
+screen.loop = function () {
+    return dxui.handler()
+}
+
+/**
+ * 浜戣瘉婵�娲�
+ * 婵�娲荤數瀛愯韩浠借瘉
+ * @param {string} code - 婵�娲荤爜
+ * @returns {number} 婵�娲荤粨鏋滐紝0琛ㄧず鎴愬姛锛岄潪0琛ㄧず澶辫触
+ */
+screen.nfcIdentityCardActivation = function (code) {
+    return driver.eid.active(config.get("sys.sn"), config.get("sys.appVersion"), config.get("sys.mac"), code);
+
+}
+
+/**
+ * 鍒犻櫎浜哄憳
+ * 鍒犻櫎鐢ㄦ埛淇℃伅銆佹潈闄愩�佸嚟璇佸拰浜鸿劯鏁版嵁
+ * @param {object} user - 鐢ㄦ埛瀵硅薄
+ * @returns {boolean} 鍒犻櫎缁撴灉
+ */
+screen.deleteUser = function (user) {
+    // 鍒犻櫎浜哄憳淇℃伅
+    sqliteService.d1_person.deleteByUserId(user.userId)
+    // 鍒犻櫎鏉冮檺淇℃伅
+    sqliteService.d1_permission.deleteByUserId(user.userId)
+    // 鍒犻櫎鍑瘉淇℃伅
+    sqliteService.d1_voucher.deleteByUserId(user.userId)
+    // 鍒犻櫎浜鸿劯鏁版嵁
+    let res = driver.face.delete(user.userId)
+
+    return true
+}
+
+/**
+ * 鏇存柊浜哄憳淇℃伅
+ * 鏇存柊鐢ㄦ埛淇℃伅銆佸瘑鐮併�佸崱鐗囧拰浜鸿劯鏁版嵁
+ * @param {object} user - 鐢ㄦ埛瀵硅薄
+ * @returns {boolean|string} 鏇存柊缁撴灉锛屾垚鍔熻繑鍥瀟rue锛屽け璐ヨ繑鍥為敊璇俊鎭�
+ */
+screen.updateUser = function (user) {
+    //淇敼浜哄憳淇℃伅
+    let res = sqliteService.d1_person.updatenameAndExtraByUserId(user.userId, user.name, JSON.stringify({ type: user.type, idCard: user.idCard }))
+    if (res != 0) {
+        return false
+    }
+    
+    //澶勭悊鍑瘉
+    let ret
+    
+    //澶勭悊瀵嗙爜鍑瘉
+    if (user.pwd) {
+        //鍒ゆ柇搴撹〃鏄惁瀛樺湪杩欎釜鍑瘉
+        let pwdData = sqliteService.d1_voucher.findByCodeAndType(user.pwd, "400");
+        if (pwdData.length > 0 && pwdData[0].userId != user.userId) {
+            //瀛樺湪涓嶈兘娣诲姞杩斿洖澶辫触
+            log.info("瀵嗙爜閲嶅");
+            return "localUserAddView.failPwdRepeat"
+        }
+        //鏌ヨ鏄惁鏈夊瘑鐮佸嚟璇佹湁鏇存柊娌℃湁鏂板
+        let countByuserIdAndType = sqliteService.d1_voucher.findByuserIdAndType(user.userId, "400");
+        if (countByuserIdAndType.length > 0) {
+            ret = sqliteService.d1_voucher.updatecodeByuserIdAndtype(user.userId, "400", user.pwd)
+            if (ret != 0) {
+                return false
+            }
+        } else {
+            //鏂板涓�涓�
+            ret = sqliteService.d1_voucher.save({ keyId: std.genRandomStr(32), type: "400", code: user.pwd, userId: user.userId })
+            if (ret != 0) {
+                return false
+            }
+        }
+    } else {
+        //娌℃湁鍐呭鍘绘暟鎹簱琛ㄥ垹闄や竴涓�
+        sqliteService.d1_voucher.deleteByuserIdAndtype(user.userId, "400")
+    }
+    
+    //澶勭悊鍗$墖鍑瘉
+    if (user.card) {
+        //鍒ゆ柇搴撹〃鏄惁瀛樺湪杩欎釜鍑瘉
+        let cardData = sqliteService.d1_voucher.findByCodeAndType(user.card, "200");
+        if (cardData.length > 0 && cardData[0].userId != user.userId) {
+            //瀛樺湪涓嶈兘娣诲姞杩斿洖澶辫触
+            log.info("鍗¢噸澶�");
+            return "localUserAddView.failCardRepeat"
+        }
+        //鏌ヨ鏄惁鏈夊瘑鐮佸嚟璇佹湁鏇存柊娌℃湁鏂板
+        let countByuserIdAndType = sqliteService.d1_voucher.countByuserIdAndType(user.userId, "200");
+        if (countByuserIdAndType > 0) {
+            ret = sqliteService.d1_voucher.updatecodeByuserIdAndtype(user.userId, "200", user.card)
+            if (ret != 0) {
+                return false
+            }
+        } else {
+            //鏂板涓�涓�
+            ret = sqliteService.d1_voucher.save({ keyId: std.genRandomStr(32), type: "200", code: user.card, userId: user.userId })
+
+            if (ret != 0) {
+                return false
+            }
+        }
+    } else {
+        //娌℃湁鍐呭鍘绘暟鎹簱琛ㄥ垹闄や竴涓�
+        sqliteService.d1_voucher.deleteByuserIdAndtype(user.userId, "200")
+    }
+    
+    //澶勭悊浜鸿劯鍑瘉
+    if (user.face) {
+        let findByuserIdAndType = sqliteService.d1_voucher.findByuserIdAndType(user.userId, "300");
+        if (findByuserIdAndType.length <= 0) {
+            let ret = driver.face.registerFaceByPicFile(user.userId, user.face)
+            log.info("2娉ㄥ唽浜鸿劯,ret:", ret)
+            if (ret != 0) {
+                return faceService.regErrorEnum.picture[ret + '']
+            }
+            //娉ㄥ唽鎴愬姛鍚庨渶瑕佸惂鍘熸潵鍥剧墖绉诲姩鍒� user 瀵瑰簲鐩綍涓�
+            let src = "/app/data/user/" + user.userId + "/register.jpg"
+            std.ensurePathExists(src)
+            common.systemBrief('mv ' + user.face + " " + src)
+
+            //鏂板涓�涓�
+            ret = sqliteService.d1_voucher.save({ keyId: std.genRandomStr(32), type: "300", code: src, userId: user.userId })
+            if (ret != 0) {
+                return false
+            }
+        } else {
+            //鍘熸潵鏈夊張浼犲叆 鍏堝垹闄ゅ悗鏂板
+            if (findByuserIdAndType[0].code != user.face) {
+                //鍒犻櫎鑰佷汉鑴�
+                driver.face.delete(user.userId)
+                //娉ㄥ唽鏂颁汉鑴�
+                let res = driver.face.registerFaceByPicFile(user.userId, user.face)
+                log.info("3娉ㄥ唽浜鸿劯,res:", res)
+                if (res != 0) {
+                    return faceService.regErrorEnum.picture[res + '']
+                }
+                let src = "/app/data/user/" + user.userId + "/register.jpg"
+                std.ensurePathExists(src)
+                //鎶婁复鏃剁洰褰曚汉鑴哥Щ鍔ㄥ埌 user 瀵瑰簲鐨勬枃浠跺す涓�
+                common.systemBrief('mv ' + user.face + " " + src)
+                ret = sqliteService.d1_voucher.updatecodeAndExtraByuserIdAndtype(user.userId, "300", src, JSON.stringify({ faceType: 0 }))
+
+            }
+        }
+    } else {
+        //娌℃湁鍐呭鍘绘暟鎹簱琛ㄥ垹闄や竴涓�
+        sqliteService.d1_voucher.deleteByuserIdAndtype(user.userId, "300")
+        driver.face.delete(user.userId)
+        common.systemBrief("rm -rf /app/data/user/" + user.userId)
+    }
+
+    return true
+}
+
+/**
+ * 鏂板浜哄憳
+ * 娣诲姞鏂扮敤鎴蜂俊鎭�佸瘑鐮併�佸崱鐗囧拰浜鸿劯鏁版嵁
+ * @param {object} user - 鐢ㄦ埛瀵硅薄
+ * @returns {boolean|string} 娣诲姞缁撴灉锛屾垚鍔熻繑鍥瀟rue锛屽け璐ヨ繑鍥為敊璇俊鎭�
+ */
+screen.insertUser = async function (user) {
+    /**
+     * 淇濆瓨鍑瘉
+     * @param {string} type - 鍑瘉绫诲瀷
+     * @param {string} code - 鍑瘉浠g爜
+     * @returns {boolean|string} 淇濆瓨缁撴灉
+     */
+    const saveVoucher = async (type, code) => {
+        // 妫�鏌ュ崱鐗囧嚟璇佹槸鍚﹂噸澶�
+        if (type == "200") {
+            let cardData = sqliteService.d1_voucher.findByCodeAndType(code, "200");
+            if (cardData.length > 0 && cardData[0].userId != user.userId) {
+                //瀛樺湪涓嶈兘娣诲姞杩斿洖澶辫触
+                log.info("鍗¢噸澶�");
+                return "localUserAddView.failCardRepeat"
+            }
+        }
+        
+        // 褰� type 涓� "300" 鏃讹紝棣栧厛璋冪敤鐗瑰畾鏂规硶妫�鏌ユ槸鍚﹀彲浠ョ户缁繚瀛樺嚟璇�
+        if (type === "300") {
+            let preCheckResult = await preSaveCheck(code); // 鍋囪杩欐槸鎮ㄦ彁鍒扮殑闇�瑕佽皟鐢ㄧ殑鏂规硶
+            if (preCheckResult !== true) { // 濡傛灉棰勬鏌ヤ笉閫氳繃锛屽垯鐩存帴杩斿洖 false
+                return preCheckResult;
+            }
+            code = "/app/data/user/" + user.userId + "/register.jpg"
+        }
+
+        // 妫�鏌ュ瘑鐮佸嚟璇佹槸鍚﹂噸澶�
+        if (type == "400") {
+            let pwdData = sqliteService.d1_voucher.findByCodeAndType(code, "400");
+            if (pwdData.length > 0 && pwdData[0].userId != user.userId) {
+                //瀛樺湪涓嶈兘娣诲姞杩斿洖澶辫触
+                log.info("瀵嗙爜閲嶅");
+                return "localUserAddView.failPwdRepeat"
+            }
+        }
+
+        let keyId = std.genRandomStr(32);
+
+        let extra = type == 300 ? JSON.stringify({ faceType: 0 }) : JSON.stringify({})
+        let voucherRet = await sqliteService.d1_voucher.save({
+            keyId: keyId,
+            type: type,
+            code: code,
+            userId: user.userId,
+            extra: extra
+        });
+
+        if (voucherRet != 0) {
+            // 濡傛灉鍑瘉淇濆瓨澶辫触锛屽垯鍒犻櫎宸蹭繚瀛樼殑鐢ㄦ埛淇℃伅鍙婂彲鑳藉凡淇濆瓨鐨勫叾浠栧嚟璇�
+            await sqliteService.d1_person.deleteByUserId(user.userId);
+            await sqliteService.d1_voucher.deleteByUserId(user.userId);
+            return false;
+        }
+        return true;
+    };
+    
+    /**
+     * 淇濆瓨鍓嶆鏌�
+     * @param {string} code - 浜鸿劯鍥剧墖璺緞
+     * @returns {boolean|string} 妫�鏌ョ粨鏋�
+     */
+    async function preSaveCheck(code) {
+        let ret = driver.face.registerFaceByPicFile(user.userId, code)
+        log.info("1娉ㄥ唽浜鸿劯,ret:", ret)
+        if (ret != 0) {
+            return faceService.regErrorEnum.picture[ret + '']
+        }
+        //娉ㄥ唽鎴愬姛鍚庨渶瑕佸惂鍘熸潵鍥剧墖绉诲姩鍒� user 瀵瑰簲鐩綍涓�
+        let src = "/app/data/user/" + user.userId + "/register.jpg"
+        std.ensurePathExists(src)
+        common.systemBrief('mv ' + code + " " + src)
+        return true;
+    }
+
+    let success = true;
+    // 淇濆瓨浜鸿劯鍑瘉
+    if (success === true && user.face && !(success = await saveVoucher("300", user.face)));
+    // 淇濆瓨瀵嗙爜鍑瘉
+    if (success === true && user.pwd && !(success = await saveVoucher("400", user.pwd)));
+    // 淇濆瓨鍗$墖鍑瘉
+    if (success === true && user.card && !(success = await saveVoucher("200", user.card)));
+
+    if (success === true) {
+        //{"id":"423","userId":"423","name":"寰厜浜掕仈","idCard":"123","pwd":"251574","card":"123"}
+        //淇濆瓨浜哄憳淇℃伅
+        let personRet = await sqliteService.d1_person.save({
+            userId: user.userId,
+            name: user.name,
+            extra: JSON.stringify({ type: user.type == 1 ? 1 : 0, idCard: user.idCard })
+        });
+        if (personRet != 0) {
+            sqliteService.d1_voucher.deleteByUserId(user.userId);
+            return "localUserAddView.failRepeat"
+        }
+        //鏂板涓�鏉℃案涔呮潈闄�
+        sqliteService.d1_permission.save({ permissionId: user.userId, userId: user.userId, timeType: 0 })
+    } else {
+        await sqliteService.d1_voucher.deleteByUserId(user.userId);
+    }
+
+    return success;
+
+}
+
+/**
+ * 鑾峰彇鏈湴浜哄憳淇℃伅
+ * 鑾峰彇鐢ㄦ埛鐨勫嚟璇佷俊鎭紝鍖呮嫭韬唤璇併�佸崱鐗囥�佸瘑鐮佸拰浜鸿劯鏁版嵁
+ * @param {string} userId - 鐢ㄦ埛ID
+ * @returns {object} 鐢ㄦ埛鍑瘉淇℃伅
+ */
+screen.getVoucher = function (userId) {
+    // 鑾峰彇鐢ㄦ埛淇℃伅
+    let person = sqliteService.d1_person.find({ userId: userId });
+
+    if (person.length < 0) {
+        return
+    }
+    
+    // 鑾峰彇瀵嗙爜鍑瘉
+    let pwd_voucher = sqliteService.d1_voucher.find({ userId: userId, type: "400" })[0] || undefined
+    
+    // 鑾峰彇鍗$墖鍑瘉
+    let card_voucher = sqliteService.d1_voucher.find({ userId: userId, type: "200" })[0] || undefined
+    
+    // 鑾峰彇浜鸿劯鍑瘉
+    let face_voucher = sqliteService.d1_voucher.find({ userId: userId, type: "300" })[0] || undefined
+    
+    // 鑾峰彇韬唤璇佷俊鎭�
+    let idCard_voucher
+    try {
+        idCard_voucher = JSON.parse(person[0].extra).idCard
+    } catch (error) {
+    }
+
+    return {
+        id: userId,
+        idCard: idCard_voucher ? idCard_voucher : undefined,
+        card: card_voucher ? card_voucher.code : undefined,
+        pwd: pwd_voucher ? pwd_voucher.code : undefined,
+        face: face_voucher ? face_voucher.code : undefined,
+        type: JSON.parse(person[0].extra).type || 0
+    }
+
+}
+
+/**
+ * 鑾峰彇鐢ㄦ埛鍒楄〃
+ * 鏍规嵁鏉′欢鏌ヨ鐢ㄦ埛鍒楄〃锛屾敮鎸佸垎椤靛拰鎼滅储
+ * @param {number} page - 椤电爜锛岄粯璁�0
+ * @param {number} size - 姣忛〉澶у皬锛岄粯璁�6
+ * @param {string} userId - 鐢ㄦ埛ID锛岀敤浜庣簿纭悳绱�
+ * @param {string} name - 鐢ㄦ埛濮撳悕锛岀敤浜庢ā绯婃悳绱�
+ * @returns {object} 鐢ㄦ埛鍒楄〃鏁版嵁锛屽寘鍚垎椤典俊鎭�
+ */
+screen.getUsers = function (page = 0, size = 6, userId, name) {
+    // 鎸夌敤鎴稩D鎴栧鍚嶆悳绱�
+    if (userId || name) {
+        // 鎸夌敤鎴稩D鎼滅储
+        let user = sqliteService.d1_person.findByUserId(userId)[0]
+        if (user) {
+            user.id = user.userId
+            return { data: [user], totalPage: 1, totalSize: 1, currentPage: 1 }
+        }
+        // 鎸夌敤鎴峰鍚嶆悳绱�
+        let users = sqliteService.d1_person.findByName(name)
+        if (users && users.length > 0) {
+            users.map(v => {
+                v.id = v.userId
+            })
+            
+            /**
+             * 鏁扮粍鍒嗗潡
+             * @param {array} arr - 婧愭暟缁�
+             * @param {number} size - 鍧楀ぇ灏�
+             * @returns {array} 鍒嗗潡鍚庣殑鏁扮粍
+             */
+            function chunkArray(arr, size) {
+                // 濡傛灉鏁扮粍涓虹┖鎴栬�呭ぇ灏忎负闆讹紝杩斿洖绌烘暟缁�
+                if (arr.length === 0 || size <= 0) {
+                    return [];
+                }
+                const result = [];
+                // 浣跨敤寰幆閬嶅巻鏁扮粍锛屽苟鎸夌収澶у皬鍒囧壊
+                for (let i = 0; i < arr.length; i += size) {
+                    result.push(arr.slice(i, i + size));  // slice 鎴彇鎸囧畾鑼冨洿鐨勫厓绱�
+                }
+                return result;
+            }
+            
+            const chunkedArray = chunkArray(users, size);
+            return { data: chunkedArray[page], totalPage: Math.ceil(users.length / size), totalSize: users.length, currentPage: page + 1 }
+        }
+        return { data: [], totalPage: 0, totalSize: 0, currentPage: 1 }
+    }
+    
+    // 鑾峰彇鎵�鏈夌敤鎴�
+    let userCount = sqliteService.d1_person.count()
+    let users = sqliteService.d1_person.findOrderByUserIdAsc({ page, size })
+    if (users.length > 0) {
+        users.forEach(element => { element.id = element.userId });
+    }
+    // 鎬婚〉鏁�
+    let totalPage = Math.ceil(userCount / size)
+    return { data: users, totalPage: totalPage, totalSize: userCount, currentPage: page + 1 }
+}
+
+/**
+ * 鑾峰彇閫氳璁板綍
+ * 鑾峰彇鐢ㄦ埛閫氳璁板綍锛屾敮鎸佸垎椤�
+ * @param {number} page - 椤电爜锛岄粯璁�0
+ * @param {number} size - 姣忛〉澶у皬锛岄粯璁�6
+ * @returns {object} 閫氳璁板綍鏁版嵁锛屽寘鍚垎椤典俊鎭�
+ */
+screen.getPassRecord = function (page = 0, size = 6) {
+    let passCount = sqliteService.d1_pass_record.count()
+    let datas = sqliteService.d1_pass_record.findOrderByTimeDesc({ page, size })
+    // 鎬婚〉鏁�
+    let totalPage = Math.ceil(passCount / size)
+    return { data: datas, totalPage: totalPage, totalSize: passCount, currentPage: page + 1 }
+}
+
+/**
+ * 浜鸿劯褰曞叆寮�濮�
+ * 寮�濮嬩汉鑴稿綍鍏ワ紝UI鎺у埗
+ * @param {string} userId - 鐢ㄦ埛ID
+ */
+screen.faceEnterStart = function (userId) {
+    dxMap.get("UI").put("faceEnterStart", userId)
+    driver.face.status(1)
+    driver.face.mode(1)
+}
+
+/**
+ * 浜鸿劯褰曞叆缁撴潫
+ * 缁撴潫浜鸿劯褰曞叆锛孶I鎺у埗
+ */
+screen.faceEnterEnd = function () {
+    dxMap.get("UI").del("faceEnterStart")
+    driver.face.status(0)
+    // driver.face.mode(0)
+}
+
+/**
+ * 鑾峰彇鍗″彿寮�濮�
+ * 寮�濮嬭幏鍙栧崱鍙凤紝UI鎺у埗
+ */
+screen.getCardStart = function () {
+    dxMap.get("UI").put("getCardStart", true)
+}
+
+/**
+ * 鑾峰彇鍗″彿缁撴潫
+ * 缁撴潫鑾峰彇鍗″彿锛孶I鎺у埗
+ */
+screen.endCardEnd = function () {
+    dxMap.get("UI").del("getCardStart")
+}
+
+/**
+ * 寮�鍚汉鑴歌瘑鍒�
+ * 寮�濮嬩汉鑴歌瘑鍒姛鑳�
+ */
+screen.faceRecgStart = function () {
+    driver.face.status(1)
+    driver.face.mode(0)
+}
+
+/**
+ * 浜鸿劯璇嗗埆鏆傚仠
+ * 鏆傚仠浜鸿劯璇嗗埆鍔熻兘
+ */
+screen.faceRecgPause = function () {
+    driver.face.status(0)
+}
+
+/**
+ * 浜鸿劯褰曞叆缁撴灉
+ * 澶勭悊浜鸿劯褰曞叆缁撴灉
+ * @param {string} facePic - 浜鸿劯鍥剧墖璺緞
+ */
+screen.faceEnterResult = function (facePic) {
+    if (facePic) {
+        faceEnterView.successFlag = true
+        // 鎴愬姛锛屾樉绀轰汉鑴哥収鐗�
+        localUserAddView.addFace(facePic)
+        dxui.loadMain(localUserAddView.screenMain)
+        faceEnterView.backCb()
+    } else {
+        // 澶辫触锛屾姤閿�
+        faceEnterView.timeout()
+    }
+}
+
+/**
+ * 闈炶瘑鍒〉闈汉鑴歌璇佸紑濮�
+ * 寮�濮嬩汉鑴歌璇侊紝UI鎺у埗
+ */
+screen.faceAuthStart = function () {
+    dxMap.get("UI").put("faceAuthStart", "Y")
+    driver.face.status(1)
+    driver.face.mode(0)
+}
+
+/**
+ * 闈炶瘑鍒〉闈汉鑴歌璇佺粨鏉�
+ * 缁撴潫浜鸿劯璁よ瘉锛孶I鎺у埗
+ */
+screen.faceAuthEnd = function () {
+    dxMap.get("UI").del("faceAuthStart")
+    driver.face.status(0)
+}
+
+/**
+ * 闈炶瘑鍒〉闈汉鑴歌璇佺粨鏋�
+ * 澶勭悊浜鸿劯璁よ瘉缁撴灉
+ * @param {boolean} bool - 璁よ瘉缁撴灉锛宼rue琛ㄧず鎴愬姛锛宖alse琛ㄧず澶辫触
+ */
+screen.faceAuthResult = function (bool) {
+    if (bool) {
+        // 鎴愬姛锛岃繘鍏ヨ缃彍鍗�
+        driver.alsa.play(`/app/code/resource/${config.get("base.language") == "CN" ? "CN" : "EN"}/wav/recg_s.wav`)
+        dxui.loadMain(configView.screenMain)
+    } else {
+        // 澶辫触锛屾姤閿�
+        driver.alsa.play(`/app/code/resource/${config.get("base.language") == "CN" ? "CN" : "EN"}/wav/recg_f.wav`)
+        identityVerificationView.statusPanel.fail()
+    }
+}
+
+/**
+ * 淇濆瓨閰嶇疆
+ * 淇濆瓨绯荤粺閰嶇疆
+ * @param {object} configAll - 閰嶇疆瀵硅薄
+ * @returns {boolean} 淇濆瓨缁撴灉
+ */
+screen.saveConfig = function (configAll) {
+    // 鐩存帴璋冪敤閰嶇疆楠岃瘉鍜屼繚瀛樺嚱鏁�
+    return configService.configVerifyAndSave(configAll)
+}
+
+/**
+ * 鑾峰彇閰嶇疆
+ * 鑾峰彇绯荤粺閰嶇疆
+ * @returns {object} 閰嶇疆瀵硅薄
+ */
+screen.getConfig = function () {
+    let config1 = config.getAll()
+    return config1
+}
+
+/**
+ * 瀵嗙爜閫氳
+ * 浣跨敤瀵嗙爜杩涜閫氳楠岃瘉
+ * @param {string} pwd - 瀵嗙爜
+ * @returns {boolean} 楠岃瘉缁撴灉锛宼rue琛ㄧず鎴愬姛锛宖alse琛ㄧず澶辫触
+ */
+screen.pwdAccess = function (pwd) {
+    // 妫�鏌ユ暟鎹簱涓殑搴旀�ュ紑浠撳瘑鐮�
+    try {
+        const passwords = sqliteService.d1_emergency_password.findAll({ status: 1 })
+        for (let i = 0; i < passwords.length; i++) {
+            if (passwords[i].password === pwd) {
+                return true
+            }
+        }
+    } catch (error) {
+        logger.error('妫�鏌ュ簲鎬ュ紑浠撳瘑鐮佸け璐�:', error)
+    }
+    
+    // 鍏朵粬瀵嗙爜楠岃瘉閫昏緫
+    bus.fire("access", { data: { type: "400", code: pwd } })
+    return false
+}
+
+/**
+ * 鍒囨崲缃戠粶绫诲瀷
+ * 鍒囨崲缃戠粶杩炴帴绫诲瀷
+ * @param {object} data - 缃戠粶绫诲瀷鏁版嵁
+ */
+screen.switchNetworkType = function (data) {
+    bus.fire("switchNetworkType", data)
+}
+
+/**
+ * 鑾峰彇WiFi鍒楄〃
+ * 鑾峰彇鍙敤鐨刉iFi缃戠粶鍒楄〃
+ */
+screen.netGetWifiSsidList = function () {
+    bus.fire("netGetWifiSsidList")
+}
+
+/**
+ * WiFi鍒楄〃鏁版嵁
+ * 澶勭悊WiFi鍒楄〃鏁版嵁
+ * @param {array} data - WiFi鍒楄〃鏁版嵁
+ */
+screen.netWifiSsidList = function (data) {
+    if (data.length == 0 && config.get("net.type") == 2) {
+        //鏃犵嚎缃�
+        std.setTimeout(() => {
+            screen.netGetWifiSsidList()
+        }, 1000)
+        return
+    }
+    networkSettingView.wifiListData = data
+    networkSettingView.wifiList.refresh()
+}
+
+/**
+ * 杩炴帴WiFi
+ * 杩炴帴鍒版寚瀹氱殑WiFi缃戠粶
+ * @param {string} ssid - WiFi鍚嶇О
+ * @param {string} psk - WiFi瀵嗙爜
+ * @returns {boolean} 杩炴帴缁撴灉
+ */
+screen.netConnectWifiSsid = function (ssid, psk) {
+    return driver.net.netConnectWifiSsid(ssid, psk)
+}
+
+/**
+ * 鑾峰彇鍗″彿
+ * 澶勭悊鑾峰彇鍒扮殑鍗″彿
+ * @param {string} card - 鍗″彿
+ */
+screen.getCard = function (card) {
+    localUserAddView.cardBoxInput.text(card)
+}
+
+/**
+ * 浜嬩欢鎬荤嚎浜嬩欢澶勭悊
+ * 娉ㄥ唽鍜屽鐞嗙郴缁熶簨浠�
+ */
+function busEvents() {
+    // 缃戠粶鐘舵��
+    bus.on('netStatus', (data) => {
+        console.log(JSON.stringify(data));
+        let type = config.get("net.type")
+        if (data.connected) {
+            let ip = net.getModeByCard(type).param.ip
+            mainView.overlayIpLbl.text("IP:" + ip)
+            config.setAndSave("net.ip", ip)
+            config.setAndSave("net.mac", net.getMacaddr(type))
+            topView.ethConnectState(true, type)
+            networkSettingView.netInfo[10].label.dataI18n = "networkSettingView.networkConnected"
+        } else {
+            topView.ethConnectState(false, type)
+            networkSettingView.netInfo[10].label.dataI18n = "networkSettingView.networkUnconnected"
+        }
+        i18n.refreshObj(networkSettingView.netInfo[10].label)
+    })
+    
+    // mqtt杩炴帴鐘舵��
+    bus.on('mqttStatus', (data) => {
+        if (data == "connected") {
+            topView.mqttConnectState(true)
+        } else {
+            topView.mqttConnectState(false)
+        }
+    })
+    
+    // 浜鸿劯褰曞叆寮�濮�
+    bus.on("beginAddFace", screen.beginAddFace)
+    
+    // 浜鸿劯褰曞叆缁撴灉
+    bus.on("faceEnterResult", screen.faceEnterResult)
+    
+    // 閫�鍑哄睆淇�
+    bus.on("exitIdle", screen.exitIdle)
+    
+    // 鑾峰彇WiFi鍒楄〃 - 绉婚櫎浜嬩欢鐩戝惉鍣紝閬垮厤鏃犻檺寰幆
+    
+    // 鑾峰彇鍗″彿
+    bus.on("getCard", screen.getCard)
+    
+    // 浜鸿劯璁よ瘉缁撴灉
+    bus.on("faceAuthResult", screen.faceAuthResult)
+    
+    // 閫氳缁撴灉
+    bus.on("accessRes", screen.accessRes)
+    
+    // 璺熻釜鏇存柊
+    // bus.on("trackUpdate", screen.trackUpdate)
+    
+    // 闅愯棌SN
+    bus.on("hideSn", screen.hideSn)
+    
+    // 鍒囨崲璇█
+    bus.on("changeLanguage", screen.changeLanguage)
+    
+    // 闅愯棌IP
+    bus.on("hideIp", screen.hideIp)
+    
+    // 鍒锋柊灞忓箷绠$悊鍣�
+    bus.on("screenManagerRefresh", screen.screenManagerRefresh)
+    
+    // WiFi鍒楄〃鏁版嵁
+    bus.on("netWifiSsidList", screen.netWifiSsidList)
+    
+    // APP妯″紡
+    bus.on("appMode", screen.appMode)
+    
+    // 鍗囩骇
+    bus.on("upgrade", screen.upgrade)
+    
+    // 鍗$墖閲嶇疆
+    // bus.on("cardReset", screen.cardReset)
+    
+    // 璺熻釜缁撴灉
+    bus.on("trackResult", screen.trackResult)
+    bus.on("showAccessResult", screen.showAccessResult)
+}
+
+/**
+ * 鍗$墖閲嶇疆瀹氭椂鍣�
+ */
+let setTimeout
+
+/**
+ * 鍗$墖閲嶇疆
+ * 澶勭悊鍗$墖閲嶇疆閫昏緫
+ * @param {object} msg - 娑堟伅瀵硅薄
+ */
+screen.cardReset = function (msg) {
+    if (msg.type == 2 && msg.status == 3) {
+        setTimeout = std.setTimeout(() => {
+            driver.net.cardReset()
+        }, 30 * 1000);
+    } else {
+        if (setTimeout) {
+            std.clearTimeout(setTimeout)
+        }
+    }
+}
+
+/**
+ * 寮�濮嬫敞鍐屼汉鑴�
+ * 澶勭悊浜鸿劯娉ㄥ唽寮�濮嬮�昏緫
+ * @param {object} data - 浜鸿劯鏁版嵁瀵硅薄
+ */
+screen.beginAddFace = function (data) {
+    log.info('screen.beginAddFace', JSON.stringify(data));
+
+    if (!data.fileName) {
+        return screen.faceEnterResult()
+    }
+
+    driver.alsa.play(`/app/code/resource/${config.get("base.language") == "CN" ? "CN" : "EN"}/wav/recognition_s.wav`)
+    faceEnterView.statusPanel.success("faceEnterView.recogSuccess")
+    // 淇濆瓨鍥剧墖鍒版湰鍦�   
+    let src = `/app/data/user/register.jpg`
+    common.systemBrief(`mv ${data.fileName} ${src}`)
+    common.systemBrief(`rm -rf /app/data/user/temp/*`)
+
+    screen.faceEnterResult(src)
+}
+
+/**
+ * 閫氳缁撴灉
+ * 澶勭悊閫氳鎴愬姛鎴栧け璐ョ殑缁撴灉
+ * @param {boolean} bool - 閫氳缁撴灉锛宼rue琛ㄧず鎴愬姛锛宖alse琛ㄧず澶辫触
+ */
+screen.accessRes = function (bool) {
+    if (bool) {
+        if (mainView.smallStatusPanel && mainView.smallStatusPanel.success) {
+            mainView.smallStatusPanel.success()
+        }
+    } else {
+        if (mainView.smallStatusPanel && mainView.smallStatusPanel.fail) {
+            mainView.smallStatusPanel.fail()
+        }
+    }
+}
+
+/**
+ * 鍒囨崲APP妯″紡
+ * 鍒囨崲搴旂敤绋嬪簭鏄剧ず妯″紡锛堟爣鍑嗘ā寮忔垨绠�娲佹ā寮忥級
+ * @param {number} mode - 妯″紡鍊硷紝0琛ㄧず鏍囧噯妯″紡锛�1琛ㄧず绠�娲佹ā寮�
+ */
+screen.appMode = function (mode) {
+    if (mode == 0) {
+        // 鍒囨崲鍒版爣鍑嗘ā寮�
+    } else if (mode == 1) {
+        // 鍒囨崲鍒扮畝娲佹ā寮�
+    }
+}
+
+/**
+ * 鏇存柊浜鸿劯璺熻釜妗�
+ * 鏇存柊浜鸿劯璺熻釜妗嗙殑浣嶇疆鍜岀姸鎬�
+ * @param {object} data - 鍧愭爣淇℃伅
+ * @param {number} id - face_id锛岀敤浜庡叧鑱旇瘑鍒鍚嶇敤
+ * @param {boolean} isLiving - 鏄惁娲讳綋
+ */
+screen.trackUpdate = function (data, id, isLiving) {
+    let item = mainView.trackFaces[0]
+    for (let i = 0; i < 10; i++) {
+        let ele = mainView.trackFaces[i]
+        if (ele.face_id == id) {
+            item = ele
+            break
+        }
+    }
+    item.face_id = id
+
+    if (item && item.timer) {
+        std.clearTimeout(item.timer)
+        item.timer = null
+    }
+
+    item.timer = std.setTimeout(() => {
+        item.trackFace.hide()
+        // item.trackFaceName.hide()
+        if (item.timer) {
+            std.clearTimeout(item.timer)
+            item.timer = null
+        }
+    }, 300)
+
+    let edge = data.w > data.h ? data.w : data.h
+    let offset = Math.abs(data.w - data.h) / 2
+    item.trackFace.show()
+    item.trackFace.setSize(edge, edge)
+    item.trackFace.radius(edge / 2)
+    if (data.w > data.h) {
+        item.trackFace.setPos(data.x, data.y - offset)
+    } else {
+        item.trackFace.setPos(data.x - offset, data.y)
+    }
+
+    item.trackFaceName.text(" ")
+
+    if (item.result && item.result.result === true && item.result.id == id) {
+        item.trackFace.setBorderColor(viewUtils.color.success)
+        let user = sqliteService.d1_person.findByUserId(item.result.userId)[0]
+        item.trackFaceName.text(user ? user.name : "")
+    } else if (item.result && item.result.result === false && item.result.id == id) {
+        item.trackFace.setBorderColor(viewUtils.color.fail)
+    } else if (isLiving) {
+        item.trackFace.setBorderColor(0xf3e139)
+    } else {
+        item.trackFace.setBorderColor(0xffffff)
+    }
+}
+
+/**
+ * 璁よ瘉缁撴灉
+ * 澶勭悊浜鸿劯璇嗗埆璁よ瘉缁撴灉
+ * @param {object} data - 璁よ瘉缁撴灉鏁版嵁
+ */
+screen.trackResult = function (data) {
+    for (let i = 0; i < 10; i++) {
+        let ele = mainView.trackFaces[i]
+        if (ele.face_id == data.id) {
+            ele.result = data
+            return
+        }
+    }
+}
+
+/**
+ * 闅愯棌SN鎸夐挳
+ * 鎺у埗SN鎸夐挳鐨勬樉绀哄拰闅愯棌
+ * @param {boolean} bool - 鏄惁鏄剧ず锛宼rue琛ㄧず鏄剧ず锛宖alse琛ㄧず闅愯棌
+ */
+screen.hideSn = function (bool) {
+    if (bool) {
+        mainView.bottomSnBtn.show()
+    } else {
+        mainView.bottomSnBtn.hide()
+    }
+}
+
+/**
+ * 闅愯棌IP鏍囩
+ * 鎺у埗IP鏍囩鐨勬樉绀哄拰闅愯棌
+ * @param {boolean} bool - 鏄惁鏄剧ず锛宼rue琛ㄧず鏄剧ず锛宖alse琛ㄧず闅愯棌
+ */
+screen.hideIp = function (bool) {
+    // 涓嶅啀闇�瑕佹鍑芥暟锛屽洜涓篒P淇℃伅鐜板湪鏄剧ず鍦ㄥ崐閫忔槑瑕嗙洊鍥惧眰涓�
+}
+
+/**
+ * 闅愯棌搴曢儴妗�
+ * 鎺у埗搴曢儴妗嗙殑鏄剧ず鍜岄殣钘�
+ * @param {boolean} bool - 鏄惁鏄剧ず锛宼rue琛ㄧず鏄剧ず锛宖alse琛ㄧず闅愯棌
+ */
+screen.hideBottomBox = function (bool) {
+    if (bool) {
+        mainView.bottomBox.hide()
+    } else {
+        mainView.bottomBox.show()
+    }
+}
+
+/**
+ * 鍒囨崲璇█
+ * 鍒囨崲绯荤粺璇█璁剧疆
+ */
+screen.changeLanguage = function () {
+    i18n.setLanguage(screen.getConfig()['base.language'])
+}
+
+/**
+ * 鍗囩骇鎻愮ず
+ * 鏄剧ず绯荤粺鍗囩骇鎻愮ず淇℃伅
+ * @param {object} data - 鍗囩骇淇℃伅瀵硅薄锛屽寘鍚玹itle鍜宑ontent
+ */
+screen.upgrade = function (data) {
+    const { title, content } = data
+    viewUtils.confirmOpen(title, content)
+}
+
+/**
+ * 鏄剧ず閫氳缁撴灉寮圭獥
+ * @param {object} data - 閫氳缁撴灉鏁版嵁
+ * @param {boolean} data.faceAuth - 浜鸿劯璇嗗埆鏄惁閫氳繃
+ * @param {boolean} data.gasConcentration - 姘斾綋娴撳害鏄惁鍚堟牸
+ * @param {boolean} data.accessAllowed - 鏄惁鍏佽閫氳
+ * @param {string} data.message - 寮圭獥娑堟伅
+ */
+screen.showAccessResult = function (data) {
+    // // 鏄剧ず鐘舵�侀潰鏉匡紝3绉掑悗鑷姩鍏抽棴
+    // if (data.accessAllowed) {
+    //     mainView.statusPanel.success(data.message)
+    // } else {
+    //     mainView.statusPanel.fail(data.message)
+    // }
+
+    
+    // 鏄剧ず灏忓瀷鐘舵�侀潰鏉匡紝3绉掑悗鑷姩鍏抽棴
+    if (data.accessAllowed) {
+        mainView.smallStatusPanel.success(data.message)
+    } else {
+        mainView.smallStatusPanel.fail(data.message)
+    }
+}
+
+export default screen
diff --git a/vf205_access/src/service/accessService.js b/vf205_access/src/service/accessService.js
new file mode 100644
index 0000000..0bdd955
--- /dev/null
+++ b/vf205_access/src/service/accessService.js
@@ -0,0 +1,501 @@
+/**
+ * 闂ㄧ閫氳鏈嶅姟妯″潡
+ * 澶勭悊闂ㄧ閫氳鐩稿叧鐨勪笟鍔¢�昏緫锛屽寘鎷汉鑴�/瀵嗙爜鐧藉悕鍗曟牎楠屻�佹潈闄愬垽鏂�侀�氳璁板綍淇濆瓨绛�
+ */
+import logger from "../../dxmodules/dxLogger.js"
+import std from "../../dxmodules/dxStd.js"
+import config from "../../dxmodules/dxConfig.js"
+import common from "../../dxmodules/dxCommon.js"
+import map from '../../dxmodules/dxMap.js'
+import bus from '../../dxmodules/dxEventBus.js'
+import driver from "../driver.js"
+import mqttService from "./mqttService.js"
+import sqliteService from "./sqliteService.js"
+import utils from '../common/utils/utils.js'
+import http from "../../dxmodules/dxHttp.js"
+import grainService from './grainService.js'
+const accessService = {}
+
+/**
+ * 灏嗗崄杩涘埗鏁拌浆鎹负灏忕搴忓崄鍏繘鍒跺瓧绗︿覆
+ * @param {number} decimalNumber - 鍗佽繘鍒舵暟
+ * @param {number} byteSize - 瀛楄妭澶у皬
+ * @returns {string} 灏忕搴忓崄鍏繘鍒跺瓧绗︿覆
+ */
+function decimalToLittleEndianHex(decimalNumber, byteSize) {
+    const littleEndianBytes = [];
+    for (let i = 0; i < byteSize; i++) {
+        littleEndianBytes.push(decimalNumber & 0xFF);
+        decimalNumber >>= 8; // 鐩稿綋浜庨櫎浠�256
+    }
+    const littleEndianHex = littleEndianBytes
+        .map((byte) => byte.toString(16).padStart(2, '0'))
+        .join('');
+    return littleEndianHex;
+}
+
+/**
+ * 灏嗘暟鎹寘杞崲涓哄瓧绗︿覆鏍煎紡
+ * @param {object} pack - 鏁版嵁鍖呭璞�
+ * @returns {string} 杞崲鍚庣殑瀛楃涓�
+ */
+function pack2str(pack) {
+    pack.data = (!pack.data) ? [] : pack.data.match(/.{2}/g)
+    let len = decimalToLittleEndianHex(pack.data.length, 2)
+    let str = "55aa" + pack.cmd + pack.result + len + pack.data.join('')
+    let crc = common.calculateBcc([0x55, 0xaa, parseInt(pack.cmd, 16), parseInt(pack.result, 16), pack.data.length % 256, pack.data.length / 256].concat(pack.data.map(v => parseInt(v, 16))))
+    return str + crc.toString(16).padStart(2, '0')
+}
+
+/**
+ * 浜鸿劯/瀵嗙爜鐧藉悕鍗曟牎楠�
+ * @param {object} data - 閫氳鏁版嵁锛屽寘鍚玹ype锛堢爜鍒讹級鍜宑ode锛堢爜鍐呭锛�
+ * @param {string} fileName - 閫氳鍥剧墖鏂囦欢璺緞
+ * @param {boolean|undefined} similarity - 鐩镐技搴﹂獙璇佺粨鏋滐紝false琛ㄧず楠岃瘉澶辫触
+ * @returns {number|string|boolean} -1锛堝弬鏁伴敊璇級锛�0锛堥�氳鎴愬姛锛夛紝1锛堝湪绾块獙璇侊級锛宻tring锛堟牎楠屽け璐ョ殑鍘熷洜锛夛紝false锛堥�氳鍔犻攣锛�
+ */
+accessService.access = function (data, fileName, similarity) {
+    // 閫氳鍔犻攣锛岄槻姝㈤噸澶嶉獙璇�
+    let lockMap = map.get("access_lock")
+    if (lockMap.get("access_lock")) {
+        logger.error("[access]: 閫氳鍔犻攣锛岃绋嶅悗鍐嶈瘯")
+        return false
+    }
+    lockMap.put("access_lock", true)
+
+    try {
+        // 璁板綍閫氳鏃堕棿鎴�
+        data.time = Math.floor(Date.parse(new Date()) / 1000)
+        
+        // 鏍规嵁code鏌ヨ鍑瘉
+        let res
+        if (data.type == "300") {
+            // 浜鸿劯绫诲瀷锛屼娇鐢╱serId鏌ヨ
+            res = sqliteService.d1_voucher.findByUserIdAndType(data.code, data.type)
+        } else {
+            // 鍏朵粬绫诲瀷锛屼娇鐢╟ode鏌ヨ
+            res = sqliteService.d1_voucher.findByCodeAndType(data.code, data.type)
+        }
+        
+        // 鏉冮檺璁よ瘉缁撴灉
+        let ret = true
+        // 鏄惁鏄檶鐢熶汉
+        let isStranger = false
+
+        if (similarity === false) {
+            // 濡傛灉鐩镐技搴﹂獙璇佸け璐ワ紝鍒欎笉杩涜璁よ瘉
+            ret = false
+            isStranger = true
+        } else {
+            // 楠岃瘉鍑瘉鏄惁瀛樺湪
+            if (res.length == 0) {
+                logger.error("[access]: 閫氳澶辫触锛屾病鏌ヨ鍒板嚟璇侊紒")
+                ret = false
+                isStranger = true
+            } else {
+                // 鍑瘉瀛樺湪锛岃幏鍙栫敤鎴蜂俊鎭�
+                data.userId = res[0].userId
+                data.keyId = res[0].id
+                
+                // 鏍规嵁userId鏌ヨ浜哄憳淇℃伅
+                res = sqliteService.d1_person.findByUserId(data.userId)
+                if (res.length == 0) {
+                    logger.error("[access]: 閫氳澶辫触锛屾病鏌ヨ鍒颁汉鍛橈紒")
+                    ret = false
+                    isStranger = true
+                } else {
+                    // 鑾峰彇浜哄憳濮撳悕銆佽韩浠借瘉鍙峰拰韬唤绫诲瀷
+                    let idCard
+                    let userType = 0
+                    try {
+                        idCard = JSON.parse(res[0].extra).idCard
+                        userType = JSON.parse(res[0].extra).type || 0
+                    } catch (error) {
+                        logger.error("鏃犺韩浠借瘉鍙锋垨绫诲瀷")
+                    }
+                    data.extra = { name: res[0].name, idCard: idCard, type: userType }
+                }
+                
+                // 澶勭悊鍙屼汉璁よ瘉淇℃伅
+                if (data.dualAuthInfo) {
+                    logger.info("[access]: 澶勭悊鍙屼汉璁よ瘉淇℃伅: " + JSON.stringify(data.dualAuthInfo))
+                    // 瀛樺偍绗竴鐢ㄦ埛淇℃伅
+                    let firstUserId = data.dualAuthInfo.firstUserId
+                    // 鏌ヨ绗竴鐢ㄦ埛鐨勮缁嗕俊鎭�
+                    let res1 = sqliteService.d1_person.findByUserId(firstUserId)
+                    if (res1.length > 0) {
+                        // 鑾峰彇绗竴鐢ㄦ埛鐨勫鍚嶃�佽韩浠借瘉鍙峰拰韬唤绫诲瀷
+                        let idCard1
+                        let firstUserType = 0
+                        try {
+                            idCard1 = JSON.parse(res1[0].extra).idCard
+                            firstUserType = JSON.parse(res1[0].extra).type || 0
+                        } catch (error) {
+                            logger.error("鏃犵涓�鐢ㄦ埛韬唤璇佸彿鎴栫被鍨�")
+                        }
+                        data.userId = firstUserId
+                        data.extra = { name: res1[0].name, idCard: idCard1, type: firstUserType }
+                    } else {
+                        // 濡傛灉娌℃湁鏌ヨ鍒扮涓�鐢ㄦ埛淇℃伅锛屼娇鐢ㄩ粯璁ゅ��
+                        data.userId = firstUserId
+                        data.extra = { name: data.dualAuthInfo.firstUserName, idCard: "", type: 0 }
+                    }
+                    // 瀛樺偍绗簩鐢ㄦ埛淇℃伅
+                    data.userId2 = data.dualAuthInfo.secondUserId
+                    // 鏌ヨ绗簩鐢ㄦ埛鐨勮缁嗕俊鎭�
+                    let res2 = sqliteService.d1_person.findByUserId(data.dualAuthInfo.secondUserId)
+                    if (res2.length > 0) {
+                        // 鑾峰彇绗簩鐢ㄦ埛鐨勫鍚嶅拰韬唤璇佸彿
+                        let idCard2
+                        let secondUserType = 0
+                        try {
+                            idCard2 = JSON.parse(res2[0].extra).idCard
+                            secondUserType = JSON.parse(res2[0].extra).type || 0
+                        } catch (error) {
+                            logger.error("鏃犵浜岀敤鎴疯韩浠借瘉鍙锋垨绫诲瀷")
+                        }
+                        data.extra2 = { name: res2[0].name, idCard: idCard2 }
+                        // 瀛樺偍绗簩鐢ㄦ埛鐨勬潈闄怚D锛堣韩浠界被鍨嬶級
+                        data.permissionId2 = secondUserType.toString()
+                    } else {
+                        // 濡傛灉娌℃湁鏌ヨ鍒扮浜岀敤鎴蜂俊鎭紝浣跨敤榛樿鍊�
+                        data.extra2 = { name: data.dualAuthInfo.secondUserName, idCard: "" }
+                        data.permissionId2 = ""
+                    }
+                    // 澶勭悊绗竴鐢ㄦ埛鐨勪汉鑴稿浘鐗�
+                    if (data.firstUserFileName) {
+                        let firstUserSrc = `/app/data/passRecord/${firstUserId}_${data.time}_1.jpg`
+                        std.ensurePathExists(firstUserSrc) // 纭繚鐩綍瀛樺湪
+                        if (std.exist(data.firstUserFileName)) {
+                            // 绉诲姩鍥剧墖鍒版寚瀹氱洰褰�
+                            common.systemBrief(`mv ${data.firstUserFileName} ${firstUserSrc}`)
+                            // 鏇存柊data涓殑code涓虹涓�鐢ㄦ埛鐨勫浘鐗囪矾寰�
+                            data.code = firstUserSrc
+                        }
+                    }
+                    // 澶勭悊绗簩鐢ㄦ埛鐨勪汉鑴稿浘鐗�
+                    if (fileName) {
+                        let secondUserSrc = `/app/data/passRecord/${data.userId2}_${data.time}_2.jpg`
+                        std.ensurePathExists(secondUserSrc) // 纭繚鐩綍瀛樺湪
+                        if (std.exist(fileName)) {
+                            // 绉诲姩鍥剧墖鍒版寚瀹氱洰褰�
+                            common.systemBrief(`mv ${fileName} ${secondUserSrc}`)
+                            // 鏇存柊data涓殑code2涓虹浜岀敤鎴风殑鍥剧墖璺緞
+                            data.code2 = secondUserSrc
+                        }
+                    }
+                }
+            }
+
+            // 楠岃瘉鏉冮檺
+            if (ret) {
+                // 鏍规嵁userId鏌ヨ鏉冮檺
+                res = sqliteService.d1_permission.findByUserId(data.userId)
+                if (res && res.length > 0 && judgmentPermission(res)) {
+                    logger.info("[access]: 鏉冮檺璁よ瘉閫氳繃")
+                    ret = true
+                    // 瀛樺偍鐢ㄦ埛韬唤绫诲瀷浣滀负鏉冮檺ID锛堟湰绯荤粺涓韩浠藉嵆鏉冮檺锛�
+                    let userType = 0
+                    try {
+                        if (data.extra) {
+                            userType = data.extra.type || 0
+                        } else {
+                            // 浠庢暟鎹簱鏌ヨ鐢ㄦ埛淇℃伅鑾峰彇韬唤绫诲瀷
+                            let userRes = sqliteService.d1_person.findByUserId(data.userId)
+                            if (userRes && userRes.length > 0) {
+                                userType = JSON.parse(userRes[0].extra).type || 0
+                            }
+                        }
+                    } catch (error) {
+                        logger.error("瑙f瀽鐢ㄦ埛绫诲瀷澶辫触")
+                    }
+                    data.permissionId = userType.toString()
+                    // 鏆傚仠浜鸿劯璁よ瘉鍔熻兘
+                    driver.face.status(false)
+                    logger.info("[access]: 鏆傚仠浜鸿劯璁よ瘉鍔熻兘")
+                } else {
+                    logger.info("[access]: 鏃犳潈闄�")
+                    ret = false
+                }
+            }
+
+            // 鏃犳潈闄愭椂锛屽皾璇曞湪绾块獙璇�
+            if (!ret && config.get('mqtt.onlinecheck') == 1 && driver.mqtt.getStatus()) {
+                logger.info("[access]: 鏃犳潈闄愶紝璧板湪绾块獙璇�")
+                let serialNo = std.genRandomStr(10)
+                driver.mqtt.send("access_device/v2/event/access_online", JSON.stringify(mqttService.mqttReply(serialNo, data, mqttService.CODE.S_000)))
+                driver.alsa.play(`/app/code/resource/${config.get("base.language") == "CN" ? "CN" : "EN"}/wav/verify.wav`)
+                
+                // 绛夊緟鍦ㄧ嚎楠岃瘉缁撴灉
+                let payload = driver.mqtt.getOnlinecheck()
+                if (payload && payload.serialNo == serialNo && payload.code == '000000') {
+                    ret = true
+                    // 鏆傚仠浜鸿劯璁よ瘉鍔熻兘
+                    driver.face.status(false)
+                    logger.info("[access]: 鏆傚仠浜鸿劯璁よ瘉鍔熻兘")
+                } else {
+                    logger.info("[access]: 鍦ㄧ嚎楠岃瘉澶辫触")
+                    ret = false
+                }
+            }
+        }
+
+        // 纭畾璇煶鏂囦欢鍚嶇О
+        let alsaFile = (data.type).toString().startsWith("10") ? '10x' : data.type
+        
+        //鏆傚仠浜鸿劯璁よ瘉鍔熻兘
+        
+
+        if (ret == true) {
+            // 楠岃瘉姘斾綋娴撳害
+            grainService.checkGasConcentration(function() {
+                // 浠庡瓨鍌ㄧ殑姘斾綋鏁版嵁涓幏鍙栭獙璇佺粨鏋�
+                const gasData = grainService.getGasData()
+                
+                if(gasData && gasData.data && gasData.data.status === "0") {
+                    logger.info("[access]: 姘斾綋娴撳害楠岃瘉鍚堟牸")
+                    // 閫氳鎴愬姛澶勭悊
+                    driver.screen.accessSuccess()
+                    logger.info("[access]: 閫氳鎴愬姛")
+                    
+                    // 鏄剧ず閫氳鎴愬姛缁撴灉
+                    bus.fire("showAccessResult", {
+                        faceAuth: true,
+                        gasConcentration: true,
+                        accessAllowed: true,
+                        message: "*浠撳唴姘斾綋娴撳害鍚堟牸锛屽厑璁搁�氳*"
+                    })
+                    
+                    // 瑙﹀彂閫氳鎴愬姛浜嬩欢锛岄�氱煡UI鏇存柊
+                    bus.fire("accessSuccess", { data: data, fileName: fileName })
+                    driver.alsa.play(`/app/code/resource/${config.get("base.language") == "CN" ? "CN" : "EN"}/wav/access_s.wav`)
+                    driver.gpio.open() // 寮�闂�
+                    savePassPic(data, fileName) // 淇濆瓨閫氳鍥剧墖
+                    reply(data, true) // 涓婃姤閫氳璁板綍
+                } else {
+                    logger.info("[access]: 姘斾綋娴撳害楠岃瘉涓嶅悎鏍�")
+                    // 閫氳澶辫触澶勭悊
+                    driver.screen.accessFail()
+                    logger.error("[access]: 閫氳澶辫触")
+                    // 瑙﹀彂澶辫触寮圭獥
+                    bus.fire("showAccessResult", {
+                        faceAuth: true,
+                        gasConcentration: false,
+                        accessAllowed: false,
+                        message: "*浠撳唴姘斾綋娴撳害涓嶅悎鏍硷紝绂佹閫氳*"
+                    })
+                    if (utils.isEmpty(similarity)) {
+                        driver.alsa.play(`/app/code/resource/${config.get("base.language") == "CN" ? "CN" : "EN"}/wav/access_f.wav`)
+                    }
+                    // if (isStranger && !config.get("sys.strangerImage")) {
+                    //     // 闄岀敓浜轰笉淇濆瓨鐓х墖
+                    // } else {
+                    //     savePassPic(data, fileName)
+                    // }
+                    savePassPic(data, fileName)
+                    // 娣诲姞姘斾綋娴撳害澶辫触淇℃伅
+                    data.message = "姘斾綋娴撳害涓嶅悎鏍�"
+                    reply(data, false) // 涓婃姤閫氳璁板綍
+                }
+            })
+
+        } else {
+            // 閫氳澶辫触澶勭悊
+            driver.screen.accessFail()
+            logger.error("[access]: 閫氳澶辫触")
+            // 瑙﹀彂澶辫触寮圭獥
+            bus.fire("showAccessResult", {
+                faceAuth: true,
+                gasConcentration: false,
+                accessAllowed: false,
+                message: "*鏉冮檺璁よ瘉澶辫触锛岀姝㈤�氳*"
+            })
+            if (utils.isEmpty(similarity)) {
+                driver.alsa.play(`/app/code/resource/${config.get("base.language") == "CN" ? "CN" : "EN"}/wav/recg_f.wav`)
+            }
+            // if (isStranger && !config.get("sys.strangerImage")) {
+            //     // 闄岀敓浜轰笉淇濆瓨鐓х墖
+            // } else {
+            //     savePassPic(data, fileName)
+            // }
+            savePassPic(data, fileName)
+
+            reply(data, false) // 涓婃姤閫氳璁板綍
+        }
+    } catch (error) {
+        logger.error(error)
+    }
+    
+    // 璇煶鎾姤闇�瑕佹椂闂达紝鎵�浠ュ欢杩�1绉掕В閿�
+    std.sleep(1000)
+    lockMap.put("access_lock", false)
+    logger.error("[access]: 瑙i攣鎴愬姛")
+    // 瑙﹀彂閫氳瑙i攣瀹屾垚浜嬩欢锛岄�氱煡UI閲嶇疆
+    // bus.fire("accessUnlockComplete")
+}
+
+/**
+ * 淇濆瓨閫氳鍥剧墖
+ * @param {object} data - 閫氳鏁版嵁
+ * @param {string} fileName - 鍥剧墖鏂囦欢璺緞
+ */
+function savePassPic(data, fileName) {
+    if (data.type == "300") { // 浠呭鐞嗕汉鑴哥被鍨�
+        // 濡傛灉鏄弻浜鸿璇侊紝宸茬粡鍦ㄥ鐞嗗弻浜鸿璇佷俊鎭椂淇濆瓨浜嗗浘鐗囷紝杩欓噷璺宠繃
+        if (data.dualAuthInfo) {
+            return
+        }
+        let src = `/app/data/passRecord/${data.userId}_${data.time}.jpg`
+        std.ensurePathExists(src) // 纭繚鐩綍瀛樺湪
+        if (std.exist(fileName)) {
+            // 绉诲姩鍥剧墖鍒版寚瀹氱洰褰�
+            common.systemBrief(`mv ${fileName} ${src}`)
+            // 鍙竻鐞嗗師濮嬩复鏃跺浘鐗囨枃浠讹紙浠ユ椂闂存埑鍛藉悕鐨勬枃浠讹級锛屼繚鐣欒皟鏁村悗鐨勫浘鐗囨枃浠�
+            common.systemBrief(`rm -rf /app/data/user/temp/[0-9]*.jpg`)
+            // 鏇存柊data涓殑code涓哄浘鐗囪矾寰�
+            data.code = src
+        } else {
+            logger.error("[access]: 閫氳澶辫触锛屽浘鐗囦笉瀛樺湪锛侊紒锛侊紒锛侊紒锛侊紒锛侊紒锛侊紒锛侊紒锛�" + fileName)
+        }
+    }
+}
+
+/**
+ * 鏍¢獙鏉冮檺鏃堕棿鏄惁鍙互閫氳
+ * @param {array} permissions - 鏉冮檺璁板綍鏁扮粍
+ * @returns {boolean} true琛ㄧず鏈夋潈闄愶紝false琛ㄧず鏃犳潈闄�
+ */
+function judgmentPermission(permissions) {
+    let currentTime = Math.floor(Date.now() / 1000)
+    for (let permission of permissions) {
+        if (permission.timeType == 0) {
+            // 姘镐箙鏉冮檺
+            return true
+        } else if (permission.beginTime <= currentTime && currentTime <= permission.endTime) {
+            if (permission.timeType == 1) {
+                // 鏃堕棿娈垫潈闄�
+                return true
+            }
+            if (permission.timeType == 2) {
+                // 姣忔棩鏉冮檺
+                let seconds = Math.floor((new Date() - new Date().setHours(0, 0, 0, 0)) / 1000);
+                if (permission.repeatBeginTime <= seconds && seconds <= permission.repeatEndTime) {
+                    return true
+                }
+            }
+            if (permission.timeType == 3 && permission.period) {
+                // 鍛ㄩ噸澶嶆潈闄�
+                let dayTimes = JSON.parse(permission.period)[new Date().getDay() + 1]
+                if (dayTimes && dayTimes.split("|").some((dayTime) => isCurrentTimeInTimeRange(dayTime))) {
+                    return true
+                }
+            }
+        }
+    }
+    return false
+}
+
+/**
+ * 鍒ゆ柇褰撳墠鏃堕棿鏄惁鍦ㄦ椂闂存鍐�
+ * @param {string} time - 鏃堕棿娈靛瓧绗︿覆锛屾牸寮忓"15:00-19:00"
+ * @returns {boolean} true琛ㄧず褰撳墠鏃堕棿鍦ㄦ椂闂存鍐咃紝false琛ㄧず涓嶅湪
+ */
+function isCurrentTimeInTimeRange(time) {
+    // 鍒嗗壊寮�濮嬫椂闂村拰缁撴潫鏃堕棿
+    let [startTime, endTime] = time.split('-');
+    // 瑙f瀽寮�濮嬫椂闂寸殑灏忔椂鍜屽垎閽�
+    let [startHour, startMinute] = startTime.split(':');
+    // 瑙f瀽缁撴潫鏃堕棿鐨勫皬鏃跺拰鍒嗛挓
+    let [endHour, endMinute] = endTime.split(':');
+
+    // 鑾峰彇褰撳墠鏃堕棿
+    let currentTime = new Date();
+
+    // 鍒涘缓寮�濮嬫椂闂寸殑鏃ユ湡瀵硅薄
+    let startDate = new Date();
+    startDate.setHours(parseInt(startHour, 10));
+    startDate.setMinutes(parseInt(startMinute, 10));
+    // 鍒涘缓缁撴潫鏃堕棿鐨勬棩鏈熷璞�
+    let endDate = new Date();
+    endDate.setHours(parseInt(endHour, 10));
+    endDate.setMinutes(parseInt(endMinute, 10));
+
+    // 妫�鏌ュ綋鍓嶆椂闂存槸鍚﹀湪鏃堕棿鑼冨洿鍐�
+    return currentTime >= startDate && currentTime <= endDate;
+}
+
+/**
+ * 閫氳璁板綍涓婃姤
+ * @param {object} data - 閫氳鏁版嵁
+ * @param {boolean} result - 閫氳缁撴灉锛宼rue琛ㄧず鎴愬姛锛宖alse琛ㄧず澶辫触
+ */
+function reply(data, result) {
+    // 浣跨敤绾跨▼澶勭悊鏁翠釜reply鍑芥暟锛岄伩鍏嶅牭濉炰富杩涚▼
+    std.setTimeout(() => {
+        try {
+            // 鏋勫缓閫氳璁板綍
+            let record = {
+                id: std.genRandomStr(16),
+                result: result ? 0 : 1, // 0琛ㄧず鎴愬姛锛�1琛ㄧず澶辫触
+            }
+            
+            // 澶嶅埗data涓殑瀛楁锛屾帓闄xtra鍜宔xtra2
+            for (const key in data) {
+                if (key !== 'extra' && key !== 'extra2' && !(key in record)) {
+                    record[key] = data[key]
+                }
+            }
+            
+            // 澶勭悊extra瀛楁
+            if (data.extra) {
+                record.extra = JSON.stringify(data.extra)
+            }
+            
+            // 澶勭悊extra2瀛楁
+            if (data.extra2) {
+                record.extra2 = JSON.stringify(data.extra2)
+            }
+            
+            // 瀛樺偍閫氳璁板綍锛屽垽鏂笂闄�
+            let count = sqliteService.d1_pass_record.count()
+            let configNum = config.get("access.offlineAccessNum");
+            configNum = configNum ? configNum : 2000;
+            
+            if (configNum > 0) {
+                if (count >= configNum) {
+                    // 杈惧埌鏈�澶у瓨鍌ㄦ暟閲忥紝鍒犻櫎鏈�鏃х殑璁板綍
+                    let lastRecord = sqliteService.d1_pass_record.findAllOrderBytimeDesc({ page: 0, size: 1 })
+                    if (lastRecord && lastRecord.length == 1) {
+                        // 濡傛灉鏄汉鑴歌褰曪紝鍒犻櫎瀵瑰簲鐨勫浘鐗囨枃浠�
+                        if (lastRecord[0].type == 300) {
+                            common.systemBrief(`rm -rf ${lastRecord[0].code}`)
+                        }
+                        sqliteService.d1_pass_record.deleteByid(lastRecord[0].id)
+                    }
+                }
+                // 淇濆瓨鏂拌褰�
+                sqliteService.d1_pass_record.save(record)
+            }
+            
+            // // 鐢熸垚搴忓垪鍙�
+            // let serialNo = std.genRandomStr(10)
+            
+            // // 澶勭悊浜鸿劯鍥剧墖
+            // if (record.type == 300) {
+            //     let m = map.get("faceAccesss")
+            //     m.del(serialNo)
+            //     m.put(serialNo, record.code ? record.code : "")
+            //     // 灏嗗浘鐗囪浆鎹负base64鏍煎紡
+            //     record.code = driver.face.fileToBase64(record.code)
+            // }
+            
+            // // 鏋勫缓MQTT娑堟伅骞跺彂閫�
+            // let payload = mqttService.mqttReply(serialNo, [record], mqttService.CODE.S_000)
+            // driver.mqtt.send("access_device/v2/event/access", JSON.stringify(payload))
+        } catch (error) {
+            logger.error(`[accessService]: 澶勭悊閫氳璁板綍澶辫触: ${error.message}`)
+        }
+    }, 0)
+}
+
+export default accessService
diff --git a/vf205_access/src/service/codeService.js b/vf205_access/src/service/codeService.js
new file mode 100644
index 0000000..10dfe20
--- /dev/null
+++ b/vf205_access/src/service/codeService.js
@@ -0,0 +1,205 @@
+/**
+ * 浜岀淮鐮�/鏉″舰鐮佸鐞嗘湇鍔℃ā鍧�
+ * 澶勭悊鍚勭被浜岀淮鐮�/鏉″舰鐮佺殑瑙f瀽鍜屽鐞嗭紝鍖呮嫭閰嶇疆鐮併�佷簯璇佹縺娲荤爜鍜岄�氳鐮�
+ */
+import common from '../../dxmodules/dxCommon.js';
+import log from '../../dxmodules/dxLogger.js'
+import qrRule from '../../dxmodules/dxQrRule.js'
+import std from '../../dxmodules/dxStd.js'
+import config from '../../dxmodules/dxConfig.js'
+import base64 from '../../dxmodules/dxBase64.js'
+import dxMap from '../../dxmodules/dxMap.js'
+import ota from "../../dxmodules/dxOta.js";
+import bus from "../../dxmodules/dxEventBus.js"
+import sqliteService from "./sqliteService.js";
+import driver from '../driver.js';
+import utils from '../common/utils/utils.js';
+import configConst from '../common/consts/configConst.js';
+import configService from './configService.js';
+import accessService from './accessService.js';
+import logger from '../../dxmodules/dxLogger.js';
+const codeService = {}
+
+/**
+ * 鎺ユ敹娑堟伅骞跺鐞�
+ * @param {ArrayBuffer} data - 鎺ユ敹鍒扮殑鍘熷鏁版嵁
+ */
+codeService.receiveMsg = function (data) {
+    log.info('[codeService] receiveMsg :' + JSON.stringify(data))
+    // 灏咥rrayBuffer杞崲涓哄崄鍏繘鍒跺瓧绗︿覆锛屽啀杞崲涓篣TF8瀛楃涓�
+    let str = common.utf8HexToStr(common.arrayBufferToHexString(data))
+    // 璋冪敤code鏂规硶澶勭悊瀛楃涓�
+    this.code(str)
+}
+
+/**
+ * 姣旇緝涓や釜瀛楃涓茬殑鍓峃涓瓧绗︽槸鍚︾浉绛�
+ * @param {string} str1 - 绗竴涓瓧绗︿覆
+ * @param {string} str2 - 绗簩涓瓧绗︿覆
+ * @param {number} N - 姣旇緝鐨勫瓧绗︽暟
+ * @returns {boolean} 鍓峃涓瓧绗︽槸鍚︾浉绛�
+ */
+function comparePrefix (str1, str2, N) {
+    let substring1 = str1.substring(0, N);
+    let substring2 = str2.substring(0, N);
+    return substring1 === substring2;
+}
+
+/**
+ * 澶勭悊浜岀淮鐮�/鏉″舰鐮佹暟鎹�
+ * @param {string} data - 浜岀淮鐮�/鏉″舰鐮佺殑鍘熷鏁版嵁
+ */
+codeService.code = function (data) {
+    log.info('[codeService] code :' + data)
+    // 鏍煎紡鍖栦簩缁寸爜鏁版嵁
+    data = qrRule.formatCode(data, sqliteService)
+    
+    // 鍒ゆ柇浜岀淮鐮佺被鍨�
+    if (data.type == 'config' || comparePrefix(data.code, "___VF102_CONFIG_V1.1.0___", "___VF102_CONFIG_V1.1.0___".length)) {
+        // 閰嶇疆鐮佸鐞�
+        configCode(data.code)
+    } else if (comparePrefix(data.code, "___VBAR_ID_ACTIVE_V", "___VBAR_ID_ACTIVE_V".length)) {
+        // 浜戣瘉婵�娲荤爜澶勭悊
+        let activeResute = driver.eid.active(config.get("sys.sn"), config.get("sys.appVersion"), config.get("sys.mac"), data.code);
+        log.info("[codeService] code: activeResute " + activeResute)
+        if (activeResute === 0) {
+            log.info("[codeService] code: 浜戣瘉婵�娲绘垚鍔�")
+            driver.screen.upgrade({ title: "confirm.cloudCertActive", content: "confirm.cloudCertActiveSuccess" })
+        } else {
+            log.info("[codeService] code: 浜戣瘉婵�娲诲け璐�")
+            driver.screen.upgrade({ title: "confirm.cloudCertActive", content: "confirm.cloudCertActiveFail" })
+        }
+    } else {
+        // 閫氳鐮佸鐞�
+        log.info("瑙f瀽閫氳鐮侊細", JSON.stringify(data))
+        bus.fire("access", { data })
+    }
+}
+
+/**
+ * 閰嶇疆鐮佸鐞�
+ * @param {string} code - 閰嶇疆鐮佹暟鎹�
+ * @param {boolean} configType - 閰嶇疆绫诲瀷鏍囧織
+ */
+function configCode (code, configType) {
+    // 閰嶇疆鐮佹牎楠屾殏鏃舵敞閲�
+    // if (!checkConfigCode(code)) {
+    //     log.error("閰嶇疆鐮佹牎楠屽け璐�")
+    //     return
+    // }
+    
+    // 瑙f瀽閰嶇疆鐮佷负JSON瀵硅薄
+    let json = utils.parseString(code)
+    if (Object.keys(json).length <= 0) {
+        try {
+            json = JSON.parse(code.slice(code.indexOf("{"), code.lastIndexOf("}") + 1))
+        } catch (error) {
+            log.error(error)
+        }
+    }
+    log.info("瑙f瀽閰嶇疆鐮侊細", JSON.stringify(json))
+    
+    // 妯″紡鍒囨崲澶勭悊
+    if (!utils.isEmpty(json.w_model)) {
+        try {
+            common.setMode(json.w_model)
+            common.asyncReboot(1)
+        } catch (error) {
+            log.error(error, error.stack)
+            log.info('鍒囨崲澶辫触涓嶅仛浠讳綍澶勭悊');
+        }
+        return
+    }
+    
+    let map = dxMap.get("UPDATE")
+    // 鎵爜鍗囩骇澶勭悊
+    if (json.update_flag === 1) {
+        if (!driver.net.getStatus()) {
+            driver.alsa.play(`/app/code/resource/${config.get("base.language") == "CN" ? "CN" : "EN"}/wav/network.wav`)
+            return
+        }
+        if (map.get("updateFlag")) {
+            return
+        }
+        map.put("updateFlag", true)
+        try {
+            driver.screen.upgrade({ title: "confirm.upgrade", content: "confirm.upgrading" })
+            ota.updateHttp(json.update_addr, json.update_md5, 300)
+            driver.screen.upgrade({ title: "confirm.upgrade", content: "confirm.upgradeSuccess" })
+        } catch (error) {
+            logger.info(error.message)
+            driver.screen.upgrade({ title: "confirm.upgrade", content: "confirm.upgradeFail" })
+        } finally {
+            map.del("updateFlag")
+        }
+        common.asyncReboot(3)
+        return
+    }
+    
+    // 璁惧閰嶇疆澶勭悊
+    let configData = {}
+    for (let key in json) {
+        let transKey
+        if (configType == true) {
+            transKey = key
+        } else {
+            transKey = configConst.getValueByKey(key)
+        }
+        if (transKey == undefined) {
+            continue
+        }
+        let keys = transKey.split(".")
+        if (utils.isEmpty(configData[keys[0]])) {
+            configData[keys[0]] = {}
+        }
+        configData[keys[0]][keys[1]] = json[key]
+    }
+    
+    let res = false
+    if (Object.keys(configData).length > 0) {
+        res = configService.configVerifyAndSave(configData)
+    }
+    
+    if (typeof res != 'boolean') {
+        log.error(res)
+        return
+    }
+    
+    if (res) {
+        log.info("閰嶇疆鎴愬姛")
+    } else {
+        log.error("閰嶇疆澶辫触")
+    }
+    
+    // 閰嶇疆鍚庨噸鍚�
+    if (json.reboot === 1) {
+        driver.screen.warning({ msg: config.get("sysInfo.language") == 1 ? "Rebooting" : "閲嶅惎涓�", beep: false })
+        common.asyncReboot(1)
+    }
+}
+
+/**
+ * 鏍¢獙閰嶇疆鐮�
+ * @param {string} code - 閰嶇疆鐮佹暟鎹�
+ * @returns {boolean} 鏍¢獙鏄惁鎴愬姛
+ */
+function checkConfigCode (code) {
+    let password = config.get('sysInfo.com_passwd') || '1234567887654321'
+    let lastIndex = code.lastIndexOf("--");
+    if (lastIndex < 0) {
+        lastIndex = code.lastIndexOf("__");
+    }
+    let firstPart = code.substring(0, lastIndex);
+    let secondPart = code.substring(lastIndex + 2);
+    let res
+    try {
+        res = base64.fromHexString(common.arrayBufferToHexString(common.hmac(firstPart, password)))
+    } catch (error) {
+        log.error(error)
+        return false
+    }
+
+    return res == secondPart;
+}
+
+export default codeService
diff --git a/vf205_access/src/service/configService.js b/vf205_access/src/service/configService.js
new file mode 100644
index 0000000..77c0387
--- /dev/null
+++ b/vf205_access/src/service/configService.js
@@ -0,0 +1,273 @@
+/**
+ * 閰嶇疆鏈嶅姟妯″潡
+ * 璐熻矗閰嶇疆鐨勬牎楠屻�佷繚瀛樺拰搴旂敤锛屽寘鎷悇绉嶉厤缃」鐨勮鍒欓獙璇佸拰鍥炶皟澶勭悊
+ */
+import utils from '../common/utils/utils.js'
+import config from '../../dxmodules/dxConfig.js'
+import mqtt from '../../dxmodules/dxMqtt.js'
+import std from '../../dxmodules/dxStd.js'
+import ntp from '../../dxmodules/dxNtp.js'
+import common from '../../dxmodules/dxCommon.js'
+import driver from '../driver.js'
+import bus from '../../dxmodules/dxEventBus.js'
+import mqttService from './mqttService.js'
+import logger from '../../dxmodules/dxLogger.js'
+const configService = {}
+
+/**
+ * IP鍦板潃鏍¢獙姝e垯
+ * 鍖归厤浠ョ偣鍒嗗崄杩涘埗褰㈠紡琛ㄧず鐨� IP 鍦板潃锛屼緥濡傦細192.168.0.1
+ */
+const ipCheck = v => /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/.test(v)
+
+/**
+ * IP鍦板潃鎴栧煙鍚嶆牎楠屾鍒欙紙甯︾鍙o級
+ * 鍖归厤IP鍦板潃鎴栧煙鍚嶏紝鍙�夋嫨甯︽湁绔彛鍙�
+ */
+const ipOrDomainCheckWithPort = v => /^(?:(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)|(?:[a-zA-Z0-9-]+\.)+[a-zA-Z]{2,})(:\d{1,5})?$/.test(v);
+
+/**
+ * 姝f暣鏁版牎楠屾鍒�
+ */
+const regpCheck = v => /^[1-9]\d*$/.test(v)
+
+/**
+ * 闈炶礋鏁存暟鏍¢獙姝e垯
+ */
+const regnCheck = v => /^([1-9]\d*|0{1})$/.test(v)
+
+/**
+ * 鎵�鏈夋敮鎸佺殑閰嶇疆椤圭殑妫�楠岃鍒欎互鍙婅缃垚鍔熷悗鐨勫洖璋�
+ * rule锛氭牎楠岃鍒欙紝杩斿洖true鏍¢獙鎴愬姛锛宖alse鏍¢獙澶辫触
+ * callback锛氶厤缃慨鏀硅Е鍙戝洖璋�
+ */
+const supported = {
+    // 浜鸿劯閰嶇疆
+    face: {
+        similarity: { rule: v => typeof v == 'number' && v >= 0 && v <= 1, callback: v => driver.face.faceUpdateConfig({ score: v }) },
+        livenessOff: { rule: v => [0, 1].includes(v), callback: v => driver.face.faceUpdateConfig({ livingCheckEnable: v }) },
+        livenessVal: { rule: v => typeof v == 'number' && v >= 0 && v <= 1, callback: v => driver.face.faceUpdateConfig({ livingScore: v }) },
+        showNir: { rule: v => [0, 1].includes(v), callback: v => driver.capturer.showNir(v) },
+        detectMask: { rule: v => [0, 1].includes(v), callback: v => driver.face.faceUpdateConfig({ detectMaskEnable: v }) },
+        stranger: { rule: v => [0, 1, 2].includes(v) },
+        voiceMode: { rule: v => [0, 1, 2].includes(v) },
+        voiceModeDate: { rule: v => typeof v == 'string' },
+    },
+    // MQTT閰嶇疆
+    mqtt: {
+        addr: { rule: ipOrDomainCheckWithPort },
+        clientId: { rule: v => typeof v == 'string' },
+        username: { rule: v => typeof v == 'string' },
+        password: { rule: v => typeof v == 'string' },
+        qos: { rule: v => [0, 1, 2].includes(v) },
+        prefix: { rule: v => typeof v == 'string' },
+        willtopic: { rule: v => typeof v == 'string' },
+        onlinecheck: { rule: v => [0, 1, 2].includes(v) },
+        timeout: { rule: regpCheck },
+    },
+    // 缃戠粶閰嶇疆
+    net: {
+        type: { rule: v => [0, 1, 2, 4].includes(v) }, // 缃戠粶绫诲瀷
+        dhcp: { rule: v => [1, 2, 3].includes(v) }, // DHCP璁剧疆
+        ip: { rule: ipCheck }, // IP鍦板潃
+        gateway: { rule: ipCheck }, // 缃戝叧鍦板潃
+        dns: { rule: v => !v.split(",").some(ip => !ipCheck(ip)) }, // DNS鏈嶅姟鍣�
+        mask: { rule: ipCheck }, // 瀛愮綉鎺╃爜
+        mac: { rule: v => typeof v == 'string' }, // MAC鍦板潃
+        ssid: { rule: v => typeof v == 'string' }, // WiFi SSID
+        psk: { rule: v => typeof v == 'string' }, // WiFi瀵嗙爜
+    },
+    // NTP鏃堕棿鍚屾閰嶇疆
+    ntp: {
+        ntp: { rule: v => [0, 1].includes(v) }, // NTP寮�鍏�
+        server: { rule: ipCheck }, // NTP鏈嶅姟鍣�
+        gmt: { rule: v => typeof v == 'number' && v >= 0 && v <= 24, callback: v => ntp.updateGmt(v) }, // 鏃跺尯璁剧疆
+    },
+    // 绯荤粺閰嶇疆
+    sys: {
+        uuid: { rule: v => typeof v == 'string' }, // 璁惧UUID
+        model: { rule: v => typeof v == 'string' }, // 璁惧鍨嬪彿
+        mode: { rule: v => typeof v == 'string', callback: v => setMode(v) }, // 璁惧妯″紡
+        sn: { rule: v => typeof v == 'string' }, // 璁惧搴忓垪鍙�
+        version: { rule: v => typeof v == 'string' }, // 绯荤粺鐗堟湰
+        releaseDate: { rule: v => typeof v == 'string' }, // 鍙戝竷鏃ユ湡
+        nfc: { rule: v => [0, 1].includes(v) }, // NFC寮�鍏�
+        nfcIdentityCardEnable: { rule: v => [1, 3].includes(v) }, // 浜戣瘉寮�鍏�
+        pwd: { rule: v => [0, 1].includes(v) }, // 瀵嗙爜寮�闂ㄥ紑鍏�
+        strangerImage: { rule: v => [0, 1].includes(v) }, // 闄岀敓浜轰繚瀛樺浘鐗囧紑鍏�
+        accessImageType: { rule: v => [0, 1].includes(v) }, // 閫氳鍥剧墖绫诲瀷
+        interval: { rule: regnCheck }, // 绯荤粺闂撮殧璁剧疆
+    },
+    // 闂ㄧ閰嶇疆
+    access: {
+        relayTime: { rule: regpCheck }, // 缁х數鍣ㄥ姩浣滄椂闂�
+        offlineAccessNum: { rule: regpCheck }, // 绂荤嚎寮�闂ㄦ鏁�
+        tamperAlarm: { rule: v => [0, 1].includes(v) }, // 闃叉媶鎶ヨ寮�鍏�
+    },
+    // 鍩虹閰嶇疆
+    base: {
+        firstLogin: { rule: v => [0, 1].includes(v) }, // 棣栨鐧诲綍鏍囧織
+        brightness: { rule: regnCheck, callback: v => driver.face.setDisplayBacklight(v) }, // 灞忓箷浜害
+        brightnessAuto: { rule: v => [0, 1].includes(v) }, // 鑷姩浜害寮�鍏�
+        showIp: { rule: v => [0, 1].includes(v), callback: v => driver.screen.hideIp(v) }, // 鏄惁鏄剧ずIP鍦板潃
+        showSn: { rule: v => [0, 1].includes(v), callback: v => driver.screen.hideSn(v) }, // 鏄惁鏄剧ず搴忓垪鍙�
+        appMode: { rule: v => [0, 1].includes(v), callback: v => driver.screen.appMode(v) }, // 搴旂敤妯″紡
+        screenOff: { rule: regnCheck, callback: v => bus.fire("screenManagerRefresh") }, // 鐔勫睆鏃堕棿
+        screensaver: { rule: regnCheck, callback: v => bus.fire("screenManagerRefresh") }, // 灞忓箷淇濇姢
+        volume: { rule: regnCheck, callback: v => driver.alsa.volume(v) }, // 闊抽噺璁剧疆
+        password: { rule: v => typeof v == 'string' && v.length >= 8 }, // 绠$悊鍛樺瘑鐮�
+        language: { rule: v => ["EN", "CN"].includes(v), callback: v => driver.screen.changeLanguage() }, // 璇█璁剧疆
+        showProgramCode: { rule: v => [0, 1].includes(v) }, // 鏄惁鏄剧ず绋嬪簭浠g爜
+        showIdentityCard: { rule: v => [0, 1].includes(v) }, // 鏄惁鏄剧ず韬唤璇佷俊鎭�
+        luminanceWhite: { rule: v => typeof v == 'number' && v >= 0 && v <= 100, callback: v => driver.pwm.luminanceWhite(v) }, // 鐧藉厜浜害
+        luminanceNir: { rule: v => typeof v == 'number' && v >= 0 && v <= 100, callback: v => driver.pwm.luminanceNir(v) }, // 绾㈠鍏変寒搴�
+    },
+    // 瀵嗙爜閫氳閰嶇疆
+    passwordAccess: {
+        passwordAccess: { rule: v => [0, 1].includes(v) }, // 瀵嗙爜閫氳寮�鍏�
+        emergencyPassword: { rule: v => typeof v == 'string' && v.length >= 8 }, // 搴旀�ュ紑浠撳瘑鐮�
+    },
+    // HTTP閰嶇疆
+    http: {
+        gas: { rule: v => typeof v == 'string' }, // HTTP_姘斾綋
+        status: { rule: v => typeof v == 'string' }, // HTTP_鐘舵��
+        safeInputAccess: { rule: v => typeof v == 'string' } // HTTP鎺ュ彛璺緞
+    },
+    // 浠撳粧鍚嶇О
+    houseName: {},
+    // 搴撳尯鍚嶇О
+    GranaryName: {},
+    // 鏇存柊閰嶇疆
+    update: {
+        gasTime: { rule: regpCheck }, // 姘斾綋娴撳害鏇存柊鏃堕棿锛堢锛�
+        statusTime: { rule: regpCheck } // 鐘舵�佷俊鎭洿鏂版椂闂达紙绉掞級
+    }
+}
+
+/**
+ * 闇�瑕侀噸鍚殑閰嶇疆椤�
+ */
+const needReboot = ["sys.nfc", "sys.nfcIdentityCardEnable", "ntp"]
+configService.needReboot = needReboot
+
+/**
+ * 淇敼璁惧妯″紡
+ * @param {string} params - 妯″紡鍙傛暟
+ */
+function setMode(params) {
+    common.systemWithRes(`echo 'app' > /etc/.app_v1`, 2)
+    common.setMode(params)
+}
+
+/**
+ * 閰嶇疆json鏍¢獙骞朵繚瀛�
+ * @param {object} data - 閰嶇疆json瀵硅薄
+ * @returns {boolean|string} true琛ㄧず鏍¢獙骞朵繚瀛樻垚鍔燂紝string琛ㄧず閿欒淇℃伅
+ */
+configService.configVerifyAndSave = function (data) {
+    let netFlag = false // 缃戠粶閰嶇疆鏍囧織
+    let mqttFlag = false // MQTT閰嶇疆鏍囧織
+    let isReboot = false // 鏄惁闇�瑕侀噸鍚�
+    
+    for (const key in data) {
+        if (key == 'net') {
+            netFlag = true
+        }
+        if (key == 'mqtt') {
+            mqttFlag = true
+        }
+        
+        // 妫�鏌ラ厤缃粍鏄惁鏀寔
+        if (!supported[key]) {
+            return key + " not supported"
+        }
+        
+        const item = data[key];
+        if (typeof item != 'object') {
+            // 椤跺眰閰嶇疆椤癸紝鐩存帴淇濆瓨
+            config.set(key, item)
+            continue
+        }
+        
+        // 妫�鏌ユ槸鍚﹂渶瑕侀噸鍚�
+        if (needReboot.includes(key)) {
+            isReboot = true
+        }
+        
+        for (const subKey in item) {
+            let option = supported[key][subKey]
+            if (isEmpty(option)) {
+                return subKey + " not supported"
+            }
+            
+            const value = item[subKey];
+            
+            // 妫�鏌ユ槸鍚﹂渶瑕侀噸鍚�
+            if (needReboot.includes(key + "." + subKey)) {
+                isReboot = true
+            }
+            
+            // 鏍¢獙閰嶇疆鍊�
+            if (!option.rule || option.rule(value)) {
+                // 娌℃湁鏍¢獙瑙勫垯榛樿鏍¢獙閫氳繃
+                config.set(key + "." + subKey, value)
+                if (option.callback) {
+                    // 鎵ц閰嶇疆璁剧疆鍥炶皟
+                    option.callback(value)
+                }
+            } else {
+                return value + " check failure"
+            }
+        }
+    }
+    
+    // 淇濆瓨閰嶇疆
+    config.save()
+    
+    // 妫�鏌ラ渶瑕侀噸鍚殑閰嶇疆锛�3绉掑悗閲嶅惎
+    if (isReboot) {
+        driver.screen.upgrade({ title: "confirm.restartDevice", content: "confirm.restartDeviceDis" })
+        common.asyncReboot(3)
+    }
+    
+    // 澶勭悊缃戠粶閰嶇疆鍙樻洿
+    if (netFlag) {
+        // 绛夊緟 1 绉� 鍥犱负闇�瑕佽繑鍥� mqtt
+        std.setTimeout(() => {
+            bus.fire("switchNetworkType", config.get("net.type"))
+        }, 1000);
+    }
+    
+    // 澶勭悊MQTT閰嶇疆鍙樻洿
+    if (mqttFlag) {
+        let option = { 
+            mqttAddr: config.get("mqtt.addr"), 
+            clientId: config.get('mqtt.clientId') + std.genRandomStr(3), 
+            subs: mqttService.getTopics(), 
+            username: config.get("mqtt.username"), 
+            password: config.get("mqtt.password"), 
+            qos: config.get("mqtt.qos"), 
+            willTopic: config.get("mqtt.willTopic"), 
+            willMessage: JSON.stringify({ "uuid": config.get("sys.uuid") }) 
+        }
+        logger.info("閲嶅惎mqtt", JSON.stringify(option))
+        // 閿�姣� mqtt 閲嶆柊 init
+        bus.fire(mqtt.RECONNECT, option)
+    }
+    
+    // 瑙﹀彂閰嶇疆鏇存柊浜嬩欢锛岄�氱煡鍏朵粬妯″潡閰嶇疆宸叉洿鏂�
+    bus.fire('configUpdated')
+    
+    return true
+}
+
+/**
+ * 鍒ょ┖鍑芥暟
+ * @param {*} value - 瑕佸垽鏂殑鍊�
+ * @returns {boolean} true琛ㄧず鍊间负绌猴紝false琛ㄧず鍊间笉涓虹┖
+ */
+function isEmpty(value) {
+    return value === undefined || value === null
+}
+
+export default configService
\ No newline at end of file
diff --git a/vf205_access/src/service/faceService.js b/vf205_access/src/service/faceService.js
new file mode 100644
index 0000000..a84aab1
--- /dev/null
+++ b/vf205_access/src/service/faceService.js
@@ -0,0 +1,447 @@
+/**
+ * 浜鸿劯璇嗗埆鏈嶅姟妯″潡
+ * 澶勭悊浜鸿劯璇嗗埆鐩稿叧鐨勪笟鍔¢�昏緫锛屽寘鎷汉鑴告敞鍐屽拰浜鸿劯姣斿
+ */
+import logger from "../../dxmodules/dxLogger.js";
+import dxCommon from "../../dxmodules/dxCommon.js";
+import bus from "../../dxmodules/dxEventBus.js";
+import dxMap from "../../dxmodules/dxMap.js";
+import driver from "../driver.js";
+import config from "../../dxmodules/dxConfig.js";
+import sqliteService from "./sqliteService.js";
+import std from "../../dxmodules/dxStd.js";
+import pool from "../../dxmodules/dxWorkerPool.js";
+
+let map = dxMap.get("LOGIN")
+const faceService = {}
+
+// 璇煶鎾斁闃叉姈鎺у埗
+let lastPlayTime = 0
+const PLAY_DELAY = 2000 // 2绉掑唴涓嶉噸澶嶆挱鏀剧浉鍚岃闊�
+
+/**
+ * 璇煶鎾斁闃叉姈鍑芥暟
+ * @param {function} playFunction - 鎾斁鍑芥暟
+ * @returns {boolean} 鏄惁鎵ц浜嗘挱鏀�
+ */
+function debouncePlay(playFunction) {
+    const now = Date.now()
+    if (now - lastPlayTime > PLAY_DELAY) {
+        lastPlayTime = now
+        playFunction()
+        return true
+    }
+    return false
+}
+
+// 鍙屼汉璁よ瘉鐘舵�佺鐞�
+let dualAuthState = {
+    firstUserId: null, // 绗竴涓敤鎴稩D
+    firstUserName: null, // 绗竴涓敤鎴峰鍚�
+    firstUserFileName: null, // 绗竴涓敤鎴蜂汉鑴稿浘鐗囨枃浠惰矾寰�
+    firstUserIdCard: null, // 绗竴涓敤鎴疯韩浠借瘉鍙�
+    firstUserType: null, // 绗竴涓敤鎴疯韩浠界被鍨�
+    secondUserId: null, // 绗簩涓敤鎴稩D
+    secondUserName: null, // 绗簩涓敤鎴峰鍚�
+    secondUserIdCard: null, // 绗簩涓敤鎴疯韩浠借瘉鍙�
+    secondUserType: null, // 绗簩涓敤鎴疯韩浠界被鍨�
+    startTime: 0, // 寮�濮嬫椂闂�
+    timeout: null, // 瀹氭椂鍣�
+    authComplete: false // 璁よ瘉鏄惁瀹屾垚
+}
+
+/**
+ * 鎺ユ敹浜鸿劯璇嗗埆娑堟伅骞跺鐞�
+ * @param {object} data - 浜鸿劯璇嗗埆鏁版嵁
+ */
+faceService.receiveMsg = function (data) {
+    logger.info('[faceService] receiveMsg :' + JSON.stringify(data))
+    // 瑙﹀彂閫�鍑虹┖闂茬姸鎬佷簨浠讹紙閿佸睆鍜屾伅灞忥級
+    bus.fire("exitIdle")
+
+    switch (data.type) {
+        case "register":
+            // 娉ㄥ唽浜鸿劯澶勭悊
+            for (let i = 0; i < data.faces.length; i++) {
+                const element = data.faces[i];
+                bus.fire("beginAddFace", element)
+            }
+            break;
+        case "compare":
+            // 浜鸿劯姣斿澶勭悊
+            // 鏄剧ず濮撳悕锛屼唬琛ㄦ湁娉ㄥ唽杩囦汉鑴革紝浣嗘槸鏉冮檺涓嶄竴瀹氭湁鏁堬紝闇�瑕佽繘涓�姝ヨ璇�
+            for (let i = 0; i < data.faces.length; i++) {
+                const element = data.faces[i];
+                
+                // 鍙湁鍦ㄨ璇佹湭瀹屾垚鏃舵墠瑙﹀彂trackResult浜嬩欢
+                if (!dualAuthState.authComplete) {
+                    // 鍒ゆ柇褰撳墠鏄鍑犱釜鐢ㄦ埛锛堢敤浜庡弻浜鸿璇侊級
+                    let userIndex = 1 // 0琛ㄧず鏈煡锛�1琛ㄧず绗竴涓敤鎴凤紝2琛ㄧず绗簩涓敤鎴�
+                    if (!dualAuthState.firstUserId) {
+                        // 绗竴涓敤鎴疯繕鏈缃紝褰撳墠鐢ㄦ埛灏辨槸绗竴涓敤鎴�
+                        userIndex = 1
+                    } else if (element.userId === dualAuthState.firstUserId) {
+                        userIndex = 1
+                    } else if (element.userId !== dualAuthState.firstUserId) {
+                        userIndex = 2
+                    }
+                    
+                    logger.info('[faceService]: 鍑嗗瑙﹀彂trackResult浜嬩欢, userIndex=' + userIndex + ', result=' + element.result + ', userId=' + element.userId + ', authComplete=' + dualAuthState.authComplete + ', fileName=' + element.fileName)
+                    
+                    // 鐩存帴浣跨敤bus.fire瑙﹀彂trackResult浜嬩欢
+                    bus.fire("trackResult", { id: element.id, result: element.result, userId: element.userId, userIndex: userIndex, fileName: element.fileName })
+                }
+                
+                if (element.result) {
+                    // 浜鸿劯鐩镐技搴﹂獙璇侀�氳繃
+                    let ret = sqliteService.d1_person.find({ userId: element.userId })
+                    
+                    if (dxMap.get("UI").get("faceAuthStart") == "Y") {
+                        // 姝e湪浜鸿劯鐧诲綍
+                        if (JSON.parse(ret[0].extra).type != 0) {
+                            bus.fire("faceAuthResult", true)
+                        } else {
+                            bus.fire("faceAuthResult", false)
+                        }
+                        return
+                    }
+
+                    // 妫�鏌ョ敤鎴风被鍨嬶紙绠$悊鍛樼骇鍒級
+                    let userType = 0
+                    try {
+                        userType = JSON.parse(ret[0].extra).type || 0
+                    } catch (error) {
+                        logger.error("瑙f瀽鐢ㄦ埛绫诲瀷澶辫触")
+                    }
+
+                    // 绠$悊鍛樼骇鍒敤鎴凤紙type != 0锛夌洿鎺ヨ璇侀�氳繃
+                    if (userType != 0) {
+                        // 娓呴櫎鍙屼汉璁よ瘉鐘舵��
+                        clearDualAuthState()
+                        
+                        // 鏍规嵁璇煶妯″紡鎾斁鐩稿簲鐨勮闊�
+                        switch (config.get("face.voiceMode")) {
+                            case 0:
+                                // 鏃犺闊�
+                                break;
+                            case 1:
+                                // 鎾斁鍚嶅瓧
+                                driver.alsa.ttsPlay(ret[0].name)
+                                break;
+                            case 2:
+                                // 鎾斁闂�欒
+                                driver.alsa.ttsPlay(config.get("face.voiceModeDate") ? config.get("face.voiceModeDate") : "娆㈣繋鍏変复")
+                                break;
+                            default:
+                                break;
+                        }
+
+                        // 閫氳璁よ瘉澶勭悊
+                        bus.fire("access", { data: { type: "300", code: element.userId }, fileName: element.fileName })
+                    } else {
+                        // 闈炵鐞嗗憳绾у埆鐢ㄦ埛锛岄渶瑕佸弻浜鸿璇�
+                        handleDualAuth(element.userId, ret[0].name, element.fileName)
+                    }
+                } else {
+                    // 浜鸿劯鐩镐技搴﹂獙璇佸け璐�
+                    if (dxMap.get("UI").get("faceAuthStart") == "Y") {
+                        // 浜鸿劯鐧诲綍澶辫触
+                        bus.fire("faceAuthResult", false)
+                    } else {
+                        // 闄岀敓浜哄鐞�
+                        switch (config.get("face.stranger")) {
+                            case 0:
+                                // 鏃犺闊�
+                                break;
+                            case 1:
+                                // 鎾斁璇峰厛娉ㄥ唽锛堥槻鎶栨帶鍒讹級
+                                debouncePlay(() => {
+                                    driver.alsa.play(`/app/code/resource/${config.get("base.language") == "CN" ? "CN" : "EN"}/wav/register.wav`)
+                                })
+                                break;
+                            case 2:
+                                // 鎾斁闄岀敓浜轰綘濂斤紙闃叉姈鎺у埗锛�
+                                debouncePlay(() => {
+                                    driver.alsa.play(`/app/code/resource/${config.get("base.language") == "CN" ? "CN" : "EN"}/wav/stranger.wav`)
+                                })
+                                break;
+                            default:
+                                break;
+                        }
+                        // 閫氳璁よ瘉澶勭悊锛堢浉浼煎害楠岃瘉澶辫触锛�
+                        bus.fire("access", { data: { type: "300", code: element.userId }, fileName: element.fileName, similarity: false })
+                    }
+                }
+            }
+            break;
+        default:
+            break;
+    }
+}
+
+// 鐩戝惉閫氳瑙i攣瀹屾垚浜嬩欢锛岄噸缃弻浜鸿璇佺姸鎬�
+bus.on('accessUnlockComplete', () => {
+    logger.info('[faceService]: accessUnlockComplete浜嬩欢瑙﹀彂锛岄噸缃弻浜鸿璇佺姸鎬�')
+    clearDualAuthState()
+})
+
+/**
+ * 娓呴櫎鍙屼汉璁よ瘉鐘舵��
+ */
+function clearDualAuthState() {
+    dualAuthState.firstUserId = null
+    dualAuthState.firstUserName = null
+    dualAuthState.firstUserFileName = null
+    dualAuthState.firstUserIdCard = null
+    dualAuthState.firstUserType = null
+    dualAuthState.secondUserId = null
+    dualAuthState.secondUserName = null
+    dualAuthState.secondUserIdCard = null
+    dualAuthState.secondUserType = null
+    dualAuthState.startTime = 0
+    dualAuthState.authComplete = false // 閲嶇疆璁よ瘉瀹屾垚鏍囧織
+    if (dualAuthState.timeout) {
+        std.clearTimeout(dualAuthState.timeout)
+        dualAuthState.timeout = null
+    }
+}
+
+/**
+ * 澶勭悊鍙屼汉璁よ瘉瓒呮椂
+ */
+function handleDualAuthTimeout() {
+    try {
+        // 淇濆瓨璁よ瘉璁板綍
+        if (dualAuthState.firstUserId && !dualAuthState.authComplete) {
+            // 鏌ヨ绗竴鐢ㄦ埛鐨勮缁嗕俊鎭紝鑾峰彇韬唤绫诲瀷
+            let firstUserType = dualAuthState.firstUserType || 0
+            if (!firstUserType) {
+                let res = sqliteService.d1_person.findByUserId(dualAuthState.firstUserId)
+                if (res.length > 0) {
+                    try {
+                        firstUserType = JSON.parse(res[0].extra).type || 0
+                    } catch (error) {
+                        logger.error("鏃犵涓�鐢ㄦ埛绫诲瀷")
+                    }
+                }
+            }
+            
+            // 鏌ヨ绗簩鐢ㄦ埛鐨勮缁嗕俊鎭紝鑾峰彇韬唤绫诲瀷
+            let secondUserType = dualAuthState.secondUserType || 0
+            if (dualAuthState.secondUserId && !secondUserType) {
+                let res = sqliteService.d1_person.findByUserId(dualAuthState.secondUserId)
+                if (res.length > 0) {
+                    try {
+                        secondUserType = JSON.parse(res[0].extra).type || 0
+                    } catch (error) {
+                        logger.error("鏃犵浜岀敤鎴风被鍨�")
+                    }
+                }
+            }
+            
+            // 鍒涘缓璁よ瘉璁板綍
+            const record = {
+                id: std.genRandomStr(16),
+                userId: dualAuthState.firstUserId,
+                userId2: dualAuthState.secondUserId || "",
+                type: "300", // 浜鸿劯璁よ瘉锛堝瓧绗︿覆鏍煎紡锛�
+                code: dualAuthState.firstUserFileName, // 浜鸿劯鎶撴媿鍥剧墖璺緞
+                result: 1, // 璁よ瘉澶辫触锛�0鎴愬姛锛�1澶辫触锛�
+                time: Math.floor(Date.now() / 1000), // 鏃堕棿鎴筹紙绉掞級
+                message: "鍙屼汉璁よ瘉瓒呮椂",
+                extra: JSON.stringify({ name: dualAuthState.firstUserName, idCard: dualAuthState.firstUserIdCard, type: firstUserType }),
+                extra2: dualAuthState.secondUserId ? JSON.stringify({ name: dualAuthState.secondUserName || "", idCard: dualAuthState.secondUserIdCard || "", type: secondUserType }) : "",
+                permissionId: firstUserType.toString(),
+                permissionId2: dualAuthState.secondUserId ? secondUserType.toString() : ""
+            }
+            
+            // 淇濆瓨鍒版暟鎹簱
+            sqliteService.d1_pass_record.save(record)
+            logger.info(`[faceService]: 淇濆瓨鍙屼汉璁よ瘉瓒呮椂璁板綍: ${JSON.stringify(record)}`)
+        }
+        
+        // 娓呴櫎璁よ瘉鐘舵��
+        clearDualAuthState()
+        
+        // 鎾斁澶辫触鎻愮ず闊�
+        driver.alsa.play(`/app/code/resource/${config.get("base.language") == "CN" ? "CN" : "EN"}/wav/verify_300_f.wav`)
+        
+        // 璇煶鎻愮ず璁よ瘉澶辫触
+        // driver.alsa.ttsPlay("鍙屼汉璁よ瘉瓒呮椂锛岃璇佸け璐�")
+        
+        // 瑙﹀彂璁よ瘉澶辫触浜嬩欢
+        bus.fire("showAccessResult", {
+            faceAuth: false,
+            gasConcentration: true,
+            accessAllowed: false,
+            message: "*鍙屼汉璁よ瘉瓒呮椂锛岃璇佸け璐�*"
+        })
+        
+        // 瑙﹀彂閫氳澶辫触浜嬩欢锛岄�氱煡UI閲嶇疆
+        bus.fire("accessRes", false)
+        
+
+    } catch (error) {
+        logger.error(`[faceService]: 澶勭悊鍙屼汉璁よ瘉瓒呮椂閿欒: ${error.message}`)
+    }
+}
+
+/**
+ * 澶勭悊鍙屼汉璁よ瘉閫昏緫
+ * @param {string} userId - 褰撳墠鐢ㄦ埛ID
+ * @param {string} userName - 褰撳墠鐢ㄦ埛濮撳悕
+ * @param {string} fileName - 浜鸿劯鍥剧墖鏂囦欢璺緞
+ */
+function handleDualAuth(userId, userName, fileName) {
+    try {
+        if (!dualAuthState.firstUserId) {
+            // 绗竴娆¤璇�
+            dualAuthState.firstUserId = userId
+            dualAuthState.firstUserName = userName
+            dualAuthState.firstUserFileName = fileName
+            
+            // 鏌ヨ绗竴鐢ㄦ埛鐨勮缁嗕俊鎭紝鑾峰彇韬唤璇佸彿鍜岃韩浠界被鍨�
+            let res = sqliteService.d1_person.findByUserId(userId)
+            if (res.length > 0) {
+                let idCard
+                let userType = 0
+                try {
+                    idCard = JSON.parse(res[0].extra).idCard
+                    userType = JSON.parse(res[0].extra).type || 0
+                } catch (error) {
+                    logger.error("鏃犵涓�鐢ㄦ埛韬唤璇佸彿鎴栫被鍨�")
+                }
+                dualAuthState.firstUserIdCard = idCard
+                dualAuthState.firstUserType = userType
+            }
+            
+            dualAuthState.startTime = Date.now()
+            
+            // 娓呴櫎涔嬪墠鐨勫畾鏃跺櫒
+            if (dualAuthState.timeout) {
+                std.clearTimeout(dualAuthState.timeout)
+            }
+            
+            // 璁剧疆1鍒嗛挓瓒呮椂
+            dualAuthState.timeout = std.setTimeout(() => {
+                // 瓒呮椂澶勭悊锛岃涓鸿璇佸け璐�
+                handleDualAuthTimeout()
+            }, 60000)
+            
+            // 璇煶鎻愮ず-璇风浜岀敤鎴疯繘琛岃璇�
+            driver.alsa.play(`/app/code/resource/${config.get("base.language") == "CN" ? "CN" : "EN"}/wav/user2.wav`)
+        } else {
+            // 绗簩娆¤璇�
+            if (userId !== dualAuthState.firstUserId) {
+                // 涓嶅悓鐢ㄦ埛锛岃璇侀�氳繃
+                // 鏌ヨ绗簩鐢ㄦ埛鐨勮缁嗕俊鎭紝鑾峰彇韬唤璇佸彿鍜岃韩浠界被鍨�
+                let secondUserIdCard = ""
+                let secondUserType = 0
+                let res = sqliteService.d1_person.findByUserId(userId)
+                if (res.length > 0) {
+                    try {
+                        secondUserIdCard = JSON.parse(res[0].extra).idCard
+                        secondUserType = JSON.parse(res[0].extra).type || 0
+                    } catch (error) {
+                        logger.error("鏃犵浜岀敤鎴疯韩浠借瘉鍙锋垨绫诲瀷")
+                    }
+                }
+                
+                // 淇濆瓨鍙屼汉璁よ瘉鐘舵�佷俊鎭紝鐢ㄤ簬UI鏇存柊
+                let dualAuthInfo = {
+                    firstUserId: dualAuthState.firstUserId,
+                    firstUserName: dualAuthState.firstUserName,
+                    secondUserId: userId,
+                    secondUserName: userName,
+                    secondUserIdCard: secondUserIdCard,
+                    secondUserType: secondUserType
+                }
+                // 淇濆瓨绗竴鐢ㄦ埛鐨勪汉鑴稿浘鐗囪矾寰�
+                let firstUserFileName = dualAuthState.firstUserFileName
+                // 璁剧疆璁よ瘉瀹屾垚鏍囧織
+                dualAuthState.authComplete = true
+                clearDualAuthState()
+                
+                // 璇煶鎻愮ず-鍙屼汉璁よ瘉閫氳繃
+                driver.alsa.play(`/app/code/resource/${config.get("base.language") == "CN" ? "CN" : "EN"}/wav/user2_s.wav`)
+                
+                // 閫氳璁よ瘉澶勭悊锛屼紶閫掑弻浜鸿璇佷俊鎭�
+                bus.fire("access", { data: { type: "300", code: userId, dualAuthInfo: dualAuthInfo, authComplete: true, firstUserFileName: firstUserFileName }, fileName: fileName })
+            } else {
+                // 鍚屼竴鐢ㄦ埛锛岄噸鏂板紑濮�
+                dualAuthState.firstUserId = userId
+                dualAuthState.firstUserName = userName
+                
+                // 鏌ヨ鐢ㄦ埛鐨勮缁嗕俊鎭紝鑾峰彇韬唤璇佸彿鍜岃韩浠界被鍨�
+                let idCard
+                let userType = 0
+                let res = sqliteService.d1_person.findByUserId(userId)
+                if (res.length > 0) {
+                    try {
+                        idCard = JSON.parse(res[0].extra).idCard
+                        userType = JSON.parse(res[0].extra).type || 0
+                    } catch (error) {
+                        logger.error("鏃犵敤鎴疯韩浠借瘉鍙锋垨绫诲瀷")
+                    }
+                    dualAuthState.firstUserIdCard = idCard
+                    dualAuthState.firstUserType = userType
+                }
+                
+                dualAuthState.startTime = Date.now()
+                
+                // 娓呴櫎涔嬪墠鐨勫畾鏃跺櫒
+                if (dualAuthState.timeout) {
+                    std.clearTimeout(dualAuthState.timeout)
+                }
+                
+                // 閲嶆柊璁剧疆1鍒嗛挓瓒呮椂
+                dualAuthState.timeout = std.setTimeout(() => {
+                    // 瓒呮椂澶勭悊锛岃涓鸿璇佸け璐�
+                    handleDualAuthTimeout()
+                }, 60000)
+                
+                // 璇煶鎻愮ず-璇风浜岀敤鎴疯繘琛岃璇�
+                driver.alsa.play(`/app/code/resource/${config.get("base.language") == "CN" ? "CN" : "EN"}/wav/user2.wav`)
+            }
+        }
+    } catch (error) {
+        logger.error(`[faceService]: 澶勭悊鍙屼汉璁よ瘉閿欒: ${error.message}`)
+        // 娓呴櫎璁よ瘉鐘舵��
+        clearDualAuthState()
+    }
+}
+/**
+ * 浜鸿劯娉ㄥ唽閿欒鏋氫妇
+ * 鍖呭惈鍚勭娉ㄥ唽澶辫触鐨勯敊璇爜鍜屽搴旂殑閿欒淇℃伅
+ */
+faceService.regErrorEnum = {
+    "callback": {
+        title: "娉ㄥ唽鍥炶皟鐘舵�佹灇涓�",
+        "-1": "faceService.contrastFailure",        // 瀵规瘮澶辫触
+        "-2": "faceService.scalingFailure",         // 缂╂斁澶辫触
+        "-3": "faceService.failedToSavePicture",    // 淇濆瓨鍥剧墖澶辫触
+        "-4": "faceService.convertToBase64Fail",    // 杞崲涓篵ase64澶辫触
+    },
+    "feature": {
+        title: "鐗瑰緛鍊兼敞鍐岀姸鎬佹灇涓�",
+        "-1": "faceService.base64DecodingFail",     // base64瑙g爜澶辫触
+        "-10": "faceService.contrastFailure",       // 瀵规瘮澶辫触
+        "-11": "faceService.similarityOverheight",  // 鐩镐技搴﹁繃楂�
+    },
+    "picture": {
+        title: "鍥剧墖娉ㄥ唽鐘舵�佹灇涓�",
+        "-1": "faceService.fileDoesNotExist",               // 鏂囦欢涓嶅瓨鍦�
+        "-2": "faceService.theImageFormatIsNotSupported",    // 鍥剧墖鏍煎紡涓嶆敮鎸�
+        "-3": "faceService.pictureReadFailure",              // 鍥剧墖璇诲彇澶辫触
+        "-4": "faceService.thePictureSizeDoesNotMatch",      // 鍥剧墖灏哄涓嶅尮閰�
+        "-5": "faceService.imageParsingFailure",             // 鍥剧墖瑙f瀽澶辫触
+        "-6": "faceService.imageYUVProcessingFailed",        // 鍥剧墖YUV澶勭悊澶辫触
+        "-7": "faceService.failedToConvertJpegToImage",      // JPEG杞崲涓哄浘鐗囧け璐�
+        "-8": "faceService.faceInformationExtractionFailed", // 浜鸿劯淇℃伅鎻愬彇澶辫触
+        "-9": "faceService.theFaceIsNotUnique",              // 浜鸿劯涓嶅敮涓�
+        "-10": "faceService.contrastFailure",                // 瀵规瘮澶辫触
+        "-11": "faceService.similarityOverheight",           // 鐩镐技搴﹁繃楂�
+    }
+}
+
+export default faceService
\ No newline at end of file
diff --git a/vf205_access/src/service/gpiokeyService.js b/vf205_access/src/service/gpiokeyService.js
new file mode 100644
index 0000000..bfbae2a
--- /dev/null
+++ b/vf205_access/src/service/gpiokeyService.js
@@ -0,0 +1,52 @@
+/**
+ * GPIO鎸夐敭鏈嶅姟妯″潡
+ * 澶勭悊GPIO鎸夐敭鐩稿叧鐨勪笟鍔¢�昏緫锛屼富瑕佸寘鎷槻鎷嗘姤璀﹀姛鑳�
+ */
+import logger from "../../dxmodules/dxLogger.js";
+import config from "../../dxmodules/dxConfig.js";
+import driver from "../driver.js";
+import bus from "../../dxmodules/dxEventBus.js";
+
+const gpiokeyService = {}
+
+/**
+ * 鎺ユ敹GPIO鎸夐敭娑堟伅骞跺鐞�
+ * @param {object} data - GPIO鎸夐敭鏁版嵁
+ * @param {number} data.code - GPIO鐨勬爣璇嗭紝琛ㄧず鏄摢涓狦PIO鏈夎緭鍏�  256-闃叉媶锛�257-闂ㄧ
+ * @param {number} data.type - 鎸夐敭绫诲瀷锛�1琛ㄧず闃叉媶/闂ㄧ鐘舵�佸彉鍖�
+ * @param {number} data.value - 鎸夐敭鍊硷紝1琛ㄧず瑙﹀彂/闂ㄥ紑锛�0琛ㄧず鏈Е鍙�/闂ㄥ叧
+ */
+gpiokeyService.receiveMsg = function (data) {
+    logger.info('[gpiokeyService] 鎺ユ敹鍒癎PIO娑堟伅:', JSON.stringify(data))
+    
+    // 闃叉媶鎶ヨ澶勭悊
+    if (data.code === 256) {
+        if (config.get("access.tamperAlarm") && data.type == 1 && data.value == 1) {
+            logger.info('[gpiokeyService] 闃叉媶鎶ヨ瑙﹀彂')
+            driver.alsa.play("/app/code/resource/wav/alarm.wav")
+        }
+    }
+    
+    // 闂ㄧ鐘舵�佸彉鍖栧鐞�
+    if (data.code === 257) {
+        const doorStatus = data.value == 1 ? "闂ㄥ紑" : "闂ㄥ叧"
+        logger.info(`[gpiokeyService] 闂ㄧ鐘舵�佸彉鍖�: ${doorStatus}`)
+
+        if (data.value === 1) {
+            // 闂ㄥ紑
+            driver.alsa.play("/app/code/resource/CN/wav/door_open.wav")
+        } else {
+            // 闂ㄥ叧
+            driver.alsa.play("/app/code/resource/CN/wav/door_close.wav")
+        }
+        
+        // 鍙戦�侀棬纾佺姸鎬佸彉鍖栭�氱煡浜嬩欢
+        bus.fire('doorStatusChanged', {
+            status: data.value,
+            statusText: doorStatus,
+            time: Math.floor(Date.now() / 1000)
+        })
+    }
+}
+
+export default gpiokeyService
\ No newline at end of file
diff --git a/vf205_access/src/service/grainService.js b/vf205_access/src/service/grainService.js
new file mode 100644
index 0000000..4c5721c
--- /dev/null
+++ b/vf205_access/src/service/grainService.js
@@ -0,0 +1,676 @@
+/**
+ * 绮儏鏈嶅姟妯″潡
+ * 璐熻矗姘斾綋娴撳害鏁版嵁鑾峰彇鍜岀姸鎬佷俊鎭暟鎹幏鍙�
+ */
+import logger from "../../dxmodules/dxLogger.js"
+import config from "../../dxmodules/dxConfig.js"
+import http from "../../dxmodules/dxHttp.js"
+import bus from '../../dxmodules/dxEventBus.js'
+import std from "../../dxmodules/dxStd.js"
+import driver from "../driver.js"
+const grainService = {}
+
+// 浠庨厤缃腑鑾峰彇涓氬姟缂栫爜瀹氫箟
+const functionId = {
+    gasDetection: config.get('functionId.gasDetection') || "1000",
+    safeInputControl: config.get('functionId.safeInputControl') || "2000",
+    lightControl: config.get('functionId.lightControl') || "3000",
+    doorStatus: config.get('functionId.doorStatus') || "4000"
+}
+
+// 浠庨厤缃腑鑾峰彇鎺ュ彛杩斿洖缂栫爜
+const respCode = {
+    success: config.get('respCode.success') || "200",
+    badRequest: config.get('respCode.badRequest') || "400",
+    unauthorized: config.get('respCode.unauthorized') || "401",
+    forbidden: config.get('respCode.forbidden') || "403",
+    notFound: config.get('respCode.notFound') || "404",
+    serverError: config.get('respCode.serverError') || "500"
+}
+
+// 閿欒鐮佸搴旂殑閿欒淇℃伅
+const errorMessages = {
+    "400": "璇锋眰鍙傛暟鏈夎",
+    "401": "鏈櫥褰曪紝鐢ㄦ埛涓嶅瓨鍦�",
+    "403": "鐢ㄦ埛鏃犳潈闄�",
+    "404": "璇锋眰鍔熻兘涓嶅瓨鍦�",
+    "500": "璇锋眰鎵ц寮傚父锛岃鑱旂郴绠$悊鍛�"
+}
+
+// 鎿嶄綔鎸夐挳瀵瑰簲鐨勮闊虫枃浠�
+const voiceFiles = {
+    // 鍏佽杩涗粨妯″紡
+    "11": "btn11.wav", // 鍏佽杩涗粨妯″紡
+    "12": "btn12.wav", // 鍏ヤ粨
+    "13": "btn13.wav", // 鍑轰粨
+    // 鍐閫氶妯″紡
+    "21": "btn21.wav", // 鍐閫氶妯″紡
+    "22": "btn22.wav", // 鍚姩
+    "23": "btn23.wav", // 鍏抽棴
+    // 绂佹杩涗粨妯″紡
+    "31": "btn31.wav", // 绂佹杩涗粨妯″紡
+    "32": "btn32.wav", // 绱ф�ュ叆浠�
+    "33": "btn33.wav", // 鍑轰粨
+    // 鐓ф槑鎺у埗
+    "light_open": "light_open.wav", // 寮�鐏�
+    "light_close": "light_close.wav" // 鍏崇伅
+}
+
+/**
+ * 鏍规嵁閿欒鐮佽幏鍙栭敊璇俊鎭�
+ * @param {string} code - 閿欒鐮�
+ * @returns {string} 閿欒淇℃伅
+ */
+function getErrorMessage(code) {
+    return errorMessages[code] || "鎿嶄綔澶辫触"
+}
+
+/**
+ * 鏍规嵁鎿嶄綔鎸夐挳鍜屽姛鑳界爜鑾峰彇璇煶鏂囦欢
+ * @param {string} functionId - 鍔熻兘鐮�
+ * @param {object} params - 璇锋眰鍙傛暟锛屽寘鍚玬ode鍜宐tn
+ * @returns {string} 璇煶鏂囦欢璺緞
+ */
+function getVoiceFile(functionId, params) {
+    // 鐓ф槑鎺у埗鍔熻兘
+    if (functionId === "3000") {
+        // 寮�鐏�
+        if (String(params.btn) === "1") return voiceFiles["light_open"]
+        // 鍏崇伅
+        if (String(params.btn) === "2") return voiceFiles["light_close"]
+    }
+    // 瀹夊叏鍏ヤ粨鎺у埗鍔熻兘
+    if (functionId === "2000" && params) {
+        const { mode, btn } = params
+        // 妯″紡1: 鍏佽杩涗粨妯″紡
+        if (mode === 1) {
+            if (!btn) return voiceFiles["11"] // 鍏佽杩涗粨妯″紡鎸夐挳
+            if (String(btn) === "1") return voiceFiles["12"] // 鍏ヤ粨鎸夐挳
+            if (String(btn) === "2") return voiceFiles["13"] // 鍑轰粨鎸夐挳
+        }
+        // 妯″紡2: 鍐閫氶妯″紡
+        if (mode === 2) {
+            if (!btn) return voiceFiles["21"] // 鍐閫氶妯″紡鎸夐挳
+            if (String(btn) === "1") return voiceFiles["22"] // 鍚姩鎸夐挳
+            if (String(btn) === "2") return voiceFiles["23"] // 鍏抽棴鎸夐挳
+        }
+        // 妯″紡3: 绂佹杩涗粨妯″紡
+        if (mode === 3) {
+            if (!btn) return voiceFiles["31"] // 绂佹杩涗粨妯″紡鎸夐挳
+            if (String(btn) === "1") return voiceFiles["32"] // 绱ф�ュ叆浠撴寜閽�
+            if (String(btn) === "2") return voiceFiles["33"] // 鍑轰粨鎸夐挳
+        }
+    }
+    return null
+}
+
+// 浠庨厤缃腑鑾峰彇HTTP鎺ュ彛璺緞
+function getHttpUrl() {
+    return config.get('http.safeInputAccess') || "http://192.168.1.199:80/cgi-bin/safeInputAccess"
+}
+
+// 瀛樺偍姘斾綋娴撳害鏁版嵁
+let gasDataStorage = null
+
+/**
+ * 妫�鏌ユ皵浣撴祿搴�
+ * @param {function} callback - 鍥炶皟鍑芥暟锛屽湪姘斾綋娴撳害妫�娴嬪畬鎴愬悗璋冪敤
+ * @returns {boolean} true琛ㄧず姘斾綋娴撳害鍚堟牸锛宖alse琛ㄧず姘斾綋娴撳害涓嶅悎鏍�
+ */
+grainService.checkGasConcentration = function(callback) {
+    // 浣跨敤setTimeout灏咹TTP璇锋眰鏀惧叆鍚庡彴鎵ц锛岄伩鍏嶉樆濉炰富绾跨▼
+    std.setTimeout(() => {
+        try {
+            // 纭繚URL鏍煎紡姝g‘锛屾坊鍔爃ttp://鍓嶇紑
+            let url = getHttpUrl()
+            if (!url.startsWith('http://') && !url.startsWith('https://')) {
+                url = 'http://' + url
+            }
+            
+            const timeout = 3000 // 3绉掕秴鏃�
+            
+            logger.info(`[grain]: 姝e湪鑾峰彇姘斾綋娴撳害鏁版嵁: ${url}`)
+            
+            // 鏋勫缓POST璇锋眰鏁版嵁
+            const postData = {
+                sn: config.get("sys.sn") || " ", // 璁惧搴忓垪鍙凤紝浠庨厤缃腑鑾峰彇
+                houseId: "0000", // 浠撳粧缂栫爜锛岄粯璁ゅ~鍏�"0000"
+                outId: "0000", // 鑷畾涔夌紪鐮侊紝榛樿濉厖"0000"
+                functionId: functionId.gasDetection, // 姘斾綋娴撳害妫�娴嬪姛鑳界爜
+                timestamp: Date.now().toString() // 鏃堕棿鎴�
+            }
+            
+            logger.info(`[grain]: 鍙戦�丳OST璇锋眰鏁版嵁: ${JSON.stringify(postData)}`)
+            
+            // 鍙戦�丠TTP POST璇锋眰
+            let response = http.post(url, postData, timeout)
+            
+            // logger.info(`[grain]: 姘斾綋娴撳害鏁版嵁鍝嶅簲: ${JSON.stringify(response)}`)
+            
+            // 瑙f瀽鍝嶅簲鏁版嵁
+            // 妫�鏌esponse鏄惁涓哄瓧绗︿覆锛屽鏋滄槸鍒欒В鏋愪负瀵硅薄
+            if (typeof response === 'string') {
+                response = JSON.parse(response)
+            }
+            
+            if (response && response.body) {
+                // 瑙f瀽鍝嶅簲浣�
+                let gasData
+                try {
+                    gasData = JSON.parse(response.body)
+                    logger.info(`[grain]: 瑙f瀽鍚庣殑姘斾綋娴撳害鏁版嵁: ${JSON.stringify(gasData)}`)
+                    
+                    // 鏍规嵁鎺ュ彛杩斿洖缂栫爜杩涜鏃ュ織杈撳嚭
+                    if (gasData.respCode === respCode.success) {
+                        logger.info(`[grain]: 姘斾綋娴撳害妫�娴嬫帴鍙h皟鐢ㄦ垚鍔焋)
+                    } else {
+                        logger.error(`[grain]: 姘斾綋娴撳害妫�娴嬫帴鍙h皟鐢ㄥけ璐ワ紝杩斿洖缂栫爜: ${gasData.respCode}, 杩斿洖淇℃伅: ${gasData.respMsg}`)
+                    }
+                } catch (parseError) {
+                    logger.error(`[grain]: 瑙f瀽姘斾綋娴撳害鏁版嵁澶辫触: ${parseError.message}`)
+                    // 灏濊瘯娓呯悊鍝嶅簲浣撲腑鐨勮浆涔夊瓧绗�
+                    try {
+                        // 绉婚櫎澶氫綑鐨勮浆涔夊瓧绗�
+                        const cleanedBody = response.body.replace(/\\r\\n/g, '').replace(/\\t/g, '').replace(/\"/g, '"')
+                        gasData = JSON.parse(cleanedBody)
+                        logger.info(`[grain]: 娓呯悊鍚庤В鏋愮殑姘斾綋娴撳害鏁版嵁: ${JSON.stringify(gasData)}`)
+                        
+                        // 鏍规嵁鎺ュ彛杩斿洖缂栫爜杩涜鏃ュ織杈撳嚭
+                        if (gasData.respCode === respCode.success) {
+                            logger.info(`[grain]: 姘斾綋娴撳害妫�娴嬫帴鍙h皟鐢ㄦ垚鍔焋)
+                        } else {
+                            logger.error(`[grain]: 姘斾綋娴撳害妫�娴嬫帴鍙h皟鐢ㄥけ璐ワ紝杩斿洖缂栫爜: ${gasData.respCode}, 杩斿洖淇℃伅: ${gasData.respMsg}`)
+                        }
+                    } catch (cleanError) {
+                        logger.error(`[grain]: 娓呯悊鍚庤В鏋愭皵浣撴祿搴︽暟鎹粛澶辫触: ${cleanError.message}`)
+                        // 璋冪敤鍥炶皟鍑芥暟
+                        if (callback) {
+                            callback()
+                        }
+                        return
+                    }
+                }
+                
+                // 瀛樺偍姘斾綋鏁版嵁
+                gasDataStorage = gasData
+                
+                // 妫�鏌ユ皵浣撴祿搴︽槸鍚﹀悎鏍�
+                // 鏂版牸寮�: {"value":[{"o2":"20.5","statusO2":"0","co2":"401","statusCo2":"0","ph3":"0","statusPh3":"0"}],"status":"1"}
+                // statusO2/statusCo2/statusPh3: "0"琛ㄧず鍚堟牸锛�"1"琛ㄧず涓嶅悎鏍硷紙浠呯敤浜嶶I鏄剧ず锛�
+                // data.status: "0"琛ㄧず鏈�缁堝悎鏍硷紝"1"琛ㄧず鏈�缁堜笉鍚堟牸
+                const gasValue = gasData.data && gasData.data.value ? gasData.data.value[0] : null
+                const isO2Qualified = gasValue && gasValue.statusO2 === "0"
+                const isCo2Qualified = gasValue && gasValue.statusCo2 === "0"
+                const isPh3Qualified = gasValue && gasValue.statusPh3 === "0"
+                
+                // 瑙﹀彂浜嬩欢鏇存柊UI
+                bus.fire('gasConcentrationUpdated', gasData)
+                
+                // 鏈�缁堝悎鏍煎垽鏂彧渚濊禆status瀛楁鍊�
+                const isAllQualified = gasData.data && gasData.data.status === "0"
+                
+                if (isAllQualified) {
+                    logger.info("[grain]: 姘斾綋娴撳害妫�娴嬪悎鏍�")
+                } else {
+                    logger.info("[grain]: 姘斾綋娴撳害妫�娴嬩笉鍚堟牸")
+                }
+                
+                // 璋冪敤鍥炶皟鍑芥暟
+                if (callback) {
+                    callback()
+                }
+            } else {
+                logger.error(`[grain]: 姘斾綋娴撳害鏁版嵁鑾峰彇澶辫触: ${response ? "鏃犲搷搴斾綋" : "鏃犲搷搴�"}`)
+                // 璋冪敤鍥炶皟鍑芥暟
+                if (callback) {
+                    callback()
+                }
+            }
+        } catch (error) {
+            logger.error(`[grain]: 姘斾綋娴撳害妫�娴嬮敊璇�: ${error.message}`)
+            // 璋冪敤鍥炶皟鍑芥暟
+            if (callback) {
+                callback()
+            }
+        }
+    }, 0)
+    
+    // 绔嬪嵆杩斿洖锛岄伩鍏嶉樆濉炰富绾跨▼
+    return true
+}
+
+/**
+ * 鑾峰彇瀛樺偍鐨勬皵浣撴祿搴︽暟鎹�
+ * @returns {object|null} 瀛樺偍鐨勬皵浣撴祿搴︽暟鎹紝濡傛灉娌℃湁鍒欒繑鍥瀗ull
+ */
+grainService.getGasData = function() {
+    return gasDataStorage
+}
+
+/**
+ * 妫�鏌ヨ澶囩姸鎬佷俊鎭�
+ * @param {object} params - 璇锋眰鍙傛暟
+ * @param {string} params.user1 - 浜鸿劯璇嗗埆鐢ㄦ埛1
+ * @param {string} params.user2 - 浜鸿劯璇嗗埆鐢ㄦ埛2
+ * @param {string} params.mode - 閫夋嫨妯″紡锛�1-鍏佽鍏ヤ粨锛�2-鍐閫氶锛�3-绂佹鍏ヤ粨锛�
+ * @param {string} params.btn - 鎿嶄綔鎸夐挳锛�1-鍏ヤ粨/寮�鍚紱2-鍑轰粨/鍏抽棴锛�
+ * @returns {boolean} true琛ㄧず鐘舵�佷俊鎭幏鍙栨垚鍔燂紝false琛ㄧず澶辫触
+ */
+grainService.checkDevConcentration = function(params) {
+    // 浣跨敤setTimeout灏咹TTP璇锋眰鏀惧叆鍚庡彴鎵ц锛岄伩鍏嶉樆濉炰富绾跨▼
+    std.setTimeout(() => {
+        try {
+            // 纭繚URL鏍煎紡姝g‘锛屾坊鍔爃ttp://鍓嶇紑
+            let url = getHttpUrl()
+            if (!url.startsWith('http://') && !url.startsWith('https://')) {
+                url = 'http://' + url
+            }
+            
+            const timeout = 3000 // 3绉掕秴鏃�
+            
+            // logger.info(`[grain]: 姝e湪鑾峰彇鐘舵�佷俊鎭暟鎹�: ${url}`)
+            
+            // 鏋勫缓POST璇锋眰鏁版嵁
+            const postData = {
+                sn: config.get("sys.sn") || " ", // 璁惧搴忓垪鍙凤紝浠庨厤缃腑鑾峰彇
+                houseId: "0000", // 浠撳粧缂栫爜锛岄粯璁ゅ~鍏�"0000"
+                outId: "0000", // 鑷畾涔夌紪鐮侊紝榛樿濉厖"0000"
+                functionId: params && params.functionId ? params.functionId : functionId.safeInputControl, // 鍔熻兘鐮侊紝榛樿涓哄畨鍏ㄥ叆浠撹仈鍔ㄦ帶鍒�
+                timestamp: Date.now().toString(), // 鏃堕棿鎴�
+                data: {}
+            }
+            
+            // 娣诲姞鍙�夊弬鏁�
+            if (params) {
+                if (params.user1) postData.data.user1 = params.user1
+                if (params.user2) postData.data.user2 = params.user2
+                if (params.mode) postData.data.mode = params.mode
+                if (params.btn) postData.data.btn = params.btn
+            }
+            
+            logger.info(`[grain]: 鍙戦�丳OST璇锋眰鏁版嵁: ${JSON.stringify(postData)}`)
+            
+            // 鍙戦�丠TTP POST璇锋眰
+            let response = http.post(url, postData, timeout)
+            
+            // logger.info(`[grain]: 鐘舵�佷俊鎭暟鎹搷搴�: ${JSON.stringify(response)}`)
+            
+            // 瑙f瀽鍝嶅簲鏁版嵁
+            // 妫�鏌esponse鏄惁涓哄瓧绗︿覆锛屽鏋滄槸鍒欒В鏋愪负瀵硅薄
+            if (typeof response === 'string') {
+                response = JSON.parse(response)
+            }
+            
+            if (response && response.body) {
+                // 瑙f瀽鍝嶅簲浣�
+                let statusData
+                try {
+                    statusData = JSON.parse(response.body)
+                    logger.info(`[grain]: 瑙f瀽鍚庣殑鐘舵�佷俊鎭暟鎹�: ${JSON.stringify(statusData)}`)
+                    
+                    // 鏍规嵁鎺ュ彛杩斿洖缂栫爜杩涜鏃ュ織杈撳嚭
+                    if (statusData.respCode === respCode.success) {
+                        logger.info(`[grain]: 鐘舵�佷俊鎭帴鍙h皟鐢ㄦ垚鍔焋)
+                        // 妫�鏌ata鏄惁涓虹┖锛屼笉涓虹┖鎵嶈Е鍙戦�氱煡
+                        if (Object.keys(postData.data).length > 0) {
+                            // 瑙﹀彂鎴愬姛寮圭獥
+                            bus.fire('showAccessResult', {
+                                faceAuth: true,
+                                gasConcentration: true,
+                                accessAllowed: true,
+                                message: '*鎵ц鎴愬姛*'
+                            })
+                            
+                            // 鎾斁鎴愬姛璇煶鎻愮ず
+                            try {
+                                const voiceFile = getVoiceFile(postData.functionId, postData.data)
+                                if (voiceFile) {
+                                    driver.alsa.play(`/app/code/resource/${config.get("base.language") == "CN" ? "CN" : "EN"}/wav/${voiceFile}`)
+                                    logger.info(`[grain]: 鎾斁鎴愬姛璇煶鎻愮ず: ${voiceFile}`)
+                                }
+                            } catch (error) {
+                                logger.error(`[grain]: 鎾斁璇煶鎻愮ず澶辫触: ${error.message}`)
+                            }
+                        }
+                    } else {
+                        logger.error(`[grain]: 鐘舵�佷俊鎭帴鍙h皟鐢ㄥけ璐ワ紝杩斿洖缂栫爜: ${statusData.respCode}, 杩斿洖淇℃伅: ${statusData.respMsg}`)
+                        // 妫�鏌ata鏄惁涓虹┖锛屼笉涓虹┖鎵嶈Е鍙戦�氱煡
+                        if (Object.keys(postData.data).length > 0) {
+                            // 瑙﹀彂澶辫触寮圭獥
+                            bus.fire('showAccessResult', {
+                                faceAuth: true,
+                                gasConcentration: true,
+                                accessAllowed: false,
+                                message: statusData.respMsg || getErrorMessage(statusData.respCode)
+                            })
+                            // 鎾斁澶辫触璇煶鎻愮ず
+                            try {
+                                driver.alsa.play(`/app/code/resource/${config.get("base.language") == "CN" ? "CN" : "EN"}/wav/failed.wav`)
+                                logger.info(`[grain]: 鎾斁澶辫触璇煶鎻愮ず: failed.wav`)
+                            } catch (error) {
+                                logger.error(`[grain]: 鎾斁璇煶鎻愮ず澶辫触: ${error.message}`)
+                            }
+                        }
+                    }
+                } catch (parseError) {
+                    logger.error(`[grain]: 瑙f瀽鐘舵�佷俊鎭暟鎹け璐�: ${parseError.message}`)
+                    // 灏濊瘯娓呯悊鍝嶅簲浣撲腑鐨勮浆涔夊瓧绗�
+                    try {
+                        // 绉婚櫎澶氫綑鐨勮浆涔夊瓧绗�
+                        const cleanedBody = response.body.replace(/\\r\\n/g, '').replace(/\\t/g, '').replace(/\"/g, '"')
+                        statusData = JSON.parse(cleanedBody)
+                        logger.info(`[grain]: 娓呯悊鍚庤В鏋愮殑鐘舵�佷俊鎭暟鎹�: ${JSON.stringify(statusData)}`)
+                        
+                        // 鏍规嵁鎺ュ彛杩斿洖缂栫爜杩涜鏃ュ織杈撳嚭
+                        if (statusData.respCode === respCode.success) {
+                            logger.info(`[grain]: 鐘舵�佷俊鎭帴鍙h皟鐢ㄦ垚鍔焋)
+                            // 妫�鏌ata鏄惁涓虹┖锛屼笉涓虹┖鎵嶈Е鍙戦�氱煡
+                            if (Object.keys(postData.data).length > 0) {
+                                // 瑙﹀彂鎴愬姛寮圭獥
+                                bus.fire('showAccessResult', {
+                                    faceAuth: true,
+                                    gasConcentration: true,
+                                    accessAllowed: true,
+                                    message: '*鎵ц鎴愬姛*'
+                                })
+                                
+                                // 鎾斁鎴愬姛璇煶鎻愮ず
+                                try {
+                                    const voiceFile = getVoiceFile(postData.functionId, postData.data)
+                                    if (voiceFile) {
+                                        driver.alsa.play(`/app/code/resource/${config.get("base.language") == "CN" ? "CN" : "EN"}/wav/${voiceFile}`)
+                                        logger.info(`[grain]: 鎾斁鎴愬姛璇煶鎻愮ず: ${voiceFile}`)
+                                    }
+                                } catch (error) {
+                                    logger.error(`[grain]: 鎾斁璇煶鎻愮ず澶辫触: ${error.message}`)
+                                }
+                            }
+                        } else {
+                            logger.error(`[grain]: 鐘舵�佷俊鎭帴鍙h皟鐢ㄥけ璐ワ紝杩斿洖缂栫爜: ${statusData.respCode}, 杩斿洖淇℃伅: ${statusData.respMsg}`)
+                            // 妫�鏌ata鏄惁涓虹┖锛屼笉涓虹┖鎵嶈Е鍙戦�氱煡
+                            if (Object.keys(postData.data).length > 0) {
+                                // 瑙﹀彂澶辫触寮圭獥
+                                bus.fire('showAccessResult', {
+                                    faceAuth: true,
+                                    gasConcentration: true,
+                                    accessAllowed: false,
+                                    message: statusData.respMsg || getErrorMessage(statusData.respCode)
+                                })
+                                // 鎾斁澶辫触璇煶鎻愮ず
+                                try {
+                                    driver.alsa.play(`/app/code/resource/${config.get("base.language") == "CN" ? "CN" : "EN"}/wav/failed.wav`)
+                                    logger.info(`[grain]: 鎾斁澶辫触璇煶鎻愮ず: failed.wav`)
+                                } catch (error) {
+                                    logger.error(`[grain]: 鎾斁璇煶鎻愮ず澶辫触: ${error.message}`)
+                                }
+                            }
+                        }
+                    } catch (cleanError) {
+                        logger.error(`[grain]: 娓呯悊鍚庤В鏋愮姸鎬佷俊鎭暟鎹粛澶辫触: ${cleanError.message}`)
+                        return false
+                    }
+                }
+                
+                // 瑙﹀彂浜嬩欢鏇存柊UI
+                bus.fire('statusInfoUpdated', statusData)
+                
+                return true
+            } else {
+                logger.error(`[grain]: 鐘舵�佷俊鎭暟鎹幏鍙栧け璐�: ${response ? "鏃犲搷搴斾綋" : "鏃犲搷搴�"}`)
+                // 缃戠粶璇锋眰澶辫触鏃讹紝榛樿杩斿洖false锛堝畨鍏ㄨ捣瑙侊級
+                return false
+            }
+        } catch (error) {
+            logger.error(`[grain]: 鐘舵�佷俊鎭娴嬮敊璇�: ${error.message}`)
+            // 鍙戠敓閿欒鏃讹紝榛樿杩斿洖false锛堝畨鍏ㄨ捣瑙侊級
+            return false
+        }
+    }, 0)
+    
+    // 绔嬪嵆杩斿洖锛岄伩鍏嶉樆濉炰富绾跨▼
+    return true
+}
+
+/**
+ * 浠撳唴鐓ф槑鑱斿姩鎺у埗
+ * @param {object} params - 璇锋眰鍙傛暟
+ * @param {string} params.user1 - 浜鸿劯璇嗗埆鐢ㄦ埛1
+ * @param {string} params.user2 - 浜鸿劯璇嗗埆鐢ㄦ埛2
+ * @param {string} params.btn - 鎿嶄綔鎸夐挳锛�1-寮�鐏紱2-鍏崇伅锛�
+ * @returns {boolean} true琛ㄧず鎺у埗鎴愬姛锛宖alse琛ㄧず鎺у埗澶辫触
+ */
+grainService.controlLight = function(params) {
+    // 浣跨敤setTimeout灏咹TTP璇锋眰鏀惧叆鍚庡彴鎵ц锛岄伩鍏嶉樆濉炰富绾跨▼
+    std.setTimeout(() => {
+        try {
+            // 纭繚URL鏍煎紡姝g‘锛屾坊鍔爃ttp://鍓嶇紑
+            let url = getHttpUrl()
+            if (!url.startsWith('http://') && !url.startsWith('https://')) {
+                url = 'http://' + url
+            }
+            
+            const timeout = 3000 // 3绉掕秴鏃�
+            
+            // 鏋勫缓POST璇锋眰鏁版嵁
+            const postData = {
+                sn: config.get("sys.sn") || " ", // 璁惧搴忓垪鍙凤紝浠庨厤缃腑鑾峰彇
+                houseId: "0000", // 浠撳粧缂栫爜锛岄粯璁ゅ~鍏�"0000"
+                outId: "0000", // 鑷畾涔夌紪鐮侊紝榛樿濉厖"0000"
+                functionId: functionId.lightControl, // 浠撳唴鐓ф槑鑱斿姩鎺у埗鍔熻兘鐮�
+                timestamp: Date.now().toString(), // 鏃堕棿鎴�
+                data: {}
+            }
+            
+            // 娣诲姞鍙�夊弬鏁�
+            if (params) {
+                if (params.user1) postData.data.user1 = params.user1
+                if (params.user2) postData.data.user2 = params.user2
+                if (params.btn) postData.data.btn = params.btn
+            }
+            
+            logger.info(`[grain]: 鍙戦�佷粨鍐呯収鏄庤仈鍔ㄦ帶鍒惰姹傛暟鎹�: ${JSON.stringify(postData)}`)
+            
+            // 鍙戦�丠TTP POST璇锋眰
+            let response = http.post(url, postData, timeout)
+            
+            // 瑙f瀽鍝嶅簲鏁版嵁
+            // 妫�鏌esponse鏄惁涓哄瓧绗︿覆锛屽鏋滄槸鍒欒В鏋愪负瀵硅薄
+            if (typeof response === 'string') {
+                response = JSON.parse(response)
+            }
+            
+            if (response && response.body) {
+                // 瑙f瀽鍝嶅簲浣�
+                let statusData
+                try {
+                    statusData = JSON.parse(response.body)
+                    logger.info(`[grain]: 瑙f瀽鍚庣殑浠撳唴鐓ф槑鑱斿姩鎺у埗鍝嶅簲鏁版嵁: ${JSON.stringify(statusData)}`)
+                    
+                    // 鏍规嵁鎺ュ彛杩斿洖缂栫爜杩涜鏃ュ織杈撳嚭
+                    if (statusData.respCode === respCode.success) {
+                        logger.info(`[grain]: 浠撳唴鐓ф槑鑱斿姩鎺у埗鎺ュ彛璋冪敤鎴愬姛`)
+                        // 瑙﹀彂鎴愬姛寮圭獥
+                        bus.fire('showAccessResult', {
+                            faceAuth: true,
+                            gasConcentration: true,
+                            accessAllowed: true,
+                            message: '*鎵ц鎴愬姛*'
+                        })
+                        
+                        // 鎾斁鎴愬姛璇煶鎻愮ず
+                        try {
+                            const voiceFile = getVoiceFile(postData.functionId, postData.data)
+                            if (voiceFile) {
+                                driver.alsa.play(`/app/code/resource/${config.get("base.language") == "CN" ? "CN" : "EN"}/wav/${voiceFile}`)
+                                logger.info(`[grain]: 鎾斁鎴愬姛璇煶鎻愮ず: ${voiceFile}`)
+                            }
+                        } catch (error) {
+                            logger.error(`[grain]: 鎾斁璇煶鎻愮ず澶辫触: ${error.message}`)
+                        }
+                    } else {
+                        logger.error(`[grain]: 浠撳唴鐓ф槑鑱斿姩鎺у埗鎺ュ彛璋冪敤澶辫触锛岃繑鍥炵紪鐮�: ${statusData.respCode}, 杩斿洖淇℃伅: ${statusData.respMsg}`)
+                        // 瑙﹀彂澶辫触寮圭獥
+                        bus.fire('showAccessResult', {
+                            faceAuth: true,
+                            gasConcentration: true,
+                            accessAllowed: false,
+                            message: statusData.respMsg || getErrorMessage(statusData.respCode)
+                        })
+                        // 鎾斁澶辫触璇煶鎻愮ず
+                        try {
+                            driver.alsa.play(`/app/code/resource/${config.get("base.language") == "CN" ? "CN" : "EN"}/wav/failed.wav`)
+                            logger.info(`[grain]: 鎾斁澶辫触璇煶鎻愮ず: failed.wav`)
+                        } catch (error) {
+                            logger.error(`[grain]: 鎾斁璇煶鎻愮ず澶辫触: ${error.message}`)
+                        }
+                    }
+                } catch (parseError) {
+                    logger.error(`[grain]: 瑙f瀽浠撳唴鐓ф槑鑱斿姩鎺у埗鍝嶅簲鏁版嵁澶辫触: ${parseError.message}`)
+                    // 灏濊瘯娓呯悊鍝嶅簲浣撲腑鐨勮浆涔夊瓧绗�
+                    try {
+                        // 绉婚櫎澶氫綑鐨勮浆涔夊瓧绗�
+                        const cleanedBody = response.body.replace(/\\r\\n/g, '').replace(/\\t/g, '').replace(/\"/g, '"')
+                        statusData = JSON.parse(cleanedBody)
+                        logger.info(`[grain]: 娓呯悊鍚庤В鏋愮殑浠撳唴鐓ф槑鑱斿姩鎺у埗鍝嶅簲鏁版嵁: ${JSON.stringify(statusData)}`)
+                        
+                        // 鏍规嵁鎺ュ彛杩斿洖缂栫爜杩涜鏃ュ織杈撳嚭
+                        if (statusData.respCode === respCode.success) {
+                            logger.info(`[grain]: 浠撳唴鐓ф槑鑱斿姩鎺у埗鎺ュ彛璋冪敤鎴愬姛`)
+                            // 瑙﹀彂鎴愬姛寮圭獥
+                            bus.fire('showAccessResult', {
+                                faceAuth: true,
+                                gasConcentration: true,
+                                accessAllowed: true,
+                                message: '*鎵ц鎴愬姛*'
+                            })
+                            
+                            // 鎾斁鎴愬姛璇煶鎻愮ず
+                            try {
+                                const voiceFile = getVoiceFile(postData.functionId, postData.data)
+                                if (voiceFile) {
+                                    driver.alsa.play(`/app/code/resource/${config.get("base.language") == "CN" ? "CN" : "EN"}/wav/${voiceFile}`)
+                                    logger.info(`[grain]: 鎾斁鎴愬姛璇煶鎻愮ず: ${voiceFile}`)
+                                }
+                            } catch (error) {
+                                logger.error(`[grain]: 鎾斁璇煶鎻愮ず澶辫触: ${error.message}`)
+                            }
+                        } else {
+                            logger.error(`[grain]: 浠撳唴鐓ф槑鑱斿姩鎺у埗鎺ュ彛璋冪敤澶辫触锛岃繑鍥炵紪鐮�: ${statusData.respCode}, 杩斿洖淇℃伅: ${statusData.respMsg}`)
+                            // 瑙﹀彂澶辫触寮圭獥
+                            bus.fire('showAccessResult', {
+                                faceAuth: true,
+                                gasConcentration: true,
+                                accessAllowed: false,
+                                message: statusData.respMsg || getErrorMessage(statusData.respCode)
+                            })
+                            // 鎾斁澶辫触璇煶鎻愮ず
+                            try {
+                                driver.alsa.play(`/app/code/resource/${config.get("base.language") == "CN" ? "CN" : "EN"}/wav/failed.wav`)
+                                logger.info(`[grain]: 鎾斁澶辫触璇煶鎻愮ず: failed.wav`)
+                            } catch (error) {
+                                logger.error(`[grain]: 鎾斁璇煶鎻愮ず澶辫触: ${error.message}`)
+                            }
+                        }
+                    } catch (cleanError) {
+                        logger.error(`[grain]: 娓呯悊鍚庤В鏋愪粨鍐呯収鏄庤仈鍔ㄦ帶鍒跺搷搴旀暟鎹粛澶辫触: ${cleanError.message}`)
+                        return false
+                    }
+                }
+                
+                // 瑙﹀彂浜嬩欢鏇存柊UI
+                bus.fire('statusInfoUpdated', statusData)
+                
+                return true
+            } else {
+                logger.error(`[grain]: 浠撳唴鐓ф槑鑱斿姩鎺у埗璇锋眰澶辫触: ${response ? "鏃犲搷搴斾綋" : "鏃犲搷搴�"}`)
+                // 缃戠粶璇锋眰澶辫触鏃讹紝榛樿杩斿洖false锛堝畨鍏ㄨ捣瑙侊級
+                return false
+            }
+        } catch (error) {
+            logger.error(`[grain]: 浠撳唴鐓ф槑鑱斿姩鎺у埗閿欒: ${error.message}`)
+            // 鍙戠敓閿欒鏃讹紝榛樿杩斿洖false锛堝畨鍏ㄨ捣瑙侊級
+            return false
+        }
+    }, 0)
+    
+    // 绔嬪嵆杩斿洖锛岄伩鍏嶉樆濉炰富绾跨▼
+    return true
+}
+
+/**
+ * 鍙戦�侀棬纾佺姸鎬佹秷鎭�
+ * @param {object} doorStatusData - 闂ㄧ鐘舵�佹暟鎹�
+ * @param {number} doorStatusData.status - 闂ㄧ鐘舵�侊紝0琛ㄧず闂ㄥ叧锛�1琛ㄧず闂ㄥ紑
+ * @param {string} doorStatusData.statusText - 闂ㄧ鐘舵�佹枃鏈�
+ * @param {number} doorStatusData.time - 鏃堕棿鎴�
+ */
+grainService.sendDoorStatusMessage = function(doorStatusData) {
+    // 浣跨敤setTimeout灏咹TTP璇锋眰鏀惧叆鍚庡彴鎵ц锛岄伩鍏嶉樆濉炰富绾跨▼
+    std.setTimeout(() => {
+        try {
+            // 纭繚URL鏍煎紡姝g‘锛屾坊鍔爃ttp://鍓嶇紑
+            let url = getHttpUrl()
+            if (!url.startsWith('http://') && !url.startsWith('https://')) {
+                url = 'http://' + url
+            }
+            
+            const timeout = 3000 // 3绉掕秴鏃�
+            
+            logger.info(`[grain]: 姝e湪鍙戦�侀棬纾佺姸鎬佹秷鎭�: ${url}`)
+            
+            // 鏋勫缓POST璇锋眰鏁版嵁
+                const postData = {
+                    sn: config.get("sys.sn") || " ", // 璁惧搴忓垪鍙凤紝浠庨厤缃腑鑾峰彇
+                    houseId: "0000", // 浠撳粧缂栫爜锛岄粯璁ゅ~鍏�"0000"
+                    outId: "0000", // 鑷畾涔夌紪鐮侊紝榛樿濉厖"0000"
+                    functionId: functionId.doorStatus, // 闂ㄧ鐘舵�佸姛鑳界爜
+                    timestamp: Date.now().toString(), // 鏃堕棿鎴�
+                    data: {
+                        doorStatus: doorStatusData.status // 闂ㄧ鐘舵��
+                    }
+                }
+            
+            logger.info(`[grain]: 鍙戦�侀棬纾佺姸鎬佹秷鎭暟鎹�: ${JSON.stringify(postData)}`)
+            
+            // 鍙戦�丠TTP POST璇锋眰
+            let response = http.post(url, postData, timeout)
+            
+            // 瑙f瀽鍝嶅簲鏁版嵁
+            if (typeof response === 'string') {
+                response = JSON.parse(response)
+            }
+            
+            if (response && response.body) {
+                let respData
+                try {
+                    respData = JSON.parse(response.body)
+                    logger.info(`[grain]: 闂ㄧ鐘舵�佹秷鎭搷搴�: ${JSON.stringify(respData)}`)
+                } catch (error) {
+                    logger.error(`[grain]: 瑙f瀽闂ㄧ鐘舵�佹秷鎭搷搴斿け璐�: ${error.message}`)
+                }
+            } else {
+                logger.info(`[grain]: 闂ㄧ鐘舵�佹秷鎭搷搴斾负绌篳)
+            }
+        } catch (error) {
+            logger.error(`[grain]: 鍙戦�侀棬纾佺姸鎬佹秷鎭け璐�: ${error.message}`)
+        }
+    }, 0)
+}
+
+// 鐩戝惉闂ㄧ鐘舵�佸彉鍖栦簨浠�
+bus.on('doorStatusChanged', (doorStatusData) => {
+    logger.info(`[grain]: 鎺ユ敹鍒伴棬纾佺姸鎬佸彉鍖栦簨浠�: ${JSON.stringify(doorStatusData)}`)
+    // 璋冪敤鍙戦�侀棬纾佺姸鎬佹秷鎭殑鍑芥暟
+    try {
+        if (typeof grainService.sendDoorStatusMessage === 'function') {
+            grainService.sendDoorStatusMessage(doorStatusData)
+        } else {
+            logger.error('[grain]: sendDoorStatusMessage 涓嶆槸涓�涓嚱鏁�')
+            logger.error('[grain]: grainService.sendDoorStatusMessage =', grainService.sendDoorStatusMessage)
+        }
+    } catch (error) {
+        logger.error('[grain]: 璋冪敤sendDoorStatusMessage鍑洪敊:', error.message)
+    }
+})
+
+export default grainService
\ No newline at end of file
diff --git a/vf205_access/src/service/mqttService.js b/vf205_access/src/service/mqttService.js
new file mode 100644
index 0000000..63dad5a
--- /dev/null
+++ b/vf205_access/src/service/mqttService.js
@@ -0,0 +1,1832 @@
+/**
+ * MQTT鏈嶅姟妯″潡
+ * 澶勭悊MQTT娑堟伅鐨勬帴鏀跺拰鍙戦�侊紝鍖呮嫭璁惧绠$悊銆佷汉鍛樼鐞嗐�佹潈闄愮鐞嗙瓑鍔熻兘
+ */
+import common from "../../dxmodules/dxCommon.js";
+import config from "../../dxmodules/dxConfig.js";
+import logger from "../../dxmodules/dxLogger.js";
+import ota from "../../dxmodules/dxOta.js";
+import std from "../../dxmodules/dxStd.js";
+import dxMap from '../../dxmodules/dxMap.js'
+import driver from "../driver.js";
+import configService from "./configService.js";
+import sqliteService from "./sqliteService.js";
+import sqlite from "../../dxmodules/dxSqlite.js";
+import utils from '../common/utils/utils.js'
+
+const mqttService = {}
+let map = dxMap.get("faceAccesss")
+
+/**
+ * 鎺ユ敹MQTT娑堟伅骞跺鐞�
+ * @param {object} data - MQTT娑堟伅鏁版嵁
+ * @param {string} data.topic - 娑堟伅涓婚
+ * @param {string} data.payload - 娑堟伅杞借嵎
+ */
+mqttService.receiveMsg = function (data) {
+    // {"topic":"ddddd","payload":"{\n  \"msg\": \"world\"\n}"}
+    logger.info('[mqttService] receiveMsg :' + JSON.stringify(data.topic))
+    // 鎻愬彇涓婚鐨勬渶鍚庨儴鍒嗕綔涓哄嚱鏁板悕
+    if (typeof mqttService[data.topic.match(/[^/]+$/)[0]] == 'function') {
+        mqttService[data.topic.match(/[^/]+$/)[0]](data)
+    } else {
+        logger.error("鏈疄鐜扮殑topic", data.topic)
+    }
+}
+
+// =================================鏉冮檺澧炲垹鏀规煡=================================
+/**
+ * 娣诲姞鏉冮檺
+ * @param {object} event - MQTT浜嬩欢瀵硅薄
+ */
+mqttService.insertPermission = function (event) {
+    try {
+        logger.info('[mqttService] 鎺ユ敹鍒癷nsertPermission鍛戒护:', JSON.stringify(event.topic))
+        logger.info('[mqttService] 鍛戒护payload:', event.payload)
+        let payload = JSON.parse(event.payload)
+        let data = payload.payload && payload.payload.data ? payload.payload.data : {}
+        logger.info('[mqttService] 瑙f瀽鍚庣殑鍙傛暟:', JSON.stringify(data))
+        let res = this.insertPermissionAgreement(data)
+        if (typeof res == 'string') {
+            logger.error('[mqttService] insertPermission澶辫触:', res)
+            return reply(event, res, CODE.E_100)
+        }
+        logger.info('[mqttService] insertPermission鎴愬姛')
+        return reply(event)
+    } catch (error) {
+        logger.error('[mqttService] insertPermission error:', error)
+        return reply(event, { error: error.message }, CODE.E_100)
+    }
+}
+
+/**
+ * 娣诲姞鏉冮檺閫氱敤鍗忚鏍煎紡
+ * @param {array} data - 鏉冮檺鏁版嵁鏁扮粍
+ * @returns {boolean|string} true琛ㄧず鎴愬姛锛宻tring琛ㄧず閿欒淇℃伅
+ */
+mqttService.insertPermissionAgreement = function (data) {
+    let permissions = []
+    for (let i = 0; i < data.length; i++) {
+        const permission = data[i];
+        if (!permission.permissionId || !permission.userId) {
+            return "id or userId cannot be empty"
+        }
+        if (!permission.extra) {
+            permission.extra = ""
+        }
+        if (!permission.time) {
+            return "time and type cannot be empty"
+        }
+        if (permission.time.type != 0 && permission.time.type != 1 && permission.time.type != 2 && permission.time.type != 3) {
+            return "time type is not supported"
+        }
+        let record = {}
+        record.permissionId = permission.permissionId
+        record.userId = permission.userId
+        record.door = isEmpty(permission.index) ? 0 : permission.index
+        record.extra = isEmpty(permission.extra) ? JSON.stringify({}) : JSON.stringify(permission.extra)
+        record.timeType = permission.time.type
+        record.beginTime = permission.time.type == 0 ? 0 : permission.time.range.beginTime
+        record.endTime = permission.time.type == 0 ? 0 : permission.time.range.endTime
+        record.repeatBeginTime = permission.time.type != 2 ? 0 : permission.time.beginTime
+        record.repeatEndTime = permission.time.type != 2 ? 0 : permission.time.endTime
+        record.period = permission.time.type != 3 ? 0 : JSON.stringify(permission.time.weekPeriodTime)
+        let ret = sqliteService.d1_permission.save(record)
+        if (ret != 0) {
+            // 濡傛灉淇濆瓨澶辫触锛屽皾璇曞垹闄ゅ悗閲嶆柊淇濆瓨
+            sqliteService.d1_permission.deleteByPermissionId(record.permissionId)
+            ret = sqliteService.d1_permission.save(record)
+            if (ret != 0) {
+                return "sql error ret:" + ret
+            } else {
+                continue
+            }
+        }
+    }
+    return true
+}
+
+/**
+ * 鏌ヨ鏉冮檺
+ * @param {object} event - MQTT浜嬩欢瀵硅薄
+ */
+mqttService.getPermission = function (event) {
+    try {
+        logger.info('[mqttService] 鎺ユ敹鍒癵etPermission鍛戒护:', JSON.stringify(event.topic))
+        logger.info('[mqttService] 鍛戒护payload:', event.payload)
+        let payload = JSON.parse(event.payload)
+        let data = payload.payload && payload.payload.data ? payload.payload.data : {}
+        logger.info('[mqttService] 瑙f瀽鍚庣殑鏌ヨ鍙傛暟:', JSON.stringify(data))
+        let res = this.getPermissionAgreement(data)
+        logger.info('[mqttService] 鏌ヨ缁撴灉:', JSON.stringify(res))
+        return reply(event, res)
+    } catch (error) {
+        logger.error('[mqttService] getPermission error:', error)
+        return reply(event, { error: error.message }, CODE.E_100)
+    }
+}
+
+/**
+ * 鏌ヨ鏉冮檺閫氱敤鍗忚鏍煎紡
+ * @param {object} data - 鏌ヨ鍙傛暟
+ * @returns {object} 鏌ヨ缁撴灉
+ */
+mqttService.getPermissionAgreement = function (data) {
+    try {
+        // 纭繚data鍙傛暟涓嶄负undefined
+        data = data || {}
+        data.page = isEmpty(data.page) ? 0 : data.page
+        data.size = isEmpty(data.size) ? 10 : data.size
+        let totalCount = sqliteService.d1_permission.count(data)
+        let permissions = sqliteService.d1_permission.findAll(data)
+        // 鏋勫缓杩斿洖缁撴灉
+        let content = permissions.map(permission => ({
+            permissionId: permission.permissionId,
+            userId: permission.userId,
+            extra: JSON.parse(permission.extra ? permission.extra : "{}"),
+            time: {
+                type: permission.timeType,
+                beginTime: permission.timeType != 2 ? undefined : permission.repeatBeginTime,
+                endTime: permission.timeType != 2 ? undefined : permission.repeatEndTime,
+                range: permission.timeType === 0 ? undefined : { beginTime: permission.beginTime, endTime: permission.endTime },
+                weekPeriodTime: permission.timeType != 3 ? undefined : JSON.parse(permission.period)
+            }
+        }))
+        return {
+            content: content,
+            page: data.page,
+            size: data.size,
+            total: totalCount,
+            totalPage: Math.ceil(totalCount / data.size),
+            count: content.length
+        }
+    } catch (error) {
+        logger.error('[mqttService] getPermissionAgreement error:', error)
+        throw error
+    }
+}
+
+/**
+ * 鍒犻櫎鏉冮檺
+ * @param {object} event - MQTT浜嬩欢瀵硅薄
+ */
+mqttService.delPermission = function (event) {
+    try {
+        logger.info('[mqttService] 鎺ユ敹鍒癲elPermission鍛戒护:', JSON.stringify(event.topic))
+        logger.info('[mqttService] 鍛戒护payload:', event.payload)
+        let payload = JSON.parse(event.payload)
+        let data = payload.payload && payload.payload.data ? payload.payload.data : {}
+        logger.info('[mqttService] 瑙f瀽鍚庣殑鍙傛暟:', JSON.stringify(data))
+        let res = this.delPermissionAgreement(data)
+        if (typeof res == 'string') {
+            logger.error('[mqttService] delPermission澶辫触:', res)
+            return reply(event, res, CODE.E_100)
+        }
+        logger.info('[mqttService] delPermission鎴愬姛')
+        return reply(event)
+    } catch (error) {
+        logger.error('[mqttService] delPermission error:', error)
+        return reply(event, { error: error.message }, CODE.E_100)
+    }
+}
+
+/**
+ * 鍒犻櫎鏉冮檺閫氱敤鍗忚鏍煎紡
+ * @param {object} data - 鍒犻櫎鍙傛暟
+ * @returns {boolean|string} true琛ㄧず鎴愬姛锛宻tring琛ㄧず閿欒淇℃伅
+ */
+mqttService.delPermissionAgreement = function (data) {
+    if (data.permissionIds && data.permissionIds.length > 0) {
+        let ret = sqliteService.d1_permission.deleteByPermissionIdInBatch(data.permissionIds)
+        if (ret != 0) {
+            return "sql error ret:" + ret
+        }
+    }
+    if (data.userIds && data.userIds.length > 0) {
+        let ret = sqliteService.d1_permission.deleteByUserIdInBatch(data.userIds)
+        if (ret != 0) {
+            return "sql error ret:" + ret
+        }
+    }
+    return true
+}
+
+/**
+ * 娓呯┖鏉冮檺
+ * @param {object} event - MQTT浜嬩欢瀵硅薄
+ */
+mqttService.clearPermission = function (event) {
+    try {
+        logger.info('[mqttService] 鎺ユ敹鍒癱learPermission鍛戒护:', JSON.stringify(event.topic))
+        logger.info('[mqttService] 鍛戒护payload:', event.payload)
+        let ret = sqliteService.d1_permission.deleteAll()
+        if (ret == 0) {
+            logger.info('[mqttService] clearPermission鎴愬姛')
+            return reply(event)
+        } else {
+            logger.error('[mqttService] clearPermission澶辫触:', "sql error ret:" + ret)
+            return reply(event, "sql error ret:" + ret, CODE.E_100)
+        }
+    } catch (error) {
+        logger.error('[mqttService] clearPermission error:', error)
+        return reply(event, { error: error.message }, CODE.E_100)
+    }
+}
+
+
+// =================================浜哄憳澧炲垹鏀规煡=================================
+/**
+ * 娣诲姞浜哄憳
+ * @param {object} event - MQTT浜嬩欢瀵硅薄
+ */
+mqttService.insertUser = function (event) {
+    try {
+        logger.info('[mqttService] 鎺ユ敹鍒癷nsertUser鍛戒护:', JSON.stringify(event.topic))
+        logger.info('[mqttService] 鍛戒护payload:', event.payload)
+        let payload = JSON.parse(event.payload)
+        let data = payload.payload && payload.payload.data ? payload.payload.data : []
+        logger.info('[mqttService] 瑙f瀽鍚庣殑鍙傛暟:', JSON.stringify(data))
+        let res = this.insertUserAgreement(data)
+        if (typeof res == 'string') {
+            logger.error('[mqttService] insertUser澶辫触:', res)
+            return reply(event, res, CODE.E_100)
+        }
+        logger.info('[mqttService] insertUser鎴愬姛')
+        return reply(event)
+    } catch (error) {
+        logger.error('[mqttService] insertUser error:', error)
+        return reply(event, { error: error.message }, CODE.E_100)
+    }
+}
+
+/**
+ * 娣诲姞浜哄憳閫氱敤鍗忚鏍煎紡
+ * @param {array} data - 浜哄憳鏁版嵁鏁扮粍
+ * @returns {boolean|string} true琛ㄧず鎴愬姛锛宻tring琛ㄧず閿欒淇℃伅
+ */
+mqttService.insertUserAgreement = function (data) {
+    let persons = []
+    for (let i = 0; i < data.length; i++) {
+        const person = data[i];
+        // 涓ユ牸妫�鏌ユ暟鎹牸寮�
+        if (!person.userId || !person.name || person.type === undefined || !person.idCard) {
+            return "鏁版嵁鏍煎紡閿欒锛岀己灏戝繀瑕佸瓧娈碉紙userId銆乶ame銆乼ype銆乮dCard锛�"
+        }
+        // 妫�鏌ype瀛楁绫诲瀷
+        if (typeof person.type !== 'number') {
+            return "鏁版嵁鏍煎紡閿欒锛宼ype瀛楁蹇呴』鏄暟瀛�"
+        }
+        // 妫�鏌ype瀛楁鍊艰寖鍥�
+        if (person.type < 0 || person.type > 1) {
+            return "鏁版嵁鏍煎紡閿欒锛宼ype瀛楁鍊煎繀椤诲湪0-1涔嬮棿"
+        }
+        let record = {}
+        record.userId = person.userId
+        record.name = person.name
+        // 澶勭悊浜哄憳绫诲瀷瀛楁鍜岃韩浠借瘉鍙�
+        let extra = {}
+        extra.type = person.type
+        extra.idCard = person.idCard
+        record.extra = JSON.stringify(extra)
+        persons.push(record)
+        
+        // 澶勭悊浜鸿劯淇℃伅
+        if (person.face) {
+            try {
+                logger.info('[mqttService] 寮�濮嬪鐞嗕汉鑴镐俊鎭�:', person.userId)
+                
+                let faceFilePath = person.face
+                
+                // 妫�鏌ユ槸鍚︽槸base64缂栫爜鐨勫浘鐗囨暟鎹�
+                if (person.face.startsWith('data:image/')) {
+                    logger.info('[mqttService] 妫�娴嬪埌base64缂栫爜鐨勫浘鐗囨暟鎹�')
+                    // 鎻愬彇base64鏁版嵁
+                    let base64Data = person.face.split(',')[1]
+                    // 鍒涘缓涓存椂鏂囦欢
+                    faceFilePath = '/app/data/user/temp_face_' + person.userId + '.jpg'
+                    std.ensurePathExists(faceFilePath)
+                    // 灏哹ase64鏁版嵁杞崲涓烘枃浠�
+                    common.base64_2binfile(faceFilePath, base64Data)
+                    logger.info('[mqttService] 宸插皢base64鏁版嵁淇濆瓨涓烘枃浠�:', faceFilePath)
+                } else {
+                    return "鏁版嵁鏍煎紡閿欒锛宖ace瀛楁蹇呴』鏄痓ase64缂栫爜鐨勫浘鐗囨暟鎹�"
+                }
+                
+                // 妫�鏌ユ枃浠舵槸鍚﹀瓨鍦�
+                let fileExists = common.systemWithRes(`test -e "${faceFilePath}" && echo "OK" || echo "NO"`, 2)
+                logger.info('[mqttService] 浜鸿劯鍥剧墖鏂囦欢瀛樺湪:', fileExists.includes('OK'))
+                
+                if (fileExists.includes('OK')) {
+                    // 娉ㄥ唽浜鸿劯
+                    logger.info('[mqttService] 寮�濮嬫敞鍐屼汉鑴�:', person.userId)
+                    let ret = driver.face.registerFaceByPicFile(person.userId, faceFilePath)
+                    logger.info('[mqttService] 娉ㄥ唽浜鸿劯缁撴灉:', ret)
+                    
+                    if (ret == 0) {
+                        // 娉ㄥ唽鎴愬姛鍚庣Щ鍔ㄥ浘鐗囧埌鐢ㄦ埛鐩綍
+                        let src = "/app/data/user/" + person.userId + "/register.jpg"
+                        std.ensurePathExists(src)
+                        logger.info('[mqttService] 绉诲姩浜鸿劯鍥剧墖鍒扮敤鎴风洰褰�:', faceFilePath, '->', src)
+                        common.systemBrief('mv ' + faceFilePath + " " + src)
+                        
+                        // 淇濆瓨浜鸿劯鍑瘉
+                        logger.info('[mqttService] 淇濆瓨浜鸿劯鍑瘉:', person.userId)
+                        let voucherRet = sqliteService.d1_voucher.save({
+                            keyId: std.genRandomStr(32),
+                            type: "300",
+                            code: src,
+                            userId: person.userId,
+                            extra: JSON.stringify({ faceType: 0 })
+                        });
+                        logger.info('[mqttService] 淇濆瓨浜鸿劯鍑瘉缁撴灉:', voucherRet)
+                    } else {
+                        logger.error('[mqttService] 娉ㄥ唽浜鸿劯澶辫触锛岃繑鍥炵爜:', ret)
+                    }
+                } else {
+                    logger.error('[mqttService] 浜鸿劯鍥剧墖鏂囦欢涓嶅瓨鍦�:', faceFilePath)
+                }
+            } catch (error) {
+                logger.error('[mqttService] 澶勭悊浜鸿劯淇℃伅閿欒:', error)
+                return "澶勭悊浜鸿劯淇℃伅閿欒: " + error.message
+            } finally {
+                logger.info('[mqttService] 浜鸿劯淇℃伅澶勭悊瀹屾垚:', person.userId)
+            }
+        }
+    }
+    let ret = sqliteService.d1_person.saveAll(persons)
+    if (ret != 0) {
+        //澶辫触浜� 鎶婅繖浜涗汉鍏ㄩ兘鍒犻櫎鍚庡湪鏂板涓�涓�
+        let userIds = persons.map(obj => obj.userId);
+        sqliteService.d1_person.deleteByUserIdInBatch(userIds)
+        //閲嶆柊鏂板
+        let ret = sqliteService.d1_person.saveAll(persons)
+        if (ret != 0) {
+            return "sql error ret:" + ret
+        }
+    }
+    
+    // 涓虹敤鎴锋坊鍔犲搴旀潈闄�
+    for (let i = 0; i < data.length; i++) {
+        const person = data[i];
+        let userId = person.userId
+        let userType = person.type
+        
+        // 鍙湁淇濈鍛橈紙0锛夊拰绉戦暱锛�1锛夐渶瑕佹坊鍔犳潈闄�
+        if (userType == 0 || userType == 1) {
+            try {
+                // 妫�鏌ユ槸鍚﹀凡瀛樺湪鏉冮檺璁板綍
+                let existingPermissions = sqliteService.d1_permission.findByUserId(userId)
+                if (existingPermissions && existingPermissions.length == 0) {
+                    // 娣诲姞姘镐箙鏉冮檺
+                    let permissionRet = sqliteService.d1_permission.save({
+                        permissionId: std.genRandomStr(32),
+                        userId: userId,
+                        timeType: 0, // 姘镐箙鏉冮檺
+                        beginTime: 0,
+                        endTime: 0,
+                        repeatBeginTime: 0,
+                        repeatEndTime: 0,
+                        period: ""
+                    });
+                    logger.info('[mqttService] 涓虹敤鎴锋坊鍔犳潈闄愮粨鏋�:', permissionRet)
+                } else {
+                    logger.info('[mqttService] 鐢ㄦ埛宸插瓨鍦ㄦ潈闄愯褰曪紝璺宠繃鏉冮檺娣诲姞:', userId)
+                }
+            } catch (error) {
+                logger.error('[mqttService] 娣诲姞鏉冮檺鏃跺嚭閿�:', error)
+            }
+        }
+    }
+    
+    return true
+
+}
+
+/**
+ * 鏌ヨ浜哄憳
+ * @param {object} event - MQTT浜嬩欢瀵硅薄
+ */
+mqttService.getUser = function (event) {
+    try {
+        logger.info('[mqttService] 鎺ユ敹鍒癵etUser鍛戒护:', JSON.stringify(event.topic))
+        logger.info('[mqttService] 鍛戒护payload:', event.payload)
+        let payload = JSON.parse(event.payload)
+        let data = payload.payload && payload.payload.data ? payload.payload.data : {}
+        let res = this.getUserAgreement(data)
+        logger.info('[mqttService] 鏌ヨ缁撴灉:', JSON.stringify(res))
+        return reply(event, res)
+    } catch (error) {
+        logger.error('[mqttService] getUser error:', error)
+        return reply(event, { error: error.message }, CODE.E_100)
+    }
+}
+
+/**
+ * 鏌ヨ浜哄憳閫氱敤鍗忚鏍煎紡
+ * @param {object} data - 鏌ヨ鍙傛暟
+ * @returns {object} 鏌ヨ缁撴灉
+ */
+mqttService.getUserAgreement = function (data) {
+    try {
+        data.page = isEmpty(data.page) ? 0 : data.page
+        data.size = isEmpty(data.size) ? 10 : data.size
+        let totalCount = sqliteService.d1_person.count(data)
+        let persons = sqliteService.d1_person.findAll(data)
+        // 瑙f瀽 extra 瀛楁锛孞SON瀛楃涓茶浆鍖栦负JSON瀵硅薄锛屾秷闄よ浆涔夊瓧绗�
+        persons.forEach(person => {
+            try {
+                if (person.extra) {
+                    person.extra = JSON.parse(person.extra)
+                }
+            } catch (error) {
+                logger.error('[mqttService] 瑙f瀽 extra 瀛楁閿欒:', error)
+            }
+        })
+
+        let result = {
+            content: persons,
+            page: data.page,
+            size: data.size,
+            total: totalCount,
+            totalPage: Math.ceil(totalCount / data.size),
+            count: persons.length
+        }
+
+        return result
+    } catch (error) {
+        logger.error('[mqttService] getUserAgreement error:', error)
+        throw error
+    }
+}
+
+/**
+ * 鍒犻櫎浜哄憳
+ * @param {object} event - MQTT浜嬩欢瀵硅薄
+ */
+mqttService.delUser = function (event) {
+    try {
+        logger.info('[mqttService] 鎺ユ敹鍒癲elUser鍛戒护:', JSON.stringify(event.topic))
+        logger.info('[mqttService] 鍛戒护payload:', event.payload)
+        let payload = JSON.parse(event.payload)
+        let data = payload.payload && payload.payload.data ? payload.payload.data : []
+        logger.info('[mqttService] 瑙f瀽鍚庣殑鍙傛暟:', JSON.stringify(data))
+        let res = this.delUserAgreement(data)
+        if (typeof res == 'string') {
+            logger.error('[mqttService] delUser澶辫触:', res)
+            return reply(event, res, CODE.E_100)
+        }
+        logger.info('[mqttService] delUser鎴愬姛')
+        return reply(event)
+    } catch (error) {
+        logger.error('[mqttService] delUser error:', error)
+        return reply(event, { error: error.message }, CODE.E_100)
+    }
+}
+
+/**
+ * 鍒犻櫎浜哄憳閫氱敤鍗忚鏍煎紡
+ * @param {array} data - 浜哄憳ID鏁扮粍
+ * @returns {boolean|string} true琛ㄧず鎴愬姛锛宻tring琛ㄧず閿欒淇℃伅
+ */
+mqttService.delUserAgreement = function (data) {
+    if (data && data.length > 0) {
+        sqliteService.transaction()
+        let ret1 = sqliteService.d1_person.deleteByUserIdInBatch(data)
+        let ret2 = sqliteService.d1_permission.deleteByUserIdInBatch(data)
+        let ret3 = sqliteService.d1_voucher.deleteByUserIdInBatch(data)
+        if (ret1 != 0 || ret2 != 0 || ret3 != 0) {
+            sqliteService.rollback()
+            return "sql error"
+        }
+        sqliteService.commit()
+        // 鍒犻櫎浜哄憳鐨勪汉鑴告暟鎹�
+        data.forEach(element => {
+            driver.face.delete(element)
+        });
+    }
+    return true
+}
+
+
+/**
+ * 娓呯┖浜哄憳
+ * @param {object} event - MQTT浜嬩欢瀵硅薄
+ */
+mqttService.clearUser = function (event) {
+    try {
+        logger.info('[mqttService] 鎺ユ敹鍒癱learUser鍛戒护:', JSON.stringify(event.topic))
+        logger.info('[mqttService] 鍛戒护payload:', event.payload)
+        let persons = sqliteService.d1_person.findAll()
+        // 鍒犻櫎鎵�鏈変汉鍛樼殑浜鸿劯鏁版嵁
+        logger.info('[mqttService] 寮�濮嬪垹闄や汉鑴告暟鎹紝鍏�', persons.length, '鏉�')
+        persons.forEach(element => {
+            driver.face.delete(element.userId)
+        });
+        let ret1 = sqliteService.d1_person.deleteAll()
+        let ret2 = sqliteService.d1_permission.deleteAll()
+        let ret3 = sqliteService.d1_voucher.deleteAll()
+        if (ret1 == 0 && ret2 == 0 && ret3 == 0) {
+            logger.info('[mqttService] clearUser鎴愬姛')
+            return reply(event)
+        } else {
+            let errorMsg = "sql error ret: " + ret1 + ", " + ret2 + ", " + ret3
+            logger.error('[mqttService] clearUser澶辫触:', errorMsg)
+            return reply(event, errorMsg, CODE.E_100)
+        }
+    } catch (error) {
+        logger.error('[mqttService] clearUser error:', error)
+        return reply(event, { error: error.message }, CODE.E_100)
+    }
+}
+
+// =================================鍑瘉澧炲垹鏀规煡=================================
+/**
+ * 娣诲姞鍑瘉
+ * @param {object} event - MQTT浜嬩欢瀵硅薄
+ */
+mqttService.insertKey = function (event) {
+    try {
+        logger.info('[mqttService] 鎺ユ敹鍒癷nsertKey鍛戒护:', JSON.stringify(event.topic))
+        logger.info('[mqttService] 鍛戒护payload:', event.payload)
+        let payload = JSON.parse(event.payload)
+        let data = payload.payload && payload.payload.data ? payload.payload.data : {}
+        logger.info('[mqttService] 瑙f瀽鍚庣殑鍙傛暟:', JSON.stringify(data))
+        let res = this.insertKeyAgreement(data)
+        if (typeof res == 'string') {
+            logger.error('[mqttService] insertKey澶辫触:', res)
+            return reply(event, res, CODE.E_100)
+        }
+        logger.info('[mqttService] insertKey鎴愬姛')
+        return reply(event)
+    } catch (error) {
+        logger.error('[mqttService] insertKey error:', error)
+        return reply(event, { error: error.message }, CODE.E_100)
+    }
+}
+
+/**
+ * 娣诲姞鍑瘉閫氱敤鍗忚鏍煎紡
+ * @param {array} data - 鍑瘉鏁版嵁鏁扮粍
+ * @returns {boolean|string} true琛ㄧず鎴愬姛锛宻tring琛ㄧず閿欒淇℃伅
+ */
+mqttService.insertKeyAgreement = function (data) {
+    let vouchers = []
+    for (let i = 0; i < data.length; i++) {
+        const voucher = data[i];
+        if (!voucher.keyId || !voucher.type || !voucher.code || !voucher.userId) {
+            return "keyId or type or code  or userId cannot be empty"
+        }
+
+        // 鍑瘉閲嶅
+        let ret = sqliteService.d1_voucher.findAllBycode(voucher.code)
+        if (ret.length != 0) {
+            return "Duplicate vouchers"
+        }
+
+        if (voucher.type == 300) {
+            if (voucher.extra) {
+                if (voucher.extra.faceType != 0 && voucher.extra.faceType != 1) {
+                    return "faceType Incorrect format"
+                }
+            } else {
+                return "faceType is required"
+            }
+        }
+        let record = {}
+        record.keyId = voucher.keyId
+        record.type = voucher.type
+        if (voucher.type == "400") {
+            if (voucher.code.length > 6) {
+                return "Password length cannot exceed 6 digits"
+            }
+        }
+        if (voucher.type == "300") {
+            if (voucher.extra.faceType == 0) {
+                record.code = `/app/data/user/${voucher.userId}/register.jpg`
+                // 淇濆瓨base64鍥剧墖
+                std.ensurePathExists(record.code)
+                common.base64_2binfile(record.code, voucher.code)
+                // 娉ㄥ唽浜鸿劯
+                let weq = driver.face.registerFaceByPicFile(voucher.userId, record.code)
+                if (weq == 0) {
+                    logger.info("娉ㄥ唽浜鸿劯鎴愬姛")
+                } else {
+                    logger.info("绗竴娆′汉鑴告敞鍐屽け璐�")
+                    //鍒犻櫎閲嶆柊娉ㄥ唽
+                    driver.face.delete(voucher.userId)
+                    let res = driver.face.registerFaceByPicFile(voucher.userId, record.code)
+                    if (res == 0) {
+                        logger.info("绗簩娆℃敞鍐屼汉鑴告垚鍔�")
+                        sqliteService.d1_voucher.deleteByKeyId(record.keyId)
+                    } else {
+                        return "Face registration failed"
+                    }
+                }
+            } else {
+                record.code = voucher.code
+                //鐗瑰緛鍊兼敞鍐�
+                let res = driver.face.reg(voucher.userId, voucher.code)
+                if (res != 0) {
+                    return "Face registration failed"
+                }
+            }
+        } else {
+            record.code = voucher.code
+            let ret = sqliteService.d1_voucher.findAllByCodeAndType(voucher.code, voucher.type)
+            if (ret.length != 0) {
+                return "Duplicate vouchers"
+            }
+        }
+
+        record.userId = voucher.userId
+        record.extra = isEmpty(voucher.extra) ? JSON.stringify({ type: 0 }) : JSON.stringify(voucher.extra)
+        vouchers.push(record)
+    }
+    let ret = sqliteService.d1_voucher.saveAll(vouchers)
+    if (ret == 0) {
+        return true
+    } else {
+        return "sql error ret:" + ret
+    }
+}
+
+/**
+ * 鏌ヨ鍑瘉
+ * @param {object} event - MQTT浜嬩欢瀵硅薄
+ */
+mqttService.getKey = function (event) {
+    try {
+        logger.info('[mqttService] 鎺ユ敹鍒癵etKey鍛戒护:', JSON.stringify(event.topic))
+        logger.info('[mqttService] 鍛戒护payload:', event.payload)
+        let payload = JSON.parse(event.payload)
+        let data = payload.payload && payload.payload.data ? payload.payload.data : {}
+        logger.info('[mqttService] 瑙f瀽鍚庣殑鏌ヨ鍙傛暟:', JSON.stringify(data))
+        let res = this.getKeyAgreement(data)
+        if (typeof res == 'string') {
+            logger.error('[mqttService] getKey澶辫触:', res)
+            return reply(event, res, CODE.E_100)
+        }
+        logger.info('[mqttService] 鏌ヨ缁撴灉:', JSON.stringify(res))
+        return reply(event, res)
+    } catch (error) {
+        logger.error('[mqttService] getKey error:', error)
+        return reply(event, { error: error.message }, CODE.E_100)
+    }
+}
+
+/**
+ * 鏌ヨ鍑瘉閫氱敤鍗忚鏍煎紡
+ * @param {object} data - 鏌ヨ鍙傛暟
+ * @returns {object|string} 鏌ヨ缁撴灉鎴栭敊璇俊鎭�
+ */
+mqttService.getKeyAgreement = function (data) {
+    if (!data.type) {
+        return "type is required"
+    }
+    if (data.type == 300) {
+        data.size = 1
+    } else {
+        data.page = isEmpty(data.page) ? 0 : data.page
+        data.size = isEmpty(data.size) ? 10 : data.size
+    }
+    let totalCount = sqliteService.d1_voucher.count(data)
+    let vouchers = sqliteService.d1_voucher.findAll(data)
+    vouchers.forEach(element => {
+        if (element.type == 300 && element.extra && JSON.parse(element.extra).faceType == 0) {
+            //浜鸿劯鐗规畩澶勭悊涓�涓� 
+            element.code = driver.face.fileToBase64(element.code)
+        }
+    });
+    return {
+        content: vouchers,
+        page: data.page,
+        size: data.size,
+        total: totalCount,
+        totalPage: Math.ceil(totalCount / data.size),
+        count: vouchers.length
+    }
+}
+
+/**
+ * 鍒犻櫎鍑瘉
+ * @param {object} event - MQTT浜嬩欢瀵硅薄
+ */
+mqttService.delKey = function (event) {
+    try {
+        logger.info('[mqttService] 鎺ユ敹鍒癲elKey鍛戒护:', JSON.stringify(event.topic))
+        logger.info('[mqttService] 鍛戒护payload:', event.payload)
+        let payload = JSON.parse(event.payload)
+        let data = payload.payload && payload.payload.data ? payload.payload.data : {}
+        logger.info('[mqttService] 瑙f瀽鍚庣殑鍙傛暟:', JSON.stringify(data))
+        let res = this.delKeyAgreement(data)
+        if (typeof res == 'string') {
+            logger.error('[mqttService] delKey澶辫触:', res)
+            return reply(event, res, CODE.E_100)
+        }
+        logger.info('[mqttService] delKey鎴愬姛')
+        return reply(event)
+    } catch (error) {
+        logger.error('[mqttService] delKey error:', error)
+        return reply(event, { error: error.message }, CODE.E_100)
+    }
+}
+
+/**
+ * 鍒犻櫎鍑瘉閫氱敤鍗忚鏍煎紡
+ * @param {object} data - 鍒犻櫎鍙傛暟
+ * @returns {boolean|string} true琛ㄧず鎴愬姛锛宻tring琛ㄧず閿欒淇℃伅
+ */
+mqttService.delKeyAgreement = function (data) {
+    if (data.keyIds && data.keyIds.length > 0) {
+        let userIds = []
+        for (let i = 0; i < data.keyIds.length; i++) {
+            const element = data.keyIds[i];
+            let res = sqliteService.d1_voucher.findAllByKeyId(element)
+            if (res.length <= 0) {
+                continue
+            }
+            if (res[0].type == 300) {
+                userIds.push(res[0].userId)
+            }
+        }
+        let ret = sqliteService.d1_voucher.deleteByKeyIdInBatch(data.keyIds)
+        if (ret != 0) {
+            return "sql error ret:" + ret
+        }
+        // 鍒犻櫎浜鸿劯鏁版嵁
+        userIds.forEach(element => {
+            driver.face.delete(element)
+        });
+    }
+    if (data.userIds && data.userIds.length > 0) {
+        let ret = sqliteService.d1_voucher.deleteByUserIdInBatch(data.userIds)
+        if (ret != 0) {
+            return "sql error ret:" + ret
+        }
+        // 鍒犻櫎浜鸿劯鏁版嵁
+        data.userIds.forEach(element => {
+            driver.face.delete(element)
+        });
+    }
+    return true
+}
+
+/**
+ * 娓呯┖鍑瘉
+ * @param {object} event - MQTT浜嬩欢瀵硅薄
+ */
+mqttService.clearKey = function (event) {
+    try {
+        logger.info('[mqttService] 鎺ユ敹鍒癱learKey鍛戒护:', JSON.stringify(event.topic))
+        logger.info('[mqttService] 鍛戒护payload:', event.payload)
+        let res = sqliteService.d1_voucher.findAll()
+        let userIds = []
+        res.forEach(element => {
+            if (element.type == 300) {
+                userIds.push(element.userId)
+            }
+        });
+        logger.info('[mqttService] 鎵惧埌闇�瑕佸垹闄ょ殑浜鸿劯鏁版嵁锛屽叡', userIds.length, '鏉�')
+        let ret = sqliteService.d1_voucher.deleteAll()
+        if (ret == 0) {
+            // 鍒犻櫎浜鸿劯鏁版嵁
+            logger.info('[mqttService] 寮�濮嬪垹闄や汉鑴告暟鎹�')
+            userIds.forEach((element, index) => {
+                driver.face.delete(element)
+            });
+            logger.info('[mqttService] clearKey鎴愬姛')
+            reply(event)
+        } else {
+            logger.error('[mqttService] clearKey澶辫触:', "sql error ret:" + ret)
+            reply(event, "sql error ret:" + ret, CODE.E_100)
+        }
+    } catch (error) {
+        logger.error('[mqttService] clearKey error:', error)
+        return reply(event, { error: error.message }, CODE.E_100)
+    }
+}
+
+// =================================搴旀�ュ紑浠撳瘑鐮佸鍒犳敼鏌�=================================
+/**
+ * 娣诲姞搴旀�ュ紑浠撳瘑鐮�
+ * @param {object} event - MQTT浜嬩欢瀵硅薄
+ */
+mqttService.insertEmergencyPassword = function (event) {
+    try {
+        logger.info('[mqttService] 鎺ユ敹鍒癷nsertEmergencyPassword鍛戒护:', JSON.stringify(event.topic))
+        logger.info('[mqttService] 鍛戒护payload:', event.payload)
+        let payload = JSON.parse(event.payload)
+        let data = payload.payload && payload.payload.data ? payload.payload.data : {}
+        logger.info('[mqttService] 瑙f瀽鍚庣殑鍙傛暟:', JSON.stringify(data))
+        let res = this.insertEmergencyPasswordAgreement(data)
+        if (typeof res == 'string') {
+            logger.error('[mqttService] insertEmergencyPassword澶辫触:', res)
+            return reply(event, res, CODE.E_100)
+        }
+        logger.info('[mqttService] insertEmergencyPassword鎴愬姛')
+        return reply(event)
+    } catch (error) {
+        logger.error('[mqttService] insertEmergencyPassword error:', error)
+        return reply(event, { error: error.message }, CODE.E_100)
+    }
+}
+
+/**
+ * 娣诲姞搴旀�ュ紑浠撳瘑鐮侀�氱敤鍗忚鏍煎紡
+ * @param {object} data - 搴旀�ュ紑浠撳瘑鐮佹暟鎹璞�
+ * @returns {boolean|string} true琛ㄧず鎴愬姛锛宻tring琛ㄧず閿欒淇℃伅
+ */
+mqttService.insertEmergencyPasswordAgreement = function (data) {
+    // 搴旀�ュ紑浠撳瘑鐮佸湪璁惧涓粎鏈夊敮涓�鐨�1涓紝鎵�浠ュ厛娓呯┖琛�
+    let deleteRet = sqliteService.d1_emergency_password.deleteAll()
+    if (deleteRet != 0) {
+        return "娓呯┖鏃у瘑鐮佸け璐�: " + deleteRet
+    }
+    
+    // 妫�鏌ュ瘑鐮佹槸鍚︽湁鏁�
+    if (!data.password) {
+        return "password cannot be empty"
+    }
+    
+    // 妫�鏌ュ瘑鐮侀暱搴︽槸鍚﹀ぇ浜庣瓑浜�8浣�
+    if (data.password.length < 8) {
+        return "Password length must be at least 8 digits"
+    }
+    
+    // 鏋勫缓瀵嗙爜璁板綍
+    let record = {}
+    record.id = data.id || 'emergency_' + Date.now() // 濡傛灉娌℃湁id锛岃嚜鍔ㄧ敓鎴�
+    record.password = data.password
+    record.description = data.description || ""
+    record.createTime = Date.now()
+    record.updateTime = Date.now()
+    record.status = data.status || 1
+    
+    // 淇濆瓨瀵嗙爜
+    let ret = sqliteService.d1_emergency_password.save(record)
+    if (ret == 0) {
+        return true
+    } else {
+        return "sql error ret:" + ret
+    }
+}
+
+/**
+ * 鏌ヨ搴旀�ュ紑浠撳瘑鐮�
+ * @param {object} event - MQTT浜嬩欢瀵硅薄
+ */
+mqttService.getEmergencyPassword = function (event) {
+    try {
+        logger.info('[mqttService] 鎺ユ敹鍒癵etEmergencyPassword鍛戒护:', JSON.stringify(event.topic))
+        logger.info('[mqttService] 鍛戒护payload:', event.payload)
+        let payload = JSON.parse(event.payload)
+        let res = this.getEmergencyPasswordAgreement()
+        logger.info('[mqttService] 鏌ヨ缁撴灉:', JSON.stringify(res))
+        return reply(event, res)
+    } catch (error) {
+        logger.error('[mqttService] getEmergencyPassword error:', error)
+        return reply(event, { error: error.message }, CODE.E_100)
+    }
+}
+
+/**
+ * 鏃堕棿鎴宠浆鏃ユ湡瀛楃涓�
+ * @param {number} timestamp - 鏃堕棿鎴�
+ * @returns {string} 鏃ユ湡瀛楃涓诧紝鏍煎紡锛歒YYY-MM-DD HH:MM:SS
+ */
+function timestampToDateString(timestamp) {
+    const date = new Date(timestamp);
+    const year = date.getFullYear();
+    const month = String(date.getMonth() + 1).padStart(2, '0');
+    const day = String(date.getDate()).padStart(2, '0');
+    const hours = String(date.getHours()).padStart(2, '0');
+    const minutes = String(date.getMinutes()).padStart(2, '0');
+    const seconds = String(date.getSeconds()).padStart(2, '0');
+    return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
+}
+
+/**
+ * 鏌ヨ搴旀�ュ紑浠撳瘑鐮侀�氱敤鍗忚鏍煎紡
+ * @returns {object} 鏌ヨ缁撴灉
+ */
+mqttService.getEmergencyPasswordAgreement = function () {
+    let passwords = sqliteService.d1_emergency_password.findAll()
+    if (passwords && passwords.length > 0) {
+        let password = passwords[0];
+        // 杞崲鏃堕棿鎴充负瀛楃涓叉牸寮�
+        password.createTime = timestampToDateString(password.createTime);
+        password.updateTime = timestampToDateString(password.updateTime);
+        return password;
+    }
+    return {};
+}
+
+
+/**
+ * 娓呯┖搴旀�ュ紑浠撳瘑鐮�
+ * @param {object} event - MQTT浜嬩欢瀵硅薄
+ */
+mqttService.clearEmergencyPassword = function (event) {
+    try {
+        logger.info('[mqttService] 鎺ユ敹鍒癱learEmergencyPassword鍛戒护:', JSON.stringify(event.topic))
+        logger.info('[mqttService] 鍛戒护payload:', event.payload)
+        let ret = sqliteService.d1_emergency_password.deleteAll()
+        if (ret == 0) {
+            logger.info('[mqttService] clearEmergencyPassword鎴愬姛')
+            return reply(event)
+        } else {
+            logger.error('[mqttService] clearEmergencyPassword澶辫触:', "sql error ret:" + ret)
+            return reply(event, "sql error ret:" + ret, CODE.E_100)
+        }
+    } catch (error) {
+        logger.error('[mqttService] clearEmergencyPassword error:', error)
+        return reply(event, { error: error.message }, CODE.E_100)
+    }
+}
+
+// =================================瀵嗛挜澧炲垹鏀规煡=================================
+/**
+ * 娣诲姞瀵嗛挜
+ * @param {object} event - MQTT浜嬩欢瀵硅薄
+ */
+mqttService.insertSecurity = function (event) {
+    try {
+        logger.info('[mqttService] 鎺ユ敹鍒癷nsertSecurity鍛戒护:', JSON.stringify(event.topic))
+        logger.info('[mqttService] 鍛戒护payload:', event.payload)
+        let payload = JSON.parse(event.payload)
+        let data = payload.payload && payload.payload.data ? payload.payload.data : {}
+        logger.info('[mqttService] 瑙f瀽鍚庣殑鍙傛暟:', JSON.stringify(data))
+        let res = this.insertSecurityAgreement(data)
+        if (typeof res == 'string') {
+            logger.error('[mqttService] insertSecurity澶辫触:', res)
+            return reply(event, res, CODE.E_100)
+        }
+        logger.info('[mqttService] insertSecurity鎴愬姛')
+        return reply(event)
+    } catch (error) {
+        logger.error('[mqttService] insertSecurity error:', error)
+        return reply(event, { error: error.message }, CODE.E_100)
+    }
+}
+
+/**
+ * 娣诲姞瀵嗛挜閫氱敤鍗忚鏍煎紡
+ * @param {array} data - 瀵嗛挜鏁版嵁鏁扮粍
+ * @returns {boolean|string} true琛ㄧず鎴愬姛锛宻tring琛ㄧず閿欒淇℃伅
+ */
+mqttService.insertSecurityAgreement = function (data) {
+    let securities = []
+    for (let i = 0; i < data.length; i++) {
+        const security = data[i];
+        let record = []
+        record.securityId = security.securityId
+        record.type = security.type
+        record.key = security.key
+        record.value = security.value
+        record.startTime = security.startTime
+        record.endTime = security.endTime
+        securities.push(record)
+    }
+    let ret = sqliteService.d1_security.saveAll(securities)
+    if (ret == 0) {
+        return true
+    } else {
+        return "sql error ret:" + ret
+    }
+}
+
+/**
+ * 鏌ヨ瀵嗛挜
+ * @param {object} event - MQTT浜嬩欢瀵硅薄
+ */
+mqttService.getKey = function (event) {
+    try {
+        logger.info('[mqttService] 鎺ユ敹鍒癵etKey鍛戒护:', JSON.stringify(event.topic))
+        logger.info('[mqttService] 鍛戒护payload:', event.payload)
+        let payload = JSON.parse(event.payload)
+        let data = payload.payload && payload.payload.data ? payload.payload.data : {}
+        logger.info('[mqttService] 瑙f瀽鍚庣殑鏌ヨ鍙傛暟:', JSON.stringify(data))
+        let res = this.getKeyAgreement(data)
+        logger.info('[mqttService] 鏌ヨ缁撴灉:', JSON.stringify(res))
+        return reply(event, res)
+    } catch (error) {
+        logger.error('[mqttService] getKey error:', error)
+        return reply(event, { error: error.message }, CODE.E_100)
+    }
+}
+
+/**
+ * 鏌ヨ瀵嗛挜閫氱敤鍗忚鏍煎紡
+ * @param {object} data - 鏌ヨ鍙傛暟
+ * @returns {object} 鏌ヨ缁撴灉
+ */
+mqttService.getSecurityAgreement = function (data) {
+    data.page = isEmpty(data.page) ? 0 : data.page
+    data.size = isEmpty(data.size) ? 10 : data.size
+    let totalCount = sqliteService.d1_security.count(data)
+    let securities = sqliteService.d1_security.findAll(data)
+    return {
+        content: securities,
+        page: data.page,
+        size: data.size,
+        total: totalCount,
+        totalPage: Math.ceil(totalCount / data.size),
+        count: securities.length
+    }
+}
+
+/**
+ * 鍒犻櫎瀵嗛挜
+ * @param {object} event - MQTT浜嬩欢瀵硅薄
+ */
+mqttService.delSecurity = function (event) {
+    try {
+        logger.info('[mqttService] 鎺ユ敹鍒癲elSecurity鍛戒护:', JSON.stringify(event.topic))
+        logger.info('[mqttService] 鍛戒护payload:', event.payload)
+        let payload = JSON.parse(event.payload)
+        let data = payload.payload && payload.payload.data ? payload.payload.data : {}
+        logger.info('[mqttService] 瑙f瀽鍚庣殑鍙傛暟:', JSON.stringify(data))
+        let res = this.delSecurityAgreement(data)
+        if (typeof res == 'string') {
+            logger.error('[mqttService] delSecurity澶辫触:', res)
+            return reply(event, res, CODE.E_100)
+        }
+        logger.info('[mqttService] delSecurity鎴愬姛')
+        return reply(event)
+    } catch (error) {
+        logger.error('[mqttService] delSecurity error:', error)
+        return reply(event, { error: error.message }, CODE.E_100)
+    }
+}
+
+/**
+ * 鍒犻櫎瀵嗛挜閫氱敤鍗忚鏍煎紡
+ * @param {array} data - 瀵嗛挜ID鏁扮粍
+ * @returns {boolean|string} true琛ㄧず鎴愬姛锛宻tring琛ㄧず閿欒淇℃伅
+ */
+mqttService.delSecurityAgreement = function (data) {
+    if (data.length > 0) {
+        let ret = sqliteService.d1_security.deleteBySecurityIdInBatch(data)
+        if (ret != 0) {
+            return "sql error ret:" + ret
+        }
+    }
+    return true
+}
+
+/**
+ * 娓呯┖瀵嗛挜
+ * @param {object} event - MQTT浜嬩欢瀵硅薄
+ */
+mqttService.clearSecurity = function (event) {
+    try {
+        logger.info('[mqttService] 鎺ユ敹鍒癱learSecurity鍛戒护:', JSON.stringify(event.topic))
+        logger.info('[mqttService] 鍛戒护payload:', event.payload)
+        let ret = sqliteService.d1_key.deleteAll()
+        if (ret == 0) {
+            logger.info('[mqttService] clearSecurity鎴愬姛')
+            return reply(event)
+        } else {
+            logger.error('[mqttService] clearSecurity澶辫触:', "sql error ret:" + ret)
+            return reply(event, "sql error ret:" + ret, CODE.E_100)
+        }
+    } catch (error) {
+        logger.error('[mqttService] clearSecurity error:', error)
+        return reply(event, { error: error.message }, CODE.E_100)
+    }
+}
+
+/**
+ * 杩滅▼鎺у埗
+ * @param {object} event - MQTT浜嬩欢瀵硅薄
+ */
+mqttService.control = function (event) {
+    try {
+        logger.info('[mqttService] 鎺ユ敹鍒癱ontrol鍛戒护:', JSON.stringify(event.topic))
+        logger.info('[mqttService] 鍛戒护payload:', event.payload)
+        let payload = JSON.parse(event.payload)
+        let data = payload.payload.data || {}
+        switch (data.command) {
+            case 0:
+                //閲嶅惎
+                logger.info('[mqttService] 鎵ц閲嶅惎鍛戒护')
+                reply(event)
+                common.asyncReboot(2)
+                return
+            case 1:
+                //杩滅▼寮�闂�
+                logger.info('[mqttService] 鎵ц杩滅▼寮�闂ㄥ懡浠�')
+                driver.gpio.open()
+                break
+            case 4:
+                //閲嶇疆
+                logger.info('[mqttService] 鎵ц閲嶇疆鍛戒护')
+                common.systemBrief("rm -rf /app/data/config/*")
+                common.systemBrief("rm -rf /app/data/db/*")
+                common.systemBrief("rm -rf /app/data/user/*")
+                common.systemBrief("rm -rf /app/data/user/*")
+                common.systemBrief("rm -rf /vgmj.db")
+                reply(event)
+                common.asyncReboot(2)
+                return
+            case 5:
+                //鎾斁璇煶
+                logger.info('[mqttService] 鎵ц鎾斁璇煶鍛戒护')
+                if (data.extra) {
+                    let res = common.systemWithRes(`test -e "/app/code/resource/wav/${data.extra.wav}.wav" && echo "OK" || echo "NO"`, 2)
+                    if (res.includes('OK')) {
+                        driver.alsa.play(`/app/code/resource/wav/${data.extra.wav}.wav`)
+                    }
+                }
+                break
+            case 6:
+                // 6锛氬睆骞曞睍绀哄浘鐗�
+                // TODO
+                logger.info('[mqttService] 鎵ц灞忓箷灞曠ず鍥剧墖鍛戒护')
+                break
+            case 7:
+                // 7锛氬睆骞曞睍绀烘枃瀛�
+                // TODO
+                logger.info('[mqttService] 鎵ц灞忓箷灞曠ず鏂囧瓧鍛戒护')
+                break
+            case 10:
+                logger.info('[mqttService] 鎵ц浜岀淮鐮佸睍绀哄懡浠�')
+                if (!isEmpty(data.extra.qrCodeBase64) && typeof data.extra.qrCodeBase64 == 'string') {
+                    //base64杞浘鐗囦繚瀛�
+                    let src = `/app/code/resource/image/app_qrcode.png`
+                    std.ensurePathExists(src)
+                    common.base64_2binfile(src, data.extra.qrCodeBase64)
+                    logger.info('[mqttService] 浜岀淮鐮佷繚瀛樻垚鍔�')
+                    return reply(event)
+                }
+                break
+            default:
+                logger.info('[mqttService] 鏈煡鍛戒护:', data.command)
+                break
+        }
+        logger.info('[mqttService] control鍛戒护鎵ц瀹屾垚')
+        return reply(event)
+    } catch (error) {
+        logger.error('[mqttService] control error:', error)
+        return reply(event, { error: error.message }, CODE.E_100)
+    }
+}
+
+/**
+ * 鏌ヨ閰嶇疆
+ * @param {object} event - MQTT浜嬩欢瀵硅薄
+ */
+mqttService.getConfig = function (event) {
+    try {
+        logger.info('[mqttService] 鎺ユ敹鍒癵etConfig鍛戒护:', JSON.stringify(event.topic))
+        logger.info('[mqttService] 鍛戒护payload:', event.payload)
+        let payload = JSON.parse(event.payload)
+        let data = payload.payload && payload.payload.data ? payload.payload.data : {}
+        logger.info('[mqttService] 瑙f瀽鍚庣殑鍙傛暟:', JSON.stringify(data))
+        let configAll = config.getAll()
+        let res = {}
+        // 閰嶇疆鍒嗙粍
+        for (const key in configAll) {
+            const value = configAll[key];
+            const keys = key.split(".")
+            if (keys.length == 2) {
+                if (!res[keys[0]]) {
+                    res[keys[0]] = {}
+                }
+                res[keys[0]][keys[1]] = value
+            } else {
+                res[keys[0]] = value
+            }
+        }
+        res.sys = {
+            // 淇濈暀鍘熸湁鐨� sysInfo 涓殑鍏朵粬鍊�
+            ...res.sys,
+            totalmem: common.getTotalmem(),
+            freemem: common.getFreemem(),
+            totaldisk: common.getTotaldisk(),
+            freedisk: common.getFreedisk(),
+            freecpu: common.getFreecpu()
+        };
+        if (isEmpty(data) || typeof data != "string" || data == "") {
+            // 鏌ヨ鍏ㄩ儴
+            logger.info('[mqttService] getConfig鎴愬姛锛岃繑鍥炲叏閮ㄩ厤缃紝閰嶇疆鏁伴噺:', Object.keys(res).length)
+            return reply(event, res)
+        }
+        // 鍗曟潯浠舵煡璇�"data": "mqttInfo.clientId"
+        let keys = data.split(".")
+        let search = {}
+        if (keys.length == 2) {
+            if (res[keys[0]]) {
+                search[keys[0]] = {}
+                search[keys[0]][keys[1]] = res[keys[0]][keys[1]]
+            }
+        } else {
+            search[keys[0]] = res[keys[0]]
+        }
+        logger.info('[mqttService] getConfig鎴愬姛锛岃繑鍥炴寚瀹氶厤缃�:', JSON.stringify(search))
+        return reply(event, search)
+    } catch (error) {
+        logger.error('[mqttService] getConfig error:', error)
+        return reply(event, { error: error.message }, CODE.E_100)
+    }
+}
+
+/**
+ * 淇敼閰嶇疆
+ * @param {object} event - MQTT浜嬩欢瀵硅薄
+ */
+mqttService.setConfig = function (event) {
+    try {
+        logger.info('[mqttService] 鎺ユ敹鍒皊etConfig鍛戒护:', JSON.stringify(event.topic))
+        logger.info('[mqttService] 鍛戒护payload:', event.payload)
+        let payload = JSON.parse(event.payload)
+        let data = payload.payload && payload.payload.data ? payload.payload.data : {}
+        logger.info('[mqttService] 瑙f瀽鍚庣殑鍙傛暟:', JSON.stringify(data))
+        if (!data || typeof data != 'object') {
+            logger.error('[mqttService] setConfig澶辫触: data should not be empty')
+            return reply(event, "data should not be empty", CODE.E_100)
+        }
+        let res = configService.configVerifyAndSave(data)
+        if (typeof res != 'boolean') {
+            // 杩斿洖閿欒淇℃伅
+            logger.error('[mqttService] setConfig澶辫触:', res)
+            return reply(event, res, CODE.E_100)
+        }
+        if (res) {
+            logger.info('[mqttService] setConfig鎴愬姛')
+            return reply(event)
+        } else {
+            logger.error('[mqttService] setConfig澶辫触: unknown failure')
+            return reply(event, "unknown failure", CODE.E_100)
+        }
+    } catch (error) {
+        logger.error('[mqttService] setConfig error:', error)
+        return reply(event, { error: error.message }, CODE.E_100)
+    }
+}
+
+/**
+ * 鍗囩骇鍥轰欢
+ * @param {object} event - MQTT浜嬩欢瀵硅薄
+ */
+mqttService.upgradeFirmware = function (event) {
+    try {
+        logger.info('[mqttService] 鎺ユ敹鍒皍pgradeFirmware鍛戒护:', JSON.stringify(event.topic))
+        logger.info('[mqttService] 鍛戒护payload:', event.payload)
+        let payload = JSON.parse(event.payload)
+        let data = payload.payload && payload.payload.data ? payload.payload.data : {}
+        logger.info('[mqttService] 瑙f瀽鍚庣殑鍙傛暟:', JSON.stringify(data))
+        if (!data || typeof data != 'object' || typeof data.type != 'number' || typeof data.url != 'string' || typeof data.md5 != 'string') {
+            logger.error('[mqttService] upgradeFirmware澶辫触: data\'s params error')
+            return reply(event, "data's params error", CODE.E_100)
+        }
+
+        if (data.type == 0) {
+            try {
+                logger.info('[mqttService] 寮�濮嬪浐浠跺崌绾э紝url:', data.url, 'md5:', data.md5)
+                driver.screen.upgrade({ title: "confirm.upgrade", content: "confirm.upgrading" })
+                ota.updateHttp(data.url, data.md5, 300)
+                driver.screen.upgrade({ title: "confirm.upgrade", content: "confirm.upgradeSuccess" })
+                logger.info('[mqttService] 鍥轰欢鍗囩骇鎴愬姛')
+                reply(event)
+                common.asyncReboot(3)
+                return
+            } catch (error) {
+                logger.error('[mqttService] 鍥轰欢鍗囩骇澶辫触:', error)
+                driver.screen.upgrade({ title: "confirm.upgrade", content: "confirm.upgradeFail" })
+                return reply(event, "upgrade failure", CODE.E_100)
+            }
+        }
+
+        logger.error('[mqttService] upgradeFirmware澶辫触: 涓嶆敮鎸佺殑鍗囩骇绫诲瀷')
+        return reply(event, "upgrade failure", CODE.E_100)
+    } catch (error) {
+        logger.error('[mqttService] upgradeFirmware error:', error)
+        return reply(event, { error: error.message }, CODE.E_100)
+    }
+}
+
+/**
+ * 鏌ヨ璇嗗埆璁板綍
+ * @param {object} event - MQTT浜嬩欢瀵硅薄
+ */
+mqttService.getRecords = function (event) {
+    try {
+        logger.info('[mqttService] 鎺ユ敹鍒癵etRecords鍛戒护:', JSON.stringify(event.topic))
+        logger.info('[mqttService] 鍛戒护payload:', event.payload)
+        let payload = JSON.parse(event.payload)
+        let data = payload.payload && payload.payload.data ? payload.payload.data : {}
+        logger.info('[mqttService] 瑙f瀽鍚庣殑鏌ヨ鍙傛暟:', JSON.stringify(data))
+        let res = this.getRecordsAgreement(data)
+        logger.info('[mqttService] 鏌ヨ缁撴灉:', JSON.stringify(res))
+        return reply(event, res)
+    } catch (error) {
+        logger.error('[mqttService] getRecords error:', error)
+        return reply(event, { error: error.message }, CODE.E_100)
+    }
+}
+
+/**
+ * 灏嗘棩鏈熷瓧绗︿覆杞崲涓烘椂闂存埑锛堢锛�
+ * @param {string} dateString - 鏃ユ湡瀛楃涓诧紝鏍煎紡锛歒YYY-MM-DD HH:MM:SS
+ * @returns {number} 鏃堕棿鎴筹紙绉掞級
+ */
+function dateStringToTimestamp(dateString) {
+    if (!dateString) return null
+    // 灏哬YYY-MM-DD HH:MM:SS鏍煎紡杞崲涓篩YYY-MM-DDTHH:MM:SS鏍煎紡锛屼互渚縩ew Date()姝g‘瑙f瀽
+    const formattedDateString = dateString.replace(' ', 'T')
+    const date = new Date(formattedDateString)
+    return Math.floor(date.getTime() / 1000)
+}
+
+/**
+ * 鏌ヨ璇嗗埆璁板綍閫氱敤鍗忚鏍煎紡
+ * @param {object} data - 鏌ヨ鍙傛暟
+ * @returns {object} 鏌ヨ缁撴灉
+ */
+mqttService.getRecordsAgreement = function (data) {
+    data.page = isEmpty(data.page) ? 0 : data.page
+    data.size = isEmpty(data.size) ? 10 : data.size
+    
+    // 澶勭悊鏃堕棿鍙傛暟锛屽皢瀛楃涓叉牸寮忚浆鎹负鏃堕棿鎴�
+    let startTime = null
+    let endTime = null
+    if (data.startTime) {
+        if (typeof data.startTime === 'string') {
+            startTime = dateStringToTimestamp(data.startTime)
+        } else {
+            startTime = Math.floor(data.startTime / 1000) // 杞崲涓虹绾ф椂闂存埑
+        }
+    }
+    if (data.endTime) {
+        if (typeof data.endTime === 'string') {
+            endTime = dateStringToTimestamp(data.endTime)
+        } else {
+            endTime = Math.floor(data.endTime / 1000) // 杞崲涓虹绾ф椂闂存埑
+        }
+    }
+    
+    // 鏋勫缓鏌ヨ鏉′欢
+    let queryData = {}
+    let nameFilter = null
+    // 澶嶅埗鍏朵粬鏌ヨ鍙傛暟
+    for (const key in data) {
+        if (key !== 'startTime' && key !== 'endTime' && key !== 'name') {
+            queryData[key] = data[key]
+        } else if (key === 'name') {
+            nameFilter = data[key]
+        }
+    }
+    
+    // 鏋勫缓SQL鏉′欢
+    let whereClause = ''
+    if (startTime) {
+        whereClause += `time >= ${startTime} `
+    }
+    if (endTime) {
+        if (whereClause) {
+            whereClause += `AND `
+        }
+        whereClause += `time <= ${endTime} `
+    }
+    
+    // 澶嶅埗鍏朵粬鏉′欢
+    for (const key in queryData) {
+        if (key !== 'page' && key !== 'size') {
+            if (whereClause) {
+                whereClause += `AND `
+            }
+            if (typeof queryData[key] === 'string') {
+                whereClause += `${key} = '${queryData[key]}' `
+            } else {
+                whereClause += `${key} = ${queryData[key]} `
+            }
+        }
+    }
+    
+    // 鎵ц鏌ヨ
+    let totalCount = 0
+    let securities = []
+    try {
+        // 鏋勫缓count SQL
+        let countSql = `SELECT COUNT(*) FROM d1_pass_record `
+        if (whereClause) {
+            countSql += `WHERE ${whereClause} `
+        }
+        countSql += `;`
+        let countResult = sqlite.select(countSql)
+        if (countResult && countResult[0] && countResult[0]['COUNT(*)']) {
+            totalCount = countResult[0]['COUNT(*)']
+        }
+        
+        // 鏋勫缓findAll SQL
+        let findSql = `SELECT * FROM d1_pass_record `
+        if (whereClause) {
+            findSql += `WHERE ${whereClause} `
+        }
+        findSql += `ORDER BY time DESC `
+        if (queryData.page !== undefined && queryData.size !== undefined) {
+            findSql += `LIMIT ${queryData.size} OFFSET ${queryData.page * queryData.size} `
+        }
+        findSql += `;`
+        securities = sqlite.select(findSql)
+    } catch (error) {
+        logger.error('[mqttService] 鏌ヨ璁板綍澶辫触:', error)
+    }
+    
+    // 澶勭悊姣忔潯璁板綍
+    let processedSecurities = securities.map(record => {
+        // 瑙f瀽extra瀛楁
+        let extraData = {}
+        try {
+            if (record.extra && record.extra !== '') {
+                extraData = JSON.parse(record.extra)
+            }
+        } catch (error) {
+            logger.error('[mqttService] 瑙f瀽extra澶辫触:', error)
+        }
+        
+        // 瑙f瀽extra2瀛楁
+        let extra2Data = {}
+        try {
+            if (record.extra2 && record.extra2 !== '') {
+                extra2Data = JSON.parse(record.extra2)
+            }
+        } catch (error) {
+            logger.error('[mqttService] 瑙f瀽extra2澶辫触:', error)
+        }
+        
+        // 鏋勫缓鏂拌褰�
+        return {
+            id: record.id,
+            keyId: record.keyId,
+            permissionId: record.permissionId,
+            permissionId2: record.permissionId2,
+            userId: record.userId,
+            userId2: record.userId2,
+            type: record.type,
+            code: record.code,
+            door: record.door,
+            time: timestampToDateString(record.time * 1000), // 灏嗙绾ф椂闂存埑杞崲涓烘绉掔骇锛屽啀杞崲涓烘棩鏈熷瓧绗︿覆
+            result: record.result,
+            name: extraData.name || '',
+            idCard: extraData.idCard || '',
+            name2: extra2Data.name || '',
+            idCard2: extra2Data.idCard || '',
+            message: record.message
+        }
+    })
+    
+    // 搴旂敤name杩囨护
+    if (nameFilter) {
+        processedSecurities = processedSecurities.filter(record => 
+            record.name.toLowerCase().includes(nameFilter.toLowerCase())
+        )
+        // 鏇存柊鎬绘暟鍜屾�婚〉鏁�
+        totalCount = processedSecurities.length
+    }
+    
+    return {
+        content: processedSecurities,
+        page: data.page,
+        size: data.size,
+        total: totalCount,
+        totalPage: Math.ceil(totalCount / data.size),
+        count: processedSecurities.length
+    }
+}
+
+/**
+ * 鍒犻櫎璁板綍
+ * @param {object} event - MQTT浜嬩欢瀵硅薄
+ */
+mqttService.delRecords = function (event) {
+    try {
+        logger.info('[mqttService] 鎺ユ敹鍒癲elRecords鍛戒护:', JSON.stringify(event.topic))
+        logger.info('[mqttService] 鍛戒护payload:', event.payload)
+        let payload = JSON.parse(event.payload)
+        let data = payload.payload && payload.payload.data ? payload.payload.data : {}
+        logger.info('[mqttService] 瑙f瀽鍚庣殑鍙傛暟:', JSON.stringify(data))
+        let res = this.delRecordsAgreement(data)
+        if (typeof res == 'string') {
+            logger.error('[mqttService] delRecords澶辫触:', res)
+            return reply(event, res, CODE.E_100)
+        }
+        logger.info('[mqttService] delRecords鎴愬姛')
+        return reply(event)
+    } catch (error) {
+        logger.error('[mqttService] delRecords error:', error)
+        return reply(event, { error: error.message }, CODE.E_100)
+    }
+}
+
+/**
+ * 鍒犻櫎璁板綍閫氱敤鍗忚鏍煎紡
+ * @param {object} data - 鍒犻櫎鍙傛暟
+ * @returns {boolean|string} true琛ㄧず鎴愬姛锛宻tring琛ㄧず閿欒淇℃伅
+ */
+mqttService.delRecordsAgreement = function (data) {
+    
+    // 鏍规嵁鏃堕棿鑼冨洿鍒犻櫎璁板綍
+    if (data.startTime || data.endTime) {
+        logger.info('[mqttService] 鏃堕棿鑼冨洿: startTime=' + data.startTime + ', endTime=' + data.endTime)
+        
+        try {
+            // 鏋勫缓鏌ヨ鏉′欢
+            let query = {};
+            if (data.startTime) {
+                query.startTime = data.startTime;
+            }
+            if (data.endTime) {
+                query.endTime = data.endTime;
+            }
+            
+            // 浣跨敤getRecordsAgreement鍑芥暟鐨勬煡璇㈤�昏緫鏉ヨ幏鍙栫鍚堟潯浠剁殑璁板綍
+            let result = mqttService.getRecordsAgreement(query);
+            let records = result.content || [];
+            
+            // 閫愪釜鍒犻櫎璁板綍
+            let deletedCount = 0;
+            for (let record of records) {
+                // 濡傛灉鏄汉鑴歌褰曪紝鍒犻櫎瀵瑰簲鐨勫浘鐗囨枃浠�
+                if (record.type == 300 && record.code) {
+                    try {
+                        common.systemBrief(`rm -rf ${record.code}`);
+                    } catch (error) {
+                        logger.error('[mqttService] 鍒犻櫎鍥剧墖鏂囦欢鍑洪敊: ' + error.message);
+                    }
+                }
+                // 鍒犻櫎璁板綍
+                sqliteService.d1_pass_record.delete({ id: record.id });
+                deletedCount++;
+            }
+            
+            logger.info('[mqttService] 鎴愬姛鍒犻櫎 ' + deletedCount + ' 鏉¤褰�');
+        } catch (error) {
+            logger.error('[mqttService] 鍒犻櫎璁板綍鍑洪敊: ' + error.message);
+            // 蹇界暐閿欒锛岃繑鍥炴垚鍔�
+        }
+    }
+    
+    return true
+}
+/**
+ * 閫氳涓婃姤鍥炲
+ * @param {object} event - MQTT浜嬩欢瀵硅薄
+ */
+mqttService.access_reply = function (event) {
+    try {
+        logger.info('[mqttService] 鎺ユ敹鍒癮ccess_reply鍛戒护:', JSON.stringify(event.topic))
+        logger.info('[mqttService] 鍛戒护payload:', event.payload)
+        let payload = JSON.parse(event.payload)
+        logger.info('[mqttService] 瑙f瀽鍚庣殑鍙傛暟:', JSON.stringify(payload))
+        let serialNo = map.get(payload.serialNo)
+        if (serialNo) {
+            logger.info('[mqttService] 娓呯悊涓存椂鏂囦欢:', serialNo)
+            common.systemBrief(`rm -rf ${serialNo}`)
+            map.del(payload.serialNo)
+        }
+        logger.info('[mqttService] 娓呯┖閫氳璁板綍')
+        sqliteService.d1_pass_record.deleteAll()
+        logger.info('[mqttService] access_reply澶勭悊瀹屾垚')
+    } catch (error) {
+        logger.error('[mqttService] access_reply error:', error)
+    }
+}
+
+/**
+ * 鍦ㄧ嚎楠岃瘉鍥炲
+ * @param {object} raw - MQTT浜嬩欢瀵硅薄
+ */
+mqttService.access_online_reply = function (raw) {
+    try {
+        logger.info('[mqttService] 鎺ユ敹鍒癮ccess_online_reply鍛戒护:', JSON.stringify(raw.topic))
+        logger.info('[mqttService] 鍛戒护payload:', raw.payload)
+        let payload = JSON.parse(raw.payload)
+        logger.info('[mqttService] 瑙f瀽鍚庣殑鍙傛暟:', JSON.stringify(payload))
+        let map = dxMap.get("VERIFY")
+        let data = map.get(payload.serialNo)
+        if (data) {
+            logger.info('[mqttService] 澶勭悊鍦ㄧ嚎楠岃瘉鍥炲锛宻erialNo:', payload.serialNo)
+            map.del(payload.serialNo)
+            driver.mqtt.getOnlinecheckReply(payload)
+        }
+        logger.info('[mqttService] access_online_reply澶勭悊瀹屾垚')
+    } catch (error) {
+        logger.error('[mqttService] access_online_reply error:', error)
+    }
+}
+
+/**
+ * 閿欒浠g爜瀹氫箟
+ */
+const CODE = {
+    // 鎴愬姛
+    S_000: "000000",
+    // 鏈煡閿欒
+    E_100: "100000",
+    // 璁惧宸茶绂佺敤	
+    E_101: "100001",
+    // 璁惧姝e繖锛岃绋嶅悗鍐嶈瘯	
+    E_102: "100002",
+    // 绛惧悕妫�楠屽け璐�	
+    E_103: "100003",
+    // 瓒呮椂閿欒
+    E_104: "100004",
+    // 璁惧绂荤嚎	
+    E_105: "100005",
+}
+mqttService.CODE = CODE
+
+/**
+ * 涓婃姤璁惧淇℃伅鍜岄�氳璁板綍
+ */
+mqttService.report = function () {
+    // 鍦ㄧ嚎涓婃姤
+    let payloadReply = mqttReply(std.genRandomStr(10), {
+        mac: config.get("sys.mac") || '',
+        version: config.get("sys.version"),
+        appVersion: config.get("sys.version"),
+        releaseTime: config.get("sys.createTime"),
+        type: config.get("net.type"),
+    }, CODE.S_000)
+    driver.mqtt.send("access_device/v2/event/connect", JSON.stringify(payloadReply))
+
+    //閫氳璁板綍涓婃姤 - 宸插叧闂�
+    // let res = sqliteService.d1_pass_record.findAll()
+    // if (res.length <= 0) {
+    //     return
+    // }
+    // // 绛涢�夊嚭 type === 300 鐨勫璞★紙浜鸿劯璁板綍锛�
+    // let faceArray = res.filter(item => item.type == 300);
+    // // 绛涢�夊嚭 type !== 300 鐨勫璞★紙鍏朵粬璁板綍锛�
+    // let recordArray = res.filter(item => item.type != 300);
+    // if (recordArray.length > 0) {
+    //     driver.mqtt.send("access_device/v2/event/access", JSON.stringify(mqttReply(std.genRandomStr(10), recordArray, CODE.S_000)))
+    // }
+    // if (faceArray.length > 0) {
+    //     let index = 0
+    //     let timer = std.setInterval(() => {
+    //         let serialNo = std.genRandomStr(10)
+    //         //缂撳瓨鏀惧叆瑕佸垹闄ょ殑浜鸿劯鐓х墖 src
+    //         map.del(serialNo)
+    //         map.put(serialNo, faceArray[index].code)
+    //         
+    //         // 妫�鏌aceArray[index].code鏄惁鏈夋晥
+    //         if (faceArray[index].code) {
+    //             faceArray[index].code = driver.face.fileToBase64(faceArray[index].code)
+    //         } else {
+    //             faceArray[index].code = ""
+    //             logger.info("浜鸿劯璁板綍涓璫ode瀛楁涓虹┖锛岃烦杩嘊ase64杞崲")
+    //         }
+    //         
+    //         driver.mqtt.send("access_device/v2/event/access", JSON.stringify(mqttReply(serialNo, [faceArray[index]], CODE.S_000)))
+    //         index++
+    //         if (!faceArray[index]) {
+    //             std.clearInterval(saveTimer)
+    //             std.clearInterval(timer)
+    //         }
+    //     }, 1000)
+    //     // 姣忛殧500ms妫�鏌ヤ竴娆qtt杩炴帴鐘舵�侊紝濡傛灉鏂紑锛屽垯鍋滄涓婃姤
+    //     let saveTimer = std.setInterval(() => {
+    //         if (!driver.mqtt.getStatus()) {
+    //             std.clearInterval(saveTimer)
+    //             std.clearInterval(timer)
+    //         }
+    //     }, 500)
+    // }
+}
+
+/**
+ * mqtt璇锋眰缁熶竴鍥炲
+ * @param {object} event - MQTT浜嬩欢瀵硅薄
+ * @param {any} data - 鍥炲鏁版嵁
+ * @param {string} code - 閿欒浠g爜
+ */
+function reply(event, data, code) {
+    try {
+        let topic = getReplyTopic(event)
+        let payload = JSON.parse(event.payload)
+        let serialNo = payload.serialNo || std.genRandomStr(10)
+        let reply = JSON.stringify(mqttReply(serialNo, data, isEmpty(code) ? CODE.S_000 : code))
+        driver.mqtt.send(topic, reply)
+    } catch (error) {
+        logger.error('[mqttService] reply error:', error)
+    }
+}
+
+/**
+ * 鑾峰彇鍥炲涓婚
+ * @param {object} data - MQTT浜嬩欢瀵硅薄
+ * @returns {string} 鍥炲涓婚
+ */
+function getReplyTopic(data) {
+    //    return data.topic.replace("/" + config.get("sys.sn"), '') + "_reply";
+    try {
+        let sn = config.get("mqtt.clientId")
+        return data.topic.replace("/" + sn, '') + "_reply";
+    } catch (error) {
+        logger.error('[mqttService] getReplyTopic error:', error)
+        // 鍥為��鍒颁娇鐢ㄥ浐瀹氭牸寮�
+        return data.topic + "_reply"
+    }
+}
+
+/**
+ * mqtt鍥炲鏍煎紡鏋勫缓
+ * @param {string} serialNo - 搴忓垪鍙�
+ * @param {any} data - 鍥炲鏁版嵁
+ * @param {string} code - 閿欒浠g爜
+ * @returns {object} 鍥炲鏍煎紡瀵硅薄
+ */
+function mqttReply(serialNo, data, code) {
+    // 鐢熸垚褰撳墠鏃堕棿鐨勫瓧绗︿覆鏍煎紡
+    const now = new Date();
+    const year = now.getFullYear();
+    const month = String(now.getMonth() + 1).padStart(2, '0');
+    const day = String(now.getDate()).padStart(2, '0');
+    const hours = String(now.getHours()).padStart(2, '0');
+    const minutes = String(now.getMinutes()).padStart(2, '0');
+    const seconds = String(now.getSeconds()).padStart(2, '0');
+    const timeString = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
+    
+    return {
+        serialNo: serialNo,
+        uuid: config.get("sys.uuid"),
+        sign: '',
+        code: code,
+        data: data,
+        time: timeString
+    }
+}
+mqttService.mqttReply = mqttReply
+
+/**
+ * 鑾峰彇鎵�鏈夎闃呯殑topic
+ * @returns {array} 璁㈤槄鐨則opic鍒楄〃
+ */
+mqttService.getTopics = function () {
+    // 鑾峰彇鎵�鏈夎闃呯殑topic
+    let sn = config.get("mqtt.clientId")
+    const topics = [
+        "control", "getConfig", "setConfig", "upgradeFirmware", "test",
+        "getPermission", "insertPermission", "delPermission", "clearPermission",
+        "getKey", "insertKey", "delKey", "clearKey",
+        "getUser", "insertUser", "delUser", "clearUser",
+        "getSecurity", "insertSecurity", "delSecurity", "clearSecurity", "getRecords", "delRecords",
+        "insertEmergencyPassword", "delEmergencyPassword", "clearEmergencyPassword", "getEmergencyPassword"
+    ]
+    const eventReplies = ["connect_reply", "alarm_reply", "access_reply", "access_online_reply"]
+
+    let flag = 'access_device/v2/cmd/' + sn + "/"
+    let eventFlag = 'access_device/v2/event/' + sn + "/"
+    return topics.map(item => flag + item).concat(eventReplies.map(item => eventFlag + item));
+}
+
+/**
+ * 鍒ょ┖鍑芥暟
+ * @param {any} value - 瑕佸垽鏂殑鍊�
+ * @returns {boolean} 鏄惁涓虹┖
+ */
+function isEmpty(value) {
+    return value === undefined || value === null || value === ""
+}
+
+export default mqttService
+
+/*
+`mqttService.getTopics()` 鍑芥暟杩斿洖鐨勬墍鏈� topic 濡備笅锛�
+
+### 鍛戒护 topic锛堢敤浜庢帴鏀舵湇鍔″櫒涓嬪彂鐨勫懡浠わ級锛�
+- `access_device/v2/cmd/{sn}/control` - 鎺у埗鍛戒护
+- `access_device/v2/cmd/{sn}/getConfig` - 鑾峰彇閰嶇疆
+- `access_device/v2/cmd/{sn}/setConfig` - 璁剧疆閰嶇疆
+- `access_device/v2/cmd/{sn}/upgradeFirmware` - 鍥轰欢鍗囩骇
+- `access_device/v2/cmd/{sn}/test` - 娴嬭瘯鍛戒护
+- `access_device/v2/cmd/{sn}/getPermission` - 鑾峰彇鏉冮檺
+- `access_device/v2/cmd/{sn}/insertPermission` - 鎻掑叆鏉冮檺
+- `access_device/v2/cmd/{sn}/delPermission` - 鍒犻櫎鏉冮檺
+- `access_device/v2/cmd/{sn}/clearPermission` - 娓呴櫎鏉冮檺
+- `access_device/v2/cmd/{sn}/getKey` - 鑾峰彇瀵嗛挜
+- `access_device/v2/cmd/{sn}/insertKey` - 鎻掑叆瀵嗛挜
+- `access_device/v2/cmd/{sn}/delKey` - 鍒犻櫎瀵嗛挜
+- `access_device/v2/cmd/{sn}/clearKey` - 娓呴櫎瀵嗛挜
+- `access_device/v2/cmd/{sn}/getUser` - 鑾峰彇鐢ㄦ埛
+- `access_device/v2/cmd/{sn}/insertUser` - 鎻掑叆鐢ㄦ埛
+- `access_device/v2/cmd/{sn}/delUser` - 鍒犻櫎鐢ㄦ埛
+- `access_device/v2/cmd/{sn}/clearUser` - 娓呴櫎鐢ㄦ埛
+- `access_device/v2/cmd/{sn}/getSecurity` - 鑾峰彇瀹夊叏淇℃伅
+- `access_device/v2/cmd/{sn}/insertSecurity` - 鎻掑叆瀹夊叏淇℃伅
+- `access_device/v2/cmd/{sn}/delSecurity` - 鍒犻櫎瀹夊叏淇℃伅
+- `access_device/v2/cmd/{sn}/clearSecurity` - 娓呴櫎瀹夊叏淇℃伅
+- `access_device/v2/cmd/{sn}/getRecords` - 鑾峰彇璁板綍
+- `access_device/v2/cmd/{sn}/delRecords` - 鍒犻櫎璁板綍
+
+### 浜嬩欢鍥炲 topic锛堢敤浜庢帴鏀舵湇鍔″櫒瀵逛簨浠剁殑鍥炲锛夛細
+- `access_device/v2/event/{sn}/connect_reply` - 杩炴帴鍥炲
+- `access_device/v2/event/{sn}/alarm_reply` - 鍛婅鍥炲
+- `access_device/v2/event/{sn}/access_reply` - 閫氳鍥炲
+- `access_device/v2/event/{sn}/access_online_reply` - 鍦ㄧ嚎楠岃瘉鍥炲
+
+鍏朵腑 `{sn}` 鏄澶囩殑搴忓垪鍙凤紝浼氳鏇挎崲涓哄疄闄呯殑璁惧搴忓垪鍙枫��
+*/
\ No newline at end of file
diff --git a/vf205_access/src/service/nfcService.js b/vf205_access/src/service/nfcService.js
new file mode 100644
index 0000000..bfb90a4
--- /dev/null
+++ b/vf205_access/src/service/nfcService.js
@@ -0,0 +1,44 @@
+/**
+ * NFC鏈嶅姟妯″潡
+ * 澶勭悊NFC鍗$墖鐩稿叧鐨勪笟鍔¢�昏緫锛屽寘鎷韩浠借瘉鍗″拰浜戣瘉鐨勫鐞�
+ */
+import log from '../../dxmodules/dxLogger.js'
+import dxMap from '../../dxmodules/dxMap.js'
+import accessService from '../service/accessService.js'
+import config from '../../dxmodules/dxConfig.js'
+import driver from '../driver.js';
+
+const nfcService = {}
+
+/**
+ * 鎺ユ敹NFC鍗$墖娑堟伅骞跺鐞�
+ * @param {object} data - NFC鍗$墖鏁版嵁
+ * @param {string} [data.card_type] - 鍗$墖绫诲瀷
+ * @param {string} [data.id] - 韬唤璇佺墿鐞嗗崱鍙�
+ * @param {string} [data.name] - 濮撳悕锛堜簯璇侊級
+ * @param {string} [data.sex] - 鎬у埆锛堜簯璇侊級
+ * @param {string} [data.idCardNo] - 韬唤璇佸彿鐮侊紙浜戣瘉锛�
+ */
+nfcService.receiveMsg = function (data) {
+    // log.info('[nfcService] receiveMsg :' + JSON.stringify(data))
+
+    // 棣栧厛鍒ゆ柇鏄惁鏄韩浠借瘉鍗�
+    if (data.card_type && data.id) {
+        if (dxMap.get("UI").get("getCardStart")) {
+            driver.screen.getCard(data.id)
+            return
+        }
+        // 韬唤璇佺墿鐞嗗崱鍙�/鏅�氬崱
+        accessService.access({ type: "200", code: data.id })
+    } else if (data.name && data.sex && data.idCardNo) {
+        if (dxMap.get("UI").get("getCardStart")) {
+            driver.screen.getCard(data.idCardNo)
+            return
+        }
+        // 浜戣瘉
+        accessService.access({ type: "200", code: data.idCardNo });
+    }
+
+}
+
+export default nfcService
diff --git a/vf205_access/src/service/platService.js b/vf205_access/src/service/platService.js
new file mode 100644
index 0000000..a1e9d22
--- /dev/null
+++ b/vf205_access/src/service/platService.js
@@ -0,0 +1,4 @@
+/**
+ * 骞冲彴鏈嶅姟閫氫俊妯″潡
+ * 澶勭悊骞冲彴鏈嶅姟鐩稿叧鐨勪笟鍔¢�昏緫锛屽寘鎷嚟璇佷笅鍙戝拰浜戣瘉鐨勫鐞�
+ */
\ No newline at end of file
diff --git a/vf205_access/src/service/sqliteService.js b/vf205_access/src/service/sqliteService.js
new file mode 100644
index 0000000..7993751
--- /dev/null
+++ b/vf205_access/src/service/sqliteService.js
@@ -0,0 +1,616 @@
+/**
+ * SQLite鏈嶅姟妯″潡
+ * 鎻愪緵鏁版嵁搴撳垵濮嬪寲銆佽〃缁撴瀯绠$悊銆丣PA椋庢牸鐨勫鍒犳敼鏌ユ柟娉曞拰浜嬪姟绠$悊
+ */
+import log from '../../dxmodules/dxLogger.js'
+import sqlite from '../../dxmodules/dxSqlite.js'
+
+//-------------------------variable-------------------------
+const sqliteService = {}
+//-------------------------public-------------------------
+
+/**
+ * 鍒濆鍖栨暟鎹簱
+ * @param {string} path - 鏁版嵁搴撴枃浠惰矾寰�
+ * @throws {Error} 濡傛灉璺緞涓虹┖鍒欐姏鍑洪敊璇�
+ */
+sqliteService.init = function (path) {
+    if (!path) {
+        throw new Error("path should not be null or empty")
+    }
+    // 鍒涘缓鏁版嵁搴�
+    sqlite.init(path)
+    // 鍒涘缓琛�
+    createTables()
+}
+
+/**
+ * 鏁版嵁搴撹〃缁撴瀯瀹氫箟
+ */
+let entities = {
+    d1_pass_record: {
+        id: "VARCHAR(128) PRIMARY KEY",
+        keyId: "VARCHAR(128)",
+        permissionId: "VARCHAR(128)",
+        permissionId2: "VARCHAR(128)",
+        userId: "VARCHAR(128)",
+        userId2: "VARCHAR(128)",
+        type: "VARCHAR(128)",
+        code: "VARCHAR(128)",
+        door: "VARCHAR(128)",
+        time: "INTEGER",
+        result: "INTEGER",
+        extra: "TEXT",
+        extra2: "TEXT",
+        message: "TEXT",
+    },
+    d1_permission: {
+        permissionId: "VARCHAR(128) PRIMARY KEY",
+        userId: "VARCHAR(128)",
+        door: "VARCHAR(128)",
+        extra: "TEXT",
+        timeType: "INTEGER",
+        beginTime: "INTEGER",
+        endTime: "INTEGER",
+        repeatBeginTime: "INTEGER",
+        repeatEndTime: "INTEGER",
+        period: "TEXT",
+    },
+    d1_security: {
+        securityId: "VARCHAR(128) PRIMARY KEY",
+        type: "VARCHAR(128)",
+        key: "VARCHAR(128)",
+        value: "TEXT",
+        startTime: "INTEGER",
+        endTime: "INTEGER",
+    },
+    d1_voucher: {
+        keyId: "VARCHAR(128) PRIMARY KEY",
+        type: "VARCHAR(128)",
+        code: "TEXT",
+        userId: "VARCHAR(128)",
+        extra: "TEXT",
+    },
+    d1_person: {
+        userId: "VARCHAR(128) PRIMARY KEY",
+        name: "VARCHAR(128)",
+        extra: "TEXT",
+    },
+    d1_emergency_password: {
+        id: "VARCHAR(128) PRIMARY KEY",
+        password: "VARCHAR(128)",
+        description: "VARCHAR(256)",
+        createTime: "INTEGER",
+        updateTime: "INTEGER",
+        status: "INTEGER"
+    }
+}
+
+/**
+ * SQL绫诲瀷杞琂S绫诲瀷
+ * @param {string} sqlType - SQL鏁版嵁绫诲瀷
+ * @returns {string} JavaScript鏁版嵁绫诲瀷
+ */
+let sqlType2jsType = (sqlType) => {
+    if (sqlType.indexOf("INTEGER") > -1) {
+        return 'number'
+    } else {
+        return 'string'
+    }
+}
+
+/**
+ * 鍒涘缓琛ㄧ粨鏋�
+ * @throws {Error} 濡傛灉琛ㄥ垱寤哄け璐ュ垯鎶涘嚭閿欒
+ */
+function createTables() {
+    for (const tableName in entities) {
+        const table = entities[tableName];
+        let sql = `CREATE TABLE IF NOT EXISTS ${tableName} (`
+        for (const column in table) {
+            const type = table[column];
+            sql += ` ${column} ${type},`
+        }
+        sql = sql.slice(0, -1);
+        sql += ")"
+        let ret = sqlite.exec(sql)
+        if (ret != 0) {
+            throw new Error(`table ${tableName} create exception: ${ret}`)
+        }
+    }
+}
+
+/**
+ * 鍒涘缓JPA椋庢牸鐨勪唬鐞嗗鐞嗗櫒
+ */
+let handler = {
+    get: function (target, prop, receiver) {
+        return (...args) => {
+            return createJPA(prop, target.tableName, ...args)
+        }
+    }
+}
+
+// 涓烘瘡涓〃鍒涘缓JPA椋庢牸鐨勫鍒犳敼鏌ユ柟娉�
+sqliteService.d1_pass_record = new Proxy({ tableName: "d1_pass_record" }, handler);
+
+// 娣诲姞鏍规嵁鏃堕棿鑼冨洿鍒犻櫎璁板綍鐨勬柟娉�
+sqliteService.d1_pass_record.deleteByTimeRange = function (startTime, endTime) {
+    try {
+        // 鏋勫缓鏌ヨ鏉′欢
+        let conditions = {};
+        if (startTime) {
+            conditions.time = {
+                $gte: startTime
+            };
+        }
+        if (endTime) {
+            if (!conditions.time) {
+                conditions.time = {};
+            }
+            conditions.time.$lte = endTime;
+        }
+        
+        // 浣跨敤JPA椋庢牸鐨刣elete鏂规硶
+        let ret = sqliteService.d1_pass_record.delete(conditions);
+        log.info('[sqliteService] deleteByTimeRange杩斿洖鍊�: ' + ret);
+        return ret;
+    } catch (error) {
+        log.error('deleteByTimeRange error:', error);
+        return -1;
+    }
+};
+sqliteService.d1_permission = new Proxy({ tableName: "d1_permission" }, handler);
+sqliteService.d1_security = new Proxy({ tableName: "d1_security" }, handler);
+sqliteService.d1_voucher = new Proxy({ tableName: "d1_voucher" }, handler);
+sqliteService.d1_person = new Proxy({ tableName: "d1_person" }, handler);
+sqliteService.d1_emergency_password = new Proxy({ tableName: "d1_emergency_password" }, handler);
+
+/**
+ * 寮�濮嬩簨鍔�
+ * 浜嬪姟涓嶆彁浜ゆ暟鎹簱閲嶅惎鍚庯紝鏁版嵁浼氳繕鍘燂紝鎵�浠ransaction鍚庝竴瀹氳commit
+ * 濡傛灉鍦ㄤ竴涓簨鍔″皻鏈彁浜ゆ垨鍥炴粴鐨勬儏鍐典笅鎵ц鍙︿竴涓� BEGIN TRANSACTION锛孲QLite 浼氳嚜鍔ㄥ皢鏂扮殑浜嬪姟宓屽鍦ㄤ箣鍓嶇殑浜嬪姟鍐呴儴锛岃�屼笉鏄鐩栦箣鍓嶇殑浜嬪姟銆�
+ */
+sqliteService.transaction = function () {
+    sqlite.exec("BEGIN TRANSACTION;")
+}
+
+/**
+ * 鍥炴粴浜嬪姟
+ */
+sqliteService.rollback = function () {
+    sqlite.exec("ROLLBACK;")
+}
+
+/**
+ * 鎻愪氦浜嬪姟
+ * 鎻愪氦鍚庢棤娉曞洖婊氾紝鏁版嵁鏃犳硶杩樺師
+ */
+sqliteService.commit = function () {
+    sqlite.exec("COMMIT;")
+}
+
+/**
+ * 鑷姩鍒涘缓jpa甯哥敤澧炲垹鏀规煡sql鏂规硶锛�
+ * 鏀寔鐨勮鍒欙細findByAAndBAndC,findAll,findAllOrderByADescBAsc,deleteByAAndBAndC,deleteAll,deleteInBatch,deleteByIdInBatch,updateAByBAndCAndD,save,saveAll,count,countBy
+ * 鏉′欢鍒嗛〉鏌ヨ锛宔g锛歠indByAAndBAndC(x,x,x,{ page: 0, size: 200, 鍏朵粬鏉′欢, id:"123456" })
+ * 鎵归噺鍒犻櫎锛宔g锛歞eleteInBatch([{ a: 1, b: 2, c: "3" }, { a: 2 }])
+ * 鏉′欢鍒犻櫎锛宔g锛歞eleteAll({ a: 1, b: 2, c: "3" })
+ * 鍗曟潯浠舵壒閲忓垹闄わ紝eg锛歞eleteByIdInBatch([1,2,3,4,5,6])
+ * 鏇村绀轰緥鍙弬鑰冧笅闈㈡祴璇曟柟娉�
+ * @param {string} methodName 鏂规硶鍚�
+ * @param {string} tableName 琛ㄥ悕
+ * @param  {...any} nums 鏂规硶鍙傛暟
+ * @returns {any} sqlite鎵ц缁撴灉
+ */
+function createJPA(methodName, tableName, ...nums) {
+    let sql
+    let isFind = false
+    let isCount = false
+    let noPageable = false
+    let hasOrderBy = false
+    if (methodName.startsWith("save")) {
+        // 澧�
+        if (methodName.startsWith("saveAll")) {
+            // 鎵归噺
+            nums = nums[0]
+            sql = `INSERT INTO ${tableName} VALUES `
+            for (let i = 0; i < nums.length; i++) {
+                const record = nums[i];
+                sql += `(`
+                for (const column in entities[tableName]) {
+                    const item = record[column];
+                    if (sqlType2jsType(entities[tableName][column]) == 'string') {
+                        sql += `'${isEmpty(item) ? "" : item}',`
+                    } else {
+                        sql += `${isEmpty(item) ? 0 : item},`
+                    }
+                }
+                sql = sql.slice(0, -1);
+                sql += `)`
+                if (i != nums.length - 1) {
+                    sql += `, `
+                }
+            }
+        } else {
+            // 鍗曟潯
+            let record = nums[0]
+            sql = `INSERT INTO ${tableName} VALUES (`
+            for (const column in entities[tableName]) {
+                const item = record[column];
+                if (sqlType2jsType(entities[tableName][column]) == 'string') {
+                    sql += `'${isEmpty(item) ? "" : item}',`
+                } else {
+                    sql += `${isEmpty(item) ? 0 : item},`
+                }
+            }
+            sql = sql.slice(0, -1);
+            sql += `)`
+        }
+        methodName = ""
+        noPageable = true
+    } else if (methodName.startsWith("delete")) {
+        // 鍒�
+        if (methodName.startsWith("deleteAll")) {
+            // 娓呯┖琛�
+            sql = `DELETE FROM ${tableName} `
+            methodName = ""
+        } else if (methodName.endsWith("InBatch")) {
+            if (nums.length != 1) {
+                log.error("[JPA]:", "缂哄皯鍙傛暟")
+                return
+            }
+            sql = `DELETE FROM ${tableName} WHERE `
+            if (methodName.indexOf("By") > -1) {
+                methodName = methodName.split("By")[1].split("InBatch")[0]
+                sql += `${firstLower(methodName)} IN `
+                let whereClauses = ""
+                for (let i = 0; i < nums[0].length; i++) {
+                    const value = nums[0][i];
+                    if (typeof value == 'string') {
+                        whereClauses += `'${value}'`
+                    } else {
+                        whereClauses += `${value} `
+                    }
+                    if (i != nums[0].length - 1) {
+                        whereClauses += ","
+                    }
+                }
+                sql += `(${whereClauses})`
+            } else {
+                for (let i = 0; i < nums[0].length; i++) {
+                    let whereClauses = ""
+                    const record = nums[0][i];
+                    for (const column in record) {
+                        const value = record[column];
+                        if (typeof value == 'string') {
+                            whereClauses += `${column} = '${value}'`
+                        } else {
+                            whereClauses += `${column} = ${value}`
+                        }
+                        whereClauses += ` AND `
+                    }
+                    whereClauses = whereClauses.slice(0, " AND ".length * (-1))
+                    sql += `(${whereClauses})`
+                    if (i != nums[0].length - 1) {
+                        sql += ` OR `
+                    }
+                }
+            }
+            methodName = ""
+            noPageable = true
+        } else {
+            sql = `DELETE FROM ${tableName} `
+            methodName = methodName.substring("delete".length)
+        }
+    } else if (methodName.startsWith("update")) {
+        // 鏀�
+        sql = `UPDATE ${tableName} SET`
+        methodName = methodName.substring("update".length)
+    } else if (methodName.startsWith("find")) {
+        // 鏌�
+        isFind = true
+        sql = `SELECT * FROM ${tableName} `
+        if (methodName.startsWith("findAll")) {
+            methodName = methodName.substring("findAll".length)
+        } else {
+            methodName = methodName.substring("find".length)
+        }
+        let index = methodName.indexOf("OrderBy")
+        if (index > -1) {
+            hasOrderBy = methodName.substring(index + "OrderBy".length).match(/\w+?(Desc|Asc)/g)
+            methodName = methodName.substring(0, index)
+        }
+    } else if (methodName.startsWith("count")) {
+        // 缁熻
+        isFind = true
+        isCount = true
+        sql = `SELECT COUNT(*) FROM ${tableName} `
+        methodName = methodName.substring("count".length)
+    } else {
+        log.error("[JPA]:", "涓嶆敮鎸佺殑鏂规硶")
+        return
+    }
+    // where鏉′欢鏋勫缓
+    let index = methodName.indexOf("By")
+    let whereClauses = ""
+    if (index > -1) {
+        let count = 0
+        let conditionsPart = methodName.substring(index + 2)
+        if (conditionsPart.indexOf("And") > -1) {
+            conditionsPart = conditionsPart.split("And")
+            if (nums.length < conditionsPart.length) {
+                log.error("[JPA]:", "缂哄皯鍙傛暟")
+                return
+            }
+            for (let i = 0; i < conditionsPart.length; i++) {
+                const field = conditionsPart[i];
+                if (typeof nums[i] == 'string') {
+                    whereClauses += `${firstLower(field)} = '${nums[i]}'`
+                } else {
+                    whereClauses += `${firstLower(field)} = ${nums[i]}`
+                }
+                if (i != conditionsPart.length - 1) {
+                    whereClauses += ` AND `
+                }
+                count = i
+            }
+        } else if (conditionsPart.indexOf("Or") > -1) {
+            conditionsPart = conditionsPart.split("Or")
+            if (nums.length < conditionsPart.length) {
+                log.error("[JPA]:", "缂哄皯鍙傛暟")
+                return
+            }
+            for (let i = 0; i < conditionsPart.length; i++) {
+                const field = conditionsPart[i];
+                if (typeof nums[i] == 'string') {
+                    whereClauses += `${firstLower(field)} = '${nums[i]}'`
+                } else {
+                    whereClauses += `${firstLower(field)} = ${nums[i]}`
+                }
+                if (i != conditionsPart.length - 1) {
+                    whereClauses += ` OR `
+                }
+                count = i
+            }
+        } else {
+            if (nums.length < 1) {
+                log.error("[JPA]:", "缂哄皯鍙傛暟")
+                return
+            }
+            if (typeof nums[0] == 'string') {
+                whereClauses = `${firstLower(conditionsPart)} = '${nums[0]}' `
+            } else {
+                whereClauses = `${firstLower(conditionsPart)} = ${nums[0]} `
+            }
+        }
+        count++
+        // update鐨剆et椤规瀯寤�
+        let setClauses = ""
+        let prefix = methodName.substring(0, index);
+        if (prefix.length > 0) {
+            prefix = prefix.split("And")
+            if ((nums.length - count) < prefix.length) {
+                log.error("[JPA]:", "缂哄皯鍙傛暟")
+                return
+            }
+            for (let i = 0; i < prefix.length; i++) {
+                const field = prefix[i];
+                if (typeof nums[i + count] == 'string') {
+                    setClauses += `${firstLower(field)} = '${nums[i + count]}',`
+                } else {
+                    setClauses += `${firstLower(field)} = ${nums[i + count]},`
+                }
+            }
+            setClauses = setClauses.slice(0, -1)
+            sql += ` ${setClauses} `
+        }
+        sql += `WHERE ${whereClauses} `
+    }
+    // order鎺掑簭
+    let orderByClauses = ""
+    if (hasOrderBy) {
+        orderByClauses = "ORDER BY "
+        let conditionsPart = hasOrderBy
+        for (let i = 0; i < conditionsPart.length; i++) {
+            const orderItem = conditionsPart[i];
+            let isDesc = orderItem.indexOf("Desc")
+            let isAsc = orderItem.indexOf("Asc")
+            if (isDesc > -1) {
+                orderByClauses += `${firstLower(orderItem.substring(0, isDesc))} DESC,`
+            }
+            if (isAsc > -1) {
+                orderByClauses += `${firstLower(orderItem.substring(0, isAsc))} ASC,`
+            }
+        }
+        orderByClauses = orderByClauses.slice(0, -1)
+    }
+    // 鍒ゆ柇鍒嗛〉鏉′欢鏌ヨ
+    let pageable = nums[nums.length - 1]
+    if (typeof pageable == 'object' && !noPageable) {
+        let clauses = ""
+        for (const key in pageable) {
+            const condition = pageable[key];
+            if (key == "page" || key == "size") {
+                continue
+            }
+            if (typeof condition == 'string') {
+                clauses += `${firstLower(key)} = '${condition}'`
+            } else {
+                clauses += `${firstLower(key)} = ${condition}`
+            }
+            clauses += ` AND `
+        }
+        if (clauses.length > 0) {
+            clauses = clauses.slice(0, " AND ".length * (-1))
+            if (sql.indexOf("WHERE") > -1) {
+                sql += `AND ${clauses} `
+            } else {
+                sql += `WHERE ${clauses} `
+            }
+        }
+        sql += `${orderByClauses} `
+        if (isFind && !isCount && !isEmpty(pageable.page) && !isEmpty(pageable.size)) {
+            sql += `LIMIT ${pageable.size} OFFSET ${pageable.page * pageable.size} `
+        }
+    } else {
+        sql += `${orderByClauses} `
+    }
+    sql += `;`;
+    // log.info("[JPA]:", sql)
+    let ret
+    if (isFind) {
+        ret = sqlite.select(sql)
+        if (isCount) {
+            if (ret[0] && ret[0]["COUNT(*)"]) {
+                return ret[0]["COUNT(*)"]
+            } else {
+                return 0
+            }
+        }
+    } else {
+        ret = sqlite.exec(sql)
+    }
+    return ret
+}
+
+/**
+ * 鍒ょ┖鍑芥暟
+ * @param {any} value - 瑕佸垽鏂殑鍊�
+ * @returns {boolean} 鏄惁涓虹┖
+ */
+function isEmpty(value) {
+    return value === undefined || value === null
+}
+
+/**
+ * 棣栧瓧姣嶅皬鍐�
+ * @param {string} str - 瀛楃涓�
+ * @returns {string} 棣栧瓧姣嶅皬鍐欑殑瀛楃涓�
+ */
+function firstLower(str) {
+    return str.charAt(0).toLowerCase() + str.slice(1);
+}
+
+/**
+ * JPA娴嬭瘯鏂规硶
+ * 鎻愪緵鍚勭JPA鏂规硶鐨勪娇鐢ㄧず渚�
+ */
+sqliteService.testJPA = function () {
+    // 鏌ヨ
+    // SELECT * FROM d1_pass_record ;
+    sqliteService.d1_pass_record.find()
+    // SELECT * FROM d1_pass_record WHERE a = 1 AND b = 2 ;
+    sqliteService.d1_pass_record.find({ a: 1, b: 2 })
+    // SELECT * FROM d1_pass_record WHERE a = 1 AND b = 2 ;
+    sqliteService.d1_pass_record.find({ a: 1, b: 2, page: 1 })
+    // SELECT * FROM d1_pass_record WHERE a = 1 AND b = 2 LIMIT 1 OFFSET 1 ;
+    sqliteService.d1_pass_record.find({ a: 1, b: 2, page: 1, size: 1 })
+    // SELECT * FROM d1_pass_record WHERE a = 1 AND b = 2 AND c = 3 ;
+    sqliteService.d1_pass_record.findByAAndBAndC(1, 2, 3)
+    // SELECT * FROM d1_pass_record WHERE a = 1 AND b = 2 AND c = 3 AND a = 1 AND b = 2 ;
+    sqliteService.d1_pass_record.findByAAndBAndC(1, 2, 3, { a: 1, b: 2 })
+    // SELECT * FROM d1_pass_record WHERE a = 1 AND b = 2 AND c = 3 AND a = 1 AND b = 2 LIMIT 1 OFFSET 1 ;
+    sqliteService.d1_pass_record.findByAAndBAndC(1, 2, 3, { a: 1, b: 2, page: 1, size: 1 })
+    // SELECT * FROM d1_pass_record ;
+    sqliteService.d1_pass_record.findAll()
+    // SELECT * FROM d1_pass_record WHERE a = 1 AND b = 2 ;
+    sqliteService.d1_pass_record.findAll({ a: 1, b: 2 })
+    // SELECT * FROM d1_pass_record WHERE a = 1 AND b = 2 ;
+    sqliteService.d1_pass_record.findAll({ a: 1, b: 2, page: 1 })
+    // SELECT * FROM d1_pass_record WHERE a = 1 AND b = 2 LIMIT 1 OFFSET 1 ;
+    sqliteService.d1_pass_record.findAll({ a: 1, b: 2, page: 1, size: 1 })
+    // SELECT * FROM d1_pass_record WHERE a = 1 AND b = 2 AND c = 3 ;
+    sqliteService.d1_pass_record.findAllByAAndBAndC(1, 2, 3)
+    // SELECT * FROM d1_pass_record WHERE a = 1 AND b = 2 AND c = 3 AND a = 1 AND b = 2 ;
+    sqliteService.d1_pass_record.findAllByAAndBAndC(1, 2, 3, { a: 1, b: 2 })
+    // SELECT * FROM d1_pass_record WHERE a = 1 AND b = 2 AND c = 3 AND a = 1 AND b = 2 LIMIT 1 OFFSET 1 ;
+    sqliteService.d1_pass_record.findAllByAAndBAndC(1, 2, 3, { a: 1, b: 2, page: 1, size: 1 })
+    // SELECT * FROM d1_pass_record WHERE a = 1 AND b = 2 AND c = 3 AND a = 1 AND b = 2 ORDER BY a DESC,b ASC,c ASC LIMIT 1 OFFSET 1 ;
+    sqliteService.d1_pass_record.findAllByAAndBAndCOrderByADescBAscCAsc(1, 2, 3, { a: 1, b: 2, page: 1, size: 1 })
+    // 鍒犻櫎
+    // DELETE FROM d1_pass_record ;
+    sqliteService.d1_pass_record.delete()
+    // DELETE FROM d1_pass_record WHERE a = 1 AND b = 2 ;
+    sqliteService.d1_pass_record.delete({ a: 1, b: 2 })
+    // DELETE FROM d1_pass_record WHERE a = 1 AND b = 2 ;
+    sqliteService.d1_pass_record.delete({ a: 1, b: 2, page: 1 })
+    // DELETE FROM d1_pass_record WHERE a = 1 AND b = 2 ;
+    sqliteService.d1_pass_record.delete({ a: 1, b: 2, page: 1, size: 1 })
+    // DELETE FROM d1_pass_record WHERE a = 1 AND b = 2 AND c = 3 ;
+    sqliteService.d1_pass_record.deleteByAAndBAndC(1, 2, 3)
+    // DELETE FROM d1_pass_record WHERE a = 1 AND b = 2 AND c = 3 AND a = 1 AND b = 2 ;
+    sqliteService.d1_pass_record.deleteByAAndBAndC(1, 2, 3, { a: 1, b: 2 })
+    // DELETE FROM d1_pass_record WHERE a = 1 AND b = 2 AND c = 3 AND a = 1 AND b = 2 ;
+    sqliteService.d1_pass_record.deleteByAAndBAndC(1, 2, 3, { a: 1, b: 2, page: 1, size: 1 })
+    // DELETE FROM d1_pass_record ;
+    sqliteService.d1_pass_record.deleteAll()
+    // DELETE FROM d1_pass_record WHERE a = 1 AND b = 2 ;
+    sqliteService.d1_pass_record.deleteAll({ a: 1, b: 2 })
+    // DELETE FROM d1_pass_record WHERE a = 1 AND b = 2 ;
+    sqliteService.d1_pass_record.deleteAll({ a: 1, b: 2, page: 1 })
+    // DELETE FROM d1_pass_record WHERE a = 1 AND b = 2 ;
+    sqliteService.d1_pass_record.deleteAll({ a: 1, b: 2, page: 1, size: 1 })
+    // DELETE FROM d1_pass_record ;
+    sqliteService.d1_pass_record.deleteAllByAAndBAndC(1, 2, 3)
+    // DELETE FROM d1_pass_record WHERE a = 1 AND b = 2 ;
+    sqliteService.d1_pass_record.deleteAllByAAndBAndC(1, 2, 3, { a: 1, b: 2 })
+    // DELETE FROM d1_pass_record WHERE a = 1 AND b = 2 ;
+    sqliteService.d1_pass_record.deleteAllByAAndBAndC(1, 2, 3, { a: 1, b: 2, page: 1, size: 1 })
+    // DELETE FROM d1_pass_record WHERE (a = 1 AND b = 2) OR (a = 1 AND b = 2 AND page = 1) OR (a = 1 AND b = 2 AND page = 1 AND size = 1);
+    sqliteService.d1_pass_record.deleteInBatch([{ a: 1, b: 2 }, { a: 1, b: 2, page: 1 }, { a: 1, b: 2, page: 1, size: 1 }])
+    // DELETE FROM d1_pass_record WHERE id IN (1 ,2 ,3 );
+    sqliteService.d1_pass_record.deleteByIdInBatch([1, 2, 3])
+    // 鏇存柊
+    // UPDATE d1_pass_record SET a = 4 WHERE b = 1 AND c = 2 AND d = 3 ;
+    sqliteService.d1_pass_record.updateAByBAndCAndD(1, 2, 3, 4)
+    // UPDATE d1_pass_record SET a = 4,b = 5,c = 6 WHERE d = 1 AND e = 2 AND f = 3 ;
+    sqliteService.d1_pass_record.updateAAndBAndCByDAndEAndF(1, 2, 3, 4, 5, 6)
+    // 娣诲姞
+    // INSERT INTO d1_pass_record VALUES (,,,,,,,0,0,,);
+    sqliteService.d1_pass_record.save({ a: 1, b: 2 })
+    // INSERT INTO d1_pass_record VALUES (,,,,,,,0,0,,), (,,,,,,,0,0,,);
+    sqliteService.d1_pass_record.saveAll([{ a: 1, b: 2 }, { a: 1, b: 2 }])
+    // 鑱氬悎
+    // SELECT COUNT(*) FROM d1_pass_record ;
+    sqliteService.d1_pass_record.count();
+    // SELECT COUNT(*) FROM d1_pass_record WHERE a = 1 AND b = 2 AND c = 3 ;
+    sqliteService.d1_pass_record.countByAAndBAndC(1, 2, 3);
+}
+
+/**
+ * 瀹夊叏瀵嗛挜鏌ヨ
+ * @param {string} code - 浠g爜
+ * @param {string} type - 绫诲瀷
+ * @param {string} id - 瀹夊叏ID
+ * @param {number} time - 鏃堕棿
+ * @param {string} key - 瀵嗛挜
+ * @param {string} index - 绱㈠紩
+ * @returns {array} 鏌ヨ缁撴灉
+ */
+sqliteService.securityFindAllByCodeAndTypeAndTimeAndkey = function (code, type, id, time, key, index) {
+    var query = `SELECT * FROM d1_security WHERE 1=1`
+    if (code) {
+        query += ` AND code = '${code}'`
+    }
+    if (type) {
+        query += ` AND type = '${type}'`
+    }
+    if (id) {
+        query += ` AND securityId = '${id}'`
+    }
+    if (index) {
+        query += ` AND door = '${index}'`
+    }
+    if (key) {
+        query += ` AND key = '${key}'`
+    }
+    if (time) {
+        query += ` AND endTime >= '${time}'`
+    }
+    return sqlite.select(query)
+}
+
+export default sqliteService
+
+
diff --git a/vf205_access/src/service/uart485Service.js b/vf205_access/src/service/uart485Service.js
new file mode 100644
index 0000000..ade31dc
--- /dev/null
+++ b/vf205_access/src/service/uart485Service.js
@@ -0,0 +1,190 @@
+/**
+ * UART485鏈嶅姟妯″潡
+ * 澶勭悊UART485閫氫俊鐩稿叧鐨勪笟鍔¢�昏緫锛屽寘鎷潯鐮佹暟鎹帴鏀躲�佽澶囬厤缃鐞嗙瓑鍔熻兘
+ */
+import bus from "../../dxmodules/dxEventBus.js"
+import common from "../../dxmodules/dxCommon.js"
+import log from "../../dxmodules/dxLogger.js"
+import std from '../../dxmodules/dxStd.js'
+import driver from '../driver.js'
+import utils from '../common/utils/utils.js'
+import dxMap from '../../dxmodules/dxMap.js'
+import config from '../../dxmodules/dxConfig.js'
+const uart485Service = {}
+
+/**
+ * 灏嗗崄杩涘埗鏁拌浆鎹负灏忕搴忓崄鍏繘鍒跺瓧绗︿覆
+ * @param {number} decimalNumber - 鍗佽繘鍒舵暟瀛�
+ * @param {number} byteSize - 瀛楄妭澶у皬
+ * @returns {string} 灏忕搴忓崄鍏繘鍒跺瓧绗︿覆
+ */
+function decimalToLittleEndianHex (decimalNumber, byteSize) {
+  const littleEndianBytes = [];
+  for (let i = 0; i < byteSize; i++) {
+    littleEndianBytes.push(decimalNumber & 0xFF);
+    decimalNumber >>= 8; // 鐩稿綋浜庨櫎浠�256
+  }
+  const littleEndianHex = littleEndianBytes
+    .map((byte) => byte.toString(16).padStart(2, '0'))
+    .join('');
+  return littleEndianHex;
+}
+
+/**
+ * 灏嗘暟鎹寘杞崲涓哄瓧绗︿覆鏍煎紡
+ * @param {object} pack - 鏁版嵁鍖呭璞�
+ * @param {string} pack.cmd - 鍛戒护鐮�
+ * @param {string} pack.result - 缁撴灉鐮�
+ * @param {string} [pack.data] - 鏁版嵁
+ * @returns {string} 杞崲鍚庣殑瀛楃涓�
+ */
+function pack2str (pack) {
+  pack.data = (!pack.data) ? [] : pack.data.match(/.{2}/g)
+  let len = decimalToLittleEndianHex(pack.data.length, 2)
+  let str = "55aa" + pack.cmd + pack.result + len + pack.data.join('')
+  let crc = common.calculateBcc([0x55, 0xaa, parseInt(pack.cmd, 16), parseInt(pack.result, 16), pack.data.length % 256, pack.data.length / 256].concat(pack.data.map(v => parseInt(v, 16))))
+  return str + crc.toString(16).padStart(2, '0')
+}
+
+/**
+ * 鎺ユ敹UART485鏁版嵁骞跺鐞�
+ * @param {object} data - 鎺ユ敹鍒扮殑鏁版嵁
+ * @param {string} type - 鏁版嵁绫诲瀷锛�'code'琛ㄧず鏉$爜鏁版嵁锛�'instruction'琛ㄧず鎸囦护
+ */
+uart485Service.receive = function (data, type) {
+  log.info("code:",JSON.stringify(data))
+  if (type == 'code') {
+    if(data.cmd == "30") {
+      if(data.length > 0) {
+        let code = common.hexToString(data.data)
+        const now = new Date().getTime()
+        let map = dxMap.get("CODETIME")
+        let time = map.get("time") || 0
+        let interval = Math.max(1000, config.get("sys.interval"))
+        if(now -  time > interval) {
+          bus.fire("getCode", code)
+          map.put("time", new Date().getTime())
+        }
+      }
+    }
+  }
+  if (type == 'instruction') {
+    if (data.cmd == "0a") {
+      // 鑾峰彇璁惧SN
+      if (data.length > 0) {
+        console.log('---0A鍐欏叆--');
+        
+        let newSn = common.hexToString(data.data)
+        //淇敼 sn 鍙锋敼鎴愪紶鍏ュ弬鏁�
+        try {
+          let wgetApp = common.systemWithRes(`test -e "/etc/.sn" && echo "OK" || echo "NO"`, 2)
+          if (!wgetApp.includes('OK')) {
+            //娌℃湁鍒涘缓涓�涓�
+            common.systemBrief("touch /etc/.sn")
+          }
+          std.saveFile('/etc/.sn', newSn)
+          common.systemWithRes(`rm -rf /app/data/config/config.json`, 2)
+        } catch (error) {
+          log.info('0A鍐欏叆 sn 澶辫触鍘熷洜:', error.stack)
+          let pack1 = { "cmd": '0A', "result": '90', 'data': '' }
+          driver.uart485.sendVg(pack2str(pack1))
+          return
+        }
+        //杩斿洖涓插彛
+        let pack1 = { "cmd": '0A', "result": '00', 'data': common.stringToHex(newSn) }
+        driver.uart485.sendVg(pack2str(pack1))
+        common.asyncReboot(2)
+      } else {
+        log.info('-----0A鏌ヨ-----', common.getSn());
+        let pack1 = { "cmd": '0A', "result": '00', "data": common.stringToHex(common.getSn()) }
+        // log.info(pack2str(pack1));
+        driver.uart485.sendVg(pack2str(pack1))
+      }
+    } else if (data.cmd == "b0") {
+        log.info("----b0---")
+      // 鏌ヨ/淇敼璁惧閰嶇疆
+      let str = data.data
+      if (!str) {
+        return
+      }
+      //鏁版嵁鍩熺涓�涓瓧鑺傝〃绀轰慨鏀硅繕鏄煡璇�   00 鏌ヨ 01 淇敼	
+      if (parseInt(str.substring(0, 2)) == 0) {
+        //鏌ヨ閰嶇疆
+        let pack1 = { "cmd": 'B0', "result": '00', "data": common.stringToHex(common.getSn()) }
+        driver.uart485.sendVg(pack2str(pack1))
+      } else {
+        //淇敼閰嶇疆
+        if (data.dlen <= 1) {
+          return
+        }
+        // ___VBAR_CONFIG_V1.1.0___{ble_name="11127S"}--lLqHBRnE2bU8D2HJ5RTioQ==
+        let toString = common.hexToString(str.substring(2))
+        let content = parseString(toString)
+        if (content.sn) {
+          //淇敼 sn 鍙锋敼鎴愪紶鍏ュ弬鏁�
+          try {
+            let wgetApp = common.systemWithRes(`test -e "/etc/.sn" && echo "OK" || echo "NO"`, 2)
+            if (!wgetApp.includes('OK')) {
+              //娌℃湁鍒涘缓涓�涓�
+              common.systemBrief("touch /etc/.sn")
+            }
+            std.saveFile('/etc/.sn', content.sn)
+            common.systemWithRes(`rm -rf /app/data/config/config.json`, 2)
+          } catch (error) {
+            log.info('鍐欏叆/etc/.sn鏂囦欢澶辫触,鍘熷洜:', error.stack)
+            let pack1 = { "cmd": 'B0', "result": '90', "data": common.stringToHex(common.getSn()) }
+            driver.uart485.sendVg(pack2str(pack1))
+            return
+          }
+          //杩斿洖涓插彛
+          let pack1 = { "cmd": 'B0', "result": '00', "data": common.stringToHex(content.sn) }
+          driver.uart485.sendVg(pack2str(pack1))
+          common.asyncReboot(2)
+        }
+
+      }
+    } else if (data.cmd == "0c") {
+        log.info("----0c--")
+      // 鑾峰彇涓绘帶chipID
+      let pack = { "cmd": '0C', "result": '00', "data": common.stringToHex(common.getUuid()) }
+      driver.uart485.sendVg(pack2str(pack))
+    } 
+  }
+}
+
+/**
+ * 瑙f瀽瀛楃涓蹭负JSON瀵硅薄锛屾敞鎰弙alue鍐呬笉鑳芥湁"鍙�
+ * @param {string} inputString - 杈撳叆瀛楃涓�
+ * @returns {object} 瑙f瀽鍚庣殑JSON瀵硅薄
+ */
+utils.parseString = function (inputString) {
+    // 鑾峰彇{}鍙婂叾涔嬮棿鐨勫唴瀹�
+    inputString = inputString.slice(inputString.indexOf("{"), inputString.lastIndexOf("}") + 1)
+    // key=value姝e垯锛宬ey鏄痋w+锛堝瓧姣嶆暟瀛椾笅鍒掔嚎锛屽尯鍒ぇ灏忓啓锛夛紝=涓よ竟鍙湁绌烘牸锛寁alue鏄痋w+鎴栫浉閭讳袱涓�"涔嬮棿鐨勫唴瀹癸紙鍖呭惈"锛�
+    const keyValueRegex = /(\w+)\s*=\s*("[^"]*"|\w+)/g;
+    let jsonObject = {};
+    let match;
+    while ((match = keyValueRegex.exec(inputString)) !== null) {
+        let key = match[1];
+        let value = match[2]
+
+        if (/^\d+$/.test(value)) {
+            // 鏁板瓧
+            value = parseInt(value)
+        } else if (/^\d+\.\d+$/.test(value)) {
+            // 灏忔暟
+            value = parseFloat(value)
+        } else if (value == 'true') {
+            value = true
+        } else if (value == 'false') {
+            value = false
+        } else {
+            // 瀛楃涓�
+            value = value.replace(/"/g, '').trim()
+        }
+        jsonObject[key] = value;
+    }
+    return jsonObject;
+}
+
+export default uart485Service
diff --git a/vf205_access/src/services.js b/vf205_access/src/services.js
new file mode 100644
index 0000000..10962f0
--- /dev/null
+++ b/vf205_access/src/services.js
@@ -0,0 +1,109 @@
+/**
+ * 鏈嶅姟姹犻厤缃枃浠�
+ * 娉ㄥ唽绯荤粺涓墍鏈夋湇鍔$殑浜嬩欢澶勭悊鍥炶皟锛屽鐞嗘潵鑷悇妯″潡鐨勪簨浠�
+ */
+import pool from '../dxmodules/dxWorkerPool.js'
+import face from '../dxmodules/dxFace.js'
+import driver from './driver.js'
+import bus from '../dxmodules/dxEventBus.js'
+import faceService from './service/faceService.js'
+import net from '../dxmodules/dxNet.js'
+import config from '../dxmodules/dxConfig.js'
+import nfc from '../dxmodules/dxNfc.js'
+import mqtt from '../dxmodules/dxMqtt.js'
+import map from '../dxmodules/dxMap.js'
+import mqttService from './service/mqttService.js'
+import accessService from './service/accessService.js'
+import nfcService from './service/nfcService.js'
+import common from '../dxmodules/dxCommon.js'
+import log from '../dxmodules/dxLogger.js'
+import dxGpioKey from '../dxmodules/dxGpioKey.js'
+import uart from '../dxmodules/dxUart.js'
+import uart485Service from './service/uart485Service.js'
+import configService from './service/configService.js'
+import grainService from './service/grainService.js'
+import gpiokeyService from './service/gpiokeyService.js'
+import codeService from './service/codeService.js'
+
+/**
+ * 鏈嶅姟姹犲洖璋冨嚱鏁�
+ * 澶勭悊鏉ヨ嚜鍚勬ā鍧楃殑浜嬩欢娑堟伅锛屾牴鎹簨浠朵富棰樺垎鍙戝埌鐩稿簲鐨勬湇鍔″鐞�
+ * @param {object} data - 浜嬩欢鏁版嵁
+ * @param {string} data.topic - 浜嬩欢涓婚
+ * @param {any} data.data - 浜嬩欢鏁版嵁
+ */
+pool.callback((data) => {
+    let topic = data.topic
+    let msg = data.data
+    switch (topic) {
+        case face.RECEIVE_MSG:
+            // 澶勭悊浜鸿劯璇嗗埆娑堟伅
+            faceService.receiveMsg(msg)
+            break;
+        case dxGpioKey.RECEIVE_MSG:
+            // 澶勭悊GPIO鎸夐敭娑堟伅
+            gpiokeyService.receiveMsg(msg)
+            break;
+        case "netGetWifiSsidList":
+            // 鑾峰彇WiFi鍒楄〃
+            let wifiList = driver.net.netGetWifiSsidList()
+            bus.fire("netWifiSsidList", wifiList)
+            break;
+        case "switchNetworkType":
+            // 鍒囨崲缃戠粶绫诲瀷
+            config.setAndSave("net.type", msg)
+            console.log("鍒囨崲缃戠粶", msg);
+            driver.net.changeNetType()
+            break;
+        case "setConfig":
+            // 閰嶇疆楠岃瘉鍜屼繚瀛�
+            configService.configVerifyAndSave(msg)
+            break;
+        case "access":
+            // 澶勭悊閫氳楠岃瘉
+            accessService.access(msg.data, msg.fileName, msg.similarity)
+            break;
+        case nfc.RECEIVE_MSG:
+            // 澶勭悊NFC鍗$墖娑堟伅
+            nfcService.receiveMsg(msg)
+            break;
+        case net.STATUS_CHANGE:
+            // 缃戠粶鐘舵�佸彉鍖�
+            map.get("NET").put("status", msg.status)
+            bus.fire("netStatus", msg)
+            break;
+        case mqtt.CONNECTED_CHANGED:
+            // MQTT杩炴帴鐘舵�佸彉鍖�
+            bus.fire("mqttStatus", msg)
+            // mqtt杩炴帴涓婃姤
+            if (msg == "connected") {
+                mqttService.report()
+            }
+            break;
+        case mqtt.RECEIVE_MSG:
+            // 澶勭悊MQTT娑堟伅
+            mqttService.receiveMsg(msg)
+            break;
+        case uart.VG.RECEIVE_MSG + driver.uart485.id:
+            // 澶勭悊UART485鎸囦护娑堟伅
+            uart485Service.receive(msg, 'instruction')
+            break;
+        case uart.VG.RECEIVE_MSG + driver.uartCode.id:
+            // 澶勭悊UART鐮佹秷鎭�
+            uart485Service.receive(msg, 'code')
+            break;
+        case "getCode":
+            // 澶勭悊鏉$爜鏁版嵁
+            codeService.code(msg)
+            break;
+        case "trackResult":
+            // 澶勭悊浜鸿劯璇嗗埆缁撴灉浜嬩欢锛堢敱mainView.js澶勭悊锛�
+            break;
+
+        default:
+            // 鏈煡涓婚
+            log.error("No such topic ", topic)
+            break;
+    }
+})
+
diff --git a/vf205_access/src/ui.js b/vf205_access/src/ui.js
new file mode 100644
index 0000000..71ba065
--- /dev/null
+++ b/vf205_access/src/ui.js
@@ -0,0 +1,32 @@
+import ui from "../dxmodules/dxUi.js";
+import std from "../dxmodules/dxStd.js"
+
+// ui涓婁笅鏂�
+let context = {}
+
+// ui鍒濆鍖�
+ui.init({ orientation: 0 }, context);
+
+const screenMain = ui.View.build('mainView', ui.Utils.LAYER.MAIN)
+
+const bottomSnBtn = ui.Button.build('bottomSnBtn', screenMain)
+bottomSnBtn.bgColor(0xff0000)
+bottomSnBtn.bgOpa(20)
+bottomSnBtn.setSize(200, 100)
+bottomSnBtn.setPos(100, 700)
+
+
+bottomSnBtn.on(ui.Utils.EVENT.CLICK, () => {
+    print("passwordView")
+})
+
+// 鍔犺浇灞忓箷
+ui.loadMain(screenMain)
+
+// 鍒锋柊ui
+let timer = std.setInterval(() => {
+    if (ui.handler() < 0) {
+        std.clearInterval(timer)
+    }
+}, 1)
+
diff --git a/vf205_access/src/view/appView.js b/vf205_access/src/view/appView.js
new file mode 100644
index 0000000..7aa7be4
--- /dev/null
+++ b/vf205_access/src/view/appView.js
@@ -0,0 +1,47 @@
+import dxui from '../../dxmodules/dxUi.js'
+import std from '../../dxmodules/dxStd.js'
+import viewUtils from "./viewUtils.js"
+import topView from './topView.js'
+import mainView from './mainView.js'
+import i18n from './i18n.js'
+const appView = {}
+appView.init = function () {
+    /**************************************************鍒涘缓灞忓箷*****************************************************/
+    const screenMain = dxui.View.build('appView', dxui.Utils.LAYER.MAIN)
+    appView.screenMain = screenMain
+    screenMain.scroll(false)
+    screenMain.bgColor(0xffffff)
+    screenMain.on(dxui.Utils.ENUM.LV_EVENT_SCREEN_LOADED, () => {
+        topView.changeTheme(true)
+        appQrcode.source('/app/code/resource/image/app_qrcode.png')
+        // 鏃犳搷浣�10绉掕嚜鍔ㄨ繑鍥�
+        if (appView.timer) {
+            std.clearInterval(appView.timer)
+        }
+        appView.timer = std.setInterval(() => {
+            let count = dxui.Utils.GG.NativeDisp.lvDispGetInactiveTime()
+            if (count > 10 * 1000) {
+                std.clearInterval(appView.timer)
+                appView.timer = null
+                dxui.loadMain(mainView.screenMain)
+            }
+        }, 1000)
+    })
+
+    const appQrcode = dxui.Image.build('appQrcode', screenMain)
+    appQrcode.source('/app/code/resource/image/app_qrcode.png')
+    appQrcode.align(dxui.Utils.ALIGN.TOP_MID, 0, 206)
+
+    const knowedBtn = viewUtils.bottomBtn(screenMain, 'knowedBtn', 'appView.knowed', () => {
+        dxui.loadMain(mainView.screenMain)
+    })
+    knowedBtn.align(dxui.Utils.ALIGN.BOTTOM_MID, 0, -124)
+
+    const appQrcodeLbl = dxui.Label.build('appQrcodeLbl', screenMain)
+    appQrcodeLbl.text('浣跨敤灏忕▼搴忎究鎹风鐞�')
+    appQrcodeLbl.textFont(viewUtils.font(30))
+    appQrcodeLbl.align(dxui.Utils.ALIGN.BOTTOM_MID, 0, -403)
+    appQrcodeLbl.dataI18n = 'appView.appQrcodeLbl'
+}
+
+export default appView
\ No newline at end of file
diff --git a/vf205_access/src/view/config/configView.js b/vf205_access/src/view/config/configView.js
new file mode 100644
index 0000000..0a01162
--- /dev/null
+++ b/vf205_access/src/view/config/configView.js
@@ -0,0 +1,136 @@
+import dxui from "../../../dxmodules/dxUi.js"
+import config from "../../../dxmodules/dxConfig.js"
+import viewUtils from "../viewUtils.js"
+import topView from "../topView.js"
+import mainView from "../mainView.js"
+import cloudCertView from "./menu/cloudCertView.js"
+import doorControlView from "./menu/doorControlView.js"
+import helpView from "./menu/helpView.js"
+import networkSettingView from "./menu/networkSettingView.js"
+import systemSettingView from "./menu/systemSettingView.js"
+import deviceInfoView from "./menu/deviceInfoView.js"
+import factoryTestView from "./menu/factoryTestView.js"
+import localUserView from "./menu/localUserView.js"
+import recordQueryView from "./menu/recordQueryView.js"
+import voiceBroadcastView from "./menu/voiceBroadcastView.js"
+
+import screen from '../../screen.js'
+const configView = {}
+configView.init = function () {
+    /**************************************************鍒涘缓灞忓箷*****************************************************/
+    const screenMain = dxui.View.build('configView', dxui.Utils.LAYER.MAIN)
+    configView.screenMain = screenMain
+    screenMain.scroll(false)
+    screenMain.bgColor(0xffffff)
+    screenMain.on(dxui.Utils.ENUM.LV_EVENT_SCREEN_LOADED, () => {
+        topView.changeTheme(true)
+    })
+
+    // const confirm = viewUtils.confirmWin('configViewConfirm', 'configView.confirmExit', () => {
+    //     dxui.loadMain(mainView.screenMain)
+    // })
+
+    const titleBox = viewUtils.title(screenMain, undefined, 'configViewTitle', 'configView.title', () => {
+        viewUtils.confirmOpen('configView.confirmExit', 'configView.confirmExitContent', () => {
+            dxui.loadMain(mainView.screenMain)
+        }, () => { })
+    })
+    titleBox.align(dxui.Utils.ALIGN.TOP_MID, 0, 70)
+
+
+    const menuBox = dxui.View.build('menuBox', screenMain)
+    viewUtils._clearStyle(menuBox)
+    menuBox.setSize(screen.screenSize.width, 800)
+    menuBox.bgOpa(0)
+    menuBox.align(dxui.Utils.ALIGN.TOP_MID, 0, 178)
+    menuBox.flexFlow(dxui.Utils.FLEX_FLOW.ROW_WRAP)
+    menuBox.flexAlign(dxui.Utils.FLEX_ALIGN.START, dxui.Utils.FLEX_ALIGN.START, dxui.Utils.FLEX_ALIGN.START)
+    menuBox.obj.lvObjSetStylePadGap(0, dxui.Utils.ENUM._LV_STYLE_STATE_CMP_SAME)
+
+    configView.menuBtn('localUser', menuBox, screen.screenSize.width / 4, screen.screenSize.width / 4, '/app/code/resource/image/localUser.png', 'configView.localUser', () => {
+        dxui.loadMain(localUserView.screenMain)
+    })
+
+    configView.menuBtn('networkSetting', menuBox, screen.screenSize.width / 4, screen.screenSize.width / 4, '/app/code/resource/image/networkSetting.png', 'configView.networkSetting', () => {
+        dxui.loadMain(networkSettingView.screenMain)
+    })
+
+    configView.menuBtn('doorControl', menuBox, screen.screenSize.width / 4, screen.screenSize.width / 4, '/app/code/resource/image/doorControl.png', 'configView.doorControl', () => {
+        dxui.loadMain(doorControlView.screenMain)
+    })
+
+    configView.menuBtn('systemSetting', menuBox, screen.screenSize.width / 4, screen.screenSize.width / 4, '/app/code/resource/image/systemSetting.png', 'configView.systemSetting', () => {
+        dxui.loadMain(systemSettingView.screenMain)
+    })
+
+    configView.menuBtn('deviceInfo', menuBox, screen.screenSize.width / 4, screen.screenSize.width / 4, '/app/code/resource/image/deviceInfo.png', 'configView.deviceInfo', () => {
+        dxui.loadMain(deviceInfoView.screenMain)
+    })
+
+    configView.menuBtn('recordQuery', menuBox, screen.screenSize.width / 4, screen.screenSize.width / 4, '/app/code/resource/image/recordQuery.png', 'configView.recordQuery', () => {
+        dxui.loadMain(recordQueryView.screenMain)
+    })
+
+    configView.menuBtn('voiceBroadcast', menuBox, screen.screenSize.width / 4, screen.screenSize.width / 4, '/app/code/resource/image/voiceBroadcast.png', 'configView.voiceBroadcast', () => {
+        dxui.loadMain(voiceBroadcastView.screenMain)
+    })
+
+    if (config.get("base.showIdentityCard") == 1) {
+        configView.menuBtn('cloudCert', menuBox, screen.screenSize.width / 4, screen.screenSize.width / 4, '/app/code/resource/image/cloudCert.png', 'configView.cloudCert', () => {
+            dxui.loadMain(cloudCertView.screenMain)
+        })
+    }
+
+
+
+    configView.menuBtn('help', menuBox, screen.screenSize.width / 4, screen.screenSize.width / 4, '/app/code/resource/image/help.png', 'configView.help', () => {
+        dxui.loadMain(helpView.screenMain)
+    })
+}
+
+configView.menuBtn = function (id, parent, width, height, src, dataI18n, callback = () => { }) {
+    const box = dxui.View.build(id, parent)
+    viewUtils._clearStyle(box)
+    box.setSize(width, height)
+    box.bgOpa(0)
+
+    const zoom = 1.02
+
+    const bg = dxui.View.build(id + 'bg', box)
+    viewUtils._clearStyle(bg)
+    bg.setSize(140, 140)
+    bg.bgColor(0xf6f6f6)
+    bg.radius(30)
+    bg.align(dxui.Utils.ALIGN.TOP_MID, 0, 10)
+
+    const image = dxui.Image.build(id + 'image', bg)
+    image.source(src)
+    image.align(dxui.Utils.ALIGN.CENTER, 0, 0)
+
+    bg.on(dxui.Utils.ENUM.LV_EVENT_PRESSED, () => {
+        bg.setSize(140 * zoom, 140 * zoom)
+        image.obj.lvImgSetZoom(256 * zoom)
+    })
+    bg.on(dxui.Utils.ENUM.LV_EVENT_RELEASED, () => {
+        bg.setSize(140, 140)
+        image.obj.lvImgSetZoom(256)
+    })
+
+    bg.on(dxui.Utils.EVENT.CLICK, () => {
+        callback()
+    })
+
+    const textLbl = dxui.Label.build(id + 'text', box)
+    textLbl.textFont(viewUtils.font(22))
+    textLbl.textColor(0x767676)
+    textLbl.dataI18n = dataI18n
+    textLbl.align(dxui.Utils.ALIGN.BOTTOM_MID, 0, -10)
+    textLbl.width(width)
+    textLbl.textAlign(dxui.Utils.TEXT_ALIGN.CENTER)
+    textLbl.longMode(dxui.Utils.LABEL_LONG_MODE.SCROLL_CIRCULAR)
+
+
+}
+
+
+export default configView
diff --git a/vf205_access/src/view/config/identityVerificationView.js b/vf205_access/src/view/config/identityVerificationView.js
new file mode 100644
index 0000000..417263d
--- /dev/null
+++ b/vf205_access/src/view/config/identityVerificationView.js
@@ -0,0 +1,185 @@
+import dxui from '../../../dxmodules/dxUi.js'
+import std from '../../../dxmodules/dxStd.js'
+import viewUtils from "../viewUtils.js"
+import topView from '../topView.js'
+import mainView from '../mainView.js'
+import configView from './configView.js'
+import i18n from '../i18n.js'
+import screen from '../../screen.js'
+const identityVerificationView = {}
+identityVerificationView.init = function () {
+    /**************************************************鍒涘缓灞忓箷*****************************************************/
+    const screenMain = dxui.View.build('identityVerificationView', dxui.Utils.LAYER.MAIN)
+    identityVerificationView.screenMain = screenMain
+    screenMain.scroll(false)
+    screenMain.bgColor(0xffffff)
+    screenMain.on(dxui.Utils.ENUM.LV_EVENT_SCREEN_LOADED, () => {
+        topView.changeTheme(true)
+        toggleTab(0)
+
+        // 鏃犳搷浣�15绉掕嚜鍔ㄨ繑鍥�
+        if (identityVerificationView.timer) {
+            std.clearInterval(identityVerificationView.timer)
+        }
+        identityVerificationView.timer = std.setInterval(() => {
+            let count = dxui.Utils.GG.NativeDisp.lvDispGetInactiveTime()
+            if (count > 15 * 1000) {
+                std.clearInterval(identityVerificationView.timer)
+                identityVerificationView.timer = null
+                dxui.loadMain(mainView.screenMain)
+            }
+        }, 1000)
+    })
+
+    screenMain.on(dxui.Utils.ENUM.LV_EVENT_SCREEN_UNLOADED, () => {
+        // 浜鸿劯璁よ瘉缁撴潫
+        if (identityVerificationView.timer) {
+            std.clearInterval(identityVerificationView.timer)
+        }
+        if (!faceRec.isHide()) {
+            screen.faceAuthEnd()
+        }
+    })
+
+    const titleBoxBg = dxui.View.build('titleBoxBg', screenMain)
+    viewUtils._clearStyle(titleBoxBg)
+    titleBoxBg.setSize(screen.screenSize.width, 70)
+    titleBoxBg.align(dxui.Utils.ALIGN.TOP_MID, 0, 0)
+    titleBoxBg.bgColor(0xffffff)
+
+    const titleBox = viewUtils.title(screenMain, mainView.screenMain, 'identityVerificationViewTitle', 'identityVerificationView.title')
+    titleBox.align(dxui.Utils.ALIGN.TOP_MID, 0, 70)
+
+    const tab = dxui.View.build('tab', screenMain)
+    viewUtils._clearStyle(tab)
+    tab.setSize(screen.screenSize.width, 80)
+    tab.alignTo(titleBox, dxui.Utils.ALIGN.OUT_BOTTOM_MID, 0, 0)
+    tab.flexFlow(dxui.Utils.FLEX_FLOW.ROW)
+    tab.flexAlign(dxui.Utils.FLEX_ALIGN.SPACE_AROUND, dxui.Utils.FLEX_ALIGN.CENTER, dxui.Utils.FLEX_ALIGN.CENTER)
+
+    const pwdLogBox = dxui.View.build('pwdLogBox', tab)
+    viewUtils._clearStyle(pwdLogBox)
+    const pwdLogLbl = dxui.Label.build('pwdLogLbl', pwdLogBox)
+    pwdLogLbl.textFont(viewUtils.font(28))
+    pwdLogLbl.textColor(0x888888)
+    pwdLogLbl.text('瀵嗙爜鐧诲綍')
+    pwdLogLbl.dataI18n = 'identityVerificationView.pwdLog'
+    const pwdLogText = pwdLogLbl.text
+    pwdLogLbl.text = (data) => {
+        pwdLogText.call(pwdLogLbl, data)
+        pwdLogLbl.update()
+        pwdLogBox.setSize(pwdLogLbl.width() + 8, 80)
+    }
+    pwdLogLbl.align(dxui.Utils.ALIGN.CENTER, 0, 0)
+    pwdLogLbl.update()
+    pwdLogBox.setSize(pwdLogLbl.width() + 8, 80)
+    pwdLogBox.borderWidth(4)
+    pwdLogBox.obj.setStyleBorderSide(dxui.Utils.ENUM.LV_BORDER_SIDE_BOTTOM, 0)
+    pwdLogBox.setBorderColor(0x0836C)
+    pwdLogBox.on(dxui.Utils.EVENT.CLICK, () => {
+        toggleTab(0)
+    })
+
+    const faceLogBox = dxui.View.build('faceLogBox', tab)
+    viewUtils._clearStyle(faceLogBox)
+    const faceLogLbl = dxui.Label.build('faceLogLbl', faceLogBox)
+    faceLogLbl.textFont(viewUtils.font(28))
+    faceLogLbl.textColor(0x888888)
+    faceLogLbl.text('浜鸿劯鐧诲綍')
+    faceLogLbl.dataI18n = 'identityVerificationView.faceLog'
+    const faceLogText = faceLogLbl.text
+    faceLogLbl.text = (data) => {
+        faceLogText.call(faceLogLbl, data)
+        faceLogLbl.update()
+        faceLogBox.setSize(faceLogLbl.width() + 8, 80)
+    }
+    faceLogLbl.align(dxui.Utils.ALIGN.CENTER, 0, 0)
+    faceLogLbl.update()
+    faceLogBox.setSize(faceLogLbl.width() + 8, 80)
+    faceLogBox.borderWidth(4)
+    faceLogBox.obj.setStyleBorderSide(dxui.Utils.ENUM.LV_BORDER_SIDE_BOTTOM, 0)
+    faceLogBox.setBorderColor(0x0836C)
+    faceLogBox.on(dxui.Utils.EVENT.CLICK, () => {
+        toggleTab(1)
+    })
+
+    const pwdInput = viewUtils.input(screenMain, screenMain.id + 'pwdInput', undefined, undefined, 'identityVerificationView.pwd')
+    pwdInput.align(dxui.Utils.ALIGN.TOP_MID, 0, 263)
+    pwdInput.setPasswordMode(true)
+
+    const eyeFill = viewUtils.imageBtn(screenMain, screenMain.id + 'eye_fill', '/app/code/resource/image/eye-fill.png')
+    eyeFill.alignTo(pwdInput, dxui.Utils.ALIGN.RIGHT_MID, 0, 0)
+    eyeFill.on(dxui.Utils.EVENT.CLICK, () => {
+        pwdInput.setPasswordMode(true)
+        eyeFill.hide()
+        eyeOff.show()
+    })
+    eyeFill.hide()
+
+    const eyeOff = viewUtils.imageBtn(screenMain, screenMain.id + 'eye_off', '/app/code/resource/image/eye-off.png')
+    eyeOff.alignTo(pwdInput, dxui.Utils.ALIGN.RIGHT_MID, 0, 0)
+    eyeOff.on(dxui.Utils.EVENT.CLICK, () => {
+        pwdInput.setPasswordMode(false)
+        eyeFill.show()
+        eyeOff.hide()
+    })
+
+    const pwdAccessBtn = viewUtils.bottomBtn(screenMain, screenMain.id + 'pwdAccessBtn', 'identityVerificationView.pwdAccess', () => {
+        if (screen.getConfig()['base.password'] === pwdInput.text()) {
+            // 杩涘叆璁剧疆鑿滃崟
+            std.clearInterval(identityVerificationView.timer)
+            dxui.loadMain(configView.screenMain)
+        } else {
+            if (faceRec.isHide()) {
+                // 瀵嗙爜閿欒
+                identityVerificationView.statusPanel.fail('identityVerificationView.pwdFail')
+            } else {
+                // 浜鸿劯璁よ瘉澶辫触
+                identityVerificationView.statusPanel.fail('identityVerificationView.fail')
+            }
+        }
+    })
+    pwdAccessBtn.align(dxui.Utils.ALIGN.BOTTOM_MID, 0, -83)
+
+    const faceRec = dxui.Image.build('faceRec', screenMain)
+    faceRec.source('/app/code/resource/image/faceRec.png')
+    faceRec.alignTo(tab, dxui.Utils.ALIGN.OUT_BOTTOM_MID, 0, 70)
+
+    identityVerificationView.statusPanel = viewUtils.statusPanel(screenMain, 'identityVerificationView.success', 'identityVerificationView.fail')
+
+    function toggleTab(index) {
+        screenMain.send(dxui.Utils.EVENT.CLICK)
+        if (index == 0) {
+            pwdLogLbl.textColor(0x0836C)
+            faceLogLbl.textColor(0x888888)
+            pwdLogBox.setBorderColor(0x0836C)
+            faceLogBox.setBorderColor(0xffffff)
+            pwdInput.show()
+            eyeFill.show()
+            eyeOff.show()
+            pwdAccessBtn.show()
+            screenMain.bgOpa(100)
+            faceRec.hide()
+
+            // 浜鸿劯璁よ瘉缁撴潫
+            screen.faceAuthEnd()
+        } else {
+            pwdLogLbl.textColor(0x888888)
+            faceLogLbl.textColor(0x0836C)
+            pwdLogBox.setBorderColor(0xffffff)
+            faceLogBox.setBorderColor(0x0836C)
+            pwdInput.hide()
+            eyeFill.hide()
+            eyeOff.hide()
+            pwdAccessBtn.hide()
+            screenMain.bgOpa(0)
+            faceRec.show()
+
+            // 浜鸿劯璁よ瘉寮�濮�
+            screen.faceAuthStart()
+        }
+    }
+    toggleTab(0)
+}
+
+export default identityVerificationView
\ No newline at end of file
diff --git a/vf205_access/src/view/config/menu/cloudCertView.js b/vf205_access/src/view/config/menu/cloudCertView.js
new file mode 100644
index 0000000..007f389
--- /dev/null
+++ b/vf205_access/src/view/config/menu/cloudCertView.js
@@ -0,0 +1,42 @@
+import dxui from '../../../../dxmodules/dxUi.js'
+import viewUtils from "../../viewUtils.js"
+import topView from "../../topView.js"
+import configView from '../configView.js'
+const cloudCertView = {}
+cloudCertView.init = function () {
+    /**************************************************鍒涘缓灞忓箷*****************************************************/
+    const screenMain = dxui.View.build('cloudCertView', dxui.Utils.LAYER.MAIN)
+    cloudCertView.screenMain = screenMain
+    screenMain.scroll(false)
+    screenMain.bgColor(0xffffff)
+    screenMain.on(dxui.Utils.ENUM.LV_EVENT_SCREEN_LOADED, () => {
+        topView.changeTheme(true)
+    })
+
+    const titleBox = viewUtils.title(screenMain, configView.screenMain, 'cloudCertViewTitle', 'cloudCertView.cloudCertActive')
+    titleBox.align(dxui.Utils.ALIGN.TOP_MID, 0, 70)
+
+    const inputBox = viewUtils.input(screenMain, 'cloudCertViewInput', undefined, () => {
+        console.log('cloudCertViewInput')
+    }, 'cloudCertView.inputKey')
+    inputBox.align(dxui.Utils.ALIGN.TOP_LEFT, 109, 179)
+    inputBox.width(654)
+
+    const keyLbl = dxui.Label.build('cloudCertViewKey', screenMain)
+    keyLbl.dataI18n = 'cloudCertView.key'
+    keyLbl.textFont(viewUtils.font(26))
+    keyLbl.align(dxui.Utils.ALIGN.TOP_LEFT, 43, 201)
+
+    const tipLbl = dxui.Label.build('cloudCertViewTip', screenMain)
+    tipLbl.dataI18n = 'cloudCertView.tip'
+    tipLbl.textFont(viewUtils.font(22))
+    tipLbl.textColor(0x888888)
+    tipLbl.align(dxui.Utils.ALIGN.TOP_MID, 0, 650)
+
+
+    const saveBtn = viewUtils.bottomBtn(screenMain, screenMain.id + 'saveBtn', 'cloudCertView.save', () => {
+    })
+    saveBtn.align(dxui.Utils.ALIGN.BOTTOM_MID, 0, -83)
+}
+
+export default cloudCertView 
diff --git a/vf205_access/src/view/config/menu/deviceInfo/dataCapacityInfoView.js b/vf205_access/src/view/config/menu/deviceInfo/dataCapacityInfoView.js
new file mode 100644
index 0000000..ef90a0b
--- /dev/null
+++ b/vf205_access/src/view/config/menu/deviceInfo/dataCapacityInfoView.js
@@ -0,0 +1,118 @@
+import dxui from '../../../../../dxmodules/dxUi.js'
+import dxCommon from '../../../../../dxmodules/dxCommon.js'
+import viewUtils from "../../../viewUtils.js"
+import topView from "../../../topView.js"
+import deviceInfoView from '../deviceInfoView.js'
+import i18n from "../../../i18n.js"
+import sqliteService from '../../../../service/sqliteService.js'
+import screen from '../../../../screen.js'
+const dataCapacityInfoView = {}
+dataCapacityInfoView.init = function () {
+    /**************************************************鍒涘缓灞忓箷*****************************************************/
+    const screenMain = dxui.View.build('dataCapacityInfoView', dxui.Utils.LAYER.MAIN)
+    dataCapacityInfoView.screenMain = screenMain
+    screenMain.scroll(false)
+    screenMain.bgColor(0xffffff)
+    screenMain.on(dxui.Utils.ENUM.LV_EVENT_SCREEN_LOADED, () => {
+        topView.changeTheme(true)
+
+        dataCapacityInfoView.info[0].label.text(Math.floor(dxCommon.getTotaldisk() / 1024 / 1024) + ' M')
+        dataCapacityInfoView.info[1].label.text(Math.floor((dxCommon.getTotaldisk() - dxCommon.getFreedisk()) / 1024 / 1024) + ' M')
+        dataCapacityInfoView.info[2].label.text(Math.floor(dxCommon.getFreedisk() / 1024 / 1024) + ' M')
+        dataCapacityInfoView.info[3].label.text(sqliteService.d1_person.count() + '')
+        dataCapacityInfoView.info[4].label.text(sqliteService.d1_voucher.countByType(300) + '')
+        dataCapacityInfoView.info[5].label.text(sqliteService.d1_voucher.countByType(400) + '')
+        dataCapacityInfoView.info[6].label.text(sqliteService.d1_voucher.countByType(200) + '')
+        dataCapacityInfoView.info[7].label.text(sqliteService.d1_pass_record.count() + '')
+    })
+
+    const titleBox = viewUtils.title(screenMain, deviceInfoView.screenMain, 'dataCapacityInfoViewTitle', 'deviceInfoView.dataCapacityInfo')
+    titleBox.align(dxui.Utils.ALIGN.TOP_MID, 0, 70)
+
+    dataCapacityInfoView.info = [
+        {
+            title: "deviceInfoView.deviceTotalSpace",
+            type: 'label',
+            value: '5918 M',
+        },
+        {
+            title: "deviceInfoView.deviceUsedSpace",
+            type: 'label',
+            value: '344 M',
+        },
+        // {
+        //     title: "deviceInfoView.deviceFreeSpace",
+        //     type: 'label',
+        //     value: '5574 M',
+        // },
+        {
+            title: "deviceInfoView.deviceRemainingSpace",
+            type: 'label',
+            value: '3',
+        },
+        {
+            title: "deviceInfoView.registeredPersonNum",
+            type: 'label',
+            value: '3',
+        },
+        {
+            title: "deviceInfoView.localFaceWhiteListNum",
+            type: 'label',
+            value: '3',
+        },
+        {
+            title: "deviceInfoView.localPasswordWhiteListNum",
+            type: 'label',
+            value: '3',
+        },
+        {
+            title: "deviceInfoView.localSwipeCardWhiteListNum",
+            type: 'label',
+            value: '3',
+        },
+        {
+            title: "deviceInfoView.passLogTotalNum",
+            type: 'label',
+            value: '3',
+        }
+    ]
+
+    const dataCapacityInfoBox = dxui.View.build('dataCapacityInfoBox', screenMain)
+    viewUtils._clearStyle(dataCapacityInfoBox)
+    dataCapacityInfoBox.align(dxui.Utils.ALIGN.TOP_MID, 0, 140)
+    dataCapacityInfoBox.setSize(screen.screenSize.width, 700)
+    dataCapacityInfoBox.bgOpa(0)
+    dataCapacityInfoBox.flexFlow(dxui.Utils.FLEX_FLOW.ROW_WRAP)
+    dataCapacityInfoBox.flexAlign(dxui.Utils.FLEX_ALIGN.CENTER, dxui.Utils.FLEX_ALIGN.START, dxui.Utils.FLEX_ALIGN.START)
+    dataCapacityInfoBox.obj.lvObjSetStylePadGap(0, dxui.Utils.ENUM._LV_STYLE_STATE_CMP_SAME)
+    dataCapacityInfoBox.borderWidth(1)
+    dataCapacityInfoBox.setBorderColor(0xDEDEDE)
+    dataCapacityInfoBox.obj.setStyleBorderSide(dxui.Utils.ENUM.LV_BORDER_SIDE_TOP, 0)
+
+    dataCapacityInfoView.info.forEach(item => {
+        const itemBox = dxui.View.build(item.title, dataCapacityInfoBox)
+        viewUtils._clearStyle(itemBox)
+        itemBox.setSize(760, 76)
+        itemBox.borderWidth(1)
+        itemBox.setBorderColor(0xDEDEDE)
+        itemBox.obj.setStyleBorderSide(dxui.Utils.ENUM.LV_BORDER_SIDE_BOTTOM, 0)
+
+        const itemLabel = dxui.Label.build(item.title + 'Label', itemBox)
+        itemLabel.dataI18n = item.title
+        itemLabel.align(dxui.Utils.ALIGN.LEFT_MID, 0, 0)
+        itemLabel.textFont(viewUtils.font(26))
+
+        switch (item.type) {
+            case 'label':
+                const label = dxui.Label.build(item.title + 'label', itemBox)
+                label.textFont(viewUtils.font(24))
+                label.align(dxui.Utils.ALIGN.RIGHT_MID, 0, 0)
+                label.text(item.value)
+                label.textColor(0x767676)
+                item.label = label
+                break;
+        }
+    })
+}
+
+export default dataCapacityInfoView
diff --git a/vf205_access/src/view/config/menu/deviceInfo/systemInfoView.js b/vf205_access/src/view/config/menu/deviceInfo/systemInfoView.js
new file mode 100644
index 0000000..f70e9a0
--- /dev/null
+++ b/vf205_access/src/view/config/menu/deviceInfo/systemInfoView.js
@@ -0,0 +1,94 @@
+import dxui from '../../../../../dxmodules/dxUi.js'
+import viewUtils from "../../../viewUtils.js"
+import topView from "../../../topView.js"
+import deviceInfoView from '../deviceInfoView.js'
+import i18n from "../../../i18n.js"
+import screen from '../../../../screen.js'
+const systemInfoView = {}
+systemInfoView.init = function () {
+    /**************************************************鍒涘缓灞忓箷*****************************************************/
+    const screenMain = dxui.View.build('systemInfoView', dxui.Utils.LAYER.MAIN)
+    systemInfoView.screenMain = screenMain
+    screenMain.scroll(false)
+    screenMain.bgColor(0xffffff)
+    screenMain.on(dxui.Utils.ENUM.LV_EVENT_SCREEN_LOADED, () => {
+        topView.changeTheme(true)
+        const config = screen.getConfig()
+        systemInfoView.info[0].label.text(config["sys.sn"])
+        systemInfoView.info[1].label.text(config["sys.appVersion"])
+        systemInfoView.info[2].label.text(config["sys.releaseTime"])
+    })
+
+    const titleBox = viewUtils.title(screenMain, deviceInfoView.screenMain, 'systemInfoViewTitle', 'deviceInfoView.systemInfo')
+    titleBox.align(dxui.Utils.ALIGN.TOP_MID, 0, 70)
+
+    systemInfoView.info = [
+        {
+            title: "deviceInfoView.deviceSN",
+            type: 'label',
+            value: 'G2440288881',
+        },
+        {
+            title: "deviceInfoView.firmwareVersion",
+            type: 'label',
+            value: 'VF203-v1.1.36.3a885-240611',
+        },
+        {
+            title: "deviceInfoView.firmwareReleaseDate",
+            type: 'label',
+            value: '2024-06-11 18:00:00',
+        },
+    ]
+
+    const settingInfoBox = dxui.View.build('settingInfoBox', screenMain)
+    viewUtils._clearStyle(settingInfoBox)
+    settingInfoBox.align(dxui.Utils.ALIGN.TOP_MID, 0, 140)
+    settingInfoBox.setSize(screen.screenSize.width, 700)
+    settingInfoBox.bgOpa(0)
+    settingInfoBox.flexFlow(dxui.Utils.FLEX_FLOW.ROW_WRAP)
+    settingInfoBox.flexAlign(dxui.Utils.FLEX_ALIGN.CENTER, dxui.Utils.FLEX_ALIGN.START, dxui.Utils.FLEX_ALIGN.START)
+    settingInfoBox.obj.lvObjSetStylePadGap(0, dxui.Utils.ENUM._LV_STYLE_STATE_CMP_SAME)
+    settingInfoBox.borderWidth(1)
+    settingInfoBox.setBorderColor(0xDEDEDE)
+    settingInfoBox.obj.setStyleBorderSide(dxui.Utils.ENUM.LV_BORDER_SIDE_TOP, 0)
+
+    systemInfoView.info.forEach(item => {
+        const itemBox = dxui.View.build(item.title, settingInfoBox)
+        viewUtils._clearStyle(itemBox)
+        itemBox.setSize(760, 76)
+        itemBox.borderWidth(1)
+        itemBox.setBorderColor(0xDEDEDE)
+        itemBox.obj.setStyleBorderSide(dxui.Utils.ENUM.LV_BORDER_SIDE_BOTTOM, 0)
+
+        const itemLabel = dxui.Label.build(item.title + 'Label', itemBox)
+        itemLabel.dataI18n = item.title
+        itemLabel.align(dxui.Utils.ALIGN.LEFT_MID, 0, 0)
+        itemLabel.textFont(viewUtils.font(26))
+
+        switch (item.type) {
+            case 'label':
+                const label = dxui.Label.build(item.title + 'label', itemBox)
+                label.textFont(viewUtils.font(24))
+                label.align(dxui.Utils.ALIGN.RIGHT_MID, 0, 0)
+                label.text(item.value)
+                label.textColor(0x767676)
+                item.label = label
+                break;
+        }
+    })
+
+    const currentVersion = dxui.Label.build('deviceInfoView.currentVersion', screenMain)
+    currentVersion.align(dxui.Utils.ALIGN.BOTTOM_MID, 0, -213)
+    currentVersion.textFont(viewUtils.font(22))
+    currentVersion.textColor(0x888888)
+    currentVersion.dataI18n = 'deviceInfoView.currentVersion'
+    currentVersion.textAlign(dxui.Utils.TEXT_ALIGN.CENTER, 0, 0)
+    currentVersion.hide()
+
+    const saveBtn = viewUtils.bottomBtn(screenMain, screenMain.id + 'saveBtn', 'deviceInfoView.updateDevice', () => {
+    })
+    saveBtn.align(dxui.Utils.ALIGN.BOTTOM_MID, 0, -83)
+    saveBtn.hide()
+}
+
+export default systemInfoView
diff --git a/vf205_access/src/view/config/menu/deviceInfoView.js b/vf205_access/src/view/config/menu/deviceInfoView.js
new file mode 100644
index 0000000..cfe5b67
--- /dev/null
+++ b/vf205_access/src/view/config/menu/deviceInfoView.js
@@ -0,0 +1,110 @@
+import dxui from '../../../../dxmodules/dxUi.js'
+import viewUtils from "../../viewUtils.js"
+import topView from "../../topView.js"
+import configView from '../configView.js'
+import systemInfoView from './deviceInfo/systemInfoView.js'
+import dataCapacityInfoView from './deviceInfo/dataCapacityInfoView.js'
+import i18n from "../../i18n.js"
+import screen from '../../../screen.js'
+
+const deviceInfoView = {}
+deviceInfoView.init = function () {
+    /**************************************************鍒涘缓灞忓箷*****************************************************/
+    const screenMain = dxui.View.build('deviceInfoView', dxui.Utils.LAYER.MAIN)
+    deviceInfoView.screenMain = screenMain
+    screenMain.scroll(false)
+    screenMain.bgColor(0xffffff)
+    screenMain.on(dxui.Utils.ENUM.LV_EVENT_SCREEN_LOADED, () => {
+        topView.changeTheme(true)
+        let config = screen.getConfig()
+        dxui.Utils.GG.NativeBasicComponent.lvQrcodeUpdate(deviceInfoView.sysInfo[2].qrcodeObj, config["sys.sn"])
+    })
+
+    const titleBox = viewUtils.title(screenMain, configView.screenMain, 'deviceInfoViewTitle', 'deviceInfoView.title')
+    titleBox.align(dxui.Utils.ALIGN.TOP_MID, 0, 70)
+
+    deviceInfoView.sysInfo = [
+        {
+            title: 'deviceInfoView.systemInfo',
+            type: 'menu',
+            view: systemInfoView,
+            obj: null,
+        },
+        {
+            title: 'deviceInfoView.dataCapacityInfo',
+            type: 'menu',
+            view: dataCapacityInfoView,
+            obj: null,
+        },
+        {
+            title: 'deviceInfoView.deviceQrCode',
+            value: '123',
+            type: 'qrcode',
+            obj: null,
+        },
+    ]
+
+
+    const deviceInfoBox = dxui.View.build('deviceInfoBox', screenMain)
+    viewUtils._clearStyle(deviceInfoBox)
+    deviceInfoBox.setSize(screen.screenSize.width, screen.screenSize.height - 140)
+    deviceInfoBox.align(dxui.Utils.ALIGN.TOP_MID, 0, 140)
+    deviceInfoBox.bgColor(0xf7f7f7)
+    deviceInfoBox.flexFlow(dxui.Utils.FLEX_FLOW.ROW_WRAP)
+    deviceInfoBox.flexAlign(dxui.Utils.FLEX_ALIGN.CENTER, dxui.Utils.FLEX_ALIGN.START, dxui.Utils.FLEX_ALIGN.START)
+    deviceInfoBox.obj.lvObjSetStylePadGap(10, dxui.Utils.ENUM._LV_STYLE_STATE_CMP_SAME)
+    deviceInfoBox.padTop(10)
+    deviceInfoBox.padBottom(10)
+
+    deviceInfoView.sysInfo.forEach(item => {
+        item.obj = dxui.View.build(item.title, deviceInfoBox)
+        viewUtils._clearStyle(item.obj)
+        item.obj.setSize(760, 76)
+        item.obj.bgColor(0xffffff)
+        item.obj.radius(10)
+        item.obj.on(dxui.Utils.ENUM.LV_EVENT_PRESSED, () => {
+            item.obj.bgColor(0xEAEAEA)
+        })
+        item.obj.on(dxui.Utils.ENUM.LV_EVENT_RELEASED, () => {
+            item.obj.bgColor(0xffffff)
+        })
+
+        const titleLbl = dxui.Label.build(item.title + 'Label', item.obj)
+        titleLbl.dataI18n = item.title
+        titleLbl.align(dxui.Utils.ALIGN.LEFT_MID, 20, 0)
+        titleLbl.textFont(viewUtils.font(26))
+
+        switch (item.type) {
+            case 'menu':
+                const image = dxui.Image.build(item.title + 'Image', item.obj)
+                image.align(dxui.Utils.ALIGN.RIGHT_MID, -15, 0)
+                image.source('/app/code/resource/image/right.png')
+                item.obj.on(dxui.Utils.EVENT.CLICK, () => {
+                    dxui.loadMain(item.view.screenMain)
+                })
+                break
+            case 'qrcode':
+                item.obj.height(350)
+                if (item.title == "deviceInfoView.miniProgramCode") {
+                    const qrcodeImage = dxui.Image.build(item.title + 'qrcodeImage', item.obj)
+                    deviceInfoView.qrcodeImage = qrcodeImage
+                    qrcodeImage.source('/app/code/resource/image/app_qrcode.png')
+                    qrcodeImage.obj.lvImgSetZoom(256 * 0.6)
+                    qrcodeImage.obj.lvImgSetSizeMode(dxui.Utils.ENUM.LV_IMG_SIZE_MODE_REAL)
+                    qrcodeImage.align(dxui.Utils.ALIGN.RIGHT_MID, -20, 0)
+                } else {
+                    const qrcodeBox = dxui.View.build(item.title + 'QrCode', item.obj)
+                    viewUtils._clearStyle(qrcodeBox)
+                    qrcodeBox.setSize(220, 220)
+                    qrcodeBox.align(dxui.Utils.ALIGN.RIGHT_MID, -20, 0)
+                    const qrcodeObj = dxui.Utils.GG.NativeBasicComponent.lvQrcodeCreate(qrcodeBox.obj, 220, 0x000000, 0xffffff)
+                    dxui.Utils.GG.NativeBasicComponent.lvQrcodeUpdate(qrcodeObj, item.value)
+                    item.qrcodeObj = qrcodeObj
+                }
+                break
+        }
+    })
+
+}
+
+export default deviceInfoView
diff --git a/vf205_access/src/view/config/menu/dockingSetting.js b/vf205_access/src/view/config/menu/dockingSetting.js
new file mode 100644
index 0000000..1c90a38
--- /dev/null
+++ b/vf205_access/src/view/config/menu/dockingSetting.js
@@ -0,0 +1,135 @@
+import dxui from '../../../../dxmodules/dxUi.js'
+import std from '../../../../dxmodules/dxStd.js'
+import viewUtils from '../../viewUtils.js'
+import topView from '../../topView.js'
+import configView from '../configView.js'
+import i18n from '../../i18n.js'
+import screen from '../../../screen.js'
+const dockingSettingView = {}
+dockingSettingView.init = function () {
+    /**************************************************鍒涘缓灞忓箷*****************************************************/
+    const screenMain = dxui.View.build('dockingSettingView', dxui.Utils.LAYER.MAIN)
+    dockingSettingView.screenMain = screenMain
+    screenMain.scroll(false)
+    screenMain.bgColor(0xffffff)
+    screenMain.on(dxui.Utils.ENUM.LV_EVENT_SCREEN_LOADED, () => {
+        topView.changeTheme(true)
+
+        const configAll = screen.getConfig()
+        httpGasSettingInput.text(configAll['http.gas'] || '')
+        httpStatusSettingInput.text(configAll['http.status'] || '')
+        gasUpdateTimeSettingInput.text((configAll['update.gasTime'] || 5) + '')
+        statusUpdateTimeSettingInput.text((configAll['update.statusTime'] || 5) + '')
+    })
+
+    const titleBox = viewUtils.title(screenMain, configView.screenMain, 'dockingSettingViewTitle', 'dockingSettingView.title')
+    titleBox.align(dxui.Utils.ALIGN.TOP_MID, 0, 70)
+
+    const httpGasSettingBox = dxui.View.build('httpGasSettingBox', screenMain)
+    viewUtils._clearStyle(httpGasSettingBox)
+    httpGasSettingBox.align(dxui.Utils.ALIGN.TOP_MID, 0, 140)
+    httpGasSettingBox.setSize(750, 76)
+    httpGasSettingBox.borderWidth(1)
+    httpGasSettingBox.setBorderColor(0xDEDEDE)
+    httpGasSettingBox.obj.setStyleBorderSide(dxui.Utils.ENUM.LV_BORDER_SIDE_BOTTOM, 0)
+
+    const httpGasSettingLbl = dxui.Label.build('httpGasSettingLbl', httpGasSettingBox)
+    httpGasSettingLbl.text('HTTP_姘斾綋')
+    httpGasSettingLbl.align(dxui.Utils.ALIGN.LEFT_MID, 0, 0)
+    httpGasSettingLbl.textFont(viewUtils.font(26))
+
+    const httpGasSettingInput = viewUtils.input(httpGasSettingBox, 'httpGasSettingInput', undefined, undefined, 'dockingSettingView.input')
+    httpGasSettingInput.align(dxui.Utils.ALIGN.RIGHT_MID, 0, 0)
+    httpGasSettingInput.setSize(320, 60)
+
+    const httpStatusSettingBox = dxui.View.build('httpStatusSettingBox', screenMain)
+    viewUtils._clearStyle(httpStatusSettingBox)
+    httpStatusSettingBox.align(dxui.Utils.ALIGN.TOP_MID, 0, 216)
+    httpStatusSettingBox.setSize(750, 76)
+    httpStatusSettingBox.borderWidth(1)
+    httpStatusSettingBox.setBorderColor(0xDEDEDE)
+    httpStatusSettingBox.obj.setStyleBorderSide(dxui.Utils.ENUM.LV_BORDER_SIDE_BOTTOM, 0)
+
+    const httpStatusSettingLbl = dxui.Label.build('httpStatusSettingLbl', httpStatusSettingBox)
+    httpStatusSettingLbl.text('HTTP_鐘舵��')
+    httpStatusSettingLbl.align(dxui.Utils.ALIGN.LEFT_MID, 0, 0)
+    httpStatusSettingLbl.textFont(viewUtils.font(26))
+
+    const httpStatusSettingInput = viewUtils.input(httpStatusSettingBox, 'httpStatusSettingInput', undefined, undefined, 'dockingSettingView.input')
+    httpStatusSettingInput.align(dxui.Utils.ALIGN.RIGHT_MID, 0, 0)
+    httpStatusSettingInput.setSize(320, 60)
+
+    // 姘斾綋娴撳害鏇存柊鏃堕棿璁剧疆
+    const gasUpdateTimeSettingBox = dxui.View.build('gasUpdateTimeSettingBox', screenMain)
+    viewUtils._clearStyle(gasUpdateTimeSettingBox)
+    gasUpdateTimeSettingBox.align(dxui.Utils.ALIGN.TOP_MID, 0, 292)
+    gasUpdateTimeSettingBox.setSize(750, 76)
+    gasUpdateTimeSettingBox.borderWidth(1)
+    gasUpdateTimeSettingBox.setBorderColor(0xDEDEDE)
+    gasUpdateTimeSettingBox.obj.setStyleBorderSide(dxui.Utils.ENUM.LV_BORDER_SIDE_BOTTOM, 0)
+
+    const gasUpdateTimeSettingLbl = dxui.Label.build('gasUpdateTimeSettingLbl', gasUpdateTimeSettingBox)
+    gasUpdateTimeSettingLbl.text('姘斾綋娴撳害鏇存柊鏃堕棿')
+    gasUpdateTimeSettingLbl.align(dxui.Utils.ALIGN.LEFT_MID, 0, 0)
+    gasUpdateTimeSettingLbl.textFont(viewUtils.font(26))
+
+    const gasUpdateTimeSettingUnitLbl = dxui.Label.build('gasUpdateTimeSettingUnitLbl', gasUpdateTimeSettingBox)
+    gasUpdateTimeSettingUnitLbl.text('绉�')
+    gasUpdateTimeSettingUnitLbl.align(dxui.Utils.ALIGN.RIGHT_MID, 0, 0)
+    gasUpdateTimeSettingUnitLbl.textFont(viewUtils.font(26))
+
+    const gasUpdateTimeSettingInput = viewUtils.input(gasUpdateTimeSettingBox, 'gasUpdateTimeSettingInput', 2, undefined, 'dockingSettingView.input')
+    gasUpdateTimeSettingInput.align(dxui.Utils.ALIGN.RIGHT_MID, -45, 0)
+    gasUpdateTimeSettingInput.setSize(150, 60)
+
+    // 鐘舵�佷俊鎭洿鏂版椂闂磋缃�
+    const statusUpdateTimeSettingBox = dxui.View.build('statusUpdateTimeSettingBox', screenMain)
+    viewUtils._clearStyle(statusUpdateTimeSettingBox)
+    statusUpdateTimeSettingBox.align(dxui.Utils.ALIGN.TOP_MID, 0, 368)
+    statusUpdateTimeSettingBox.setSize(750, 76)
+    statusUpdateTimeSettingBox.borderWidth(1)
+    statusUpdateTimeSettingBox.setBorderColor(0xDEDEDE)
+    statusUpdateTimeSettingBox.obj.setStyleBorderSide(dxui.Utils.ENUM.LV_BORDER_SIDE_BOTTOM, 0)
+
+    const statusUpdateTimeSettingLbl = dxui.Label.build('statusUpdateTimeSettingLbl', statusUpdateTimeSettingBox)
+    statusUpdateTimeSettingLbl.text('鐘舵�佷俊鎭洿鏂版椂闂�')
+    statusUpdateTimeSettingLbl.align(dxui.Utils.ALIGN.LEFT_MID, 0, 0)
+    statusUpdateTimeSettingLbl.textFont(viewUtils.font(26))
+
+    const statusUpdateTimeSettingUnitLbl = dxui.Label.build('statusUpdateTimeSettingUnitLbl', statusUpdateTimeSettingBox)
+    statusUpdateTimeSettingUnitLbl.text('绉�')
+    statusUpdateTimeSettingUnitLbl.align(dxui.Utils.ALIGN.RIGHT_MID, 0, 0)
+    statusUpdateTimeSettingUnitLbl.textFont(viewUtils.font(26))
+
+    const statusUpdateTimeSettingInput = viewUtils.input(statusUpdateTimeSettingBox, 'statusUpdateTimeSettingInput', 2, undefined, 'dockingSettingView.input')
+    statusUpdateTimeSettingInput.align(dxui.Utils.ALIGN.RIGHT_MID, -45, 0)
+    statusUpdateTimeSettingInput.setSize(150, 60)
+
+    const saveBtn = viewUtils.bottomBtn(screenMain, screenMain.id + 'saveBtn', 'dockingSettingView.save', () => {
+        const saveConfigData = {
+            http: {
+                gas: httpGasSettingInput.text(),
+                status: httpStatusSettingInput.text()
+            },
+            update: {
+                gasTime: parseInt(gasUpdateTimeSettingInput.text()) || 5,
+                statusTime: parseInt(statusUpdateTimeSettingInput.text()) || 5
+            }
+        }
+        const res = screen.saveConfig(saveConfigData)
+        if (res === true) {
+            dockingSettingView.statusPanel.success()
+            std.setTimeout(() => {
+                // 鎴愬姛杩斿洖涓婁竴灞傜晫闈�
+                dxui.loadMain(configView.screenMain)
+            }, 500)
+        } else {
+            dockingSettingView.statusPanel.fail()
+        }
+    })
+    saveBtn.align(dxui.Utils.ALIGN.BOTTOM_MID, 0, -83)
+
+    dockingSettingView.statusPanel = viewUtils.statusPanel(screenMain, 'dockingSettingView.success', 'dockingSettingView.fail')
+}
+
+export default dockingSettingView
\ No newline at end of file
diff --git a/vf205_access/src/view/config/menu/doorControlView.js b/vf205_access/src/view/config/menu/doorControlView.js
new file mode 100644
index 0000000..e8479d5
--- /dev/null
+++ b/vf205_access/src/view/config/menu/doorControlView.js
@@ -0,0 +1,258 @@
+import dxui from '../../../../dxmodules/dxUi.js'
+import std from '../../../../dxmodules/dxStd.js'
+import viewUtils from "../../viewUtils.js"
+import topView from "../../topView.js"
+import configView from '../configView.js'
+import i18n from "../../i18n.js"
+import screen from '../../../screen.js'
+import bus from '../../../../dxmodules/dxEventBus.js'
+const doorControlView = {}
+doorControlView.init = function () {
+    /**************************************************鍒涘缓灞忓箷*****************************************************/
+    const screenMain = dxui.View.build('doorControlView', dxui.Utils.LAYER.MAIN)
+    doorControlView.screenMain = screenMain
+    screenMain.scroll(false)
+    screenMain.bgColor(0xffffff)
+    screenMain.on(dxui.Utils.ENUM.LV_EVENT_SCREEN_LOADED, () => {
+        topView.changeTheme(true)
+
+        const configAll = screen.getConfig()
+        delaySettingInput.text(configAll['access.relayTime'] + '')
+        alarmSettingSwitch.select(configAll['access.tamperAlarm'] == 1)
+        mqttSettingInput.text(configAll['mqtt.addr'])
+        mqttUserSettingInput.text(configAll['mqtt.username'])
+        mqttPwdSettingInput.text(configAll['mqtt.password'])
+        onlineCheckingSettingSwitch.select(configAll['mqtt.onlinecheck'] == 1)
+        onlineCheckingTimeoutSettingInput.text(configAll['mqtt.timeout'] + '')
+        GranarySettingInput.text(configAll['GranaryName'] || '涓ぎ鍌ㄥ绮煇鏌愮洿灞炲簱')
+        houseNameSettingInput.text(configAll['houseName'] || '01鍙蜂粨')
+        doorHttpGasSettingInput.text(configAll['http.safeInputAccess'] || "http://192.168.1.199:80/cgi-bin/safeInputAccess")
+    })
+
+    const titleBox = viewUtils.title(screenMain, configView.screenMain, 'doorControlViewTitle', 'doorControlView.title')
+    titleBox.align(dxui.Utils.ALIGN.TOP_MID, 0, 70)
+
+    const delaySettingBox = dxui.View.build('delaySettingBox', screenMain)
+    viewUtils._clearStyle(delaySettingBox)
+    delaySettingBox.align(dxui.Utils.ALIGN.TOP_MID, 0, 140)
+    delaySettingBox.setSize(750, 76)
+    delaySettingBox.borderWidth(1)
+    delaySettingBox.setBorderColor(0xDEDEDE)
+    delaySettingBox.obj.setStyleBorderSide(dxui.Utils.ENUM.LV_BORDER_SIDE_BOTTOM, 0)
+
+    const delaySettingLbl = dxui.Label.build('delaySettingLbl', delaySettingBox)
+    delaySettingLbl.dataI18n = 'doorControlView.openDoorRelayDelay'
+    delaySettingLbl.align(dxui.Utils.ALIGN.LEFT_MID, 0, 0)
+    delaySettingLbl.textFont(viewUtils.font(26))
+
+    const delaySettingUnitLbl = dxui.Label.build('delaySettingUnitLbl', delaySettingBox)
+    delaySettingUnitLbl.dataI18n = "doorControlView.ms"
+    delaySettingUnitLbl.align(dxui.Utils.ALIGN.RIGHT_MID, 0, 0)
+    delaySettingUnitLbl.textFont(viewUtils.font(26))
+
+    const delaySettingInput = viewUtils.input(delaySettingBox, 'delaySettingInput', 2, undefined, 'doorControlView.input')
+    delaySettingInput.align(dxui.Utils.ALIGN.RIGHT_MID, -60, 0)
+    delaySettingInput.setSize(150, 60)
+
+    const alarmSettingBox = dxui.View.build('alarmSettingBox', screenMain)
+    viewUtils._clearStyle(alarmSettingBox)
+    alarmSettingBox.align(dxui.Utils.ALIGN.TOP_MID, 0, 216)
+    alarmSettingBox.setSize(750, 76)
+    alarmSettingBox.borderWidth(1)
+    alarmSettingBox.setBorderColor(0xDEDEDE)
+    alarmSettingBox.obj.setStyleBorderSide(dxui.Utils.ENUM.LV_BORDER_SIDE_BOTTOM, 0)
+
+    const alarmSettingLbl = dxui.Label.build('alarmSettingLbl', alarmSettingBox)
+    alarmSettingLbl.dataI18n = 'doorControlView.antiTamperAlarm'
+    alarmSettingLbl.align(dxui.Utils.ALIGN.LEFT_MID, 0, 0)
+    alarmSettingLbl.textFont(viewUtils.font(26))
+
+    const alarmSettingSwitch = dxui.Switch.build('alarmSettingSwitch', alarmSettingBox)
+    alarmSettingSwitch.align(dxui.Utils.ALIGN.RIGHT_MID, 0, 0)
+    alarmSettingSwitch.setSize(70, 35)
+
+
+    const mqttSettingBox = dxui.View.build('mqttSettingBox', screenMain)
+    viewUtils._clearStyle(mqttSettingBox)
+    mqttSettingBox.align(dxui.Utils.ALIGN.TOP_MID, 0, 292)
+    mqttSettingBox.setSize(750, 76)
+    mqttSettingBox.borderWidth(1)
+    mqttSettingBox.setBorderColor(0xDEDEDE)
+    mqttSettingBox.obj.setStyleBorderSide(dxui.Utils.ENUM.LV_BORDER_SIDE_BOTTOM, 0)
+
+    const mqttSettingLbl = dxui.Label.build('mqttSettingLbl', mqttSettingBox)
+    mqttSettingLbl.dataI18n = 'doorControlView.mqttAddr'
+    mqttSettingLbl.align(dxui.Utils.ALIGN.LEFT_MID, 0, 0)
+    mqttSettingLbl.textFont(viewUtils.font(26))
+
+    const mqttSettingInput = viewUtils.input(mqttSettingBox, 'mqttSettingInput', undefined, undefined, 'doorControlView.input')
+    mqttSettingInput.align(dxui.Utils.ALIGN.RIGHT_MID, 0, 0)
+    mqttSettingInput.setSize(320, 60)
+
+    const mqttUserSettingBox = dxui.View.build('mqttUserSettingBox', screenMain)
+    viewUtils._clearStyle(mqttUserSettingBox)
+    mqttUserSettingBox.align(dxui.Utils.ALIGN.TOP_MID, 0, 368)
+    mqttUserSettingBox.setSize(750, 76)
+    mqttUserSettingBox.borderWidth(1)
+    mqttUserSettingBox.setBorderColor(0xDEDEDE)
+    mqttUserSettingBox.obj.setStyleBorderSide(dxui.Utils.ENUM.LV_BORDER_SIDE_BOTTOM, 0)
+
+    const mqttUserSettingLbl = dxui.Label.build('mqttUserSettingLbl', mqttUserSettingBox)
+    mqttUserSettingLbl.dataI18n = 'doorControlView.mqttUser'
+    mqttUserSettingLbl.align(dxui.Utils.ALIGN.LEFT_MID, 0, 0)
+    mqttUserSettingLbl.textFont(viewUtils.font(26))
+
+    const mqttUserSettingInput = viewUtils.input(mqttUserSettingBox, 'mqttUserSettingInput', undefined, undefined, 'doorControlView.input')
+    mqttUserSettingInput.align(dxui.Utils.ALIGN.RIGHT_MID, 0, 0)
+    mqttUserSettingInput.setSize(320, 60)
+
+    const mqttPwdSettingBox = dxui.View.build('mqttPwdSettingBox', screenMain)
+    viewUtils._clearStyle(mqttPwdSettingBox)
+    mqttPwdSettingBox.align(dxui.Utils.ALIGN.TOP_MID, 0, 444)
+    mqttPwdSettingBox.setSize(750, 76)
+    mqttPwdSettingBox.borderWidth(1)
+    mqttPwdSettingBox.setBorderColor(0xDEDEDE)
+    mqttPwdSettingBox.obj.setStyleBorderSide(dxui.Utils.ENUM.LV_BORDER_SIDE_BOTTOM, 0)
+
+    const mqttPwdSettingLbl = dxui.Label.build('mqttPwdSettingLbl', mqttPwdSettingBox)
+    mqttPwdSettingLbl.dataI18n = 'doorControlView.mqttPwd'
+    mqttPwdSettingLbl.align(dxui.Utils.ALIGN.LEFT_MID, 0, 0)
+    mqttPwdSettingLbl.textFont(viewUtils.font(26))
+
+    const mqttPwdSettingInput = viewUtils.input(mqttPwdSettingBox, 'mqttPwdSettingInput', undefined, undefined, 'doorControlView.input')
+    mqttPwdSettingInput.align(dxui.Utils.ALIGN.RIGHT_MID, 0, 0)
+    mqttPwdSettingInput.setSize(320, 60)
+
+
+    const onlineCheckingSettingBox = dxui.View.build('onlineCheckingSettingBox', screenMain)
+    viewUtils._clearStyle(onlineCheckingSettingBox)
+    onlineCheckingSettingBox.align(dxui.Utils.ALIGN.TOP_MID, 0, 540)
+    onlineCheckingSettingBox.setSize(750, 76)
+    onlineCheckingSettingBox.borderWidth(1)
+    onlineCheckingSettingBox.setBorderColor(0xDEDEDE)
+    onlineCheckingSettingBox.obj.setStyleBorderSide(dxui.Utils.ENUM.LV_BORDER_SIDE_BOTTOM, 0)
+
+    const onlineCheckingSettingLbl = dxui.Label.build('onlineCheckingSettingLbl', onlineCheckingSettingBox)
+    onlineCheckingSettingLbl.dataI18n = 'doorControlView.onlineChecking'
+    onlineCheckingSettingLbl.align(dxui.Utils.ALIGN.LEFT_MID, 0, 0)
+    onlineCheckingSettingLbl.textFont(viewUtils.font(26))
+
+    const onlineCheckingSettingSwitch = dxui.Switch.build('onlineCheckingSettingSwitch', onlineCheckingSettingBox)
+    onlineCheckingSettingSwitch.align(dxui.Utils.ALIGN.RIGHT_MID, 0, 0)
+    onlineCheckingSettingSwitch.setSize(70, 35)
+
+    const onlineCheckingTimeoutSettingBox = dxui.View.build('onlineCheckingTimeoutSettingBox', screenMain)
+    viewUtils._clearStyle(onlineCheckingTimeoutSettingBox)
+    onlineCheckingTimeoutSettingBox.align(dxui.Utils.ALIGN.TOP_MID, 0, 616)
+    onlineCheckingTimeoutSettingBox.setSize(750, 76)
+    onlineCheckingTimeoutSettingBox.borderWidth(1)
+    onlineCheckingTimeoutSettingBox.setBorderColor(0xDEDEDE)
+    onlineCheckingTimeoutSettingBox.obj.setStyleBorderSide(dxui.Utils.ENUM.LV_BORDER_SIDE_BOTTOM, 0)
+
+    const onlineCheckingTimeoutSettingLbl = dxui.Label.build('onlineCheckingTimeoutSettingLbl', onlineCheckingTimeoutSettingBox)
+    onlineCheckingTimeoutSettingLbl.dataI18n = 'doorControlView.onlineCheckingTimeout'
+    onlineCheckingTimeoutSettingLbl.align(dxui.Utils.ALIGN.LEFT_MID, 0, 0)
+    onlineCheckingTimeoutSettingLbl.textFont(viewUtils.font(26))
+
+    const onlineCheckingTimeoutSettingUnitLbl = dxui.Label.build('onlineCheckingTimeoutSettingUnitLbl', onlineCheckingTimeoutSettingBox)
+    onlineCheckingTimeoutSettingUnitLbl.text('ms')
+    onlineCheckingTimeoutSettingUnitLbl.align(dxui.Utils.ALIGN.RIGHT_MID, 0, 0)
+    onlineCheckingTimeoutSettingUnitLbl.textFont(viewUtils.font(26))
+
+    const onlineCheckingTimeoutSettingInput = viewUtils.input(onlineCheckingTimeoutSettingBox, 'onlineCheckingTimeoutSettingInput', 2, undefined, 'doorControlView.input')
+    onlineCheckingTimeoutSettingInput.align(dxui.Utils.ALIGN.RIGHT_MID, -45, 0)
+    onlineCheckingTimeoutSettingInput.setSize(150, 60)
+
+    // HTTP鎺ュ彛璺緞璁剧疆
+    // 搴撳尯鍚嶇О璁剧疆
+    const GranarySettingBox = dxui.View.build('GranarySettingBox', screenMain)
+    viewUtils._clearStyle(GranarySettingBox)
+    GranarySettingBox.align(dxui.Utils.ALIGN.TOP_MID, 0, 692)
+    GranarySettingBox.setSize(750, 76)
+    GranarySettingBox.borderWidth(1)
+    GranarySettingBox.setBorderColor(0xDEDEDE)
+    GranarySettingBox.obj.setStyleBorderSide(dxui.Utils.ENUM.LV_BORDER_SIDE_BOTTOM, 0)
+
+    const GranarySettingLbl = dxui.Label.build('GranarySettingLbl', GranarySettingBox)
+    GranarySettingLbl.text('搴撳尯鍚嶇О')
+    GranarySettingLbl.align(dxui.Utils.ALIGN.LEFT_MID, 0, 0)
+    GranarySettingLbl.textFont(viewUtils.font(26))
+
+    const GranarySettingInput = viewUtils.input(GranarySettingBox, 'GranarySettingInput', undefined, undefined, 'doorControlView.input')
+    GranarySettingInput.align(dxui.Utils.ALIGN.RIGHT_MID, 0, 0)
+    GranarySettingInput.setSize(320, 60)
+
+    // 浠撳粧鍚嶇О璁剧疆
+    const houseNameSettingBox = dxui.View.build('houseNameSettingBox', screenMain)
+    viewUtils._clearStyle(houseNameSettingBox)
+    houseNameSettingBox.align(dxui.Utils.ALIGN.TOP_MID, 0, 768)
+    houseNameSettingBox.setSize(750, 76)
+    houseNameSettingBox.borderWidth(1)
+    houseNameSettingBox.setBorderColor(0xDEDEDE)
+    houseNameSettingBox.obj.setStyleBorderSide(dxui.Utils.ENUM.LV_BORDER_SIDE_BOTTOM, 0)
+
+    const houseNameSettingLbl = dxui.Label.build('houseNameSettingLbl', houseNameSettingBox)
+    houseNameSettingLbl.text('浠撳粧鍚嶇О')
+    houseNameSettingLbl.align(dxui.Utils.ALIGN.LEFT_MID, 0, 0)
+    houseNameSettingLbl.textFont(viewUtils.font(26))
+
+    const houseNameSettingInput = viewUtils.input(houseNameSettingBox, 'houseNameSettingInput', undefined, undefined, 'doorControlView.input')
+    houseNameSettingInput.align(dxui.Utils.ALIGN.RIGHT_MID, 0, 0)
+    houseNameSettingInput.setSize(320, 60)
+
+    // HTTP鎺ュ彛璺緞璁剧疆
+    const doorHttpGasSettingBox = dxui.View.build('doorHttpGasSettingBox', screenMain)
+    viewUtils._clearStyle(doorHttpGasSettingBox)
+    doorHttpGasSettingBox.align(dxui.Utils.ALIGN.TOP_MID, 0, 844)
+    doorHttpGasSettingBox.setSize(750, 76)
+    doorHttpGasSettingBox.borderWidth(1)
+    doorHttpGasSettingBox.setBorderColor(0xDEDEDE)
+    doorHttpGasSettingBox.obj.setStyleBorderSide(dxui.Utils.ENUM.LV_BORDER_SIDE_BOTTOM, 0)
+
+    const doorHttpGasSettingLbl = dxui.Label.build('doorHttpGasSettingLbl', doorHttpGasSettingBox)
+    doorHttpGasSettingLbl.text('HTTP鎺ュ彛璺緞')
+    doorHttpGasSettingLbl.align(dxui.Utils.ALIGN.LEFT_MID, 0, 0)
+    doorHttpGasSettingLbl.textFont(viewUtils.font(26))
+
+    const doorHttpGasSettingInput = viewUtils.input(doorHttpGasSettingBox, 'doorHttpGasSettingInput', undefined, undefined, 'doorControlView.input')
+    doorHttpGasSettingInput.align(dxui.Utils.ALIGN.RIGHT_MID, 0, 0)
+    doorHttpGasSettingInput.setSize(320, 60)
+
+    const saveBtn = viewUtils.bottomBtn(screenMain, screenMain.id + 'saveBtn', 'doorControlView.save', () => {
+        const saveConfigData = {
+            access: {
+                relayTime: parseInt(delaySettingInput.text()),
+                tamperAlarm: alarmSettingSwitch.isSelect() ? 1 : 0
+            },
+            mqtt: {
+                addr: mqttSettingInput.text(),
+                username: mqttUserSettingInput.text(),
+                password: mqttPwdSettingInput.text(),
+                onlinecheck: onlineCheckingSettingSwitch.isSelect() ? 1 : 0,
+                timeout: parseInt(onlineCheckingTimeoutSettingInput.text())
+            },
+            GranaryName: GranarySettingInput.text(),
+            houseName: houseNameSettingInput.text(),
+            http: {
+                safeInputAccess: doorHttpGasSettingInput.text()
+            }
+        }
+        const res = screen.saveConfig(saveConfigData)
+        if (res === true) {
+            doorControlView.statusPanel.success()
+            // 閫氱煡mainView鏇存柊搴撳尯鍚嶇О鍜屼粨鍙�
+            bus.fire('warehouseInfoUpdated')
+            std.setTimeout(() => {
+                // 鎴愬姛杩斿洖涓婁竴灞傜晫闈�
+                dxui.loadMain(configView.screenMain)
+            }, 500)
+        } else {
+            doorControlView.statusPanel.fail()
+        }
+    })
+    saveBtn.align(dxui.Utils.ALIGN.BOTTOM_MID, 0, -83)
+
+    doorControlView.statusPanel = viewUtils.statusPanel(screenMain, 'doorControlView.success', 'doorControlView.fail')
+}
+
+export default doorControlView
diff --git a/vf205_access/src/view/config/menu/factoryTestView.js b/vf205_access/src/view/config/menu/factoryTestView.js
new file mode 100644
index 0000000..661dc87
--- /dev/null
+++ b/vf205_access/src/view/config/menu/factoryTestView.js
@@ -0,0 +1,77 @@
+import dxui from "../../../../dxmodules/dxUi.js";
+import viewUtils from "../../viewUtils.js";
+import topView from "../../topView.js";
+import configView from "../configView.js";
+import i18n from "../../i18n.js";
+import screen from "../../../screen.js";
+const factoryTestView = {};
+factoryTestView.init = function () {
+    /**************************************************鍒涘缓灞忓箷*****************************************************/
+    const screenMain = dxui.View.build("factoryTestView", dxui.Utils.LAYER.MAIN);
+    factoryTestView.screenMain = screenMain;
+    screenMain.scroll(false);
+    screenMain.bgColor(0xffffff);
+    screenMain.on(dxui.Utils.ENUM.LV_EVENT_SCREEN_LOADED, () => {
+        topView.changeTheme(true);
+    });
+
+    const titleBox = viewUtils.title(
+        screenMain,
+        configView.screenMain,
+        "factoryTestViewTitle",
+        "factoryTestView.title"
+    );
+    titleBox.align(dxui.Utils.ALIGN.TOP_MID, 0, 70);
+
+    const factoryTestBox = dxui.View.build("factoryTestBox", screenMain);
+    viewUtils._clearStyle(factoryTestBox);
+    factoryTestBox.setSize(
+        screen.screenSize.width,
+        screen.screenSize.height - 140
+    );
+    factoryTestBox.align(dxui.Utils.ALIGN.TOP_MID, 0, 140);
+    factoryTestBox.bgColor(0xf7f7f7);
+    factoryTestBox.flexFlow(dxui.Utils.FLEX_FLOW.ROW_WRAP);
+    factoryTestBox.flexAlign(
+        dxui.Utils.FLEX_ALIGN.CENTER,
+        dxui.Utils.FLEX_ALIGN.START,
+        dxui.Utils.FLEX_ALIGN.START
+    );
+    factoryTestBox.obj.lvObjSetStylePadGap(
+        10,
+        dxui.Utils.ENUM._LV_STYLE_STATE_CMP_SAME
+    );
+    factoryTestBox.padTop(10);
+    factoryTestBox.padBottom(10);
+
+    const calibrationBox = dxui.View.build("calibrationBox", factoryTestBox);
+    viewUtils._clearStyle(calibrationBox);
+    // calibrationBox.align(dxui.Utils.ALIGN.TOP_MID, 0, 150);
+    calibrationBox.setSize(560, 76);
+    // calibrationBox.bgColor(0xf7f7f7);
+    calibrationBox.bgColor(0xffffff);
+    calibrationBox.radius(10);
+    calibrationBox.on(dxui.Utils.ENUM.LV_EVENT_PRESSED, () => {
+        calibrationBox.bgColor(0xeaeaea);
+    });
+    calibrationBox.on(dxui.Utils.ENUM.LV_EVENT_RELEASED, () => {
+        calibrationBox.bgColor(0xffffff);
+    });
+
+    const titleLbl = dxui.Label.build("calibrationBox" + "Label", calibrationBox);
+    titleLbl.dataI18n = "factoryTestView.calibration";
+    titleLbl.align(dxui.Utils.ALIGN.LEFT_MID, 20, 0);
+    titleLbl.textFont(viewUtils.font(26));
+
+    const image = dxui.Image.build(calibrationBox.id + "Image", calibrationBox);
+    image.align(dxui.Utils.ALIGN.RIGHT_MID, -15, 0);
+    image.source("/app/code/resource/image/right.png");
+
+    calibrationBox.on(dxui.Utils.EVENT.CLICK, () => {
+        // dxui.loadMain(item.view.screenMain);
+        console.log(123);
+        
+    });
+};
+
+export default factoryTestView;
diff --git a/vf205_access/src/view/config/menu/helpView.js b/vf205_access/src/view/config/menu/helpView.js
new file mode 100644
index 0000000..fffc887
--- /dev/null
+++ b/vf205_access/src/view/config/menu/helpView.js
@@ -0,0 +1,41 @@
+import dxui from '../../../../dxmodules/dxUi.js'
+import viewUtils from "../../viewUtils.js"
+import topView from "../../topView.js"
+import configView from '../configView.js'
+import i18n from "../../i18n.js"
+const helpView = {}
+helpView.init = function () {
+    /**************************************************鍒涘缓灞忓箷*****************************************************/
+    const screenMain = dxui.View.build('helpView', dxui.Utils.LAYER.MAIN)
+    helpView.screenMain = screenMain
+    screenMain.scroll(false)
+    screenMain.bgColor(0xffffff)
+    screenMain.on(dxui.Utils.ENUM.LV_EVENT_SCREEN_LOADED, () => {
+        topView.changeTheme(true)
+    })
+
+    const titleBox = viewUtils.title(screenMain, configView.screenMain, 'helpViewTitle', 'helpView.title')
+    titleBox.align(dxui.Utils.ALIGN.TOP_MID, 0, 70)
+
+    // 浜岀淮鐮�
+    const helpQrcode = dxui.View.build('helpQrcode', screenMain)
+    viewUtils._clearStyle(helpQrcode)
+    helpQrcode.setSize(344, 344)
+    helpQrcode.align(dxui.Utils.ALIGN.TOP_MID, 0, 170)
+    helpQrcode.bgOpa(0)
+
+    const qrcode = dxui.View.build(helpQrcode.id + 'qrcode', helpQrcode)
+    viewUtils._clearStyle(qrcode)
+    qrcode.setSize(320, 320)
+    qrcode.align(dxui.Utils.ALIGN.CENTER, 0, 0);
+    const qrcodeObj = dxui.Utils.GG.NativeBasicComponent.lvQrcodeCreate(qrcode.obj, 320, 0x000000, 0xffffff)
+    dxui.Utils.GG.NativeBasicComponent.lvQrcodeUpdate(qrcodeObj, '寰俊鏆備笉鏀寔灞曠ず浜岀淮鐮佷腑鐨勬枃鏈唴瀹�')
+
+
+    const helpLabel = dxui.Label.build('helpLabel', screenMain)
+    helpLabel.dataI18n='helpView.scanCode'
+    helpLabel.align(dxui.Utils.ALIGN.TOP_MID, 0, 541)
+    helpLabel.textFont(viewUtils.font(26))
+}
+
+export default helpView
diff --git a/vf205_access/src/view/config/menu/localUser/faceEnterView.js b/vf205_access/src/view/config/menu/localUser/faceEnterView.js
new file mode 100644
index 0000000..83fdcb8
--- /dev/null
+++ b/vf205_access/src/view/config/menu/localUser/faceEnterView.js
@@ -0,0 +1,117 @@
+import dxui from '../../../../../dxmodules/dxUi.js'
+import std from '../../../../../dxmodules/dxStd.js'
+import viewUtils from "../../../viewUtils.js"
+import topView from "../../../topView.js"
+import i18n from "../../../i18n.js"
+import localUserAddView from './localUserAddView.js'
+import screen from '../../../../screen.js'
+const faceEnterView = {}
+faceEnterView.init = function () {
+    /**************************************************鍒涘缓灞忓箷*****************************************************/
+    const screenMain = dxui.View.build('faceEnterView', dxui.Utils.LAYER.MAIN)
+    faceEnterView.screenMain = screenMain
+    screenMain.scroll(false)
+    screenMain.bgOpa(0)
+    screenMain.on(dxui.Utils.ENUM.LV_EVENT_SCREEN_LOADED, () => {
+        topView.changeTheme(false)
+        screen.faceEnterStart(localUserAddView.nowUser.id)
+
+        faceEnterView.statusPanel.success("faceEnterView.faceAdd")
+        // faceEnterView.faceAdd.show()
+        // faceEnterView.faceError.hide()
+        // 娉ㄥ唽10绉掕秴鏃�
+        faceEnterView.backTimer = std.setTimeout(() => {
+            if (!faceEnterView.successFlag) {
+                faceEnterView.statusPanel.fail("faceEnterView.faceError")
+                std.setTimeout(() => {
+                    faceEnterView.backCb()
+                    dxui.loadMain(localUserAddView.screenMain)
+                }, 500);
+            }
+        }, 10000);
+    })
+
+    screenMain.on(dxui.Utils.ENUM.LV_EVENT_SCREEN_UNLOADED, () => {
+        faceEnterView.successFlag = false
+        screen.faceEnterEnd()
+        if (faceEnterView.backTimer) {
+            std.clearTimeout(faceEnterView.backTimer)
+            faceEnterView.backTimer = null
+        }
+    })
+
+    const titleBoxBg = dxui.View.build(screenMain.id + 'titleBoxBg', screenMain)
+    viewUtils._clearStyle(titleBoxBg)
+    titleBoxBg.setSize(screen.screenSize.width, 70)
+    titleBoxBg.align(dxui.Utils.ALIGN.TOP_MID, 0, 0)
+    titleBoxBg.bgColor(0xffffff)
+
+    const titleBox = viewUtils.title(screenMain, localUserAddView.screenMain, 'faceEnterViewTitle', 'faceEnterView.title', faceEnterView.backCb)
+    titleBox.align(dxui.Utils.ALIGN.TOP_MID, 0, 70)
+
+    const faceRec2 = dxui.Image.build('faceRec2', screenMain)
+    faceRec2.align(dxui.Utils.ALIGN.TOP_MID, 0, -111)
+    faceRec2.source('/app/code/resource/image/faceRec2.png')
+
+    // const faceAdd = dxui.Image.build('faceAdd', screenMain)
+    // faceEnterView.faceAdd = faceAdd
+    // faceAdd.align(dxui.Utils.ALIGN.BOTTOM_MID, 0, -90)
+    // faceAdd.source('/app/code/resource/image/faceAdd.png')
+
+    // const faceAddLbl = dxui.Label.build('faceAddLbl', faceAdd)
+    // faceAddLbl.align(dxui.Utils.ALIGN.CENTER, 0, 0)
+    // faceAddLbl.textFont(viewUtils.font(30))
+    // faceAddLbl.textColor(0xffffff)
+    // faceAddLbl.dataI18n = 'faceEnterView.faceAdd'
+    // faceAddLbl.textAlign(dxui.Utils.TEXT_ALIGN.CENTER)
+
+
+    faceEnterView.statusPanel = viewUtils.statusPanel(screenMain)
+    // const faceError = dxui.Image.build('faceError', screenMain)
+    // faceEnterView.faceError = faceError
+    // faceError.align(dxui.Utils.ALIGN.BOTTOM_MID, 0, -90)
+    // faceError.source('/app/code/resource/image/faceError.png')
+    // faceError.hide()
+
+    // const faceErrorLbl = dxui.Label.build('faceErrorLbl', faceError)
+    // faceErrorLbl.align(dxui.Utils.ALIGN.CENTER, 0, 0)
+    // faceErrorLbl.textFont(viewUtils.font(30))
+    // faceErrorLbl.textColor(0xffffff)
+    // faceErrorLbl.dataI18n = 'faceEnterView.faceError'
+    // faceErrorLbl.textAlign(dxui.Utils.TEXT_ALIGN.CENTER)
+
+    // faceEnterView.timeout()
+}
+
+faceEnterView.timeout = function () {
+     // faceEnterView.statusPanel.fail("faceEnterView.faceError")
+    // faceEnterView.faceAdd.hide()
+    // faceEnterView.faceError.show()
+}
+
+faceEnterView.backCb = function () {
+    if (!localUserAddView.nowUser) {
+        return
+    }
+    if (localUserAddView.nowUser.id) {
+        localUserAddView.addID(localUserAddView.nowUser.id)
+    }
+    if (localUserAddView.nowUser.name) {
+        localUserAddView.addName(localUserAddView.nowUser.name)
+    }
+    if (localUserAddView.nowUser.idCard) {
+        localUserAddView.addIDCard(localUserAddView.nowUser.idCard)
+    }
+    if (localUserAddView.nowUser.face) {
+        localUserAddView.addFace(localUserAddView.nowUser.face)
+    }
+    if (localUserAddView.nowUser.pwd) {
+        localUserAddView.addPwd(localUserAddView.nowUser.pwd)
+    }
+    if (localUserAddView.nowUser.card) {
+        localUserAddView.addCard(localUserAddView.nowUser.card)
+    }
+    localUserAddView.addType(localUserAddView.nowUser.type)
+}
+
+export default faceEnterView
\ No newline at end of file
diff --git a/vf205_access/src/view/config/menu/localUser/localUserAddView.js b/vf205_access/src/view/config/menu/localUser/localUserAddView.js
new file mode 100644
index 0000000..a61655d
--- /dev/null
+++ b/vf205_access/src/view/config/menu/localUser/localUserAddView.js
@@ -0,0 +1,682 @@
+import dxui from '../../../../../dxmodules/dxUi.js'
+import std from '../../../../../dxmodules/dxStd.js'
+import viewUtils from "../../../viewUtils.js"
+import topView from "../../../topView.js"
+import localUserView from '../localUserView.js'
+import faceEnterView from './faceEnterView.js'
+import i18n from "../../../i18n.js"
+import pinyin from '../../../pinyin/pinyin.js'
+import screen from '../../../../screen.js'
+const localUserAddView = {}
+const dropdownData = ['淇濈鍛�', '绉戦暱']
+const dropdownData2 = ['User', 'Administrator']
+
+localUserAddView.init = function () {
+    /**************************************************鍒涘缓灞忓箷*****************************************************/
+    const screenMain = dxui.View.build('localUserAddView', dxui.Utils.LAYER.MAIN)
+    localUserAddView.screenMain = screenMain
+    screenMain.scroll(false)
+    screenMain.bgColor(0xffffff)
+    screenMain.on(dxui.Utils.ENUM.LV_EVENT_SCREEN_LOADED, () => {
+        topView.changeTheme(true)
+        refreshType()
+        if (!localUserAddView.deleteBtn.isHide()) {
+            //淇敼鐢ㄦ埛涓嶅厑璁告敼id
+            localUserAddView.userInfo[0].input.disable(true)
+        } else {
+            localUserAddView.userInfo[0].input.disable(false)
+        }
+    })
+
+    screenMain.on(dxui.Utils.ENUM.LV_EVENT_SCREEN_UNLOADED, () => {
+    })
+
+    const titleBox = viewUtils.title(screenMain, localUserView.screenMain, 'localUserAddViewTitle', 'localUserAddView.title', undefined)
+    localUserAddView.titleBox = titleBox
+    titleBox.align(dxui.Utils.ALIGN.TOP_MID, 0, 70)
+
+    const titleBox2 = viewUtils.title(screenMain, localUserView.screenMain, 'localUserAddViewTitle2', 'localUserAddView.title2', undefined)
+    localUserAddView.titleBox2 = titleBox2
+    titleBox2.align(dxui.Utils.ALIGN.TOP_MID, 0, 70)
+    titleBox2.hide()
+
+    const addUserBox = dxui.View.build('addUserBox', screenMain)
+    viewUtils._clearStyle(addUserBox)
+    addUserBox.setSize(screen.screenSize.width, 700)
+    addUserBox.align(dxui.Utils.ALIGN.TOP_MID, 0, 142)
+    addUserBox.borderWidth(1)
+    addUserBox.setBorderColor(0xDEDEDE)
+    addUserBox.obj.setStyleBorderSide(dxui.Utils.ENUM.LV_BORDER_SIDE_TOP, 0)
+    addUserBox.bgOpa(0)
+
+    addUserBox.flexFlow(dxui.Utils.FLEX_FLOW.ROW_WRAP)
+    addUserBox.flexAlign(dxui.Utils.FLEX_ALIGN.CENTER, dxui.Utils.FLEX_ALIGN.CENTER, dxui.Utils.FLEX_ALIGN.START)
+    addUserBox.obj.lvObjSetStylePadGap(0, dxui.Utils.ENUM._LV_STYLE_STATE_CMP_SAME)
+
+    localUserAddView.userInfo = [
+        {
+            title: 'localUserAddView.id',
+            value: null,
+            required: true,
+            type: 'input',
+            input: null
+        },
+        {
+            title: 'localUserAddView.name',
+            value: null,
+            required: true,
+            type: 'input',
+            input: null
+        },
+        {
+            title: 'localUserAddView.idCard',
+            value: null,
+            type: 'input',
+            input: null
+        },
+        {
+            title: 'localUserAddView.face',
+            value: null,
+            type: 'button',
+            btn: null,
+            btnEdit: null,
+            faceImg: null,
+            deleteBtn: null
+        },
+        {
+            title: 'localUserAddView.pwd',
+            value: null,
+            type: 'button',
+            btn: null,
+            btnEdit: null,
+            pwdLbl: null,
+            deleteBtn: null
+        },
+        {
+            title: 'localUserAddView.card',
+            value: null,
+            type: 'button',
+            btn: null,
+            btnEdit: null,
+            cardLbl: null,
+            deleteBtn: null
+        },
+        {
+            title: 'localUserAddView.type',
+            value: null,
+            type: 'dropdown'
+        }
+    ]
+
+    localUserAddView.userInfo.forEach((item, index) => {
+        const userBox = dxui.View.build('userInfo' + index, addUserBox)
+        viewUtils._clearStyle(userBox)
+        userBox.setSize(700, 65)
+        userBox.borderWidth(1)
+        userBox.setBorderColor(0xDEDEDE)
+        userBox.obj.setStyleBorderSide(dxui.Utils.ENUM.LV_BORDER_SIDE_BOTTOM, 0)
+        userBox.bgOpa(0)
+
+        if (item.required) {
+            const titleLbl = dxui.Label.build('titleLblRequired' + index, userBox)
+            titleLbl.textFont(viewUtils.font(22))
+            titleLbl.align(dxui.Utils.ALIGN.LEFT_MID, 0, 0)
+            titleLbl.text('*')
+            titleLbl.textColor(0xFD5353)
+        }
+
+        const titleLbl = dxui.Label.build('titleLbl' + index, userBox)
+        titleLbl.textFont(viewUtils.font(22))
+        titleLbl.align(dxui.Utils.ALIGN.LEFT_MID, 10, 0)
+        titleLbl.dataI18n = item.title
+
+        if (item.type === 'input') {
+            const input = viewUtils.input(userBox, item.title, item.mode, undefined, "localUserAddView.input")
+            input.align(dxui.Utils.ALIGN.RIGHT_MID, 0, 0)
+            input.textFont(viewUtils.font(22))
+            input.setSize(260, 50)
+            item.input = input
+
+            input.on(dxui.Utils.EVENT.VALUE_CHANGED, () => {
+                if (input.text() === "") {
+                    return
+                }
+                switch (item.title) {
+                    case 'localUserAddView.id':
+                        localUserAddView.nowUser.id = input.text()
+                        localUserAddView.nowUser.userId = input.text()
+                        break;
+                    case 'localUserAddView.name':
+                        localUserAddView.nowUser.name = input.text()
+                        break;
+                    case 'localUserAddView.idCard':
+                        localUserAddView.nowUser.idCard = input.text()
+                        break;
+                    default:
+                        break;
+                }
+            })
+        } else if (item.type === 'button') {
+            const btn = dxui.Button.build(item.title, userBox)
+            item.btn = btn
+            btn.setSize(150, 50)
+            btn.align(dxui.Utils.ALIGN.RIGHT_MID, 0, 0)
+            btn.bgColor(0xEEEEEE)
+            btn.radius(10)
+            const btnLbl = dxui.Label.build(item.title + 'btnLbl', btn)
+            btnLbl.textFont(viewUtils.font(22))
+            btnLbl.textColor(0x05AA8D)
+            btnLbl.align(dxui.Utils.ALIGN.CENTER, 0, 0)
+
+            const btnEdit = dxui.Button.build(item.title + 'edit', userBox)
+            item.btnEdit = btnEdit
+            btnEdit.setSize(150, 50)
+            btnEdit.align(dxui.Utils.ALIGN.RIGHT_MID, -60, 0)
+            btnEdit.bgColor(0xEEEEEE)
+            btnEdit.radius(10)
+            btnEdit.hide()
+            const btnEditLbl = dxui.Label.build(item.title + 'btnEditLbl', btnEdit)
+            btnEditLbl.textFont(viewUtils.font(22))
+            btnEditLbl.textColor(0x05AA8D)
+            btnEditLbl.align(dxui.Utils.ALIGN.CENTER, 0, 0)
+
+            const deleteBtn = viewUtils.imageBtn(userBox, item.title + 'deleteBtn', '/app/code/resource/image/delete.png')
+            item.deleteBtn = deleteBtn
+            deleteBtn.align(dxui.Utils.ALIGN.RIGHT_MID, 0, 0)
+            deleteBtn.hide()
+
+            if (item.title === 'localUserAddView.pwd') {
+                btnLbl.dataI18n = 'localUserAddView.generate'
+                btnEditLbl.dataI18n = 'localUserAddView.reset'
+
+                // 瀵嗙爜
+                const pwdLbl = dxui.Label.build(userBox.id + 'pwdLbl', userBox)
+                item.pwdLbl = pwdLbl
+                pwdLbl.align(dxui.Utils.ALIGN.LEFT_MID, 180, 0)
+                pwdLbl.textColor(0x767676)
+                pwdLbl.textFont(viewUtils.font(26))
+                pwdLbl.hide()
+
+                btn.on(dxui.Utils.EVENT.CLICK, () => {
+                    pwdBoxBg.show()
+                    pwdBoxBg.moveForeground()
+                    topView.changeTheme(false)
+                    localUserAddView.changePwd()
+                })
+
+                btnEdit.on(dxui.Utils.EVENT.CLICK, () => {
+                    btn.send(dxui.Utils.EVENT.CLICK)
+                })
+
+                deleteBtn.on(dxui.Utils.EVENT.CLICK, () => {
+                    viewUtils.confirmOpen('localUserAddView.confirm', 'localUserAddView.confirmPwd', () => {
+                        localUserAddView.removePwd()
+                    }, () => { })
+                })
+
+            } else {
+                btnLbl.dataI18n = 'localUserAddView.enter'
+                btnEditLbl.dataI18n = 'localUserAddView.edit'
+            }
+
+            if (item.title === 'localUserAddView.card') {
+                // 鍗�
+                const cardLbl = dxui.Label.build(userBox.id + 'cardLbl', userBox)
+                item.cardLbl = cardLbl
+                cardLbl.align(dxui.Utils.ALIGN.LEFT_MID, 180, 0)
+                cardLbl.textColor(0x767676)
+                cardLbl.textFont(viewUtils.font(26))
+                cardLbl.hide()
+                cardLbl.longMode(dxui.Utils.LABEL_LONG_MODE.SCROLL_CIRCULAR)
+                cardLbl.width(150)
+
+                btn.on(dxui.Utils.EVENT.CLICK, () => {
+                    cardBoxBg.show()
+                    cardBoxBg.moveForeground()
+                    topView.changeTheme(false)
+                    // 寮�鍚埛鍗¤瘑鍒�
+                    screen.getCardStart()
+                })
+
+                btnEdit.on(dxui.Utils.EVENT.CLICK, () => {
+                    btn.send(dxui.Utils.EVENT.CLICK)
+                })
+
+                deleteBtn.on(dxui.Utils.EVENT.CLICK, () => {
+                    viewUtils.confirmOpen('localUserAddView.confirm', 'localUserAddView.confirmCard', () => {
+                        localUserAddView.removeCard()
+                    }, () => { })
+                })
+            }
+
+            if (item.title === 'localUserAddView.face') {
+                // userBox.height(220)
+                btn.on(dxui.Utils.EVENT.CLICK, () => {
+                    if (!checkRequired()) {
+                        return
+                    }
+                    dxui.loadMain(faceEnterView.screenMain)
+                })
+
+                btnEdit.on(dxui.Utils.EVENT.CLICK, () => {
+                    if (!checkRequired()) {
+                        return
+                    }
+                    dxui.loadMain(faceEnterView.screenMain)
+                })
+
+                // 浜鸿劯鍥剧墖
+                const facePreview = dxui.Button.build('facePreview', userBox)
+                item.facePreview = facePreview
+                facePreview.bgColor(0x000000)
+                facePreview.align(dxui.Utils.ALIGN.LEFT_MID, 180, 0)
+                const facePreviewLbl = dxui.Label.build('facePreviewLbl', facePreview)
+                facePreviewLbl.textFont(viewUtils.font(22))
+                facePreviewLbl.dataI18n = "localUserAddView.preview"
+                facePreview.on(dxui.Utils.EVENT.CLICK, () => {
+                    facePreviewBox.show()
+                    facePreviewBox.moveForeground()
+                })
+
+                const facePreviewBox = dxui.View.build('facePreviewBox', screenMain)
+                viewUtils._clearStyle(facePreviewBox)
+                facePreviewBox.hide()
+                facePreviewBox.setSize(screenMain.width(), screenMain.height())
+                facePreviewBox.on(dxui.Utils.EVENT.CLICK, () => {
+                    facePreviewBox.hide()
+                })
+
+                const faceImg = dxui.Image.build('faceImg', facePreviewBox)
+                faceImg.align(dxui.Utils.ALIGN.CENTER, 0, 0)
+                item.faceImg = faceImg
+
+
+                deleteBtn.on(dxui.Utils.EVENT.CLICK, () => {
+                    if (!checkRequired()) {
+                        return
+                    }
+                    viewUtils.confirmOpen('localUserAddView.confirm', 'localUserAddView.confirmFace', () => {
+                        localUserAddView.removeFace()
+                    }, () => { })
+                })
+            }
+        } else if (item.type === 'dropdown') {
+            const dropdown = dxui.Dropdown.build(item.title, userBox)
+            item.dropdown = dropdown
+            dropdown.setSize(260, 50)
+            dropdown.align(dxui.Utils.ALIGN.RIGHT_MID, 0, 0)
+            dropdown.textFont(viewUtils.font(22))
+            dropdown.getList().textFont(viewUtils.font(22))
+            dropdown.setSymbol('/app/code/resource/image/down.png')
+            dropdown.on(dxui.Utils.EVENT.VALUE_CHANGED, () => {
+                localUserAddView.nowUser.type = dropdown.getSelected()
+            })
+        }
+    })
+
+    // 瀵嗙爜鐢熸垚椤�
+    const pwdBoxBg = dxui.View.build('pwdBoxBg', screenMain)
+    viewUtils._clearStyle(pwdBoxBg)
+    pwdBoxBg.bgColor(0x000000)
+    pwdBoxBg.bgOpa(50)
+    pwdBoxBg.setSize(screen.screenSize.width, screen.screenSize.height)
+    pwdBoxBg.scroll(false)
+    pwdBoxBg.hide()
+    pwdBoxBg.on(dxui.Utils.EVENT.CLICK, () => {
+        pwdBoxCloseBtn.send(dxui.Utils.EVENT.CLICK)
+    })
+
+    const pwdBox = dxui.View.build('pwdBox', pwdBoxBg)
+    viewUtils._clearStyle(pwdBox)
+    pwdBox.setSize(screen.screenSize.width, 694)
+    pwdBox.align(dxui.Utils.ALIGN.BOTTOM_MID, 0, 50)
+    pwdBox.bgColor(0xffffff)
+    pwdBox.radius(50)
+
+    const pwdBoxLbl = dxui.Label.build('pwdBoxLbl', pwdBox)
+    pwdBoxLbl.dataI18n = 'localUserAddView.pwdBoxLbl'
+    pwdBoxLbl.textFont(viewUtils.font(36))
+    pwdBoxLbl.align(dxui.Utils.ALIGN.TOP_MID, 0, 39)
+
+    const pwdBoxCloseBtn = viewUtils.imageBtn(pwdBox, 'pwdBoxCloseBtn', '/app/code/resource/image/close_small.png')
+    pwdBoxCloseBtn.align(dxui.Utils.ALIGN.TOP_RIGHT, -55, 18)
+    pwdBoxCloseBtn.on(dxui.Utils.EVENT.CLICK, () => {
+        pwdBoxBg.hide()
+        topView.changeTheme(true)
+    })
+
+    const pwdBoxContent = dxui.View.build('pwdBoxContent', pwdBox)
+    viewUtils._clearStyle(pwdBoxContent)
+    pwdBoxContent.setSize(650, 100)
+    pwdBoxContent.align(dxui.Utils.ALIGN.TOP_MID, 0, 172)
+    pwdBoxContent.flexFlow(dxui.Utils.FLEX_FLOW.ROW_WRAP)
+    pwdBoxContent.flexAlign(dxui.Utils.FLEX_ALIGN.SPACE_AROUND, dxui.Utils.FLEX_ALIGN.CENTER, dxui.Utils.FLEX_ALIGN.CENTER)
+
+    localUserAddView.pwdBoxContentItem = []
+    for (let i = 0; i < 6; i++) {
+        const pwdBoxContentItem = dxui.View.build('pwdBoxContentItem' + i, pwdBoxContent)
+        pwdBoxContentItem.setSize(78, 90)
+        pwdBoxContentItem.radius(13)
+        pwdBoxContentItem.borderWidth(1)
+        pwdBoxContentItem.setBorderColor(0xEAEAEA)
+
+        const pwdBoxContentItemLbl = dxui.Label.build('pwdBoxContentItemLbl' + i, pwdBoxContentItem)
+        pwdBoxContentItemLbl.textFont(viewUtils.font(30))
+        pwdBoxContentItemLbl.align(dxui.Utils.ALIGN.CENTER, 0, 0)
+        pwdBoxContentItemLbl.text('0')
+        localUserAddView.pwdBoxContentItem.push(pwdBoxContentItemLbl)
+    }
+
+    const pwdBoxSaveBtn = dxui.Button.build('pwdBoxSaveBtn', pwdBox)
+    pwdBoxSaveBtn.setSize(210, 60)
+    pwdBoxSaveBtn.align(dxui.Utils.ALIGN.TOP_LEFT, 87, 340)
+    pwdBoxSaveBtn.bgColor(0xEAEAEA)
+    pwdBoxSaveBtn.radius(10)
+    pwdBoxSaveBtn.on(dxui.Utils.EVENT.CLICK, () => {
+        localUserAddView.changePwd()
+    })
+
+    const pwdBoxSaveBtnLbl = dxui.Label.build('pwdBoxSaveBtnLbl', pwdBoxSaveBtn)
+    pwdBoxSaveBtnLbl.dataI18n = 'localUserAddView.pwdBoxSaveBtnLbl'
+    pwdBoxSaveBtnLbl.textFont(viewUtils.font(24))
+    pwdBoxSaveBtnLbl.align(dxui.Utils.ALIGN.CENTER, 0, 0)
+    pwdBoxSaveBtnLbl.textColor(0x000000)
+
+    const pwdBoxConfirmBtn = dxui.Button.build('pwdBoxConfirmBtn', pwdBox)
+    pwdBoxConfirmBtn.setSize(210, 60)
+    pwdBoxConfirmBtn.align(dxui.Utils.ALIGN.TOP_RIGHT, -76, 340)
+    pwdBoxConfirmBtn.bgColor(0x000000)
+    pwdBoxConfirmBtn.radius(10)
+    pwdBoxConfirmBtn.on(dxui.Utils.EVENT.CLICK, () => {
+        localUserAddView.addPwd(localUserAddView.pwdBoxContentFin)
+        pwdBoxCloseBtn.send(dxui.Utils.EVENT.CLICK)
+    })
+
+    const pwdBoxConfirmBtnLbl = dxui.Label.build('pwdBoxConfirmBtnLbl', pwdBoxConfirmBtn)
+    pwdBoxConfirmBtnLbl.dataI18n = 'localUserAddView.pwdBoxConfirmBtnLbl'
+    pwdBoxConfirmBtnLbl.textFont(viewUtils.font(24))
+    pwdBoxConfirmBtnLbl.align(dxui.Utils.ALIGN.CENTER, 0, 0)
+
+    // 璇诲彇鍗$墖涓�
+    const cardBoxBg = dxui.View.build('cardBoxBg', screenMain)
+    viewUtils._clearStyle(cardBoxBg)
+    cardBoxBg.setSize(screen.screenSize.width, screen.screenSize.height)
+    cardBoxBg.align(dxui.Utils.ALIGN.TOP_MID, 0, 0)
+    cardBoxBg.bgColor(0x000000)
+    cardBoxBg.bgOpa(50)
+    cardBoxBg.scroll(false)
+    cardBoxBg.hide()
+    cardBoxBg.on(dxui.Utils.EVENT.CLICK, () => {
+        cardBoxCloseBtn.send(dxui.Utils.EVENT.CLICK)
+    })
+
+    const cardBox = dxui.View.build('cardBox', cardBoxBg)
+    viewUtils._clearStyle(cardBox)
+    cardBox.setSize(screen.screenSize.width, 694)
+    cardBox.align(dxui.Utils.ALIGN.BOTTOM_MID, 0, 50)
+    cardBox.bgColor(0xffffff)
+    cardBox.radius(50)
+    cardBox.on(dxui.Utils.EVENT.CLICK, () => {
+    })
+
+    const cardBoxLbl = dxui.Label.build('cardBoxLbl', cardBox)
+    cardBoxLbl.dataI18n = 'localUserAddView.cardBoxLbl'
+    cardBoxLbl.textFont(viewUtils.font(36))
+    cardBoxLbl.align(dxui.Utils.ALIGN.TOP_MID, 0, 39)
+
+    const cardBoxCloseBtn = viewUtils.imageBtn(cardBox, 'cardBoxCloseBtn', '/app/code/resource/image/close_small.png')
+    cardBoxCloseBtn.align(dxui.Utils.ALIGN.TOP_RIGHT, -55, 18)
+    cardBoxCloseBtn.on(dxui.Utils.EVENT.CLICK, () => {
+        cardBoxBg.hide()
+        topView.changeTheme(true)
+        // 鍏抽棴鍒峰崱璇嗗埆
+        screen.endCardEnd()
+    })
+
+    const cardBoxInput = viewUtils.input(cardBox, 'localUserAddView.cardBoxInput', undefined, undefined, 'localUserAddView.cardBoxInput')
+    localUserAddView.cardBoxInput = cardBoxInput
+    cardBoxInput.align(dxui.Utils.ALIGN.TOP_MID, 0, 183)
+    cardBoxInput.setSize(630, 75)
+    cardBoxInput.on(dxui.Utils.EVENT.CLICK, () => {
+        cardBoxInput.align(dxui.Utils.ALIGN.TOP_MID, 0, 90)
+        pinyin.hideCb(() => {
+            cardBoxInput.align(dxui.Utils.ALIGN.TOP_MID, 0, 183)
+        })
+    })
+
+    const cardBoxResetBtn = dxui.Button.build('cardBoxResetBtn', cardBox)
+    cardBoxResetBtn.setSize(210, 60)
+    cardBoxResetBtn.align(dxui.Utils.ALIGN.TOP_LEFT, 87, 340)
+    cardBoxResetBtn.bgColor(0xEAEAEA)
+    cardBoxResetBtn.radius(10)
+    cardBoxResetBtn.on(dxui.Utils.EVENT.CLICK, () => {
+        cardBoxInput.text('')
+    })
+
+    const cardBoxResetBtnLbl = dxui.Label.build('cardBoxResetBtnLbl', cardBoxResetBtn)
+    cardBoxResetBtnLbl.dataI18n = 'localUserAddView.cardBoxResetBtnLbl'
+    cardBoxResetBtnLbl.textFont(viewUtils.font(24))
+    cardBoxResetBtnLbl.align(dxui.Utils.ALIGN.CENTER, 0, 0)
+    cardBoxResetBtnLbl.textColor(0x000000)
+
+    const cardBoxSaveBtn = dxui.Button.build('cardBoxSaveBtn', cardBox)
+    cardBoxSaveBtn.setSize(210, 60)
+    cardBoxSaveBtn.align(dxui.Utils.ALIGN.TOP_RIGHT, -76, 340)
+    cardBoxSaveBtn.bgColor(0x000000)
+    cardBoxSaveBtn.radius(10)
+    cardBoxSaveBtn.on(dxui.Utils.EVENT.CLICK, () => {
+        cardBoxCloseBtn.send(dxui.Utils.EVENT.CLICK)
+        if (cardBoxInput.text()) {
+            localUserAddView.addCard(cardBoxInput.text())
+        }
+    })
+
+    const cardBoxSaveBtnLbl = dxui.Label.build('cardBoxSaveBtnLbl', cardBoxSaveBtn)
+    cardBoxSaveBtnLbl.dataI18n = 'localUserAddView.cardBoxSaveBtnLbl'
+    cardBoxSaveBtnLbl.textFont(viewUtils.font(24))
+    cardBoxSaveBtnLbl.align(dxui.Utils.ALIGN.CENTER, 0, 0)
+
+    const deleteBtn = viewUtils.bottomBtn(screenMain, screenMain.id + 'deleteBtn', 'localUserAddView.delete', () => {
+        if (!checkRequired()) {
+            return
+        }
+
+        viewUtils.confirmOpen('localUserAddView.confirmDelete', 'localUserAddView.confirmDeleteContent', () => {
+            // 鍒犻櫎鐢ㄦ埛
+            const res = screen.deleteUser(localUserAddView.nowUser)
+            if (res) {
+                dxui.loadMain(localUserView.screenMain)
+            } else {
+                localUserAddView.statusPanel.fail()
+            }
+        }, () => { })
+
+    }, 0xEAEAEA, 0xEA0000)
+    deleteBtn.align(dxui.Utils.ALIGN.BOTTOM_MID, 0, -200)
+    localUserAddView.deleteBtn = deleteBtn
+    deleteBtn.hide()
+
+    const saveBtn = viewUtils.bottomBtn(screenMain, screenMain.id + 'saveBtn', 'localUserAddView.save', async () => {
+        if (!checkRequired()) {
+            return
+        }
+        let res = false
+        if (localUserAddView.deleteBtn.isHide()) {
+            // 鏂板鐢ㄦ埛
+            res = await screen.insertUser(localUserAddView.nowUser)
+        } else {
+            // 淇敼鐢ㄦ埛
+            res = screen.updateUser(localUserAddView.nowUser)
+        }
+
+        if (res === true) {
+            localUserAddView.statusPanel.success()
+            std.setTimeout(() => {
+                // 鎴愬姛杩斿洖涓婁竴灞傜晫闈�
+                dxui.loadMain(localUserView.screenMain)
+            }, 500)
+        } else {
+            if (typeof res === "string") {
+                localUserAddView.statusPanel.fail(res)
+            } else {
+                localUserAddView.statusPanel.fail()
+            }
+        }
+    })
+    saveBtn.align(dxui.Utils.ALIGN.BOTTOM_MID, 0, -83)
+    localUserAddView.saveBtn = saveBtn
+
+    localUserAddView.statusPanel = viewUtils.statusPanel(screenMain, 'localUserAddView.success', 'localUserAddView.fail')
+}
+
+localUserAddView.addID = function (id) {
+    localUserAddView.userInfo[0].input.text(id)
+    localUserAddView.nowUser.id = id
+}
+
+localUserAddView.removeID = function () {
+    localUserAddView.userInfo[0].input.text('')
+}
+
+localUserAddView.addName = function (name) {
+    localUserAddView.userInfo[1].input.text(name)
+    localUserAddView.nowUser.name = name
+}
+
+localUserAddView.removeName = function () {
+    localUserAddView.userInfo[1].input.text('')
+}
+
+localUserAddView.addIDCard = function (idCard) {
+    localUserAddView.userInfo[2].input.text(idCard)
+    localUserAddView.nowUser.idCard = idCard
+}
+
+localUserAddView.removeIDCard = function () {
+    localUserAddView.userInfo[2].input.text('')
+}
+
+localUserAddView.addFace = function (face) {
+    localUserAddView.userInfo[3].btnEdit.show()
+    localUserAddView.userInfo[3].btn.hide()
+
+    const faceImg = localUserAddView.userInfo[3].faceImg
+    faceImg.source(face)
+    faceImg.show()
+
+    // let header = dxui.Utils.GG.NativeDraw.lvImgDecoderGetInfo(face)
+    // let zoom = 60 / header.h * 256
+    // faceImg.obj.lvImgSetZoom(zoom)
+    // faceImg.obj.lvImgSetSizeMode(dxui.Utils.ENUM.LV_IMG_SIZE_MODE_REAL)
+    // faceImg.setSize(Math.ceil(zoom / 256 * header.w), 60)
+
+    localUserAddView.userInfo[3].deleteBtn.show()
+    localUserAddView.nowUser.face = face
+}
+
+localUserAddView.removeFace = function () {
+    localUserAddView.userInfo[3].btn.show()
+    localUserAddView.userInfo[3].btnEdit.hide()
+    localUserAddView.userInfo[3].deleteBtn.hide()
+    localUserAddView.userInfo[3].faceImg.hide()
+    if (localUserAddView.nowUser && localUserAddView.nowUser.face) {
+        delete localUserAddView.nowUser.face
+    }
+}
+
+localUserAddView.addPwd = function (pwd) {
+    localUserAddView.userInfo[4].btn.hide()
+    localUserAddView.userInfo[4].btnEdit.show()
+    localUserAddView.userInfo[4].deleteBtn.show()
+    localUserAddView.userInfo[4].pwdLbl.show()
+    localUserAddView.userInfo[4].pwdLbl.text(pwd)
+    localUserAddView.nowUser.pwd = pwd
+}
+
+localUserAddView.removePwd = function () {
+    localUserAddView.userInfo[4].btn.show()
+    localUserAddView.userInfo[4].btnEdit.hide()
+    localUserAddView.userInfo[4].deleteBtn.hide()
+    localUserAddView.userInfo[4].pwdLbl.hide()
+    if (localUserAddView.nowUser && localUserAddView.nowUser.pwd) {
+        delete localUserAddView.nowUser.pwd
+    }
+}
+
+localUserAddView.addCard = function (card) {
+    localUserAddView.userInfo[5].btn.hide()
+    localUserAddView.userInfo[5].btnEdit.show()
+    localUserAddView.userInfo[5].deleteBtn.show()
+    localUserAddView.userInfo[5].cardLbl.show()
+    localUserAddView.userInfo[5].cardLbl.text(card)
+    localUserAddView.nowUser.card = card
+}
+
+localUserAddView.removeCard = function () {
+    localUserAddView.userInfo[5].btn.show()
+    localUserAddView.userInfo[5].btnEdit.hide()
+    localUserAddView.userInfo[5].deleteBtn.hide()
+    localUserAddView.userInfo[5].cardLbl.hide()
+    if (localUserAddView.nowUser && localUserAddView.nowUser.card) {
+        delete localUserAddView.nowUser.card
+    }
+}
+
+localUserAddView.addType = function (type) {
+    localUserAddView.userInfo[6].dropdown.setSelected(type)
+}
+
+localUserAddView.changePwd = function () {
+    const randomPwd = Math.floor(Math.random() * 900000 + 100000).toString()
+    localUserAddView.pwdBoxContentFin = randomPwd
+    localUserAddView.pwdBoxContentItem.forEach((item, index) => {
+        item.text(randomPwd[index])
+    })
+}
+
+localUserAddView.isEdit = function (flag) {
+    localUserAddView.removeFace()
+    localUserAddView.removePwd()
+    localUserAddView.removeCard()
+    localUserAddView.removeID()
+    localUserAddView.removeName()
+    localUserAddView.removeIDCard()
+    if (flag) {
+        localUserAddView.saveBtn.align(dxui.Utils.ALIGN.BOTTOM_MID, 0, -53)
+        localUserAddView.deleteBtn.show()
+        localUserAddView.titleBox2.show()
+    } else {
+        localUserAddView.saveBtn.align(dxui.Utils.ALIGN.BOTTOM_MID, 0, -83)
+        localUserAddView.deleteBtn.hide()
+        localUserAddView.titleBox2.hide()
+        localUserAddView.nowUser = {}
+    }
+}
+
+// 妫�鏌ュ繀濉」
+function checkRequired() {
+    if (!localUserAddView.userInfo[0].input.text()) {
+        localUserAddView.statusPanel.fail("localUserAddView.requiredInfo")
+        return false
+    }
+    if (!localUserAddView.userInfo[1].input.text()) {
+        localUserAddView.statusPanel.fail("localUserAddView.requiredInfo")
+        return false
+    }
+    return true
+}
+
+function refreshType() {
+    switch (screen.getConfig()['base.language']) {
+        case 'CN':
+            localUserAddView.userInfo[6].dropdown.setOptions(dropdownData)
+            break;
+        case 'EN':
+            localUserAddView.userInfo[6].dropdown.setOptions(dropdownData2)
+            break;
+        default:
+            break;
+    }
+}
+
+export default localUserAddView
diff --git a/vf205_access/src/view/config/menu/localUserView.js b/vf205_access/src/view/config/menu/localUserView.js
new file mode 100644
index 0000000..3c0d986
--- /dev/null
+++ b/vf205_access/src/view/config/menu/localUserView.js
@@ -0,0 +1,315 @@
+import dxui from '../../../../dxmodules/dxUi.js'
+import viewUtils from "../../viewUtils.js"
+import topView from "../../topView.js"
+import configView from '../configView.js'
+import pinyin from '../../pinyin/pinyin.js'
+import localUserAddView from './localUser/localUserAddView.js'
+import faceEnterView from './localUser/faceEnterView.js'
+import screen from '../../../screen.js'
+const localUserView = {}
+localUserView.init = function () {
+    /**************************************************鍒涘缓灞忓箷*****************************************************/
+    const screenMain = dxui.View.build('localUserView', dxui.Utils.LAYER.MAIN)
+    localUserView.screenMain = screenMain
+    screenMain.scroll(false)
+    screenMain.bgColor(0xffffff)
+    screenMain.on(dxui.Utils.ENUM.LV_EVENT_SCREEN_LOADED, () => {
+        topView.changeTheme(true)
+
+        localUserView.nowPage = localUserView.nowPage ? localUserView.nowPage : 0
+        let users = screen.getUsers(localUserView.nowPage, 6)
+        while (users.data.length == 0 && localUserView.nowPage > 0) {
+            localUserView.nowPage -= 1
+            users = screen.getUsers(localUserView.nowPage, 6)
+        }
+        if (users.data.length > 0) {
+            // localUserView.initData([{ id: "1", name: '寮犱笁' }, { id: "2", name: '鏉庡洓' }, { id: "3", name: '鐜嬩簲' }, { id: "4", name: '璧靛叚' }, { id: "5", name: '瀛欎竷' }, { id: "6", name: '鍛ㄥ叓' }, { id: "7", name: '鍚翠節' }, { id: "8", name: '閮戝崄' }, { id: "9", name: '闄堝崄涓�' }, { id: "10", name: '璧靛崄浜�' }, { id: "11", name: '瀛欏崄涓�' }, { id: "12", name: '鍛ㄥ崄鍥�' }, { id: "13", name: '鍚村崄浜�' }, { id: "14", name: '閮戝崄鍏�' }, { id: "15", name: '闄堝崄涓�' }, { id: "16", name: '璧靛崄鍏�' }, { id: "17", name: '瀛欏崄涔�' }, { id: "20", name: '鍛ㄤ簩鍗�' },])
+            localUserView.initData(users.data)
+        } else {
+            localUserView.initData()
+        }
+        // 鍒锋柊鍒嗛〉淇℃伅
+        refreshPageInfo(users)
+    })
+
+    const titleBox = viewUtils.title(screenMain, configView.screenMain, 'localUserViewTitle', 'localUserView.title', () => { localUserView.nowPage = 0 })
+    titleBox.align(dxui.Utils.ALIGN.TOP_MID, 0, 70)
+
+    const empty = dxui.Image.build('empty', screenMain)
+    localUserView.empty = empty
+    empty.align(dxui.Utils.ALIGN.TOP_MID, 0, 218)
+    empty.source('/app/code/resource/image/empty.png')
+
+    const emptyLbl = dxui.Label.build('emptyLbl', screenMain)
+    localUserView.emptyLbl = emptyLbl
+    emptyLbl.textFont(viewUtils.font(26))
+    emptyLbl.align(dxui.Utils.ALIGN.TOP_MID, 0, 479)
+    emptyLbl.dataI18n = 'localUserView.empty'
+    emptyLbl.textColor(0x888888)
+
+    const userList = dxui.View.build('userList', screenMain)
+    viewUtils._clearStyle(userList)
+    localUserView.userList = userList
+    userList.setSize(screen.screenSize.width, 570)
+    userList.align(dxui.Utils.ALIGN.TOP_MID, 0, 142)
+    userList.flexFlow(dxui.Utils.FLEX_FLOW.ROW_WRAP)
+    userList.flexAlign(dxui.Utils.FLEX_ALIGN.START, dxui.Utils.FLEX_ALIGN.START, dxui.Utils.FLEX_ALIGN.START)
+    userList.obj.lvObjSetStylePadGap(5, dxui.Utils.ENUM._LV_STYLE_STATE_CMP_SAME)
+    userList.hide()
+
+    const searchBox = dxui.View.build('searchBox', userList)
+    viewUtils._clearStyle(searchBox)
+    searchBox.setSize(screen.screenSize.width, 76)
+    searchBox.bgOpa(0)
+    searchBox.borderWidth(1)
+    searchBox.setBorderColor(0xDEDEDE)
+    searchBox.obj.setStyleBorderSide(dxui.Utils.ENUM.LV_BORDER_SIDE_BOTTOM, 0)
+
+    const searchInput = viewUtils.input(searchBox, 'searchBoxInput', undefined, () => {
+    }, 'localUserView.search')
+    searchInput.setSize(screen.screenSize.width / 2, 60)
+    searchInput.align(dxui.Utils.ALIGN.LEFT_MID, 28, 0)
+
+    const searchBtn = dxui.Button.build('searchBtn', searchBox)
+    searchBtn.setSize(126, 44)
+    searchBtn.align(dxui.Utils.ALIGN.RIGHT_MID, -29, 0)
+    searchBtn.bgColor(0xF6FAFA)
+    searchBtn.radius(10)
+
+    searchBtn.on(dxui.Utils.EVENT.CLICK, () => {
+        const users = screen.getUsers(0, 6, searchInput.text(), searchInput.text())
+        if (users.data) {
+            localUserView.initData(users.data)
+        } else {
+            localUserView.initData([])
+        }
+        // pinyin.hide()
+    })
+
+    const searchBtnLbl = dxui.Label.build('searchBtnLbl', searchBtn)
+    searchBtnLbl.dataI18n = 'localUserView.searchBtn'
+    searchBtnLbl.textFont(viewUtils.font(26))
+    searchBtnLbl.textColor(0x05AA8D)
+    searchBtnLbl.align(dxui.Utils.ALIGN.CENTER, 0, 0)
+
+    localUserView.userItemList = []
+    for (let i = 0; i < 6; i++) {
+        const userItem = dxui.View.build('userItem' + i, userList)
+        viewUtils._clearStyle(userItem)
+        userItem.setSize(screen.screenSize.width, 76)
+        userItem.align(dxui.Utils.ALIGN.TOP_MID, 0, 0)
+        userItem.bgOpa(0)
+        userItem.borderWidth(1)
+        userItem.setBorderColor(0xDEDEDE)
+        userItem.obj.setStyleBorderSide(dxui.Utils.ENUM.LV_BORDER_SIDE_BOTTOM, 0)
+        userItem.hide()
+
+        const userItemId0 = dxui.Label.build('userItemId0' + i, userItem)
+        userItemId0.text('ID锛�')
+        userItemId0.textFont(viewUtils.font(26))
+        userItemId0.align(dxui.Utils.ALIGN.LEFT_MID, 28, 0)
+
+        const userItemId = dxui.Label.build('userItemId' + i, userItem)
+        userItemId.text(i + '')
+        userItemId.textFont(viewUtils.font(26))
+        userItemId.align(dxui.Utils.ALIGN.LEFT_MID, 80, 0)
+        userItemId.width(100)
+        userItemId.longMode(dxui.Utils.LABEL_LONG_MODE.SCROLL_CIRCULAR)
+
+        const userItemName = dxui.Label.build('userItemName' + i, userItem)
+        userItemName.text('')
+        userItemName.textFont(viewUtils.font(26))
+        userItemName.align(dxui.Utils.ALIGN.LEFT_MID, 220, 0)
+        userItemName.width(200)
+        userItemName.longMode(dxui.Utils.LABEL_LONG_MODE.SCROLL_CIRCULAR)
+
+        const userItemEdit = dxui.Button.build('userItemEdit' + i, userItem)
+        userItemEdit.setSize(126, 44)
+        userItemEdit.align(dxui.Utils.ALIGN.RIGHT_MID, -29, 0)
+        userItemEdit.bgColor(0xF6FAFA)
+        userItemEdit.radius(10)
+
+        userItemEdit.on(dxui.Utils.EVENT.CLICK, () => {
+            localUserAddView.isEdit(true)
+            dxui.loadMain(localUserAddView.screenMain)
+
+            let item = localUserView.userData.filter(item => {
+                return item.id === userItemId.text().replace('ID锛�', '')
+            })
+            if (item) {
+                item = item[0]
+                const voucher = screen.getVoucher(item.id)
+                Object.assign(item, voucher);
+                localUserAddView.nowUser = item
+
+                if (item.id) {
+                    localUserAddView.addID(item.id)
+                }
+                if (item.name) {
+                    localUserAddView.addName(item.name)
+                }
+                if (item.idCard) {
+                    localUserAddView.addIDCard(item.idCard)
+                }
+                if (item.face) {
+                    localUserAddView.addFace(item.face)
+                }
+                if (item.pwd) {
+                    localUserAddView.addPwd(item.pwd)
+                }
+                if (item.card) {
+                    localUserAddView.addCard(item.card)
+                }
+                localUserAddView.addType(item.type)
+            }
+        })
+
+        const userItemEditLbl = dxui.Label.build('userItemEditLbl' + i, userItemEdit)
+        userItemEditLbl.dataI18n = 'localUserView.edit'
+        userItemEditLbl.textFont(viewUtils.font(26))
+        userItemEditLbl.textColor(0x05AA8D)
+        userItemEditLbl.align(dxui.Utils.ALIGN.CENTER, 0, 0)
+
+        localUserView.userItemList.push({ userItem, userItemId, userItemName })
+    }
+
+    const pageNextBtn = dxui.Button.build('pageNextBtn', screenMain)
+    pageNextBtn.bgColor(0x000000)
+    localUserView.pageNextBtn = pageNextBtn
+    const pageNextLbl = dxui.Label.build('pageNextLbl', pageNextBtn)
+    pageNextLbl.text("鈫�")
+    pageNextBtn.align(dxui.Utils.ALIGN.BOTTOM_RIGHT, -20, -372)
+    pageNextBtn.textFont(viewUtils.font(20))
+    const pagePrevBtn = dxui.Button.build('pagePrevBtn', screenMain)
+    pagePrevBtn.bgColor(0x000000)
+    localUserView.pagePrevBtn = pagePrevBtn
+    const pagePrevLbl = dxui.Label.build('pagePrevLbl', pagePrevBtn)
+    pagePrevLbl.text("鈫�")
+    pagePrevBtn.align(dxui.Utils.ALIGN.BOTTOM_LEFT, 20, -372)
+    pagePrevBtn.textFont(viewUtils.font(20))
+
+    pageNextBtn.on(dxui.Utils.EVENT.CLICK, () => {
+        if (!localUserView.nowPage) {
+            localUserView.nowPage = 0
+        }
+        localUserView.pageNum += 1
+        const users = screen.getUsers(localUserView.pageNum, 6)
+        if (users.data) {
+            localUserView.initData(users.data)
+        } else {
+            localUserView.initData([])
+        }
+        refreshPageInfo(users)
+    })
+    pagePrevBtn.on(dxui.Utils.EVENT.CLICK, () => {
+        if (!localUserView.nowPage) {
+            localUserView.nowPage = 0
+        }
+        localUserView.pageNum -= 1
+        const users = screen.getUsers(localUserView.pageNum, 6)
+        if (users.data) {
+            localUserView.initData(users.data)
+        } else {
+            localUserView.initData([])
+        }
+        refreshPageInfo(users)
+    })
+
+    const pageSelect = dxui.Dropdown.build('pageSelect', screenMain)
+    localUserView.pageSelect = pageSelect
+    pageSelect.textFont(viewUtils.font(22))
+    pageSelect.getList().textFont(viewUtils.font(22))
+    pageSelect.setSize(150, 55)
+    pageSelect.setSymbol('/app/code/resource/image/down.png')
+    pageSelect.align(dxui.Utils.ALIGN.BOTTOM_MID, 0, -370)
+    pageSelect.on(dxui.Utils.EVENT.VALUE_CHANGED, () => {
+        localUserView.pageNum = pageSelect.getSelected()
+        const users = screen.getUsers(localUserView.pageNum, 6)
+        if (users.data) {
+            localUserView.initData(users.data)
+        } else {
+            localUserView.initData([])
+        }
+        refreshPageInfo(users)
+    })
+
+    const syncBtn = viewUtils.bottomBtn(screenMain, screenMain.id + 'syncBtn', 'localUserView.sync', () => {
+    }, 0xEAEAEA, 0x000000)
+    syncBtn.align(dxui.Utils.ALIGN.BOTTOM_MID, 0, -204)
+    localUserView.syncBtn = syncBtn
+    syncBtn.hide()
+
+    syncBtn.on(dxui.Utils.EVENT.CLICK, () => {
+        viewUtils.confirmOpen('localUserView.attention', 'localUserView.attentionContent', () => {
+            viewUtils.confirmOpen('localUserView.tip', 'localUserView.tipContent')
+        })
+    })
+
+    const addBtn = viewUtils.bottomBtn(screenMain, screenMain.id + 'addBtn', 'localUserView.add', () => {
+        localUserAddView.isEdit(false)
+        dxui.loadMain(localUserAddView.screenMain)
+    })
+    addBtn.align(dxui.Utils.ALIGN.BOTTOM_MID, 0, -83)
+}
+
+localUserView.initData = function (data) {
+    // 褰撳墠椤电殑浜哄憳淇℃伅
+    localUserView.userData = data
+    localUserView.refresh(data)
+}
+
+localUserView.refresh = function (data) {
+    if (data === undefined || data === null) {
+        localUserView.empty.show()
+        localUserView.emptyLbl.show()
+        localUserView.syncBtn.hide()
+        localUserView.userList.hide()
+        return
+    }
+
+    localUserView.userItemList.forEach(item => {
+        item.userItem.hide()
+    })
+
+    // 娓叉煋浜哄憳鍒楄〃
+    data.forEach((item, index) => {
+        if (index >= localUserView.userItemList.length) {
+            return
+        }
+        localUserView.userItemList[index].userItemId.text(item.id)
+        // 鏄剧ず濮撳悕鍜屼汉鍛樼被鍨�
+        let typeText = item.type == 1 ? '锛堜繚绠″憳锛�' : item.type == 2 ? '锛堢闀匡級' : ''
+        localUserView.userItemList[index].userItemName.text(item.name + typeText)
+        localUserView.userItemList[index].userItem.show()
+    })
+
+    localUserView.empty.hide()
+    localUserView.emptyLbl.hide()
+    // localUserView.syncBtn.show()
+    localUserView.userList.show()
+}
+
+function refreshPageInfo(users) {
+    if (users.currentPage == 1) {
+        localUserView.pagePrevBtn.disable(true)
+        localUserView.pagePrevBtn.hide()
+    } else {
+        localUserView.pagePrevBtn.disable(false)
+        localUserView.pagePrevBtn.show()
+    }
+    if (users.currentPage == users.totalPage || users.totalPage == 0) {
+        localUserView.pageNextBtn.disable(true)
+        localUserView.pageNextBtn.hide()
+    } else {
+        localUserView.pageNextBtn.disable(false)
+        localUserView.pageNextBtn.show()
+    }
+    if (users.totalPage == 0 || users.totalPage == 1) {
+        localUserView.pageSelect.hide()
+    } else {
+        localUserView.pageSelect.show()
+    }
+    localUserView.pageSelect.setOptions(Array.from({ length: users.totalPage }, (_, index) => String(index + 1)))
+    localUserView.pageSelect.setSelected(users.currentPage - 1)
+}
+export default localUserView
diff --git a/vf205_access/src/view/config/menu/networkSettingView.js b/vf205_access/src/view/config/menu/networkSettingView.js
new file mode 100644
index 0000000..8008c7d
--- /dev/null
+++ b/vf205_access/src/view/config/menu/networkSettingView.js
@@ -0,0 +1,441 @@
+import dxui from '../../../../dxmodules/dxUi.js'
+import std from '../../../../dxmodules/dxStd.js'
+import viewUtils from "../../viewUtils.js"
+import topView from "../../topView.js"
+import configView from '../configView.js'
+import i18n from "../../i18n.js"
+import screen from '../../../screen.js'
+
+const networkSettingView = {}
+networkSettingView.init = function () {
+    /**************************************************鍒涘缓灞忓箷*****************************************************/
+    const screenMain = dxui.View.build('networkSettingView', dxui.Utils.LAYER.MAIN)
+    networkSettingView.screenMain = screenMain
+    screenMain.scroll(false)
+    screenMain.bgColor(0xffffff)
+    screenMain.on(dxui.Utils.ENUM.LV_EVENT_SCREEN_LOADED, () => {
+        topView.changeTheme(true)
+        let devType = screen.getConfig()["sys.devType"]
+        let netTypes = []
+        netTypes = devType == 1 ? [i18n.t('networkSettingView.ethernet'), i18n.t('networkSettingView._4G')] : [i18n.t('networkSettingView.ethernet'), i18n.t('networkSettingView.wifi'), i18n.t('networkSettingView._4G')]
+        networkSettingView.netInfo[0].value = netTypes
+        networkSettingView.netInfo[0].dropdown.setOptions(networkSettingView.netInfo[0].value)
+        const configAll = screen.getConfig()
+        networkSettingView.changeNetType(configAll["net.type"] - 1)
+        networkSettingView.netInfo[0].dropdown.setSelected(configAll["net.type"] - 1)
+        networkSettingView.netInfo[1].dropdown.setOptions([configAll["net.ssid"]])
+        networkSettingView.netInfo[1].dropdown.setSelected(0)
+        networkSettingView.netInfo[2].input.text(configAll["net.psk"])
+        networkSettingView.netInfo[3].switch.select(configAll["net.dhcp"] == 2)
+        networkSettingView.netInfo[4].input.text(configAll["net.ip"])
+        networkSettingView.netInfo[5].input.text(configAll["net.mask"])
+        networkSettingView.netInfo[6].input.text(configAll["net.gateway"])
+        networkSettingView.netInfo[7].input.text(configAll["net.dns"].split(",")[0])
+        networkSettingView.netInfo[8].input.text(configAll["net.dns"].split(",")[1])
+        networkSettingView.netInfo[9].label.text(configAll["net.mac"])
+    })
+
+    screenMain.on(dxui.Utils.ENUM.LV_EVENT_SCREEN_UNLOADED, () => {
+        wifiListBoxClose.send(dxui.Utils.EVENT.CLICK)
+    })
+
+    const titleBox = viewUtils.title(screenMain, configView.screenMain, 'networkSettingViewTitle', 'networkSettingView.title')
+    titleBox.align(dxui.Utils.ALIGN.TOP_MID, 0, 70)
+
+
+    const networkSettingBox = dxui.View.build('networkSettingBox', screenMain)
+    viewUtils._clearStyle(networkSettingBox)
+    networkSettingBox.setSize(screen.screenSize.width, 830)
+    networkSettingBox.bgColor(0xeeeeee)
+    networkSettingBox.align(dxui.Utils.ALIGN.TOP_MID, 0, 142)
+    networkSettingBox.borderWidth(1)
+    networkSettingBox.setBorderColor(0xDEDEDE)
+    networkSettingBox.obj.setStyleBorderSide(dxui.Utils.ENUM.LV_BORDER_SIDE_TOP, 0)
+    networkSettingBox.bgOpa(0)
+    networkSettingBox.flexFlow(dxui.Utils.FLEX_FLOW.ROW_WRAP)
+    networkSettingBox.flexAlign(dxui.Utils.FLEX_ALIGN.CENTER, dxui.Utils.FLEX_ALIGN.START, dxui.Utils.FLEX_ALIGN.START)
+    networkSettingBox.obj.lvObjSetStylePadGap(0, dxui.Utils.ENUM._LV_STYLE_STATE_CMP_SAME)
+
+    networkSettingView.netInfo = [
+        {
+            title: 'networkSettingView.type',
+            value: [i18n.t('networkSettingView.ethernet'), i18n.t('networkSettingView.wifi'), i18n.t('networkSettingView._4G')],
+            type: 'dropdown',
+            obj: null,
+            dropdown: null
+        },
+        {
+            title: 'networkSettingView.wifiName',
+            value: [],
+            type: 'dropdown',
+            obj: null,
+            dropdown: null
+        },
+        {
+            title: 'networkSettingView.wifiPwd',
+            value: null,
+            type: 'input',
+            obj: null
+        },
+        {
+            title: 'networkSettingView.dhcp',
+            value: null,
+            type: 'switch',
+            obj: null
+        },
+        {
+            title: 'networkSettingView.ip',
+            value: null,
+            type: 'input',
+            obj: null
+        },
+        {
+            title: 'networkSettingView.mask',
+            value: null,
+            type: 'input',
+            obj: null
+        },
+        {
+            title: 'networkSettingView.gateway',
+            value: null,
+            type: 'input',
+            obj: null
+        },
+        {
+            title: 'networkSettingView.dns',
+            value: null,
+            type: 'input',
+            obj: null
+        },
+        {
+            title: 'networkSettingView.dns2',
+            value: null,
+            type: 'input',
+            obj: null
+        },
+        {
+            title: 'networkSettingView.mac',
+            value: 'DC-87-F2-97-3B-26',
+            type: 'label',
+            obj: null,
+            label: null
+        },
+        {
+            title: 'networkSettingView.status',
+            value: i18n.t('networkSettingView.networkUnconnected'),
+            type: 'label',
+            obj: null,
+            label: null
+        }
+    ]
+
+    networkSettingView.netInfo.forEach((item, index) => {
+        const networkSettingItem = dxui.View.build(networkSettingBox.id + item.title, networkSettingBox)
+        viewUtils._clearStyle(networkSettingItem)
+        item.obj = networkSettingItem
+        networkSettingItem.setSize(760, 76)
+        networkSettingItem.bgColor(0xffffff)
+        networkSettingItem.borderWidth(1)
+        networkSettingItem.setBorderColor(0xDEDEDE)
+        networkSettingItem.obj.setStyleBorderSide(dxui.Utils.ENUM.LV_BORDER_SIDE_BOTTOM, 0)
+
+        const title = dxui.Label.build(item.title, networkSettingItem)
+        title.textFont(viewUtils.font(26))
+        title.align(dxui.Utils.ALIGN.LEFT_MID, 0, 0)
+        title.dataI18n = item.title
+
+
+        if (item.type === 'input') {
+            const input = viewUtils.input(networkSettingItem, item.title + 'input', undefined, undefined, 'networkSettingView.input')
+            input.align(dxui.Utils.ALIGN.RIGHT_MID, 0, 0)
+            input.setSize(400, 60)
+            item.input = input
+        }
+
+        if (item.type === 'switch') {
+            const __switch = dxui.Switch.build(item.title + 'switch', networkSettingItem)
+            __switch.align(dxui.Utils.ALIGN.RIGHT_MID, 0, 0)
+            __switch.setSize(70, 35)
+            item.switch = __switch
+        }
+
+        if (item.type === 'dropdown') {
+            const dropdown = dxui.Dropdown.build(item.title + 'dropdown', networkSettingItem)
+            dropdown.align(dxui.Utils.ALIGN.RIGHT_MID, 0, 0)
+            dropdown.setSize(200, 60)
+            dropdown.textFont(viewUtils.font(26))
+            dropdown.getList().textFont(viewUtils.font(26))
+            dropdown.setSymbol('/app/code/resource/image/down.png')
+            dropdown.setOptions(item.value)
+            item.dropdown = dropdown
+
+            if (item.title === 'networkSettingView.type') {
+                dropdown.on(dxui.Utils.EVENT.VALUE_CHANGED, () => {
+                    networkSettingView.changeNetType(dropdown.getSelected())
+                    if(dropdown.getSelected() == 2) {
+                        // screen.switchNetworkType(dropdown.getSelected() + 2)
+                    } else {
+                        screen.switchNetworkType(dropdown.getSelected() + 1)
+                    }
+                })
+            }
+
+            if (item.title === 'networkSettingView.wifiName') {
+                dropdown.on(dxui.Utils.EVENT.CLICK, () => {
+                    screen.netGetWifiSsidList()
+                    wifiList.refresh()
+                    wifiListBoxbg.moveForeground()
+                    wifiListBoxbg.show()
+                })
+            }
+        }
+
+        if (item.type === 'label') {
+            const label = dxui.Label.build(item.title + 'label', networkSettingItem)
+            label.textFont(viewUtils.font(26))
+            label.align(dxui.Utils.ALIGN.RIGHT_MID, 0, 0)
+            label.text(item.value)
+            label.textColor(0x333333)
+            item.label = label
+        }
+
+    })
+
+    // wifi鍒楄〃
+    const wifiListBoxbg = dxui.View.build('wifiListBoxbg', screenMain)
+    viewUtils._clearStyle(wifiListBoxbg)
+    wifiListBoxbg.setSize(screen.screenSize.width, screen.screenSize.height)
+    wifiListBoxbg.bgColor(0x000000)
+    wifiListBoxbg.bgOpa(50)
+    wifiListBoxbg.hide()
+    wifiListBoxbg.on(dxui.Utils.EVENT.CLICK, () => {
+        wifiListBoxClose.send(dxui.Utils.EVENT.CLICK)
+    })
+
+    const wifiListBox = dxui.View.build('wifiListBox', wifiListBoxbg)
+    viewUtils._clearStyle(wifiListBox)
+    wifiListBox.setSize(520, 560)
+    wifiListBox.bgColor(0xffffff)
+    wifiListBox.radius(20)
+    wifiListBox.align(dxui.Utils.ALIGN.CENTER, 0, 0)
+
+    const wifiListBoxTitle = dxui.Label.build('wifiListBoxTitle', wifiListBox)
+    wifiListBoxTitle.textFont(viewUtils.font(28))
+    wifiListBoxTitle.align(dxui.Utils.ALIGN.TOP_MID, 0, 32)
+    wifiListBoxTitle.dataI18n = 'networkSettingView.wifiList'
+
+    const wifiListBoxClose = viewUtils.imageBtn(wifiListBox, 'wifiListBoxClose', '/app/code/resource/image/close_small.png')
+    wifiListBoxClose.align(dxui.Utils.ALIGN.TOP_RIGHT, -36, 30)
+    wifiListBoxClose.on(dxui.Utils.EVENT.CLICK, () => {
+        wifiListBoxbg.hide()
+    })
+
+    const closeBtn = dxui.Button.build('closeBtn', wifiListBox)
+    closeBtn.setSize(172, 50)
+    closeBtn.radius(10)
+    closeBtn.bgColor(0xEAEAEA)
+    closeBtn.align(dxui.Utils.ALIGN.BOTTOM_LEFT, 69, -53)
+    closeBtn.on(dxui.Utils.EVENT.CLICK, () => {
+        wifiListBoxClose.send(dxui.Utils.EVENT.CLICK)
+    })
+
+    const closeBtnText = dxui.Label.build('closeBtnText', closeBtn)
+    closeBtnText.textFont(viewUtils.font(24))
+    closeBtnText.dataI18n = 'networkSettingView.close'
+    closeBtnText.align(dxui.Utils.ALIGN.CENTER, 0, 0)
+    closeBtnText.textColor(0x000000)
+
+    const confirmBtn = dxui.Button.build('confirmBtn', wifiListBox)
+    confirmBtn.setSize(172, 50)
+    confirmBtn.radius(10)
+    confirmBtn.bgColor(0x000000)
+    confirmBtn.align(dxui.Utils.ALIGN.BOTTOM_RIGHT, -69, -53)
+    confirmBtn.on(dxui.Utils.EVENT.CLICK, () => {
+        wifiListBoxClose.send(dxui.Utils.EVENT.CLICK)
+        networkSettingView.netInfo[1].dropdown.setOptions([networkSettingView.selectedValue])
+    })
+
+    const confirmBtnText = dxui.Label.build('confirmBtnText', confirmBtn)
+    confirmBtnText.textFont(viewUtils.font(24))
+    confirmBtnText.dataI18n = 'networkSettingView.confirm'
+    confirmBtnText.align(dxui.Utils.ALIGN.CENTER, 0, 0)
+    confirmBtnText.textColor(0xffffff)
+    networkSettingView.wifiListData = []
+    networkSettingView.selectedValue = ''
+    networkSettingView.selectedItem = 0
+
+    const wifiList = viewUtils.cycleList(wifiListBox, 'wifiList', [440, 300], 5, (item) => {
+        const wifiItemLbl = dxui.Label.build(item.id + 'wifiItemLbl', item)
+        wifiItemLbl.align(dxui.Utils.ALIGN.LEFT_MID, 25, 0)
+        wifiItemLbl.textFont(viewUtils.font(26))
+        wifiItemLbl.textColor(0x888888)
+        wifiItemLbl.width(300)
+        wifiItemLbl.longMode(dxui.Utils.LABEL_LONG_MODE.SCROLL_CIRCULAR)
+        item.radius(10)
+        item.on(dxui.Utils.EVENT.CLICK, () => {
+            if (networkSettingView.selectedItem) {
+                networkSettingView.selectedItem.bgOpa(0)
+            }
+            networkSettingView.selectedItem = item
+            networkSettingView.selectedValue = wifiItemLbl.text()
+            item.bgColor(0xEAEAEA)
+            item.bgOpa(100)
+        })
+
+        const wifiItemImg = dxui.Image.build(item.id + 'wifi', item)
+        wifiItemImg.align(dxui.Utils.ALIGN.RIGHT_MID, -24, 0)
+        wifiItemImg.source('/app/code/resource/image/wifi.png')
+
+        const lockItemImg = dxui.Image.build(item.id + 'lock', item)
+        lockItemImg.align(dxui.Utils.ALIGN.RIGHT_MID, -55, 0)
+        lockItemImg.source('/app/code/resource/image/lock.png')
+
+        return { wifiItemLbl, wifiItemImg, lockItemImg }
+    }, (userdata, index) => {
+        const txt = networkSettingView.wifiListData[Math.abs((index % 5))]
+        if (txt) {
+            userdata.wifiItemLbl.text(txt)
+            userdata.wifiItemImg.show()
+            userdata.lockItemImg.show()
+        } else {
+            userdata.wifiItemLbl.text(' ')
+            userdata.wifiItemImg.hide()
+            userdata.lockItemImg.hide()
+        }
+    })
+    wifiList.align(dxui.Utils.ALIGN.TOP_MID, 0, 110)
+    wifiList.bgOpa(0)
+    networkSettingView.wifiList = wifiList
+
+    const saveBtn = viewUtils.bottomBtn(screenMain, screenMain.id + 'saveBtn', 'networkSettingView.save', () => {
+        // 鑾峰彇WiFi SSID锛屼紭鍏堜娇鐢ㄤ笅鎷夐�夋嫨鐨勫�硷紝濡傛灉娌℃湁鍒欎娇鐢ㄩ厤缃腑鐨勫��
+        let wifiSsid = networkSettingView.selectedValue || ""
+        
+        let saveConfigData = {
+            "net": {
+                "type": networkSettingView.netInfo[0].dropdown.getSelected() + 1,
+                "dhcp": networkSettingView.netInfo[3].switch.isSelect() ? 2 : 1,
+                "ip": networkSettingView.netInfo[4].input.text(),
+                "mask": networkSettingView.netInfo[5].input.text(),
+                "gateway": networkSettingView.netInfo[6].input.text(),
+                "dns": networkSettingView.netInfo[7].input.text() + ',' + networkSettingView.netInfo[8].input.text(),
+                "psk": networkSettingView.netInfo[2].input.text(),
+                "ssid": wifiSsid
+            }
+        }
+        if (!networkSettingView.netInfo[3].switch.isSelect()) {
+            // 闈欐�乮p
+            if (networkSettingView.netInfo[0].dropdown.getSelected() + 1 == 1) {
+                // 浠ュお缃�
+                saveConfigData = {
+                    "net": {
+                        "type": networkSettingView.netInfo[0].dropdown.getSelected() + 1,
+                        "dhcp": networkSettingView.netInfo[3].switch.isSelect() ? 2 : 1,
+                        "ip": networkSettingView.netInfo[4].input.text(),
+                        "mask": networkSettingView.netInfo[5].input.text(),
+                        "gateway": networkSettingView.netInfo[6].input.text(),
+                        "dns": networkSettingView.netInfo[7].input.text() + ',' + networkSettingView.netInfo[8].input.text(),
+                    }
+                }
+            } else if (networkSettingView.netInfo[0].dropdown.getSelected() + 1 == 2) {
+                // WIFI
+                saveConfigData = {
+                    "net": {
+                        "type": networkSettingView.netInfo[0].dropdown.getSelected() + 1,
+                        "dhcp": networkSettingView.netInfo[3].switch.isSelect() ? 2 : 1,
+                        "ip": networkSettingView.netInfo[4].input.text(),
+                        "mask": networkSettingView.netInfo[5].input.text(),
+                        "gateway": networkSettingView.netInfo[6].input.text(),
+                        "dns": networkSettingView.netInfo[7].input.text() + ',' + networkSettingView.netInfo[8].input.text(),
+                        "psk": networkSettingView.netInfo[2].input.text(),
+                        "ssid": wifiSsid
+                    }
+                }
+            } else {
+                //4G
+                saveConfigData = {
+                    "net": {
+                        "type": 4,
+                    }
+                }
+            }
+        } else {
+            // 鍔ㄦ�乮p
+            if (networkSettingView.netInfo[0].dropdown.getSelected() + 1 == 1) {
+                // 浠ュお缃�
+                saveConfigData = {
+                    "net": {
+                        "type": networkSettingView.netInfo[0].dropdown.getSelected() + 1,
+                        "dhcp": networkSettingView.netInfo[3].switch.isSelect() ? 2 : 1,
+                    }
+                }
+            } else if (networkSettingView.netInfo[0].dropdown.getSelected() + 1 == 2) {
+                // WIFI
+                saveConfigData = {
+                    "net": {
+                        "type": networkSettingView.netInfo[0].dropdown.getSelected() + 1,
+                        "dhcp": networkSettingView.netInfo[3].switch.isSelect() ? 2 : 1,
+                        "psk": networkSettingView.netInfo[2].input.text(),
+                        "ssid": wifiSsid
+                    }
+                }
+            } else {
+                //4G
+                saveConfigData = {
+                    "net": {
+                        "type": 4,
+                    }
+                }
+            }
+        }
+        const res = screen.saveConfig(saveConfigData)
+        if (res === true) {
+            networkSettingView.statusPanel.success()
+            std.setTimeout(() => {
+                // 鎴愬姛杩斿洖涓婁竴灞傜晫闈�
+                dxui.loadMain(configView.screenMain)
+            }, 500)
+        } else {
+            networkSettingView.statusPanel.fail()
+        }
+    })
+    saveBtn.align(dxui.Utils.ALIGN.BOTTOM_MID, 0, -83)
+
+    networkSettingView.changeNetType(0)
+
+    networkSettingView.statusPanel = viewUtils.statusPanel(screenMain, 'networkSettingView.success', 'networkSettingView.fail')
+}
+
+// 0:浠ュお缃� 1:wifi 3:4G
+networkSettingView.changeNetType = function (type) {
+    if (type === 0) {
+        networkSettingView.netInfo[1].obj.hide()
+        networkSettingView.netInfo[2].obj.hide()
+        networkSettingView.netInfo[3].obj.show()
+        networkSettingView.netInfo[4].obj.show()
+        networkSettingView.netInfo[5].obj.show()
+        networkSettingView.netInfo[6].obj.show()
+        networkSettingView.netInfo[7].obj.show()
+        networkSettingView.netInfo[8].obj.show()
+    } else if (type === 1) {
+        networkSettingView.netInfo[1].obj.show()
+        networkSettingView.netInfo[2].obj.show()
+        networkSettingView.netInfo[3].obj.show()
+        networkSettingView.netInfo[4].obj.show()
+        networkSettingView.netInfo[5].obj.show()
+        networkSettingView.netInfo[6].obj.show()
+        networkSettingView.netInfo[7].obj.show()
+        networkSettingView.netInfo[8].obj.show()
+    } else {
+        networkSettingView.netInfo[1].obj.hide()
+        networkSettingView.netInfo[2].obj.hide()
+        networkSettingView.netInfo[3].obj.hide()
+        networkSettingView.netInfo[4].obj.hide()
+        networkSettingView.netInfo[5].obj.hide()
+        networkSettingView.netInfo[6].obj.hide()
+        networkSettingView.netInfo[7].obj.hide()
+        networkSettingView.netInfo[8].obj.hide()
+    }
+}
+
+export default networkSettingView
diff --git a/vf205_access/src/view/config/menu/recordQuery/recordQueryDetailView.js b/vf205_access/src/view/config/menu/recordQuery/recordQueryDetailView.js
new file mode 100644
index 0000000..0067ffe
--- /dev/null
+++ b/vf205_access/src/view/config/menu/recordQuery/recordQueryDetailView.js
@@ -0,0 +1,227 @@
+import dxui from '../../../../../dxmodules/dxUi.js'
+import viewUtils from "../../../viewUtils.js"
+import topView from "../../../topView.js"
+import recordQueryView from '../recordQueryView.js'
+import i18n from "../../../i18n.js"
+import screen from '../../../../screen.js'
+import logger from '../../../../../dxmodules/dxLogger.js'
+const recordQueryDetailView = {}
+recordQueryDetailView.init = function () {
+    /**************************************************鍒涘缓灞忓箷*****************************************************/
+    const screenMain = dxui.View.build('recordQueryDetailView', dxui.Utils.LAYER.MAIN)
+    recordQueryDetailView.screenMain = screenMain
+    screenMain.scroll(false)
+    screenMain.bgColor(0xffffff)
+    screenMain.on(dxui.Utils.ENUM.LV_EVENT_SCREEN_LOADED, () => {
+        topView.changeTheme(true)
+        fillInfo()
+    })
+    const titleBox = viewUtils.title(screenMain, recordQueryView.screenMain, 'recordQueryDetailViewTitle', 'recordQueryDetailView.title')
+    titleBox.align(dxui.Utils.ALIGN.TOP_MID, 0, 70)
+
+    const box = dxui.View.build(screenMain.id + 'box', screenMain)
+    viewUtils._clearStyle(box)
+    box.align(dxui.Utils.ALIGN.TOP_MID, 0, 150)
+    box.setSize(screen.screenSize.width, screen.screenSize.height - 150)
+    box.bgOpa(0)
+    box.flexFlow(dxui.Utils.FLEX_FLOW.ROW_WRAP)
+    box.flexAlign(dxui.Utils.FLEX_ALIGN.CENTER, dxui.Utils.FLEX_ALIGN.START, dxui.Utils.FLEX_ALIGN.START)
+    box.obj.lvObjSetStylePadGap(5, dxui.Utils.ENUM._LV_STYLE_STATE_CMP_SAME)
+    box.scroll(true)
+
+    recordQueryDetailView.info = [{
+            title: 'recordQueryDetailView.result',
+            key: 'result',
+            label: null
+        }, {
+            title: 'recordQueryDetailView.time',
+            key: 'time',
+            label: null
+        }, {
+            title: 'recordQueryDetailView.id',
+            key: 'userId',
+            label: null
+        }, {
+            title: 'recordQueryDetailView.name',
+            key: 'name',
+            label: null
+        }, {
+            title: 'recordQueryDetailView.idCard',
+            key: 'idCard',
+            label: null
+        }, {
+            title: 'recordQueryDetailView.face',
+            key: 'code',
+            label: null
+        }, {
+            title: 'recordQueryDetailView.secondId',
+            key: 'userId2',
+            label: null
+        }, {
+            title: 'recordQueryDetailView.secondName',
+            key: 'name2',
+            label: null
+        }, {
+            title: 'recordQueryDetailView.secondIdCard',
+            key: 'idCard2',
+            label: null
+        }, {
+            title: 'recordQueryDetailView.secondFace',
+            key: 'code2',
+            label: null
+        }]
+
+    recordQueryDetailView.info.forEach((item, index) => {
+        const itemBox = dxui.View.build(screenMain.id + '.' + index, box)
+        viewUtils._clearStyle(itemBox)
+        itemBox.setSize(760, 76)
+        itemBox.borderWidth(1)
+        itemBox.obj.setStyleBorderSide(dxui.Utils.ENUM.LV_BORDER_SIDE_BOTTOM, 0)
+        itemBox.setBorderColor(0x767676)
+
+        const titleLbl = dxui.Label.build(screenMain.id + 'titleLbl' + index, itemBox)
+        titleLbl.align(dxui.Utils.ALIGN.LEFT_MID, 0, 0)
+        titleLbl.textFont(viewUtils.font(26))
+        titleLbl.dataI18n = item.title
+
+        if ("recordQueryDetailView.face" == item.title || "recordQueryDetailView.secondFace" == item.title) {
+            itemBox.setSize(760, 260)
+            itemBox.scroll(false)
+            const faceImg = dxui.Image.build(screenMain.id + 'faceImg' + index, itemBox)
+            faceImg.align(dxui.Utils.ALIGN.RIGHT_MID, 0, 0)
+            item.face = faceImg
+            return
+        }
+
+        const valueLbl = dxui.Label.build(screenMain.id + 'valueLbl' + index, itemBox)
+        valueLbl.align(dxui.Utils.ALIGN.RIGHT_MID, 0, 0)
+        valueLbl.textFont(viewUtils.font(26))
+        valueLbl.textColor(0x333333)
+        item.label = valueLbl
+    })
+
+}
+
+function fillInfo () {
+    let extra
+    try {
+        extra = JSON.parse(recordQueryView.nowRecord.extra)
+    } catch (error) {
+        logger.error("娌℃湁棰濆瀛楁璺宠繃")
+    }
+    
+    let extra2
+    try {
+        extra2 = JSON.parse(recordQueryView.nowRecord.extra2)
+    } catch (error) {
+        logger.error("娌℃湁绗簩鐢ㄦ埛棰濆瀛楁璺宠繃")
+    }
+    
+    const language = screen.getConfig(["base.language"])
+    recordQueryDetailView.info.forEach((item, index) => {
+        switch (item.key) {
+            case 'userId':
+                item.label.text((recordQueryView.nowRecord.userId || ' '))
+                break;
+            case 'name':
+                if (extra && extra.name) {
+                    item.label.text(extra.name)
+                } else {
+                    item.label.text(" ")
+                }
+                break;
+            case 'idCard':
+                if (extra && extra.idCard) {
+                    item.label.text(extra.idCard)
+                } else {
+                    item.label.text(" ")
+                }
+                break;
+            case 'userId2':
+                item.label.text((recordQueryView.nowRecord.userId2 || ' '))
+                break;
+            case 'name2':
+                if (extra2 && extra2.name) {
+                    item.label.text(extra2.name)
+                } else {
+                    item.label.text(" ")
+                }
+                break;
+            case 'idCard2':
+                if (extra2 && extra2.idCard) {
+                    item.label.text(extra2.idCard)
+                } else {
+                    item.label.text(" ")
+                }
+                break;
+            case 'time':
+                const t = new Date(recordQueryView.nowRecord[item.key] * 1000)
+                // 琛ラ浂鍑芥暟
+                const pad = (n) => n < 10 ? `0${n}` : n;
+                item.label.text(`${t.getFullYear()}-${pad(t.getMonth() + 1)}-${pad(t.getDate())} ${pad(t.getHours())}:${pad(t.getMinutes())}:${pad(t.getSeconds())}`)
+                break;
+            case 'result':
+                let msg = ""
+                if (recordQueryView.nowRecord.message === "姘斾綋娴撳害涓嶅悎鏍�") {
+                    msg = "姘斾綋娴撳害涓嶅悎鏍�"
+                } else if (recordQueryView.nowRecord.message === "鍙屼汉璁よ瘉瓒呮椂") {
+                    msg = "鍙屼汉璁よ瘉瓒呮椂"
+                } else {
+                    switch (recordQueryView.nowRecord.type) {
+                        case "200":
+                            msg = i18n.t('recordQueryView.card')
+                            break;
+                        case "300":
+                            msg = i18n.t('recordQueryView.face')
+                            break;
+                        case "400":
+                            msg = i18n.t('recordQueryView.password')
+                            break;
+                        case "100":
+                            msg = i18n.t('recordQueryView.qrcode')
+                            break;
+                        case "101":
+                            msg = i18n.t('recordQueryView.qrcode')
+                            break;
+                        case "103":
+                            msg = i18n.t('recordQueryView.qrcode')
+                            break;
+                        default:
+                            break;
+                    }
+                    msg += language === 'CN' ? "" : " "
+                    if (recordQueryView.nowRecord.result == 0) {
+                        msg += i18n.t('recordQueryView.success')
+                    } else {
+                        msg += i18n.t('recordQueryView.fail')
+                    }
+                }
+                item.label.text(msg)
+                break;
+            case 'code':
+                // 绗竴鐢ㄦ埛浜鸿劯鎶撴媿
+                if (recordQueryView.nowRecord.type == "300") {
+                    let src = recordQueryView.nowRecord.code || `/app/data/passRecord/${recordQueryView.nowRecord.userId ? recordQueryView.nowRecord.userId : "undefined"}_${recordQueryView.nowRecord.time}_1.jpg`
+                    item.face.show()
+                    item.face.source(src)
+                } else {
+                    item.face.hide()
+                }
+                break;
+            case 'code2':
+                // 绗簩鐢ㄦ埛浜鸿劯鎶撴媿
+                if (recordQueryView.nowRecord.type == "300" && recordQueryView.nowRecord.userId2) {
+                    let src = recordQueryView.nowRecord.code2 || `/app/data/passRecord/${recordQueryView.nowRecord.userId2}_${recordQueryView.nowRecord.time}_2.jpg`
+                    item.face.show()
+                    item.face.source(src)
+                } else {
+                    item.face.hide()
+                }
+                break;
+            default:
+                break;
+        }
+    })
+}
+
+export default recordQueryDetailView
diff --git a/vf205_access/src/view/config/menu/recordQueryView.js b/vf205_access/src/view/config/menu/recordQueryView.js
new file mode 100644
index 0000000..e1a7c67
--- /dev/null
+++ b/vf205_access/src/view/config/menu/recordQueryView.js
@@ -0,0 +1,276 @@
+import dxui from '../../../../dxmodules/dxUi.js'
+import viewUtils from "../../viewUtils.js"
+import topView from "../../topView.js"
+import configView from '../configView.js'
+import i18n from "../../i18n.js"
+import screen from '../../../screen.js'
+import recordQueryDetailView from './recordQuery/recordQueryDetailView.js'
+const recordQueryView = {}
+recordQueryView.init = function () {
+    /**************************************************鍒涘缓灞忓箷*****************************************************/
+    const screenMain = dxui.View.build('recordQueryView', dxui.Utils.LAYER.MAIN)
+    recordQueryView.screenMain = screenMain
+    screenMain.scroll(false)
+    screenMain.bgColor(0xffffff)
+    screenMain.on(dxui.Utils.ENUM.LV_EVENT_SCREEN_LOADED, () => {
+        topView.changeTheme(true)
+        refreshRecordList(recordQueryView.nowPage ? recordQueryView.nowPage : 0, 6)
+    })
+
+    const empty = dxui.Image.build(screenMain.id + 'empty', screenMain)
+    recordQueryView.empty = empty
+    empty.source('/app/code/resource/image/empty.png')
+    empty.align(dxui.Utils.ALIGN.CENTER, 0, 0)
+    empty.hide()
+
+    const titleBox = viewUtils.title(screenMain, configView.screenMain, 'recordQueryViewTitle', 'recordQueryView.title', () => { recordQueryView.nowPage = 0 })
+    titleBox.align(dxui.Utils.ALIGN.TOP_MID, 0, 70)
+
+    const box = dxui.View.build(screenMain.id + 'box', screenMain)
+    viewUtils._clearStyle(box)
+    box.align(dxui.Utils.ALIGN.TOP_MID, 0, 150)
+    box.setSize(screen.screenSize.width, 1000)
+    box.bgOpa(0)
+    box.flexFlow(dxui.Utils.FLEX_FLOW.ROW_WRAP)
+    box.flexAlign(dxui.Utils.FLEX_ALIGN.CENTER, dxui.Utils.FLEX_ALIGN.START, dxui.Utils.FLEX_ALIGN.START)
+    box.obj.lvObjSetStylePadGap(5, dxui.Utils.ENUM._LV_STYLE_STATE_CMP_SAME)
+
+    recordQueryView.items = []
+    for (let i = 0; i < 6; i++) {
+        const item = dxui.View.build(box.id + 'item' + i, box)
+        viewUtils._clearStyle(item)
+        item.setSize(760, 160)
+        item.bgOpa(0)
+        item.borderWidth(1)
+        item.obj.setStyleBorderSide(dxui.Utils.ENUM.LV_BORDER_SIDE_BOTTOM, 0)
+        item.setBorderColor(0x767676)
+
+        const name = dxui.Label.build(item.id + 'name' + i, item)
+        name.align(dxui.Utils.ALIGN.TOP_LEFT, 0, 5)
+        name.textFont(viewUtils.font(24))
+
+        const code = dxui.Label.build(item.id + 'code' + i, item)
+        code.align(dxui.Utils.ALIGN.TOP_LEFT, 0, 40)
+        code.textFont(viewUtils.font(24))
+        code.dataI18n = 'recordQueryView.code'
+
+        const codeValue = dxui.Label.build(item.id + 'codeValue' + i, item)
+        codeValue.align(dxui.Utils.ALIGN.TOP_LEFT, 0, 40)
+        codeValue.textFont(viewUtils.font(24))
+        codeValue.dataI18n = 'recordQueryView.codeValue'
+
+        const time = dxui.Label.build(item.id + 'time' + i, item)
+        time.align(dxui.Utils.ALIGN.TOP_LEFT, 0, 75)
+        time.textFont(viewUtils.font(24))
+        time.dataI18n = 'recordQueryView.time'
+
+        const timeValue = dxui.Label.build(item.id + 'timeValue' + i, item)
+        timeValue.align(dxui.Utils.ALIGN.TOP_LEFT, 0, 75)
+        timeValue.textFont(viewUtils.font(24))
+        timeValue.dataI18n = 'recordQueryView.timeValue'
+
+        const result = dxui.Label.build(item.id + 'result' + i, item)
+        result.align(dxui.Utils.ALIGN.TOP_LEFT, 0, 110)
+        result.textFont(viewUtils.font(24))
+        result.dataI18n = 'recordQueryView.result'
+
+        const resultValue = dxui.Label.build(item.id + 'resultValue' + i, item)
+        resultValue.align(dxui.Utils.ALIGN.TOP_LEFT, 0, 110)
+        resultValue.textFont(viewUtils.font(24))
+        resultValue.dataI18n = 'recordQueryView.resultValue'
+
+        const moreBtn = dxui.Button.build(item.id + 'btn' + i, item)
+        moreBtn.align(dxui.Utils.ALIGN.TOP_RIGHT, 0, 10)
+        const moreBtnLbl = dxui.Label.build(item.id + 'btnLbl' + i, moreBtn)
+        moreBtnLbl.textFont(viewUtils.font(24))
+        moreBtnLbl.text('璇︽儏')
+
+        moreBtn.on(dxui.Utils.EVENT.CLICK, () => {
+            recordQueryView.nowRecord = recordQueryView.recordData.data[i]
+            dxui.loadMain(recordQueryDetailView.screenMain)
+        })
+
+        recordQueryView.items.push({
+            item,
+            name,
+            id: codeValue,
+            idLbl: code,
+            time: timeValue,
+            timeLbl: time,
+            result: resultValue,
+            resultLbl: result
+        })
+    }
+
+    const pageNextBtn = dxui.Button.build(screenMain.id + 'pageNextBtn', screenMain)
+    recordQueryView.pageNextBtn = pageNextBtn
+    pageNextBtn.bgColor(0x000000)
+    const pageNextLbl = dxui.Label.build(screenMain.id + 'pageNextLbl', pageNextBtn)
+    pageNextLbl.text("鈫�")
+    pageNextBtn.align(dxui.Utils.ALIGN.BOTTOM_RIGHT, -20, -52)
+    pageNextBtn.textFont(viewUtils.font(20))
+    const pagePrevBtn = dxui.Button.build(screenMain.id + 'pagePrevBtn', screenMain)
+    recordQueryView.pagePrevBtn = pagePrevBtn
+    pagePrevBtn.bgColor(0x000000)
+    const pagePrevLbl = dxui.Label.build(screenMain.id + 'pagePrevLbl', pagePrevBtn)
+    pagePrevLbl.text("鈫�")
+    pagePrevBtn.align(dxui.Utils.ALIGN.BOTTOM_LEFT, 20, -52)
+    pagePrevBtn.textFont(viewUtils.font(20))
+    const pageSelect = dxui.Dropdown.build(screenMain.id + 'pageSelect', screenMain)
+    recordQueryView.pageSelect = pageSelect
+    pageSelect.textFont(viewUtils.font(22))
+    pageSelect.getList().textFont(viewUtils.font(22))
+    pageSelect.setSize(150, 55)
+    pageSelect.setSymbol('/app/code/resource/image/down.png')
+    pageSelect.align(dxui.Utils.ALIGN.BOTTOM_MID, 0, -50)
+    pageSelect.setOptions([])
+    pageSelect.on(dxui.Utils.EVENT.VALUE_CHANGED, () => {
+        refreshRecordList(pageSelect.getSelected(), 6)
+        recordQueryView.nowPage = pageSelect.getSelected()
+    })
+    pageNextBtn.on(dxui.Utils.EVENT.CLICK, () => {
+        refreshRecordList(pageSelect.getSelected() + 1, 6)
+        if (!recordQueryView.nowPage) {
+            recordQueryView.nowPage = 0
+        }
+        recordQueryView.nowPage += 1
+    })
+    pagePrevBtn.on(dxui.Utils.EVENT.CLICK, () => {
+        refreshRecordList(pageSelect.getSelected() - 1, 6)
+        if (!recordQueryView.nowPage) {
+            recordQueryView.nowPage = 0
+        }
+        recordQueryView.nowPage -= 1
+    })
+}
+
+// 鍒锋柊鍒楄〃
+function refreshRecordList (page, size) {
+    const recordData = screen.getPassRecord(page, size)
+    recordQueryView.recordData = recordData
+
+    const data = recordData.data
+    const totalPage = recordData.totalPage
+    const totalSize = recordData.totalSize
+    const currentPage = recordData.currentPage
+    const language = screen.getConfig()['base.language']
+
+    if (currentPage == 1) {
+        recordQueryView.pagePrevBtn.disable(true)
+        recordQueryView.pagePrevBtn.hide()
+    } else {
+        recordQueryView.pagePrevBtn.disable(false)
+        recordQueryView.pagePrevBtn.show()
+    }
+    if (currentPage == totalPage || totalPage == 0) {
+        recordQueryView.pageNextBtn.disable(true)
+        recordQueryView.pageNextBtn.hide()
+    } else {
+        recordQueryView.pageNextBtn.disable(false)
+        recordQueryView.pageNextBtn.show()
+    }
+    if (totalPage == 0 || totalPage == 1) {
+        recordQueryView.pageSelect.hide()
+    } else {
+        recordQueryView.pageSelect.show()
+    }
+
+    recordQueryView.pageSelect.setOptions(Array.from({ length: totalPage }, (_, index) => String(index + 1)))
+    recordQueryView.pageSelect.setSelected(currentPage - 1)
+
+    if (!data || data.length == 0) {
+        recordQueryView.items.forEach(item => {
+            item.item.hide()
+        })
+        recordQueryView.empty.show()
+        return
+    } else {
+        recordQueryView.empty.hide()
+    }
+
+    recordQueryView.items.forEach((item, index) => {
+        if (!data[index]) {
+            item.item.hide()
+        } else {
+            item.item.show()
+            let extra
+            try {
+                extra = JSON.parse(data[index].extra)
+            } catch (error) {
+            }
+            let extra2
+            try {
+                extra2 = JSON.parse(data[index].extra2)
+            } catch (error) {
+            }
+            // 鏄剧ず濮撳悕
+            let nameText = ""
+            if (extra && extra.name) {
+                nameText = extra.name
+            } else {
+                nameText = i18n.t('recordQueryView.stranger')
+            }
+            if (data[index].userId2 && extra2 && extra2.name) {
+                nameText += " / " + extra2.name
+            }
+            item.name.text(nameText)
+            // 鏄剧ず浜哄憳缂栧彿
+            let idText = ":" + data[index].userId
+            if (data[index].userId2) {
+                idText += " / " + data[index].userId2
+            }
+            item.id.text(idText)
+            item.id.alignTo(item.idLbl, dxui.Utils.ALIGN.OUT_RIGHT_MID, 0, 0)
+
+            const t = new Date(data[index].time * 1000)
+
+
+            // 琛ラ浂鍑芥暟
+            const pad = (n) => n < 10 ? `0${n}` : n;
+
+            item.time.text(":" + `${t.getFullYear()}-${pad(t.getMonth() + 1)}-${pad(t.getDate())} ${pad(t.getHours())}:${pad(t.getMinutes())}:${pad(t.getSeconds())}`)
+            // item.time.text(":" + data[index].time)
+            item.time.alignTo(item.timeLbl, dxui.Utils.ALIGN.OUT_RIGHT_MID, 0, 0)
+
+            let msg = ""
+            // 妫�鏌ユ槸鍚︽槸鐗规畩娑堟伅瀵艰嚧鐨勫け璐�
+            if (data[index].message === "姘斾綋娴撳害涓嶅悎鏍�") {
+                msg = "姘斾綋娴撳害涓嶅悎鏍�"
+            } else if (data[index].message === "鍙屼汉璁よ瘉瓒呮椂") {
+                msg = "鍙屼汉璁よ瘉瓒呮椂"
+            } else {
+                switch (data[index].type) {
+                    case "200":
+                        msg = i18n.t('recordQueryView.card')
+                        break;
+                    case "300":
+                        msg = i18n.t('recordQueryView.face')
+                        break;
+                    case "400":
+                        msg = i18n.t('recordQueryView.password')
+                        break;
+                    case "100":
+                        msg = i18n.t('recordQueryView.qrcode')
+                        break;
+                    case "101":
+                        msg = i18n.t('recordQueryView.qrcode')
+                        break;
+                    case "103":
+                        msg = i18n.t('recordQueryView.qrcode')
+                        break;
+                    default:
+                        break;
+                }
+                msg += language === 'CN' ? "" : " "
+                if (data[index].result == 0) {
+                    msg += i18n.t('recordQueryView.success')
+                } else {
+                    msg += i18n.t('recordQueryView.fail')
+                }
+            }
+            item.result.text(":" + msg)
+            item.result.alignTo(item.resultLbl, dxui.Utils.ALIGN.OUT_RIGHT_MID, 0, 0)
+        }
+    })
+}
+export default recordQueryView
diff --git a/vf205_access/src/view/config/menu/systemSetting/displaySettingView.js b/vf205_access/src/view/config/menu/systemSetting/displaySettingView.js
new file mode 100644
index 0000000..94f66de
--- /dev/null
+++ b/vf205_access/src/view/config/menu/systemSetting/displaySettingView.js
@@ -0,0 +1,289 @@
+import dxui from '../../../../../dxmodules/dxUi.js'
+import std from '../../../../../dxmodules/dxStd.js'
+import viewUtils from "../../../viewUtils.js"
+import topView from "../../../topView.js"
+import systemSettingView from '../systemSettingView.js'
+import i18n from "../../../i18n.js"
+import screen from '../../../../screen.js'
+import logger from '../../../../../dxmodules/dxLogger.js'
+const displaySettingView = {}
+const languageData = ['CN', 'EN']
+const languageData2 = ['涓枃', '鑻辨枃']
+const themeModeData = ['鏍囧噯妯″紡', '绠�娲佹ā寮�']
+const themeModeData2 = ['StandardMode', 'SimpleMode']
+
+displaySettingView.init = function () {
+    /**************************************************鍒涘缓灞忓箷*****************************************************/
+    const screenMain = dxui.View.build('displaySettingView', dxui.Utils.LAYER.MAIN)
+    displaySettingView.screenMain = screenMain
+    screenMain.scroll(false)
+    screenMain.bgColor(0xffffff)
+    screenMain.on(dxui.Utils.ENUM.LV_EVENT_SCREEN_LOADED, () => {
+        topView.changeTheme(true)
+
+        refreshLanguage()
+
+        const configAll = screen.getConfig()
+        // 鑷姩璋冭妭灞忓箷浜害
+        displaySettingView.info[0].switch.select(configAll['base.brightnessAuto'] == 1)
+        if (configAll['base.brightnessAuto'] == 1) {
+            displaySettingView.info[1].slider.disable(true)
+        } else {
+            displaySettingView.info[1].slider.disable(false)
+        }
+        // 灞忓箷浜害
+        displaySettingView.info[1].slider.value(configAll['base.brightness'])
+        displaySettingView.info[1].slider.send(dxui.Utils.EVENT.VALUE_CHANGED)
+        // 鑷姩鍏冲睆
+        displaySettingView.info[2].switch.select(configAll['base.screenOff'] != 0)
+        // 鍏冲睆鏃堕棿
+        displaySettingView.info[3].input.text(configAll['base.screenOff'] + '')
+        // 鑷姩灞忎繚
+        displaySettingView.info[4].switch.select(configAll['base.screensaver'] != 0)
+        // 灞忎繚鏃堕棿
+        displaySettingView.info[5].input.text(configAll['base.screensaver'] + '')
+        // 鏄剧ずIP
+        displaySettingView.info[6].switch.select(configAll['base.showIp'] == 1)
+        // 鏄剧ずSN
+        displaySettingView.info[7].switch.select(configAll['base.showSn'] == 1)
+        // 鏄剧ず灏忕▼搴忕爜
+        displaySettingView.info[9].switch.select(configAll['base.showProgramCode'] == 1)
+        // app妯″紡
+        displaySettingView.info[10].dropdown.setSelected(configAll['base.appMode'])
+    })
+
+    const titleBox = viewUtils.title(screenMain, systemSettingView.screenMain, 'displaySettingViewTitle', 'systemSettingView.displaySetting')
+    titleBox.align(dxui.Utils.ALIGN.TOP_MID, 0, 70)
+
+    displaySettingView.info = [
+        {
+            title: "systemSettingView.autoAdjustScreenBrightness",
+            type: 'switch',
+        },
+        {
+            title: "systemSettingView.screenBrightness",
+            type: 'slider',
+            unit: '%'
+        },
+        {
+            title: "systemSettingView.autoTurnOffScreen",
+            type: 'switch',
+        },
+        {
+            title: "systemSettingView.autoTurnOffScreenTime",
+            type: 'input',
+            i18nUnit: 'systemSettingView.min'
+        },
+        {
+            title: "systemSettingView.autoScreenSaver",
+            type: 'switch',
+        },
+        {
+            title: "systemSettingView.autoScreenSaverTime",
+            type: 'input',
+            i18nUnit: 'systemSettingView.min'
+        },
+        {
+            title: "systemSettingView.displayIp",
+            type: 'switch',
+        },
+        {
+            title: "systemSettingView.displayDeviceSn",
+            type: 'switch',
+        },
+        {
+            title: "systemSettingView.language",
+            type: 'dropdown',
+        },
+        {
+            title: "systemSettingView.displayCode",
+            type: 'switch',
+        },
+        {
+            title: "systemSettingView.themeMode",
+            type: 'dropdown',
+        },
+    ]
+
+    const displaySettingBox = dxui.View.build('displaySettingBox', screenMain)
+    viewUtils._clearStyle(displaySettingBox)
+    displaySettingBox.align(dxui.Utils.ALIGN.TOP_MID, 0, 140)
+    displaySettingBox.setSize(screen.screenSize.width, 850)
+    displaySettingBox.bgOpa(0)
+    displaySettingBox.flexFlow(dxui.Utils.FLEX_FLOW.ROW_WRAP)
+    displaySettingBox.flexAlign(dxui.Utils.FLEX_ALIGN.CENTER, dxui.Utils.FLEX_ALIGN.START, dxui.Utils.FLEX_ALIGN.START)
+    displaySettingBox.obj.lvObjSetStylePadGap(0, dxui.Utils.ENUM._LV_STYLE_STATE_CMP_SAME)
+    displaySettingBox.borderWidth(1)
+    displaySettingBox.setBorderColor(0xDEDEDE)
+    displaySettingBox.obj.setStyleBorderSide(dxui.Utils.ENUM.LV_BORDER_SIDE_TOP, 0)
+
+    displaySettingView.info.forEach(item => {
+        const itemBox = dxui.View.build(item.title, displaySettingBox)
+        viewUtils._clearStyle(itemBox)
+        itemBox.setSize(760, 76)
+        itemBox.borderWidth(1)
+        itemBox.setBorderColor(0xDEDEDE)
+        itemBox.obj.setStyleBorderSide(dxui.Utils.ENUM.LV_BORDER_SIDE_BOTTOM, 0)
+
+        const itemLabel = dxui.Label.build(item.title + 'Label', itemBox)
+        itemLabel.dataI18n = item.title
+        itemLabel.align(dxui.Utils.ALIGN.LEFT_MID, 0, 0)
+        itemLabel.textFont(viewUtils.font(26))
+
+        if (item.unit) {
+            const unitLabel = dxui.Label.build(item.title + 'UnitLabel', itemBox)
+            unitLabel.text(item.unit)
+            unitLabel.align(dxui.Utils.ALIGN.RIGHT_MID, 0, 0)
+            unitLabel.textFont(viewUtils.font(26))
+        }
+
+        if (item.i18nUnit) {
+            const unitLabel = dxui.Label.build(item.title + 'UnitLabel', itemBox)
+            unitLabel.dataI18n = item.i18nUnit
+            unitLabel.align(dxui.Utils.ALIGN.RIGHT_MID, 0, 0)
+            unitLabel.textFont(viewUtils.font(26))
+        }
+
+        switch (item.type) {
+            case 'switch':
+                const __switch = dxui.Switch.build(item.title + 'switch', itemBox)
+                __switch.align(dxui.Utils.ALIGN.RIGHT_MID, 0, 0)
+                __switch.setSize(70, 35)
+                item.switch = __switch
+
+                if (item.title == 'systemSettingView.autoAdjustScreenBrightness') {
+                    __switch.on(dxui.Utils.EVENT.VALUE_CHANGED, () => {
+                        screen.saveConfig({
+                            base: {
+                                brightnessAuto: __switch.isSelect() ? 1 : 0
+                            }
+                        })
+                        if (__switch.isSelect()) {
+                            displaySettingView.info[1].slider.disable(true)
+                        } else {
+                            displaySettingView.info[1].slider.disable(false)
+                        }
+                    })
+                }
+
+                if (item.title == 'systemSettingView.autoTurnOffScreen') {
+                    __switch.on(dxui.Utils.EVENT.VALUE_CHANGED, () => {
+                        if (!__switch.isSelect()) {
+                            displaySettingView.info[3].input.text("0")
+                        }
+                    })
+                }
+
+                if (item.title == 'systemSettingView.autoScreenSaver') {
+                    __switch.on(dxui.Utils.EVENT.VALUE_CHANGED, () => {
+                        if (!__switch.isSelect()) {
+                            displaySettingView.info[5].input.text("0")
+                        }
+                    })
+                }
+
+                break;
+            case 'input':
+                const input = viewUtils.input(itemBox, item.title + 'input', undefined, undefined, undefined)
+                input.align(dxui.Utils.ALIGN.RIGHT_MID, -60, 0)
+                input.setSize(100, 55)
+                item.input = input
+                break;
+            case 'dropdown':
+                const dropdown = dxui.Dropdown.build(item.title + 'dropdown', itemBox)
+                dropdown.align(dxui.Utils.ALIGN.RIGHT_MID, 0, 0)
+                dropdown.textFont(viewUtils.font(26))
+                dropdown.getList().textFont(viewUtils.font(26))
+                dropdown.setSize(230,55)
+                dropdown.setSymbol('/app/code/resource/image/down.png')
+                item.dropdown = dropdown
+                break;
+            case 'slider':
+                const sliderLabel = dxui.Label.build(item.title + 'sliderLabel', itemBox)
+                sliderLabel.align(dxui.Utils.ALIGN.RIGHT_MID, -30, 0)
+                sliderLabel.width(50)
+                sliderLabel.text('0')
+                sliderLabel.textFont(viewUtils.font(26))
+                sliderLabel.textAlign(dxui.Utils.TEXT_ALIGN.RIGHT)
+
+                const slider = dxui.Slider.build(item.title + 'slider', itemBox)
+                slider.align(dxui.Utils.ALIGN.RIGHT_MID, -90, 0)
+                slider.width(150)
+                slider.range(0, 100)
+
+                slider.on(dxui.Utils.EVENT.VALUE_CHANGED, () => {
+                    sliderLabel.text(slider.value() + '')
+                    if (screen.getConfig()['base.brightness'] == slider.value()) {
+                        return
+                    }
+                    screen.saveConfig({
+                        base: {
+                            brightness: slider.value()
+                        }
+                    })
+                })
+                item.slider = slider
+                break;
+        }
+
+    })
+
+    const saveBtn = viewUtils.bottomBtn(screenMain, screenMain.id + 'saveBtn', 'systemSettingView.save', () => {
+        const saveConfigData = {
+            base: {
+                language: languageData[displaySettingView.info[8].dropdown.getSelected()],
+                brightnessAuto: displaySettingView.info[0].switch.isSelect() ? 1 : 0,
+                brightness: displaySettingView.info[1].slider.value(),
+                screenOff: parseInt(displaySettingView.info[3].input.text()),
+                screensaver: parseInt(displaySettingView.info[5].input.text()),
+                showIp: displaySettingView.info[6].switch.isSelect() ? 1 : 0,
+                showSn: displaySettingView.info[7].switch.isSelect() ? 1 : 0,
+                showProgramCode: displaySettingView.info[9].switch.isSelect() ? 1 : 0,
+                appMode: displaySettingView.info[10].dropdown.getSelected(),
+            }
+        }
+
+        const res = screen.saveConfig(saveConfigData)
+        if (res === true) {
+            displaySettingView.statusPanel.success()
+            i18n.setLanguage(screen.getConfig()['base.language'])
+            refreshLanguage()
+            std.setTimeout(() => {
+                // 鎴愬姛杩斿洖涓婁竴灞傜晫闈�
+                dxui.loadMain(systemSettingView.screenMain)
+            }, 500)
+            
+            if (displaySettingView.info[0].switch.isSelect()) {
+                displaySettingView.info[1].slider.disable(true)
+            } else {
+                displaySettingView.info[1].slider.disable(false)
+            }
+        } else {
+            displaySettingView.statusPanel.fail()
+        }
+    })
+    saveBtn.align(dxui.Utils.ALIGN.BOTTOM_MID, 0, -83)
+
+    displaySettingView.statusPanel = viewUtils.statusPanel(screenMain, 'systemSettingView.success', 'systemSettingView.fail')
+}
+
+function refreshLanguage() {
+    switch (screen.getConfig()['base.language']) {
+        case 'CN':
+            displaySettingView.info[8].dropdown.setOptions(languageData2)
+            displaySettingView.info[8].dropdown.setSelected(0)
+            displaySettingView.info[10].dropdown.setOptions(themeModeData)
+            displaySettingView.info[10].dropdown.setSelected(0)
+            break;
+        case 'EN':
+            displaySettingView.info[8].dropdown.setOptions(languageData)
+            displaySettingView.info[8].dropdown.setSelected(1)
+            displaySettingView.info[10].dropdown.setOptions(themeModeData2)
+            displaySettingView.info[10].dropdown.setSelected(1)
+            break;
+        default:
+            break;
+    }
+}
+
+export default displaySettingView
diff --git a/vf205_access/src/view/config/menu/systemSetting/faceRecognitionSettingView.js b/vf205_access/src/view/config/menu/systemSetting/faceRecognitionSettingView.js
new file mode 100644
index 0000000..e50cf3c
--- /dev/null
+++ b/vf205_access/src/view/config/menu/systemSetting/faceRecognitionSettingView.js
@@ -0,0 +1,167 @@
+import dxui from '../../../../../dxmodules/dxUi.js'
+import std from '../../../../../dxmodules/dxStd.js'
+import viewUtils from "../../../viewUtils.js"
+import topView from "../../../topView.js"
+import i18n from "../../../i18n.js"
+import systemSettingView from '../systemSettingView.js'
+import screen from '../../../../screen.js'
+const faceRecognitionSettingView = {}
+faceRecognitionSettingView.init = function () {
+    /**************************************************鍒涘缓灞忓箷*****************************************************/
+    const screenMain = dxui.View.build('faceRecognitionSettingView', dxui.Utils.LAYER.MAIN)
+    faceRecognitionSettingView.screenMain = screenMain
+    screenMain.scroll(false)
+    screenMain.bgColor(0xffffff)
+    screenMain.on(dxui.Utils.ENUM.LV_EVENT_SCREEN_LOADED, () => {
+        topView.changeTheme(true)
+
+        const configAll = screen.getConfig()
+        // 浜鸿劯鐩镐技搴﹂槇鍊�
+        faceRecognitionSettingView.info[0].slider.value(configAll['face.similarity'] * 100)
+        faceRecognitionSettingView.info[0].slider.send(dxui.Utils.EVENT.VALUE_CHANGED)
+        // 娲讳綋妫�娴嬪紑鍏�
+        faceRecognitionSettingView.info[1].switch.select(configAll['face.livenessOff'] == 1)
+        // 娲讳綋妫�娴嬮槇鍊�
+        faceRecognitionSettingView.info[2].slider.value(configAll['face.livenessVal'])
+        faceRecognitionSettingView.info[2].slider.send(dxui.Utils.EVENT.VALUE_CHANGED)
+        // 绾㈠鍥惧儚鏄剧ず
+        faceRecognitionSettingView.info[3].switch.select(configAll['face.showNir'] == 1)
+        // // 鍙g僵妫�娴嬪紑鍏�
+        // faceRecognitionSettingView.info[4].switch.select(configAll['face.detectMask'] == 1)
+    })
+
+    const titleBox = viewUtils.title(screenMain, systemSettingView.screenMain, 'faceRecognitionSettingViewTitle', 'systemSettingView.faceRecognitionSetting')
+    titleBox.align(dxui.Utils.ALIGN.TOP_MID, 0, 70)
+
+
+    faceRecognitionSettingView.info = [
+        {
+            title: "systemSettingView.faceSimilarityThreshold",
+            type: 'slider',
+            unit: '%'
+        },
+        {
+            title: "systemSettingView.livenessDetectionFunction",
+            type: 'switch',
+        },
+        {
+            title: "systemSettingView.livenessDetectionThreshold",
+            type: 'slider',
+            unit: ''
+        },
+        {
+            title: "systemSettingView.infraredImageDisplay",
+            type: 'switch',
+        },
+        // {
+        //     title: "systemSettingView.maskRecognition",
+        //     type: 'switch',
+        // },
+        // {
+        //     title: "systemSettingView.maskRecognitionThreshold",
+        //     type: 'slider',
+        //     unit: '%'
+        // },
+        // {
+        //     title: "systemSettingView.recognitionDistance",
+        //     type: 'input',
+        //     unit: 'cm'
+        // }
+    ]
+
+    const faceSettingBox = dxui.View.build('faceSettingBox', screenMain)
+    viewUtils._clearStyle(faceSettingBox)
+    faceSettingBox.align(dxui.Utils.ALIGN.TOP_MID, 0, 140)
+    faceSettingBox.setSize(screen.screenSize.width, 600)
+    faceSettingBox.bgOpa(0)
+    faceSettingBox.flexFlow(dxui.Utils.FLEX_FLOW.ROW_WRAP)
+    faceSettingBox.flexAlign(dxui.Utils.FLEX_ALIGN.CENTER, dxui.Utils.FLEX_ALIGN.START, dxui.Utils.FLEX_ALIGN.START)
+    faceSettingBox.obj.lvObjSetStylePadGap(0, dxui.Utils.ENUM._LV_STYLE_STATE_CMP_SAME)
+    faceSettingBox.borderWidth(1)
+    faceSettingBox.setBorderColor(0xDEDEDE)
+    faceSettingBox.obj.setStyleBorderSide(dxui.Utils.ENUM.LV_BORDER_SIDE_TOP, 0)
+
+
+    faceRecognitionSettingView.info.forEach(item => {
+        const itemBox = dxui.View.build(item.title, faceSettingBox)
+        viewUtils._clearStyle(itemBox)
+        itemBox.setSize(760, 76)
+        itemBox.borderWidth(1)
+        itemBox.setBorderColor(0xDEDEDE)
+        itemBox.obj.setStyleBorderSide(dxui.Utils.ENUM.LV_BORDER_SIDE_BOTTOM, 0)
+
+        const itemLabel = dxui.Label.build(item.title + 'Label', itemBox)
+        itemLabel.dataI18n = item.title
+        itemLabel.align(dxui.Utils.ALIGN.LEFT_MID, 0, 0)
+        itemLabel.textFont(viewUtils.font(26))
+        itemLabel.width(280)
+        itemLabel.longMode(dxui.Utils.LABEL_LONG_MODE.SCROLL_CIRCULAR)
+
+        if (item.unit) {
+            const unitLabel = dxui.Label.build(item.title + 'UnitLabel', itemBox)
+            unitLabel.text(item.unit)
+            unitLabel.align(dxui.Utils.ALIGN.RIGHT_MID, 0, 0)
+            unitLabel.textFont(viewUtils.font(26))
+        }
+
+        switch (item.type) {
+            case 'switch':
+                const __switch = dxui.Switch.build(item.title + 'switch', itemBox)
+                __switch.align(dxui.Utils.ALIGN.RIGHT_MID, 0, 0)
+                __switch.setSize(70, 35)
+                item.switch = __switch
+                break;
+            case 'input':
+                const input = viewUtils.input(itemBox, item.title + 'input', undefined, undefined, undefined)
+                input.align(dxui.Utils.ALIGN.RIGHT_MID, -45, 0)
+                input.setSize(100, 55)
+                item.input = input
+                break;
+            case 'slider':
+                const sliderLabel = dxui.Label.build(item.title + 'sliderLabel', itemBox)
+                sliderLabel.align(dxui.Utils.ALIGN.RIGHT_MID, -20, 0)
+                sliderLabel.width(50)
+                sliderLabel.text('0')
+                sliderLabel.textFont(viewUtils.font(26))
+                sliderLabel.textAlign(dxui.Utils.TEXT_ALIGN.RIGHT)
+
+                const slider = dxui.Slider.build(item.title + 'slider', itemBox)
+                slider.align(dxui.Utils.ALIGN.RIGHT_MID, -80, 0)
+                slider.width(150)
+                slider.range(0, 100)
+
+                slider.on(dxui.Utils.EVENT.VALUE_CHANGED, () => {
+                    sliderLabel.text(slider.value() + '')
+                })
+                item.slider = slider
+                break;
+        }
+    })
+
+    const saveBtn = viewUtils.bottomBtn(screenMain, screenMain.id + 'saveBtn', 'systemSettingView.save', () => {
+        const saveConfigData = {
+            face: {
+                similarity: faceRecognitionSettingView.info[0].slider.value() / 100,
+                livenessOff: faceRecognitionSettingView.info[1].switch.isSelect() ? 1 : 0,
+                livenessVal: faceRecognitionSettingView.info[2].slider.value(),
+                showNir: faceRecognitionSettingView.info[3].switch.isSelect() ? 1 : 0,
+                // detectMask: faceRecognitionSettingView.info[4].switch.isSelect() ? 1 : 0
+            }
+        }
+        const res = screen.saveConfig(saveConfigData)
+        if (res === true) {
+            faceRecognitionSettingView.statusPanel.success()
+            std.setTimeout(() => {
+                // 鎴愬姛杩斿洖涓婁竴灞傜晫闈�
+                dxui.loadMain(systemSettingView.screenMain)
+            }, 500)
+        } else {
+            faceRecognitionSettingView.statusPanel.fail()
+        }
+    })
+    saveBtn.align(dxui.Utils.ALIGN.BOTTOM_MID, 0, -83)
+
+    faceRecognitionSettingView.statusPanel = viewUtils.statusPanel(screenMain, 'systemSettingView.success', 'systemSettingView.fail')
+}
+
+export default faceRecognitionSettingView
diff --git a/vf205_access/src/view/config/menu/systemSetting/passLogSettingView.js b/vf205_access/src/view/config/menu/systemSetting/passLogSettingView.js
new file mode 100644
index 0000000..c72d874
--- /dev/null
+++ b/vf205_access/src/view/config/menu/systemSetting/passLogSettingView.js
@@ -0,0 +1,117 @@
+import dxui from '../../../../../dxmodules/dxUi.js'
+import std from '../../../../../dxmodules/dxStd.js'
+import viewUtils from "../../../viewUtils.js"
+import topView from "../../../topView.js"
+import i18n from "../../../i18n.js"
+import systemSettingView from '../systemSettingView.js'
+import screen from '../../../../screen.js'
+const passLogSettingView = {}
+passLogSettingView.init = function () {
+    /**************************************************鍒涘缓灞忓箷*****************************************************/
+    const screenMain = dxui.View.build('passLogSettingView', dxui.Utils.LAYER.MAIN)
+    passLogSettingView.screenMain = screenMain
+    screenMain.scroll(false)
+    screenMain.bgColor(0xffffff)
+    screenMain.on(dxui.Utils.ENUM.LV_EVENT_SCREEN_LOADED, () => {
+        topView.changeTheme(true)
+
+        // passLogSettingView.info[0].value = [i18n.t('systemSettingView.fullView'), i18n.t('systemSettingView.face')]
+        // passLogSettingView.info[0].dropdown.setOptions(passLogSettingView.info[0].value)
+
+        const configAll = screen.getConfig()
+        // passLogSettingView.info[0].dropdown.setSelected(configAll['sys.accessImageType'])
+        passLogSettingView.info[0].switch.select(configAll['sys.strangerImage'] == 1)
+    })
+
+    const titleBox = viewUtils.title(screenMain, systemSettingView.screenMain, 'passLogSettingViewTitle', 'systemSettingView.passLogSetting')
+    titleBox.align(dxui.Utils.ALIGN.TOP_MID, 0, 70)
+
+    passLogSettingView.info = [
+        // {
+        //     title: "systemSettingView.imageSaveType",
+        //     type: 'dropdown',
+        //     value: [i18n.t('systemSettingView.fullView'), i18n.t('systemSettingView.face')],
+        //     dropdown: null
+        // },
+        {
+            title: "systemSettingView.saveStrangerImage",
+            type: 'switch',
+        },
+    ]
+
+    const passSettingBox = dxui.View.build('passSettingBox', screenMain)
+    viewUtils._clearStyle(passSettingBox)
+    passSettingBox.align(dxui.Utils.ALIGN.TOP_MID, 0, 140)
+    passSettingBox.setSize(screen.screenSize.width, 600)
+    passSettingBox.bgOpa(0)
+    passSettingBox.flexFlow(dxui.Utils.FLEX_FLOW.ROW_WRAP)
+    passSettingBox.flexAlign(dxui.Utils.FLEX_ALIGN.CENTER, dxui.Utils.FLEX_ALIGN.START, dxui.Utils.FLEX_ALIGN.START)
+    passSettingBox.obj.lvObjSetStylePadGap(0, dxui.Utils.ENUM._LV_STYLE_STATE_CMP_SAME)
+    passSettingBox.borderWidth(1)
+    passSettingBox.setBorderColor(0xDEDEDE)
+    passSettingBox.obj.setStyleBorderSide(dxui.Utils.ENUM.LV_BORDER_SIDE_TOP, 0)
+
+    passLogSettingView.info.forEach(item => {
+        const itemBox = dxui.View.build(item.title, passSettingBox)
+        viewUtils._clearStyle(itemBox)
+        itemBox.setSize(760, 76)
+        itemBox.borderWidth(1)
+        itemBox.setBorderColor(0xDEDEDE)
+        itemBox.obj.setStyleBorderSide(dxui.Utils.ENUM.LV_BORDER_SIDE_BOTTOM, 0)
+
+        const itemLabel = dxui.Label.build(item.title + 'Label', itemBox)
+        itemLabel.dataI18n = item.title
+        itemLabel.align(dxui.Utils.ALIGN.LEFT_MID, 0, 0)
+        itemLabel.textFont(viewUtils.font(26))
+
+        if (item.unit) {
+            const unitLabel = dxui.Label.build(item.title + 'UnitLabel', itemBox)
+            unitLabel.text(item.unit)
+            unitLabel.align(dxui.Utils.ALIGN.RIGHT_MID, 0, 0)
+            unitLabel.textFont(viewUtils.font(26))
+        }
+
+        switch (item.type) {
+            case 'switch':
+                const __switch = dxui.Switch.build(item.title + 'switch', itemBox)
+                __switch.align(dxui.Utils.ALIGN.RIGHT_MID, 0, 0)
+                __switch.setSize(70, 35)
+                item.switch = __switch
+                break;
+            case 'dropdown':
+                const dropdown = dxui.Dropdown.build(item.title + 'dropdown', itemBox)
+                dropdown.align(dxui.Utils.ALIGN.RIGHT_MID, 0, 0)
+                dropdown.setSize(200, 60)
+                dropdown.textFont(viewUtils.font(26))
+                dropdown.getList().textFont(viewUtils.font(26))
+                dropdown.setSymbol('/app/code/resource/image/down.png')
+                dropdown.setOptions(item.value)
+                item.dropdown = dropdown
+                break;
+        }
+    })
+
+    const saveBtn = viewUtils.bottomBtn(screenMain, screenMain.id + 'saveBtn', 'systemSettingView.save', () => {
+        const saveConfigData = {
+            sys: {
+                // accessImageType: passLogSettingView.info[0].dropdown.getSelected(),
+                strangerImage: passLogSettingView.info[0].switch.isSelect() ? 1 : 0
+            }
+        }
+        const res = screen.saveConfig(saveConfigData)
+        if (res === true) {
+            passLogSettingView.statusPanel.success()
+            std.setTimeout(() => {
+                // 鎴愬姛杩斿洖涓婁竴灞傜晫闈�
+                dxui.loadMain(systemSettingView.screenMain)
+            }, 500)
+        } else {
+            passLogSettingView.statusPanel.fail()
+        }
+    })
+    saveBtn.align(dxui.Utils.ALIGN.BOTTOM_MID, 0, -83)
+
+    passLogSettingView.statusPanel = viewUtils.statusPanel(screenMain, 'systemSettingView.success', 'systemSettingView.fail')
+}
+
+export default passLogSettingView
diff --git a/vf205_access/src/view/config/menu/systemSetting/passwordManagementView.js b/vf205_access/src/view/config/menu/systemSetting/passwordManagementView.js
new file mode 100644
index 0000000..1e289ab
--- /dev/null
+++ b/vf205_access/src/view/config/menu/systemSetting/passwordManagementView.js
@@ -0,0 +1,115 @@
+
+import dxui from '../../../../../dxmodules/dxUi.js'
+import std from '../../../../../dxmodules/dxStd.js'
+import viewUtils from "../../../viewUtils.js"
+import topView from "../../../topView.js"
+import systemSettingView from '../systemSettingView.js'
+import i18n from "../../../i18n.js"
+import screen from '../../../../screen.js'
+const passwordManagementView = {}
+passwordManagementView.init = function () {
+    /**************************************************鍒涘缓灞忓箷*****************************************************/
+    const screenMain = dxui.View.build('passwordManagementView', dxui.Utils.LAYER.MAIN)
+    passwordManagementView.screenMain = screenMain
+    screenMain.scroll(false)
+    screenMain.bgColor(0xffffff)
+    screenMain.on(dxui.Utils.ENUM.LV_EVENT_SCREEN_LOADED, () => {
+        topView.changeTheme(true)
+    })
+
+    const titleBox = viewUtils.title(screenMain, systemSettingView.screenMain, 'passwordManagementViewTitle', 'systemSettingView.passwordManagement')
+    titleBox.align(dxui.Utils.ALIGN.TOP_MID, 0, 70)
+
+    passwordManagementView.info = [
+        {
+            title: "systemSettingView.inputOriginalPassword",
+            type: 'input',
+        },
+        {
+            title: "systemSettingView.inputNewPassword",
+            type: 'input',
+        },
+        {
+            title: "systemSettingView.inputRepeatNewPassword",
+            type: 'input',
+        }
+    ]
+
+    const passwordManagementBox = dxui.View.build('passwordManagementBox', screenMain)
+    viewUtils._clearStyle(passwordManagementBox)
+    passwordManagementBox.align(dxui.Utils.ALIGN.TOP_MID, 0, 140)
+    passwordManagementBox.setSize(screen.screenSize.width, 300)
+    passwordManagementBox.bgOpa(0)
+    passwordManagementBox.flexFlow(dxui.Utils.FLEX_FLOW.ROW_WRAP)
+    passwordManagementBox.flexAlign(dxui.Utils.FLEX_ALIGN.CENTER, dxui.Utils.FLEX_ALIGN.START, dxui.Utils.FLEX_ALIGN.START)
+    passwordManagementBox.obj.lvObjSetStylePadGap(0, dxui.Utils.ENUM._LV_STYLE_STATE_CMP_SAME)
+    passwordManagementBox.borderWidth(1)
+    passwordManagementBox.setBorderColor(0xDEDEDE)
+    passwordManagementBox.obj.setStyleBorderSide(dxui.Utils.ENUM.LV_BORDER_SIDE_TOP, 0)
+
+    passwordManagementView.info.forEach(item => {
+        const itemBox = dxui.View.build(item.title, passwordManagementBox)
+        viewUtils._clearStyle(itemBox)
+        itemBox.setSize(760, 76)
+        itemBox.borderWidth(1)
+        itemBox.setBorderColor(0xDEDEDE)
+        itemBox.obj.setStyleBorderSide(dxui.Utils.ENUM.LV_BORDER_SIDE_BOTTOM, 0)
+
+        const itemLabel = dxui.Label.build(item.title + 'Label', itemBox)
+        itemLabel.dataI18n = item.title
+        itemLabel.align(dxui.Utils.ALIGN.LEFT_MID, 0, 0)
+        itemLabel.textFont(viewUtils.font(26))
+        itemLabel.width(300)
+        itemLabel.longMode(dxui.Utils.LABEL_LONG_MODE.SCROLL_CIRCULAR)
+
+        if (item.unit) {
+            const unitLabel = dxui.Label.build(item.title + 'UnitLabel', itemBox)
+            unitLabel.text(item.unit)
+            unitLabel.align(dxui.Utils.ALIGN.RIGHT_MID, 0, 0)
+            unitLabel.textFont(viewUtils.font(26))
+        }
+
+        switch (item.type) {
+            case 'input':
+                const input = viewUtils.input(itemBox, item.title + 'input', undefined, undefined, undefined)
+                input.align(dxui.Utils.ALIGN.RIGHT_MID, 0, 0)
+                input.setSize(280, 55)
+                item.input = input
+                break;
+        }
+    })
+
+
+    const saveBtn = viewUtils.bottomBtn(screenMain, screenMain.id + 'saveBtn', 'systemSettingView.save', () => {
+        const configAll = screen.getConfig()
+        if (configAll['base.password'] != passwordManagementView.info[0].input.text()) {
+            passwordManagementView.statusPanel.fail()
+            return
+        }
+
+        if (passwordManagementView.info[1].input.text() != passwordManagementView.info[2].input.text()) {
+            passwordManagementView.statusPanel.fail()
+            return
+        }
+
+        const saveConfigData = {
+            base: {
+                password: passwordManagementView.info[2].input.text(),
+            }
+        }
+        const res = screen.saveConfig(saveConfigData)
+        if (res === true) {
+            passwordManagementView.statusPanel.success()
+            std.setTimeout(() => {
+                // 鎴愬姛杩斿洖涓婁竴灞傜晫闈�
+                dxui.loadMain(systemSettingView.screenMain)
+            }, 500)
+        } else {
+            passwordManagementView.statusPanel.fail()
+        }
+    })
+    saveBtn.align(dxui.Utils.ALIGN.BOTTOM_MID, 0, -83)
+    passwordManagementView.statusPanel = viewUtils.statusPanel(screenMain, 'systemSettingView.success', 'systemSettingView.fail')
+}
+
+export default passwordManagementView
diff --git a/vf205_access/src/view/config/menu/systemSetting/passwordOpenDoorSettingView.js b/vf205_access/src/view/config/menu/systemSetting/passwordOpenDoorSettingView.js
new file mode 100644
index 0000000..7c4b764
--- /dev/null
+++ b/vf205_access/src/view/config/menu/systemSetting/passwordOpenDoorSettingView.js
@@ -0,0 +1,144 @@
+import dxui from '../../../../../dxmodules/dxUi.js'
+import std from '../../../../../dxmodules/dxStd.js'
+import viewUtils from "../../../viewUtils.js"
+import topView from "../../../topView.js"
+import i18n from "../../../i18n.js"
+import systemSettingView from '../systemSettingView.js'
+import screen from '../../../../screen.js'
+import sqliteService from '../../../../service/sqliteService.js'
+import logger from '../../../../../dxmodules/dxLogger.js'
+const passwordOpenDoorSettingView = {}
+passwordOpenDoorSettingView.init = function () {
+    /**************************************************鍒涘缓灞忓箷*****************************************************/
+    const screenMain = dxui.View.build('passwordOpenDoorSettingView', dxui.Utils.LAYER.MAIN)
+    passwordOpenDoorSettingView.screenMain = screenMain
+    screenMain.scroll(false)
+    screenMain.bgColor(0xffffff)
+    screenMain.on(dxui.Utils.ENUM.LV_EVENT_SCREEN_LOADED, () => {
+        topView.changeTheme(true)
+
+        const configAll = screen.getConfig()
+        passwordOpenDoorSettingView.info[0].switch.select(configAll['sys.pwd'] == 1)
+        // 鍔犺浇搴旀�ュ紑浠撳瘑鐮侊紙浠庢暟鎹簱锛�
+        if (passwordOpenDoorSettingView.info[1].input) {
+            try {
+                const passwords = sqliteService.d1_emergency_password.findAll()
+                if (passwords && passwords.length > 0) {
+                    // 鍙樉绀虹涓�涓瘑鐮侊紝鍥犱负搴旀�ュ紑浠撳瘑鐮佸湪璁惧涓粎鏈夊敮涓�鐨�1涓�
+                    passwordOpenDoorSettingView.info[1].input.text(passwords[0].password || '')
+                }
+            } catch (error) {
+                logger.error('鍔犺浇搴旀�ュ紑浠撳瘑鐮佸け璐�:', error)
+            }
+        }
+    })
+
+    const titleBox = viewUtils.title(screenMain, systemSettingView.screenMain, 'passwordOpenDoorSettingViewTitle', 'systemSettingView.passwordOpenDoorSetting')
+    titleBox.align(dxui.Utils.ALIGN.TOP_MID, 0, 70)
+
+    passwordOpenDoorSettingView.info = [
+        {
+            title: "systemSettingView.passwordOpenDoor",
+            type: 'switch',
+        },
+        {
+            title: "搴旀�ュ紑浠撳瘑鐮�",
+            type: 'input',
+            placeholder: '璇疯緭鍏ヨ嚦灏�8浣嶅簲鎬ュ紑浠撳瘑鐮�',
+            password: true
+        }
+    ]
+
+    const passwordOpenDoorSettingBox = dxui.View.build('passwordOpenDoorSettingBox', screenMain)
+    viewUtils._clearStyle(passwordOpenDoorSettingBox)
+    passwordOpenDoorSettingBox.align(dxui.Utils.ALIGN.TOP_MID, 0, 140)
+    passwordOpenDoorSettingBox.setSize(screen.screenSize.width, 600)
+    passwordOpenDoorSettingBox.bgOpa(0)
+    passwordOpenDoorSettingBox.flexFlow(dxui.Utils.FLEX_FLOW.ROW_WRAP)
+    passwordOpenDoorSettingBox.flexAlign(dxui.Utils.FLEX_ALIGN.CENTER, dxui.Utils.FLEX_ALIGN.START, dxui.Utils.FLEX_ALIGN.START)
+    passwordOpenDoorSettingBox.obj.lvObjSetStylePadGap(0, dxui.Utils.ENUM._LV_STYLE_STATE_CMP_SAME)
+    passwordOpenDoorSettingBox.borderWidth(1)
+    passwordOpenDoorSettingBox.setBorderColor(0xDEDEDE)
+    passwordOpenDoorSettingBox.obj.setStyleBorderSide(dxui.Utils.ENUM.LV_BORDER_SIDE_TOP, 0)
+
+    passwordOpenDoorSettingView.info.forEach(item => {
+        const itemBox = dxui.View.build(item.title, passwordOpenDoorSettingBox)
+        viewUtils._clearStyle(itemBox)
+        itemBox.setSize(760, 76)
+        itemBox.borderWidth(1)
+        itemBox.setBorderColor(0xDEDEDE)
+        itemBox.obj.setStyleBorderSide(dxui.Utils.ENUM.LV_BORDER_SIDE_BOTTOM, 0)
+
+        const itemLabel = dxui.Label.build(item.title + 'Label', itemBox)
+        itemLabel.dataI18n = item.title
+        itemLabel.align(dxui.Utils.ALIGN.LEFT_MID, 0, 0)
+        itemLabel.textFont(viewUtils.font(26))
+
+        if (item.unit) {
+            const unitLabel = dxui.Label.build(item.title + 'UnitLabel', itemBox)
+            unitLabel.text(item.unit)
+            unitLabel.align(dxui.Utils.ALIGN.RIGHT_MID, 0, 0)
+            unitLabel.textFont(viewUtils.font(26))
+        }
+
+        switch (item.type) {
+            case 'switch':
+                const __switch = dxui.Switch.build(item.title + 'switch', itemBox)
+                __switch.align(dxui.Utils.ALIGN.RIGHT_MID, 0, 0)
+                __switch.setSize(70, 35)
+                item.switch = __switch
+                break;
+            case 'input':
+                const input = viewUtils.input(itemBox, item.title + 'input', undefined, undefined, item.placeholder)
+                input.align(dxui.Utils.ALIGN.RIGHT_MID, 0, 0)
+                input.setSize(300, 40)
+                input.setPasswordMode(item.password)
+                item.input = input
+                break;
+        }
+    })
+
+    const saveBtn = viewUtils.bottomBtn(screenMain, screenMain.id + 'saveBtn', 'systemSettingView.save', () => {
+        const emergencyPassword = passwordOpenDoorSettingView.info[1].input.text()
+        const saveConfigData = {
+            sys: {
+                pwd: passwordOpenDoorSettingView.info[0].switch.isSelect() ? 1 : 0
+            }
+        }
+        
+        // 鏇存柊鏁版嵁搴撲腑鐨勫簲鎬ュ紑浠撳瘑鐮�
+        try {
+            // 鍏堝垹闄ゆ棫鐨勫簲鎬ュ紑浠撳瘑鐮�
+            sqliteService.d1_emergency_password.deleteAll()
+            // 娣诲姞鏂扮殑搴旀�ュ紑浠撳瘑鐮�
+            if (emergencyPassword) {
+                sqliteService.d1_emergency_password.save({
+                    id: 'emergency_' + Date.now(),
+                    password: emergencyPassword,
+                    description: '绯荤粺璁剧疆鐨勫簲鎬ュ紑浠撳瘑鐮�',
+                    createTime: Date.now(),
+                    updateTime: Date.now(),
+                    status: 1
+                })
+            }
+        } catch (error) {
+            logger.error('鏇存柊搴旀�ュ紑浠撳瘑鐮佸け璐�:', error)
+        }
+        
+        const res = screen.saveConfig(saveConfigData)
+        if (res === true) {
+            passwordOpenDoorSettingView.statusPanel.success()
+            std.setTimeout(() => {
+                // 鎴愬姛杩斿洖涓婁竴灞傜晫闈�
+                dxui.loadMain(systemSettingView.screenMain)
+            }, 500)
+        } else {
+            passwordOpenDoorSettingView.statusPanel.fail()
+        }
+    })
+    saveBtn.align(dxui.Utils.ALIGN.BOTTOM_MID, 0, -83)
+
+    passwordOpenDoorSettingView.statusPanel = viewUtils.statusPanel(screenMain, 'systemSettingView.success', 'systemSettingView.fail')
+}
+
+export default passwordOpenDoorSettingView
diff --git a/vf205_access/src/view/config/menu/systemSetting/swipeCardRecognitionSettingView.js b/vf205_access/src/view/config/menu/systemSetting/swipeCardRecognitionSettingView.js
new file mode 100644
index 0000000..ef12287
--- /dev/null
+++ b/vf205_access/src/view/config/menu/systemSetting/swipeCardRecognitionSettingView.js
@@ -0,0 +1,96 @@
+import dxui from '../../../../../dxmodules/dxUi.js'
+import std from '../../../../../dxmodules/dxStd.js'
+import viewUtils from "../../../viewUtils.js"
+import topView from "../../../topView.js"
+import systemSettingView from '../systemSettingView.js'
+import i18n from "../../../i18n.js"
+import screen from '../../../../screen.js'
+const swipeCardRecognitionSettingView = {}
+swipeCardRecognitionSettingView.init = function () {
+    /**************************************************鍒涘缓灞忓箷*****************************************************/
+    const screenMain = dxui.View.build('swipeCardRecognitionSettingView', dxui.Utils.LAYER.MAIN)
+    swipeCardRecognitionSettingView.screenMain = screenMain
+    screenMain.scroll(false)
+    screenMain.bgColor(0xffffff)
+    screenMain.on(dxui.Utils.ENUM.LV_EVENT_SCREEN_LOADED, () => {
+        topView.changeTheme(true)
+
+        const configAll = screen.getConfig()
+        swipeCardRecognitionSettingView.info[0].switch.select(configAll['sys.nfc'] == 1)
+    })
+
+    const titleBox = viewUtils.title(screenMain, systemSettingView.screenMain, 'swipeCardRecognitionSettingViewTitle', 'systemSettingView.swipeCardRecognitionSetting')
+    titleBox.align(dxui.Utils.ALIGN.TOP_MID, 0, 70)
+
+    swipeCardRecognitionSettingView.info = [
+        {
+            title: "systemSettingView.swipeCardRecognition",
+            type: 'switch',
+        }
+    ]
+
+    const swipeCardRecognitionSettingBox = dxui.View.build('swipeCardRecognitionSettingBox', screenMain)
+    viewUtils._clearStyle(swipeCardRecognitionSettingBox)
+    swipeCardRecognitionSettingBox.align(dxui.Utils.ALIGN.TOP_MID, 0, 140)
+    swipeCardRecognitionSettingBox.setSize(screen.screenSize.width, 600)
+    swipeCardRecognitionSettingBox.bgOpa(0)
+    swipeCardRecognitionSettingBox.flexFlow(dxui.Utils.FLEX_FLOW.ROW_WRAP)
+    swipeCardRecognitionSettingBox.flexAlign(dxui.Utils.FLEX_ALIGN.CENTER, dxui.Utils.FLEX_ALIGN.START, dxui.Utils.FLEX_ALIGN.START)
+    swipeCardRecognitionSettingBox.obj.lvObjSetStylePadGap(0, dxui.Utils.ENUM._LV_STYLE_STATE_CMP_SAME)
+    swipeCardRecognitionSettingBox.borderWidth(1)
+    swipeCardRecognitionSettingBox.setBorderColor(0xDEDEDE)
+    swipeCardRecognitionSettingBox.obj.setStyleBorderSide(dxui.Utils.ENUM.LV_BORDER_SIDE_TOP, 0)
+
+    swipeCardRecognitionSettingView.info.forEach(item => {
+        const itemBox = dxui.View.build(item.title, swipeCardRecognitionSettingBox)
+        viewUtils._clearStyle(itemBox)
+        itemBox.setSize(760, 76)
+        itemBox.borderWidth(1)
+        itemBox.setBorderColor(0xDEDEDE)
+        itemBox.obj.setStyleBorderSide(dxui.Utils.ENUM.LV_BORDER_SIDE_BOTTOM, 0)
+
+        const itemLabel = dxui.Label.build(item.title + 'Label', itemBox)
+        itemLabel.dataI18n = item.title
+        itemLabel.align(dxui.Utils.ALIGN.LEFT_MID, 0, 0)
+        itemLabel.textFont(viewUtils.font(26))
+
+        if (item.unit) {
+            const unitLabel = dxui.Label.build(item.title + 'UnitLabel', itemBox)
+            unitLabel.text(item.unit)
+            unitLabel.align(dxui.Utils.ALIGN.RIGHT_MID, 0, 0)
+            unitLabel.textFont(viewUtils.font(26))
+        }
+
+        switch (item.type) {
+            case 'switch':
+                const __switch = dxui.Switch.build(item.title + 'switch', itemBox)
+                __switch.align(dxui.Utils.ALIGN.RIGHT_MID, 0, 0)
+                __switch.setSize(70, 35)
+                item.switch = __switch
+                break;
+        }
+    })
+
+    const saveBtn = viewUtils.bottomBtn(screenMain, screenMain.id + 'saveBtn', 'systemSettingView.save', () => {
+        const saveConfigData = {
+            sys: {
+                nfc: swipeCardRecognitionSettingView.info[0].switch.isSelect() ? 1 : 0,
+            }
+        }
+        const res = screen.saveConfig(saveConfigData)
+        if (res === true) {
+            swipeCardRecognitionSettingView.statusPanel.success()
+            std.setTimeout(() => {
+                // 鎴愬姛杩斿洖涓婁竴灞傜晫闈�
+                dxui.loadMain(systemSettingView.screenMain)
+            }, 500)
+        } else {
+            swipeCardRecognitionSettingView.statusPanel.fail()
+        }
+    })
+    saveBtn.align(dxui.Utils.ALIGN.BOTTOM_MID, 0, -83)
+
+    swipeCardRecognitionSettingView.statusPanel = viewUtils.statusPanel(screenMain, 'systemSettingView.success', 'systemSettingView.fail')
+}
+
+export default swipeCardRecognitionSettingView
diff --git a/vf205_access/src/view/config/menu/systemSetting/timeSettingView.js b/vf205_access/src/view/config/menu/systemSetting/timeSettingView.js
new file mode 100644
index 0000000..1012fc9
--- /dev/null
+++ b/vf205_access/src/view/config/menu/systemSetting/timeSettingView.js
@@ -0,0 +1,124 @@
+import dxui from '../../../../../dxmodules/dxUi.js'
+import std from '../../../../../dxmodules/dxStd.js'
+import dxMap from '../../../../../dxmodules/dxMap.js'
+import viewUtils from "../../../viewUtils.js"
+import topView from "../../../topView.js"
+import systemSettingView from '../systemSettingView.js'
+import i18n from "../../../i18n.js"
+import screen from '../../../../screen.js'
+const timeSettingView = {}
+timeSettingView.init = function () {
+    /**************************************************鍒涘缓灞忓箷*****************************************************/
+    const screenMain = dxui.View.build('timeSettingView', dxui.Utils.LAYER.MAIN)
+    timeSettingView.screenMain = screenMain
+    screenMain.scroll(false)
+    screenMain.bgColor(0xffffff)
+    screenMain.on(dxui.Utils.ENUM.LV_EVENT_SCREEN_LOADED, () => {
+        topView.changeTheme(true)
+
+        const configAll = screen.getConfig()
+        timeSettingView.info[0].input.text(configAll['ntp.gmt'] + '')
+        timeSettingView.info[1].input.text(configAll['ntp.server'] + '')
+
+        const syncTime = dxMap.get("NTP_SYNC").get("syncTime")
+        if (syncTime) {
+            msgLabel.text(new Date(syncTime).toLocaleString())
+        }
+    })
+
+    const titleBox = viewUtils.title(screenMain, systemSettingView.screenMain, 'timeSettingViewTitle', 'systemSettingView.timeSetting')
+    titleBox.align(dxui.Utils.ALIGN.TOP_MID, 0, 70)
+
+    timeSettingView.info = [
+        {
+            title: "systemSettingView.syncMode",
+            type: 'input',
+        },
+        {
+            title: "systemSettingView.ntpAddress",
+            type: 'input',
+        }
+    ]
+
+    const timeSettingBox = dxui.View.build('timeSettingBox', screenMain)
+    viewUtils._clearStyle(timeSettingBox)
+    timeSettingBox.align(dxui.Utils.ALIGN.TOP_MID, 0, 140)
+    timeSettingBox.setSize(screen.screenSize.width, 300)
+    timeSettingBox.bgOpa(0)
+    timeSettingBox.flexFlow(dxui.Utils.FLEX_FLOW.ROW_WRAP)
+    timeSettingBox.flexAlign(dxui.Utils.FLEX_ALIGN.CENTER, dxui.Utils.FLEX_ALIGN.START, dxui.Utils.FLEX_ALIGN.START)
+    timeSettingBox.obj.lvObjSetStylePadGap(0, dxui.Utils.ENUM._LV_STYLE_STATE_CMP_SAME)
+    timeSettingBox.borderWidth(1)
+    timeSettingBox.setBorderColor(0xDEDEDE)
+    timeSettingBox.obj.setStyleBorderSide(dxui.Utils.ENUM.LV_BORDER_SIDE_TOP, 0)
+
+    timeSettingView.info.forEach(item => {
+        const itemBox = dxui.View.build(item.title, timeSettingBox)
+        viewUtils._clearStyle(itemBox)
+        itemBox.setSize(760, 76)
+        itemBox.borderWidth(1)
+        itemBox.setBorderColor(0xDEDEDE)
+        itemBox.obj.setStyleBorderSide(dxui.Utils.ENUM.LV_BORDER_SIDE_BOTTOM, 0)
+
+        const itemLabel = dxui.Label.build(item.title + 'Label', itemBox)
+        itemLabel.dataI18n = item.title
+        itemLabel.align(dxui.Utils.ALIGN.LEFT_MID, 0, 0)
+        itemLabel.textFont(viewUtils.font(26))
+
+        if (item.unit) {
+            const unitLabel = dxui.Label.build(item.title + 'UnitLabel', itemBox)
+            unitLabel.text(item.unit)
+            unitLabel.align(dxui.Utils.ALIGN.RIGHT_MID, 0, 0)
+            unitLabel.textFont(viewUtils.font(26))
+        }
+
+        switch (item.type) {
+            case 'input':
+                const input = viewUtils.input(itemBox, item.title + 'input', undefined, undefined, undefined)
+                input.align(dxui.Utils.ALIGN.RIGHT_MID, 0, 0)
+                if (item.title == "systemSettingView.ntpAddress") {
+                    input.setSize(300, 55)
+                } else {
+                    input.setSize(150, 55)
+                }
+                item.input = input
+                break;
+        }
+    })
+
+    const msgLabel = dxui.Label.build('msgLabel', screenMain)
+    msgLabel.align(dxui.Utils.ALIGN.TOP_MID, 0, 662)
+    msgLabel.textFont(viewUtils.font(22))
+    msgLabel.text('2024/02/12 19:07')
+    msgLabel.textColor(0x888888)
+
+    const msgLabel2 = dxui.Label.build('msgLabel2', screenMain)
+    msgLabel2.align(dxui.Utils.ALIGN.TOP_MID, 0, 690)
+    msgLabel2.textFont(viewUtils.font(22))
+    msgLabel2.textColor(0x888888)
+    msgLabel2.dataI18n = 'systemSettingView.timeSyncSuccess'
+
+
+    const saveBtn = viewUtils.bottomBtn(screenMain, screenMain.id + 'saveBtn', 'systemSettingView.save', () => {
+        const saveConfigData = {
+            ntp: {
+                gmt: parseInt(timeSettingView.info[0].input.text()),
+                server: timeSettingView.info[1].input.text(),
+            }
+        }
+        const res = screen.saveConfig(saveConfigData)
+        if (res === true) {
+            timeSettingView.statusPanel.success()
+            std.setTimeout(() => {
+                // 鎴愬姛杩斿洖涓婁竴灞傜晫闈�
+                dxui.loadMain(systemSettingView.screenMain)
+            }, 500)
+        } else {
+            timeSettingView.statusPanel.fail()
+        }
+    })
+    saveBtn.align(dxui.Utils.ALIGN.BOTTOM_MID, 0, -83)
+    timeSettingView.statusPanel = viewUtils.statusPanel(screenMain, 'systemSettingView.success', 'systemSettingView.fail')
+}
+
+export default timeSettingView
diff --git a/vf205_access/src/view/config/menu/systemSettingView.js b/vf205_access/src/view/config/menu/systemSettingView.js
new file mode 100644
index 0000000..dc62150
--- /dev/null
+++ b/vf205_access/src/view/config/menu/systemSettingView.js
@@ -0,0 +1,184 @@
+import dxui from '../../../../dxmodules/dxUi.js'
+import std from '../../../../dxmodules/dxStd.js'
+import dxCommon from '../../../../dxmodules/dxCommon.js'
+import viewUtils from "../../viewUtils.js"
+import topView from "../../topView.js"
+import configView from '../configView.js'
+import displaySettingView from './systemSetting/displaySettingView.js'
+import faceRecognitionSettingView from './systemSetting/faceRecognitionSettingView.js'
+import swipeCardRecognitionSettingView from './systemSetting/swipeCardRecognitionSettingView.js'
+import passLogSettingView from './systemSetting/passLogSettingView.js'
+import passwordOpenDoorSettingView from './systemSetting/passwordOpenDoorSettingView.js'
+import passwordManagementView from './systemSetting/passwordManagementView.js'
+import timeSettingView from './systemSetting/timeSettingView.js'
+import i18n from "../../i18n.js"
+import screen from '../../../screen.js'
+
+const systemSettingView = {}
+systemSettingView.init = function () {
+    /**************************************************鍒涘缓灞忓箷*****************************************************/
+    const screenMain = dxui.View.build('systemSettingView', dxui.Utils.LAYER.MAIN)
+    systemSettingView.screenMain = screenMain
+    screenMain.scroll(false)
+    screenMain.bgColor(0xffffff)
+    screenMain.on(dxui.Utils.ENUM.LV_EVENT_SCREEN_LOADED, () => {
+        topView.changeTheme(true)
+    })
+
+    const titleBox = viewUtils.title(screenMain, configView.screenMain, 'systemSettingViewTitle', 'systemSettingView.title')
+    titleBox.align(dxui.Utils.ALIGN.TOP_MID, 0, 70)
+
+    systemSettingView.sysInfo = [
+        {
+            title: 'systemSettingView.displaySetting',
+            type: 'menu',
+            view: displaySettingView,
+            obj: null,
+        },
+        {
+            title: 'systemSettingView.faceRecognitionSetting',
+            type: 'menu',
+            view: faceRecognitionSettingView,
+            obj: null,
+        },
+        {
+            title: 'systemSettingView.swipeCardRecognitionSetting',
+            type: 'menu',
+            view: swipeCardRecognitionSettingView,
+            obj: null,
+        },
+        {
+            title: 'systemSettingView.passLogSetting',
+            type: 'menu',
+            view: passLogSettingView,
+            obj: null,
+        },
+        {
+            title: 'systemSettingView.passwordOpenDoorSetting',
+            type: 'menu',
+            view: passwordOpenDoorSettingView,
+            obj: null,
+        },
+        {
+            title: 'systemSettingView.passwordManagement',
+            type: 'menu',
+            view: passwordManagementView,
+            obj: null,
+        },
+        {
+            title: 'systemSettingView.timeSetting',
+            type: 'menu',
+            view: timeSettingView,
+            obj: null,
+        },
+        {
+            title: 'systemSettingView.restartDevice',
+            type: 'button',
+            obj: null,
+        },
+        {
+            title: 'systemSettingView.restoreDefaultConfig',
+            type: 'button',
+            obj: null,
+        },
+        {
+            title: 'systemSettingView.resetDevice',
+            type: 'button',
+            obj: null,
+        },
+    ]
+
+
+    const settingBox = dxui.View.build('settingBox', screenMain)
+    viewUtils._clearStyle(settingBox)
+    settingBox.setSize(screen.screenSize.width, screen.screenSize.height - 140)
+    settingBox.align(dxui.Utils.ALIGN.TOP_MID, 0, 140)
+    settingBox.bgColor(0xf7f7f7)
+    settingBox.flexFlow(dxui.Utils.FLEX_FLOW.ROW_WRAP)
+    settingBox.flexAlign(dxui.Utils.FLEX_ALIGN.CENTER, dxui.Utils.FLEX_ALIGN.START, dxui.Utils.FLEX_ALIGN.START)
+    settingBox.obj.lvObjSetStylePadGap(10, dxui.Utils.ENUM._LV_STYLE_STATE_CMP_SAME)
+    settingBox.padTop(10)
+    settingBox.padBottom(10)
+
+    systemSettingView.sysInfo.forEach(item => {
+        item.obj = dxui.View.build(item.title, settingBox)
+        viewUtils._clearStyle(item.obj)
+        item.obj.setSize(760, 76)
+        item.obj.bgColor(0xffffff)
+        item.obj.radius(10)
+        item.obj.on(dxui.Utils.ENUM.LV_EVENT_PRESSED, () => {
+            item.obj.bgColor(0xEAEAEA)
+        })
+        item.obj.on(dxui.Utils.ENUM.LV_EVENT_RELEASED, () => {
+            item.obj.bgColor(0xffffff)
+        })
+
+        const titleLbl = dxui.Label.build(item.title + 'Label', item.obj)
+        titleLbl.dataI18n = item.title
+        titleLbl.align(dxui.Utils.ALIGN.LEFT_MID, 20, 0)
+        titleLbl.textFont(viewUtils.font(26))
+
+        switch (item.type) {
+            case 'menu':
+                const image = dxui.Image.build(item.title + 'Image', item.obj)
+                image.align(dxui.Utils.ALIGN.RIGHT_MID, -15, 0)
+                image.source('/app/code/resource/image/right.png')
+                item.obj.on(dxui.Utils.EVENT.CLICK, () => {
+                    dxui.loadMain(item.view.screenMain)
+                })
+                break
+            case 'button':
+                const btn = dxui.Button.build(item.title + 'Button', item.obj)
+                btn.align(dxui.Utils.ALIGN.RIGHT_MID, -15, 0)
+                btn.setSize(200, 44)
+                btn.radius(10)
+                btn.bgColor(0xEAEAEA)
+
+                const btnLbl = dxui.Label.build(btn.id + 'Label', btn)
+                btnLbl.align(dxui.Utils.ALIGN.CENTER, 0, 0)
+                btnLbl.textFont(viewUtils.font(24))
+                btnLbl.textColor(0x767676)
+
+                if (item.title == 'systemSettingView.restartDevice') {
+                    btnLbl.dataI18n = 'systemSettingView.restart'
+                    btn.on(dxui.Utils.EVENT.CLICK, () => {
+                        viewUtils.confirmOpen('systemSettingView.confirmation', 'systemSettingView.confirmRestart', () => {
+                            std.setTimeout(() => {
+                                dxCommon.systemBrief("reboot -f")
+                            }, 1000)
+                        }, () => { })
+                    })
+                } else if (item.title == 'systemSettingView.restoreDefaultConfig') {
+                    btnLbl.dataI18n = 'systemSettingView.restoreDefault'
+                    btn.on(dxui.Utils.EVENT.CLICK, () => {
+                        viewUtils.confirmOpen('systemSettingView.confirmation', 'systemSettingView.confirmRecoveryConfiguration', () => {
+                            dxCommon.systemBrief("rm -rf /app/data/config/*")
+                            std.setTimeout(() => {
+                                dxCommon.systemBrief("reboot -f")
+                            }, 1000)
+                        }, () => { })
+                    })
+                } else if (item.title == 'systemSettingView.resetDevice') {
+                    btnLbl.dataI18n = 'systemSettingView.reset'
+                    btn.bgColor(0xffdddd)
+                    btnLbl.textColor(0xFD5353)
+                    btn.on(dxui.Utils.EVENT.CLICK, () => {
+                        viewUtils.confirmOpen('systemSettingView.confirmation', 'systemSettingView.confirmReset', () => {
+                            dxCommon.systemBrief("rm -rf /app/data/config/*")
+                            dxCommon.systemBrief("rm -rf /app/data/db/*")
+                            dxCommon.systemBrief("rm -rf /app/data/user/*")
+                            dxCommon.systemBrief("rm -rf /vgmj.db")
+                            std.setTimeout(() => {
+                                dxCommon.systemBrief("reboot -f")
+                            }, 1000)
+                        }, () => { })
+                    })
+                }
+
+                break
+        }
+    })
+
+}
+
+export default systemSettingView
diff --git a/vf205_access/src/view/config/menu/voiceBroadcastView.js b/vf205_access/src/view/config/menu/voiceBroadcastView.js
new file mode 100644
index 0000000..3d31fce
--- /dev/null
+++ b/vf205_access/src/view/config/menu/voiceBroadcastView.js
@@ -0,0 +1,137 @@
+import dxui from '../../../../dxmodules/dxUi.js'
+import std from '../../../../dxmodules/dxStd.js'
+import viewUtils from "../../viewUtils.js"
+import topView from "../../topView.js"
+import configView from '../configView.js'
+import i18n from "../../i18n.js"
+import screen from '../../../screen.js'
+const voiceBroadcastView = {}
+
+const strangerData = ["鏃犺闊�", "璇峰厛娉ㄥ唽", "闄岀敓浜轰綘濂�"]
+const strangerData0 = ["No voice", "Play first register", "Play stranger hello"]
+const voiceModeData = ["鏃犺闊�", "鍚嶅瓧", "闂�欒"]
+const voiceModeData0 = ["No voice", "Play name", "Play greeting"]
+
+voiceBroadcastView.init = function () {
+    /**************************************************鍒涘缓灞忓箷*****************************************************/
+    const screenMain = dxui.View.build('voiceBroadcastView', dxui.Utils.LAYER.MAIN)
+    voiceBroadcastView.screenMain = screenMain
+    screenMain.scroll(false)
+    screenMain.bgColor(0xffffff)
+    screenMain.on(dxui.Utils.ENUM.LV_EVENT_SCREEN_LOADED, () => {
+        topView.changeTheme(true)
+
+        const configAll = screen.getConfig()
+        strangerVoiceDropdown.setOptions(configAll['base.language'] == 'CN' ? strangerData : strangerData0)
+        voiceModeDropdown.setOptions(configAll['base.language'] == 'CN' ? voiceModeData : voiceModeData0)
+
+        strangerVoiceDropdown.setSelected(configAll['face.stranger'])
+        voiceModeDropdown.setSelected(configAll['face.voiceMode'])
+        volumeSlider.value(configAll['base.volume'])
+        volumeSlider.send(dxui.Utils.EVENT.VALUE_CHANGED)
+    })
+
+    const titleBox = viewUtils.title(screenMain, configView.screenMain, 'voiceBroadcastViewTitle', 'voiceBroadcastView.title')
+    titleBox.align(dxui.Utils.ALIGN.TOP_MID, 0, 70)
+
+    const strangerVoiceBox = dxui.View.build('strangerVoiceBox', screenMain)
+    viewUtils._clearStyle(strangerVoiceBox)
+    strangerVoiceBox.bgOpa(0)
+    strangerVoiceBox.setSize(screen.screenSize.width - 28 * 2, 80)
+    strangerVoiceBox.align(dxui.Utils.ALIGN.TOP_MID, 0, 140)
+    strangerVoiceBox.borderWidth(1)
+    strangerVoiceBox.setBorderColor(0xDEDEDE)
+    strangerVoiceBox.obj.setStyleBorderSide(dxui.Utils.ENUM.LV_BORDER_SIDE_BOTTOM, 0)
+
+    const strangerVoiceLbl = dxui.Label.build('strangerVoiceLbl', strangerVoiceBox)
+    strangerVoiceLbl.textFont(viewUtils.font(26))
+    strangerVoiceLbl.dataI18n = 'voiceBroadcastView.strangerVoice'
+    strangerVoiceLbl.align(dxui.Utils.ALIGN.LEFT_MID, 0, 0)
+
+    const strangerVoiceDropdown = dxui.Dropdown.build('strangerVoiceDropdown', strangerVoiceBox)
+    strangerVoiceDropdown.textFont(viewUtils.font(26))
+    strangerVoiceDropdown.getList().textFont(viewUtils.font(26))
+    strangerVoiceDropdown.align(dxui.Utils.ALIGN.RIGHT_MID, 0, 0)
+    strangerVoiceDropdown.setSymbol('/app/code/resource/image/down.png')
+    strangerVoiceDropdown.width(300)
+    strangerVoiceDropdown.setOptions(['璇峰厛娉ㄥ唽', '璇峰厛娉ㄥ唽璇峰厛娉ㄥ唽璇峰厛娉ㄥ唽', '璇峰厛娉ㄥ唽'])
+
+
+    const voiceModeBox = dxui.View.build('voiceModeBox', screenMain)
+    viewUtils._clearStyle(voiceModeBox)
+    voiceModeBox.bgOpa(0)
+    voiceModeBox.setSize(screen.screenSize.width - 28 * 2, 80)
+    voiceModeBox.align(dxui.Utils.ALIGN.TOP_MID, 0, 220)
+    voiceModeBox.borderWidth(1)
+    voiceModeBox.setBorderColor(0xDEDEDE)
+    voiceModeBox.obj.setStyleBorderSide(dxui.Utils.ENUM.LV_BORDER_SIDE_BOTTOM, 0)
+
+    const voiceModeLbl = dxui.Label.build('voiceModeLbl', voiceModeBox)
+    voiceModeLbl.textFont(viewUtils.font(26))
+    voiceModeLbl.dataI18n = 'voiceBroadcastView.voiceMode'
+    voiceModeLbl.align(dxui.Utils.ALIGN.LEFT_MID, 0, 0)
+
+    const voiceModeDropdown = dxui.Dropdown.build('voiceModeDropdown', voiceModeBox)
+    voiceModeDropdown.textFont(viewUtils.font(26))
+    voiceModeDropdown.getList().textFont(viewUtils.font(26))
+    voiceModeDropdown.align(dxui.Utils.ALIGN.RIGHT_MID, 0, 0)
+    voiceModeDropdown.setSymbol('/app/code/resource/image/down.png')
+    voiceModeDropdown.width(300)
+    voiceModeDropdown.setOptions(['璇峰厛娉ㄥ唽', '璇峰厛娉ㄥ唽璇峰厛娉ㄥ唽璇峰厛娉ㄥ唽', '璇峰厛娉ㄥ唽'])
+
+
+    const volumeBox = dxui.View.build('volumeBox', screenMain)
+    viewUtils._clearStyle(volumeBox)
+    volumeBox.bgOpa(0)
+    volumeBox.setSize(screen.screenSize.width - 28 * 2, 80)
+    volumeBox.align(dxui.Utils.ALIGN.TOP_MID, 0, 300)
+    volumeBox.borderWidth(1)
+    volumeBox.setBorderColor(0xDEDEDE)
+    volumeBox.obj.setStyleBorderSide(dxui.Utils.ENUM.LV_BORDER_SIDE_BOTTOM, 0)
+
+    const volumeLbl = dxui.Label.build('volumeLbl', volumeBox)
+    volumeLbl.textFont(viewUtils.font(26))
+    volumeLbl.dataI18n = 'voiceBroadcastView.volume'
+    volumeLbl.align(dxui.Utils.ALIGN.LEFT_MID, 0, 0)
+
+    const volumeValueLbl = dxui.Label.build('volumeValueLbl', volumeBox)
+    volumeValueLbl.textFont(viewUtils.font(26))
+    volumeValueLbl.align(dxui.Utils.ALIGN.RIGHT_MID, 0, 0)
+    volumeValueLbl.width(50)
+    volumeValueLbl.text('0')
+    volumeValueLbl.textAlign(dxui.Utils.TEXT_ALIGN.RIGHT)
+
+    const volumeSlider = dxui.Slider.build('volumeSlider', volumeBox)
+    volumeSlider.width(300)
+    volumeSlider.range(0, 100)
+    volumeSlider.on(dxui.Utils.EVENT.VALUE_CHANGED, () => {
+        volumeValueLbl.text(volumeSlider.value() + '')
+    })
+    volumeSlider.alignTo(volumeValueLbl, dxui.Utils.ALIGN.OUT_LEFT_MID, -10, 0)
+
+    const saveBtn = viewUtils.bottomBtn(screenMain, screenMain.id + 'saveBtn', 'voiceBroadcastView.save', () => {
+        const saveConfigData = {
+            face: {
+                stranger: strangerVoiceDropdown.getSelected(),
+                voiceMode: voiceModeDropdown.getSelected(),
+            },
+            base: {
+                volume: volumeSlider.value(),
+            }
+        }
+        const res = screen.saveConfig(saveConfigData)
+        if (res === true) {
+            voiceBroadcastView.statusPanel.success()
+            std.setTimeout(() => {
+                // 鎴愬姛杩斿洖涓婁竴灞傜晫闈�
+                dxui.loadMain(configView.screenMain)
+            }, 500)
+        } else {
+            voiceBroadcastView.statusPanel.fail()
+        }
+    })
+    saveBtn.align(dxui.Utils.ALIGN.BOTTOM_MID, 0, -83)
+    voiceBroadcastView.statusPanel = viewUtils.statusPanel(screenMain, 'voiceBroadcastView.success', 'voiceBroadcastView.fail')
+}
+
+export default voiceBroadcastView
diff --git a/vf205_access/src/view/config/newPwdView.js b/vf205_access/src/view/config/newPwdView.js
new file mode 100644
index 0000000..da0b51b
--- /dev/null
+++ b/vf205_access/src/view/config/newPwdView.js
@@ -0,0 +1,137 @@
+import dxui from '../../../dxmodules/dxUi.js'
+import std from '../../../dxmodules/dxStd.js'
+import viewUtils from "../viewUtils.js"
+import topView from '../topView.js'
+import mainView from '../mainView.js'
+import identityVerificationView from './identityVerificationView.js'
+import screen from '../../screen.js'
+const newPwdView = {}
+newPwdView.init = function () {
+    /**************************************************鍒涘缓灞忓箷*****************************************************/
+    const screenMain = dxui.View.build('newPwdView', dxui.Utils.LAYER.MAIN)
+    newPwdView.screenMain = screenMain
+    screenMain.scroll(false)
+    screenMain.bgColor(0xffffff)
+    screenMain.on(dxui.Utils.ENUM.LV_EVENT_SCREEN_LOADED, () => {
+        topView.changeTheme(true)
+
+        newPwdView.timer = std.setInterval(() => {
+            let count = dxui.Utils.GG.NativeDisp.lvDispGetInactiveTime()
+            if (count > 15 * 1000) {
+                std.clearInterval(newPwdView.timer)
+                newPwdView.timer = null
+                dxui.loadMain(mainView.screenMain)
+            }
+        }, 1000)
+        // 濡傛灉绠$悊鍛樺瘑鐮佷负绌�,鍒欏脊鍑烘鐣岄潰,鍚﹀垯鐩存帴杩涘叆璁よ瘉鐣岄潰
+        if (screen.getConfig()['base.firstLogin'] == 1) {
+            std.clearInterval(newPwdView.timer)
+            dxui.loadMain(identityVerificationView.screenMain)
+        }
+    })
+    screenMain.on(dxui.Utils.ENUM.LV_EVENT_SCREEN_UNLOADED, () => {
+        if (newPwdView.timer) {
+            std.clearInterval(newPwdView.timer)
+        }
+    })
+
+    const titleBox = viewUtils.title(screenMain, mainView.screenMain, 'newPwdViewTitle', 'newPwdView.title')
+    titleBox.align(dxui.Utils.ALIGN.TOP_MID, 0, 70)
+
+    const pwdInput = viewUtils.input(screenMain, 'newPwdInput', undefined, undefined, 'newPwdView.pwd')
+    pwdInput.align(dxui.Utils.ALIGN.TOP_MID, 0, 211)
+    pwdInput.setPasswordMode(true)
+
+    const eyeFill = viewUtils.imageBtn(screenMain, screenMain.id + 'eye_fill', '/app/code/resource/image/eye-fill.png')
+    eyeFill.alignTo(pwdInput, dxui.Utils.ALIGN.RIGHT_MID, 0, 0)
+    eyeFill.on(dxui.Utils.EVENT.CLICK, () => {
+        pwdInput.setPasswordMode(true)
+        eyeFill.hide()
+        eyeOff.show()
+    })
+    eyeFill.hide()
+
+    const eyeOff = viewUtils.imageBtn(screenMain, screenMain.id + 'eye_off', '/app/code/resource/image/eye-off.png')
+    eyeOff.alignTo(pwdInput, dxui.Utils.ALIGN.RIGHT_MID, 0, 0)
+    eyeOff.on(dxui.Utils.EVENT.CLICK, () => {
+        pwdInput.setPasswordMode(false)
+        eyeFill.show()
+        eyeOff.hide()
+    })
+
+    const confirmPwdInput = viewUtils.input(screenMain, 'confirmPwdInput', undefined, undefined, 'newPwdView.confirmPwd')
+    confirmPwdInput.alignTo(pwdInput, dxui.Utils.ALIGN.OUT_BOTTOM_MID, 0, 30)
+    confirmPwdInput.setPasswordMode(true)
+
+    const eyeFill2 = viewUtils.imageBtn(screenMain, screenMain.id + 'eye_fill2', '/app/code/resource/image/eye-fill.png')
+    eyeFill2.alignTo(confirmPwdInput, dxui.Utils.ALIGN.RIGHT_MID, 0, 0)
+    eyeFill2.on(dxui.Utils.EVENT.CLICK, () => {
+        confirmPwdInput.setPasswordMode(true)
+        eyeFill2.hide()
+        eyeOff2.show()
+    })
+    eyeFill2.hide()
+
+    const eyeOff2 = viewUtils.imageBtn(screenMain, screenMain.id + 'eye_off2', '/app/code/resource/image/eye-off.png')
+    eyeOff2.alignTo(confirmPwdInput, dxui.Utils.ALIGN.RIGHT_MID, 0, 0)
+    eyeOff2.on(dxui.Utils.EVENT.CLICK, () => {
+        confirmPwdInput.setPasswordMode(false)
+        eyeFill2.show()
+        eyeOff2.hide()
+    })
+
+    const tipLbl = dxui.Label.build('newPwdViewTip', screenMain)
+    tipLbl.textFont(viewUtils.font(22))
+    tipLbl.textColor(0x888888)
+    tipLbl.dataI18n = 'newPwdView.tip'
+    tipLbl.align(dxui.Utils.ALIGN.TOP_MID, 0, 530)
+
+    const skipView = dxui.View.build('skipView', screenMain)
+    viewUtils._clearStyle(skipView)
+    const skipLbl = dxui.Label.build('skipLbl', skipView)
+    skipLbl.textFont(viewUtils.font(24))
+    skipLbl.textColor(0x767676)
+    skipLbl.dataI18n = 'newPwdView.skip'
+    const skipText = skipLbl.text
+    skipLbl.text = (data) => {
+        skipText.call(skipLbl, data)
+        skipLbl.update()
+        skipView.setSize(skipLbl.width(), skipLbl.height())
+    }
+    skipLbl.borderWidth(2)
+    skipLbl.obj.setStyleBorderSide(dxui.Utils.ENUM.LV_BORDER_SIDE_BOTTOM, 0)
+    skipLbl.setBorderColor(0x767676)
+
+    const pwdAccessBtn = viewUtils.bottomBtn(screenMain, screenMain.id + 'pwdAccessBtn', 'newPwdView.pwdAccess', () => {
+        if (pwdInput.text() != confirmPwdInput.text()) {
+            newPwdView.statusPanel.fail("newPwdView.pwdNotMatch")
+            return
+        }
+        const res = screen.saveConfig({
+            base: {
+                password: pwdInput.text()
+            }
+        })
+        if (res === true) {
+            newPwdView.statusPanel.success()
+            std.clearInterval(newPwdView.timer)
+            dxui.loadMain(identityVerificationView.screenMain)
+        } else {
+            newPwdView.statusPanel.fail()
+        }
+    })
+    pwdAccessBtn.align(dxui.Utils.ALIGN.BOTTOM_MID, 0, -83)
+
+    skipView.setSize(skipLbl.width(), skipLbl.height())
+    skipView.align(dxui.Utils.ALIGN.BOTTOM_MID, 0, -217)
+    skipView.on(dxui.Utils.EVENT.CLICK, () => {
+        //淇敼鐘舵��
+        screen.saveConfig({ base: { firstLogin: 1 } })
+        std.clearInterval(newPwdView.timer)
+        dxui.loadMain(identityVerificationView.screenMain)
+    })
+
+    newPwdView.statusPanel = viewUtils.statusPanel(screenMain, 'newPwdView.success', 'newPwdView.fail')
+}
+
+export default newPwdView
\ No newline at end of file
diff --git a/vf205_access/src/view/emergencyPwdView.js b/vf205_access/src/view/emergencyPwdView.js
new file mode 100644
index 0000000..01704cc
--- /dev/null
+++ b/vf205_access/src/view/emergencyPwdView.js
@@ -0,0 +1,140 @@
+import dxui from '../../dxmodules/dxUi.js'
+import std from '../../dxmodules/dxStd.js'
+import viewUtils from "./viewUtils.js"
+import topView from './topView.js'
+import mainView from './mainView.js'
+import screen from '../screen.js'
+import logger from '../../dxmodules/dxLogger.js'
+import driver from '../driver.js'
+import config from '../../dxmodules/dxConfig.js'
+
+const emergencyPwdView = {}
+emergencyPwdView.init = function () {
+    /**************************************************鍒涘缓灞忓箷*****************************************************/
+    const screenMain = dxui.View.build('emergencyPwdView', dxui.Utils.LAYER.MAIN)
+    emergencyPwdView.screenMain = screenMain
+    screenMain.scroll(false)
+    screenMain.bgColor(0xffffff)
+    screenMain.on(dxui.Utils.ENUM.LV_EVENT_SCREEN_LOADED, () => {
+        topView.changeTheme(true)
+
+        // 鎾斁搴旀�ラ�氳璇煶鎻愮ず
+        try {
+            driver.alsa.play(`/app/code/resource/${config.get("base.language") == "CN" ? "CN" : "EN"}/wav/emergency.wav`)
+            logger.info('[emergencyPwdView]: 鎾斁搴旀�ラ�氳璇煶鎻愮ず')
+        } catch (error) {
+            logger.error('[emergencyPwdView]: 鎾斁璇煶鎻愮ず澶辫触: ' + error.message)
+        }
+
+        emergencyPwdView.timer = std.setInterval(() => {
+            let count = dxui.Utils.GG.NativeDisp.lvDispGetInactiveTime()
+            if (count > 15 * 1000) {
+                std.clearInterval(emergencyPwdView.timer)
+                emergencyPwdView.timer = null
+                dxui.loadMain(mainView.screenMain)
+            }
+        }, 1000)
+
+        pwdInput.send(dxui.Utils.EVENT.CLICK)
+        pwdInput.send(dxui.Utils.EVENT.FOCUSED)
+    })
+    screenMain.on(dxui.Utils.ENUM.LV_EVENT_SCREEN_UNLOADED, () => {
+        if (emergencyPwdView.timer) {
+            std.clearInterval(emergencyPwdView.timer)
+        }
+        // 娓呯┖楠岃瘉缁撴灉鎻愮ず
+        if (emergencyPwdView.resultLbl) {
+            emergencyPwdView.resultLbl.text(' ')
+        }
+    })
+
+    const titleBox = viewUtils.title(screenMain, mainView.screenMain, 'emergencyPwdViewTitle', '搴旀�ュ瘑鐮侀�氳')
+    titleBox.align(dxui.Utils.ALIGN.TOP_MID, 0, 70)
+
+    const pwdInput = viewUtils.input(screenMain, 'emergencyPwdInput', 2, undefined, '璇疯緭鍏ュ簲鎬ュ瘑鐮�')
+    pwdInput.align(dxui.Utils.ALIGN.TOP_MID, 0, 211)
+    pwdInput.setPasswordMode(true)
+
+    const eyeFill = viewUtils.imageBtn(screenMain, screenMain.id + 'eye_fill', '/app/code/resource/image/eye-fill.png')
+    eyeFill.alignTo(pwdInput, dxui.Utils.ALIGN.RIGHT_MID, 0, 0)
+    eyeFill.on(dxui.Utils.EVENT.CLICK, () => {
+        pwdInput.setPasswordMode(true)
+        eyeFill.hide()
+        eyeOff.show()
+    })
+    eyeFill.hide()
+
+    const eyeOff = viewUtils.imageBtn(screenMain, screenMain.id + 'eye_off', '/app/code/resource/image/eye-off.png')
+    eyeOff.alignTo(pwdInput, dxui.Utils.ALIGN.RIGHT_MID, 0, 0)
+    eyeOff.on(dxui.Utils.EVENT.CLICK, () => {
+        pwdInput.setPasswordMode(false)
+        eyeFill.show()
+        eyeOff.hide()
+    })
+
+    // 娣诲姞鎻愮ず鏂囨湰
+    const hintText1 = dxui.Label.build('hintText1', screenMain)
+    hintText1.text('1.搴旀�ュ紑闂ㄦ棤瑙嗕粨鍐呮皵浣撴祿搴︽槸鍚﹁揪鏍�,璇疯嚜琛岀‘淇濆紑闂ㄥ叆浠撳畨鍏ㄣ��')
+    hintText1.textFont(viewUtils.font(24))
+    hintText1.textColor(0xff0000)
+    hintText1.align(dxui.Utils.ALIGN.TOP_MID, 0, 350)
+    hintText1.longMode(dxui.Utils.LABEL_LONG_MODE.BREAK)
+    hintText1.width(680)
+
+    const hintText2 = dxui.Label.build('hintText2', screenMain)
+    hintText2.text('2.姘旇皟浠撴垨鐔忚捀浠撹鍔″繀浣╂埓涓撲笟璁惧,纭繚鍏ヤ粨瀹夊叏銆�')
+    hintText2.textFont(viewUtils.font(24))
+    hintText2.textColor(0xff0000)
+    hintText2.align(dxui.Utils.ALIGN.TOP_MID, 0, 400)
+    hintText2.longMode(dxui.Utils.LABEL_LONG_MODE.BREAK)
+    hintText2.width(680)
+
+    // 楠岃瘉缁撴灉鎻愮ず
+    const resultLbl = dxui.Label.build('resultLbl', screenMain)
+    resultLbl.text(' ')
+    resultLbl.textFont(viewUtils.font(32))
+    resultLbl.textColor(0x000000)
+    resultLbl.align(dxui.Utils.ALIGN.TOP_MID, 0, 480)
+    emergencyPwdView.resultLbl = resultLbl
+
+    const emergencyAccessBtn = viewUtils.bottomBtn(screenMain, 'emergencyAccessBtn', '搴旀�ュ瘑鐮侀�氳', () => {
+        // 纭瀵嗙爜
+        const pwd = pwdInput.text()
+        const result = screen.pwdAccess(pwd)
+        
+        if (result) {
+            // 瀵嗙爜楠岃瘉閫氳繃
+            logger.info('[emergencyPwdView]: 搴旀�ュ瘑鐮侀獙璇侀�氳繃')
+            resultLbl.text('搴旀�ュ瘑鐮侀獙璇侀�氳繃锛屾鍦ㄥ紑浠�...')
+            resultLbl.textColor(0x008000)
+            
+            // 寮�缁х數鍣�
+            try {
+                driver.gpio.open() // 鎵撳紑缁х數鍣ㄥ苟鍦ㄦ寚瀹氭椂闂村悗鑷姩鍏抽棴
+                logger.info(`[emergencyPwdView]: 鎵撳紑缁х數鍣ㄦ垚鍔焋)
+                resultLbl.text('搴旀�ュ瘑鐮侀獙璇侀�氳繃锛屽凡寮�浠擄紒')
+            } catch (error) {
+                logger.error(`[emergencyPwdView]: 鎵撳紑缁х數鍣ㄥけ璐�: ${error.message}`)
+            }
+            
+            // 璇煶鎻愮ず
+            driver.alsa.play(`/app/code/resource/${config.get("base.language") == "CN" ? "CN" : "EN"}/wav/emergency_s.wav`)
+            
+            // 寤惰繜杩斿洖涓荤晫闈�
+            std.setTimeout(() => {
+                dxui.loadMain(mainView.screenMain)
+            }, 3000)
+        } else {
+            // 瀵嗙爜楠岃瘉澶辫触
+            logger.info('[emergencyPwdView]: 搴旀�ュ瘑鐮侀獙璇佸け璐�')
+            resultLbl.text('搴旀�ュ瘑鐮侀敊璇紝璇烽噸鏂拌緭鍏�')
+            resultLbl.textColor(0xff0000)
+            
+            // 璇煶鎻愮ず
+            driver.alsa.play(`/app/code/resource/${config.get("base.language") == "CN" ? "CN" : "EN"}/wav/emergency_f.wav`)
+        }
+    })
+    emergencyAccessBtn.align(dxui.Utils.ALIGN.BOTTOM_MID, 0, -83)
+}
+
+export default emergencyPwdView
\ No newline at end of file
diff --git a/vf205_access/src/view/i18n.js b/vf205_access/src/view/i18n.js
new file mode 100644
index 0000000..b9c8936
--- /dev/null
+++ b/vf205_access/src/view/i18n.js
@@ -0,0 +1,82 @@
+import dxMap from '../../dxmodules/dxMap.js'
+import dxui from '../../dxmodules/dxUi.js'
+// 璇█鍖�
+import messages from '../../resource/langPack.js'
+
+class I18n {
+    constructor() {
+        const i18nMap = dxMap.get("i18n")
+        this.locale = i18nMap.get("language") || 'EN'
+        this.fallbackLocale = 'CN'
+    }
+
+    // 鑾峰彇缈昏瘧鏂囨湰
+    t(key) {
+        const keys = key.split('.')
+        let result = messages[this.locale]
+
+        for (const k of keys) {
+            if (result && result[k]) {
+                result = result[k]
+            } else {
+                // 濡傛灉褰撳墠璇█娌℃湁鎵惧埌缈昏瘧锛屼娇鐢ㄥ鐢ㄨ瑷�
+                result = this._getFallbackText(key)
+                break
+            }
+        }
+
+        return result || key
+    }
+
+    // 鑾峰彇澶囩敤璇█鐨勭炕璇�
+    _getFallbackText(key) {
+        const keys = key.split('.')
+        let result = messages[this.fallbackLocale]
+
+        for (const k of keys) {
+            if (result && result[k]) {
+                result = result[k]
+            } else {
+                return key
+            }
+        }
+
+        return result
+    }
+
+    // 鍒锋柊
+    refresh() {
+        for (const key in dxui.all) {
+            const obj = dxui.all[key]
+            if (obj.dataI18n) {
+                obj.text(this.t(obj.dataI18n))
+            }
+        }
+    }
+
+    // 鍒锋柊鎸囧畾瀵硅薄
+    refreshObj(obj) {
+        if (obj.dataI18n) {
+            obj.text(this.t(obj.dataI18n))
+        }
+    }
+
+    // 鍒囨崲璇█
+    setLanguage(lang) {
+        if (messages[lang]) {
+            this.locale = lang
+            dxMap.get("i18n").put("language", lang)
+            // 瑙﹀彂鑷畾涔変簨浠讹紝閫氱煡璇█鍙樺寲
+            for (const key in dxui.all) {
+                const obj = dxui.all[key]
+                if (obj.dataI18n) {
+                    obj.text(this.t(obj.dataI18n))
+                }
+            }
+        }
+    }
+}
+
+// 鍒涘缓鍗曚緥
+const i18n = new I18n()
+export default i18n
diff --git a/vf205_access/src/view/idleView.js b/vf205_access/src/view/idleView.js
new file mode 100644
index 0000000..fb0ff43
--- /dev/null
+++ b/vf205_access/src/view/idleView.js
@@ -0,0 +1,54 @@
+import dxui from '../../dxmodules/dxUi.js'
+import viewUtils from './viewUtils.js'
+import std from '../../dxmodules/dxStd.js'
+import i18n from './i18n.js'
+import screen from '../screen.js'
+const idleView = {}
+idleView.init = function () {
+    /**************************************************鍒涘缓灞忓箷*****************************************************/
+    const screenMain = dxui.View.build('idleView', dxui.Utils.LAYER.SYS)
+    idleView.screenMain = screenMain
+    viewUtils._clearStyle(screenMain)
+    screenMain.hide()
+    screenMain.scroll(false)
+    screenMain.width(screen.screenSize.width)
+    screenMain.height(screen.screenSize.height)
+
+    const idleImage = dxui.Image.build('idleImage', screenMain)
+    // 灞忎繚鍥剧墖
+    idleImage.source('/app/code/resource/image/idleImage.jpg')
+
+    const dateBox = dxui.View.build('dateBox', screenMain)
+    viewUtils._clearStyle(dateBox)
+    dateBox.width(600)
+    dateBox.height(200)
+    dateBox.align(dxui.Utils.ALIGN.CENTER, 0, 0)
+    dateBox.bgOpa(0)
+
+    const timeLbl = dxui.Label.build(dateBox.id + 'timeLbl', dateBox)
+    timeLbl.textFont(viewUtils.font(80, dxui.Utils.FONT_STYLE.BOLD))
+    timeLbl.text("10:00:00")
+    timeLbl.textColor(0xffffff)
+    timeLbl.align(dxui.Utils.ALIGN.TOP_MID, 0, 0)
+
+    const dateLbl = dxui.Label.build(dateBox.id + 'dateLbl', dateBox)
+    dateLbl.textFont(viewUtils.font(40))
+    dateLbl.text("2025-01-17 鍛ㄤ簲")
+    dateLbl.textColor(0xffffff)
+    dateLbl.align(dxui.Utils.ALIGN.BOTTOM_MID, 0, 0)
+
+    std.setInterval(() => {
+        const t = new Date();
+        // 琛ラ浂鍑芥暟
+        const pad = (n) => n < 10 ? `0${n}` : n;
+        // 鑾峰彇鏄熸湡鐨勫浗闄呭寲鏂囨湰
+        const weekDay = i18n.t(`idleView.week.${t.getDay()}`);
+
+        timeLbl.text(`${pad(t.getHours())}:${pad(t.getMinutes())}:${pad(t.getSeconds())}`)
+        dateLbl.text(`${t.getFullYear()}-${pad(t.getMonth() + 1)}-${pad(t.getDate())} ${weekDay}`)
+    }, 1000, true)
+
+}
+
+
+export default idleView
\ No newline at end of file
diff --git a/vf205_access/src/view/mainView.js b/vf205_access/src/view/mainView.js
new file mode 100644
index 0000000..b3b35ef
--- /dev/null
+++ b/vf205_access/src/view/mainView.js
@@ -0,0 +1,1646 @@
+import dxui from '../../dxmodules/dxUi.js'
+import std from '../../dxmodules/dxStd.js'
+import viewUtils from "./viewUtils.js"
+import appView from './appView.js'
+import topView from './topView.js'
+import pwdView from './pwdView.js'
+import emergencyPwdView from './emergencyPwdView.js'
+import newPwdView from './config/newPwdView.js'
+import screen from '../screen.js'
+import logger from '../../dxmodules/dxLogger.js'
+import config from '../../dxmodules/dxConfig.js'
+import bus from '../../dxmodules/dxEventBus.js'
+import net from '../../dxmodules/dxNet.js'
+import accessService from '../service/accessService.js'
+import grainService from '../service/grainService.js'
+import dxMap from '../../dxmodules/dxMap.js'
+import sqliteService from '../service/sqliteService.js'
+import driver from '../driver.js'
+import capturer from '../../dxmodules/dxCapturer.js'
+
+let map = dxMap.get("LOGIN")
+const mainView = {
+    authComplete: false, // 璁よ瘉鏄惁瀹屾垚锛岀敤浜庢帶鍒禪I鏇存柊
+    verifiedUsers: {}, // 瀛樺偍宸叉牳楠屾垚鍔熺殑鐢ㄦ埛淇℃伅
+    eventListenersRegistered: false // 浜嬩欢鐩戝惉鍣ㄦ槸鍚﹀凡娉ㄥ唽
+}
+mainView.init = function () {
+    logger.info('[mainView]: init鍑芥暟寮�濮嬫墽琛�')
+    
+    /**************************************************鍒涘缓灞忓箷*****************************************************/
+    const screenMain = dxui.View.build('mainView', dxui.Utils.LAYER.MAIN)
+    mainView.screenMain = screenMain
+    screenMain.scroll(false)
+    screenMain.bgOpa(0)
+
+
+
+    // 鏇存柊璁惧淇℃伅锛圫N鍜孖P锛�
+    function updateDeviceInfo() {
+        let config = screen.getConfig()
+        let sn = config["sys.sn"] || ""
+        // 鐩存帴浠巒et妯″潡鑾峰彇IP鍦板潃锛岀‘淇濊幏鍙栧埌鏈�鏂扮殑IP
+        let ip = ""
+        try {
+            let netType = config["net.type"] || 1
+            let netMode = net.getModeByCard(netType)
+            if (netMode && netMode.param && netMode.param.ip) {
+                ip = netMode.param.ip
+            }
+        } catch (error) {
+            // 鍑洪敊鏃朵娇鐢╟onfig涓殑IP
+            ip = config["net.ip"] || ""
+        }
+        // 閫氳繃mainView瀵硅薄璁块棶鏍囩
+        if (mainView.snInfoLbl && mainView.ipInfoLbl) {
+            mainView.snInfoLbl.text("SN: " + sn)
+            mainView.ipInfoLbl.text("IP: " + ip)
+        }
+        // 鏇存柊overlayBox涓殑璁惧淇℃伅
+        if (mainView.overlaySnLbl && mainView.overlayIpLbl) {
+            mainView.overlaySnLbl.text("SN: " + sn)
+            mainView.overlayIpLbl.text("IP: " + ip)
+        }
+    }
+
+    // 鏇存柊搴撳尯鍚嶇О鍜屼粨鍙凤紙鍙湪绋嬪簭鍚姩鍜岄厤缃慨鏀规椂璋冪敤锛�
+    function updateWarehouseInfo() {
+        let config = screen.getConfig()
+        // 鑾峰彇浠撳彿淇℃伅
+        let houseName = config["houseName"] || "01鍙蜂粨"
+        // 鑾峰彇搴撳尯鍚嶇О
+        let GranaryName = config["GranaryName"] || "涓ぎ鍌ㄥ绮煇鏌愮洿灞炲簱"
+        logger.info(`[mainView]: 鏇存柊搴撳尯鍚嶇О鍜屼粨鍙�: 浠撳彿=${houseName}, 搴撳尯鍚嶇О=${GranaryName}`)
+        // 鏇存柊椤堕儴鏍囬鏍忕殑搴撳尯鍚嶇О
+        if (mainView.headerLbl) {
+            mainView.headerLbl.text(GranaryName)
+        }
+        // 鏇存柊浠撳彿鏄剧ず
+        if (mainView.warehouseLbl) {
+            logger.info(`[mainView]: 鏇存柊浠撳彿鏄剧ず涓�: ${houseName}`)
+            mainView.warehouseLbl.text(houseName)
+        } else {
+            logger.error('[mainView]: warehouseLbl涓嶅瓨鍦�')
+        }
+    }
+
+    screenMain.on(dxui.Utils.ENUM.LV_EVENT_SCREEN_LOADED, () => {
+        topView.changeTheme(false)
+
+        // 绋嬪簭鍚姩鏃舵洿鏂板簱鍖哄悕绉板拰浠撳彿
+        updateWarehouseInfo()
+
+        // 鍙敞鍐屼竴娆′簨浠剁洃鍚櫒
+        if (!mainView.eventListenersRegistered) {
+            logger.info('[mainView]: 寮�濮嬫敞鍐屼簨浠剁洃鍚櫒')
+            
+            // 缃戠粶鐘舵�佺洃鍚�
+            bus.on(net.STATUS_CHANGE, (data) => {
+                if (data.connected) {
+                    // 缃戠粶杩炴帴鏃舵洿鏂癐P淇℃伅
+                    updateDeviceInfo()
+                }
+            })
+
+            // 瀹氭湡鏇存柊璁惧淇℃伅锛堟瘡5绉掞級
+            std.setInterval(() => {
+                updateDeviceInfo()
+            }, 5000)
+
+            // 姘斾綋娴撳害鏇存柊浜嬩欢鐩戝惉
+            bus.on('gasConcentrationUpdated', (data) => {
+                logger.info(`[mainView]: 姘斾綋娴撳害鏇存柊浜嬩欢瑙﹀彂: ${JSON.stringify(data)}`)
+                
+                // 妫�鏌ユ皵浣撴祿搴︽暟鎹槸鍚﹀瓨鍦�
+                if (data.data && data.data.value) {
+                    const gasValue = data.data.value[0]
+                    const isO2Qualified = gasValue && gasValue.statusO2 === "0"
+                    const isCo2Qualified = gasValue && gasValue.statusCo2 === "0"
+                    const isPh3Qualified = gasValue && gasValue.statusPh3 === "0"
+                    
+                    if (mainView.oxygenValue && mainView.oxygenStatus && mainView.oxygenBox) {
+                        mainView.oxygenValue.text(gasValue ? gasValue.o2 : '鏈煡')
+                        mainView.oxygenStatus.text(isO2Qualified ? '鍚堟牸' : '涓嶅悎鏍�')
+                        // 鏍规嵁鐘舵�佹洿鏂拌儗鏅浘鐗�
+                        if (!isO2Qualified) {
+                            mainView.oxygenBox.source('/app/code/resource/image/o2_f.png') // 涓嶅悎鏍艰儗鏅浘
+                        } else {
+                            mainView.oxygenBox.source('/app/code/resource/image/o2_s.png') // 鍚堟牸鑳屾櫙鍥�
+                        }
+                        // 鍒锋柊UI
+                        mainView.oxygenValue.update()
+                        mainView.oxygenStatus.update()
+                        mainView.oxygenBox.update()
+                        mainView.oxygenValue.invalidate()
+                        mainView.oxygenStatus.invalidate()
+                        mainView.oxygenBox.invalidate()
+                    }
+                    if (mainView.co2Value && mainView.co2Status && mainView.co2Box) {
+                        mainView.co2Value.text(gasValue ? gasValue.co2 : '鏈煡')
+                        mainView.co2Status.text(isCo2Qualified ? '鍚堟牸' : '涓嶅悎鏍�')
+                        // 鏍规嵁鐘舵�佹洿鏂拌儗鏅浘鐗�
+                        if (!isCo2Qualified) {
+                            mainView.co2Box.source('/app/code/resource/image/co2_f.png') // 涓嶅悎鏍艰儗鏅浘
+                        } else {
+                            mainView.co2Box.source('/app/code/resource/image/co2_s.png') // 鍚堟牸鑳屾櫙鍥�
+                        }
+                        // 鍒锋柊UI
+                        mainView.co2Value.update()
+                        mainView.co2Status.update()
+                        mainView.co2Box.update()
+                        mainView.co2Value.invalidate()
+                        mainView.co2Status.invalidate()
+                        mainView.co2Box.invalidate()
+                    }
+                    if (mainView.ph3Value && mainView.ph3Status && mainView.ph3Box) {
+                        // 鏄庣‘妫�鏌� ph3 鏄惁瀛樺湪锛岃�屼笉鏄娇鐢� || 杩愮畻绗�
+                        let ph3Value = '0'
+                        if (gasValue) {
+                            if (gasValue.ph3) {
+                                ph3Value = gasValue.ph3
+                            } else if (gasValue.statusPh3) {
+                                ph3Value = gasValue.statusPh3
+                            }
+                        }
+                        mainView.ph3Value.text(ph3Value)
+                        mainView.ph3Status.text(isPh3Qualified ? '鍚堟牸' : '涓嶅悎鏍�')
+                        // 鏍规嵁鐘舵�佹洿鏂拌儗鏅浘鐗�
+                        if (!isPh3Qualified) {
+                            mainView.ph3Box.source('/app/code/resource/image/ph3_f.png') // 涓嶅悎鏍艰儗鏅浘
+                        } else {
+                            mainView.ph3Box.source('/app/code/resource/image/ph3_s.png') // 鍚堟牸鑳屾櫙鍥�
+                        }
+                        // 鍒锋柊UI
+                        mainView.ph3Value.update()
+                        mainView.ph3Status.update()
+                        mainView.ph3Box.update()
+                        mainView.ph3Value.invalidate()
+                        mainView.ph3Status.invalidate()
+                        mainView.ph3Box.invalidate()
+                    }
+                } else {
+                    logger.error(`[mainView]: 姘斾綋娴撳害鏁版嵁涓嶅瓨鍦╜)
+                }
+            })
+
+            // 搴撳尯鍚嶇О鍜屼粨鍙锋洿鏂颁簨浠剁洃鍚紙閰嶇疆淇敼鏃惰Е鍙戯級
+            bus.on('warehouseInfoUpdated', () => {
+                logger.info('[mainView]: 鏀跺埌搴撳尯鍚嶇О鍜屼粨鍙锋洿鏂颁簨浠�')
+                updateWarehouseInfo()
+            })
+
+            // 閫氳缁撴灉浜嬩欢鐩戝惉锛堝鐞嗘垚鍔熷拰澶辫触锛�
+            bus.on('accessRes', (result, data) => {
+                logger.info('[mainView]: accessRes浜嬩欢瑙﹀彂, result=' + result + ', data=' + JSON.stringify(data))
+                
+                // 娓呴櫎涔嬪墠鐨勫畾鏃跺櫒
+                if (resetTimerId) {
+                    std.clearTimeout(resetTimerId)
+                    resetTimerId = null
+                    logger.info('[mainView]: 娓呴櫎涔嬪墠鐨勯噸缃畾鏃跺櫒')
+                }
+                
+                // 濡傛灉鏄�氳鎴愬姛锛屾墽琛岄�氳鎴愬姛鐨勯�昏緫
+                if (result) {
+                    // 妫�鏌ユ槸鍚︽槸鍙屼汉璁よ瘉
+                    if (data && data.data && data.data.dualAuthInfo) {
+                        // 鍙屼汉璁よ瘉锛屽垎鍒洿鏂扮敤鎴�1鍜岀敤鎴�2鐨刄I
+                        let dualAuthInfo = data.data.dualAuthInfo
+                        // 璁剧疆璁よ瘉瀹屾垚鏍囧織
+                        mainView.authComplete = true
+                        
+                        // 瀛樺偍宸叉牳楠屾垚鍔熺殑鐢ㄦ埛淇℃伅
+                        mainView.verifiedUsers[1] = dualAuthInfo.firstUserId
+                        mainView.verifiedUsers[2] = dualAuthInfo.secondUserId
+                        logger.info('[mainView]: 瀛樺偍鍙屼汉璁よ瘉鐢ㄦ埛淇℃伅, user1=' + dualAuthInfo.firstUserId + ', user2=' + dualAuthInfo.secondUserId)
+                        
+                        // 鍙洿鏂扮敤鎴�2鐨勪俊鎭紝鐢ㄦ埛1鐨勪俊鎭凡缁忓湪trackResult浜嬩欢涓洿鏂�
+                        let ret2 = sqliteService.d1_person.find({ userId: dualAuthInfo.secondUserId })
+                        if (ret2 && ret2.length > 0) {
+                            let userName2 = ret2[0].name
+                            let userType2 = 0
+                            try {
+                                userType2 = JSON.parse(ret2[0].extra).type || 0
+                            } catch (error) {
+                                logger.error("瑙f瀽鐢ㄦ埛2绫诲瀷澶辫触")
+                            }
+                            
+                            // 妫�鏌ョ敤鎴�2鏉冮檺
+                            let hasPermission2 = false
+                            let permissions2 = sqliteService.d1_permission.find({ userId: dualAuthInfo.secondUserId })
+                            if (permissions2 && permissions2.length > 0) {
+                                hasPermission2 = true
+                            }
+                            
+                            // 鏇存柊鐢ㄦ埛2鐨刄I
+                            if (mainView.user2Name) {
+                                mainView.user2Name.text(userName2)
+                            }
+                            if (mainView.user2Role) {
+                                mainView.user2Role.text(userType2 === 1 ? '绉戦暱' : '淇濈鍛�')
+                            }
+                            if (mainView.user2StatusLbl) {
+                                if (hasPermission2) {
+                                    mainView.user2Box.source('/app/code/resource/image/user_s.png') // 鏍搁獙鎴愬姛鑳屾櫙鍥�
+                                    mainView.user2StatusLbl.text('鏍搁獙鎴愬姛')
+                                } else {
+                                    mainView.user2Box.source('/app/code/resource/image/user_f.png') // 鏍搁獙澶辫触鑳屾櫙鍥�
+                                    mainView.user2StatusLbl.text('鏍搁獙澶辫触')
+                                }
+                            }
+                            
+                            logger.info('[mainView]: 鐢ㄦ埛2淇℃伅宸叉洿鏂帮細' + userName2 + ', ' + (userType2 === 1 ? '绉戦暱' : '淇濈鍛�') + ', ' + (hasPermission2 ? '鏍搁獙鎴愬姛' : '鏍搁獙澶辫触'))
+                        }
+                    } else {
+                        // 鍗曚汉璁よ瘉锛屾鏌ョ敤鎴锋槸鍚﹀凡缁忎綔涓虹浜岀敤鎴疯繘琛屼簡璁よ瘉
+                        if (data && data.data && data.data.userId) {
+                            let userId = data.data.userId
+                            // 妫�鏌ョ敤鎴锋槸鍚﹀凡缁忎綔涓虹浜岀敤鎴疯繘琛屼簡璁よ瘉
+                            if (mainView.verifiedUsers[2] === userId) {
+                                // 鐢ㄦ埛宸茬粡浣滀负绗簩鐢ㄦ埛杩涜浜嗚璇侊紝涓嶆洿鏂扮敤鎴�1鐨刄I
+                                logger.info('[mainView]: 鐢ㄦ埛宸蹭綔涓虹浜岀敤鎴疯繘琛屼簡璁よ瘉锛屼笉鏇存柊鐢ㄦ埛1鐨刄I')
+                            } else {
+                                // 瀛樺偍宸叉牳楠屾垚鍔熺殑鐢ㄦ埛淇℃伅
+                                mainView.verifiedUsers[1] = userId
+                                logger.info('[mainView]: 瀛樺偍鍗曚汉璁よ瘉鐢ㄦ埛淇℃伅, user1=' + userId)
+                                
+                                let ret = sqliteService.d1_person.find({ userId: userId })
+                                
+                                if (ret && ret.length > 0) {
+                                    let userName = ret[0].name
+                                    let userType = 0
+                                    try {
+                                        userType = JSON.parse(ret[0].extra).type || 0
+                                    } catch (error) {
+                                        logger.error("瑙f瀽鐢ㄦ埛绫诲瀷澶辫触")
+                                    }
+                                    
+                                    // 妫�鏌ョ敤鎴锋潈闄�
+                                    let hasPermission = false
+                                    let permissions = sqliteService.d1_permission.find({ userId: userId })
+                                    if (permissions && permissions.length > 0) {
+                                        hasPermission = true
+                                    }
+                                    
+                                    // 鏇存柊鐢ㄦ埛1鐨刄I
+                                    if (mainView.user1Name) {
+                                        mainView.user1Name.text(userName)
+                                    }
+                                    if (mainView.user1Role) {
+                                        mainView.user1Role.text(userType === 1 ? '绉戦暱' : '淇濈鍛�')
+                                    }
+                                    // 鏇存柊鏍搁獙鍖鸿儗鏅壊鍜岀姸鎬佹枃鏈�
+                                    if (mainView.user1StatusLbl) {
+                                        if (hasPermission) {
+                                            mainView.user1Box.source('/app/code/resource/image/user_s.png') // 鏍搁獙鎴愬姛鑳屾櫙鍥�
+                                            mainView.user1StatusLbl.text('鏍搁獙鎴愬姛')
+                                        } else {
+                                            mainView.user1Box.source('/app/code/resource/image/user_f.png') // 鏍搁獙澶辫触鑳屾櫙鍥�
+                                            mainView.user1StatusLbl.text('鏍搁獙澶辫触')
+                                        }
+                                    }
+                                    logger.info('[mainView]: 鐢ㄦ埛1淇℃伅宸叉洿鏂帮細' + userName + ', ' + (userType === 1 ? '绉戦暱' : '淇濈鍛�') + ', ' + (hasPermission ? '鏍搁獙鎴愬姛' : '鏍搁獙澶辫触'))
+                                }
+                            }
+                        }
+                    }
+                } else {
+                    // 閫氳澶辫触锛屾樉绀哄け璐ヤ俊鎭�
+                    if (mainView.smallStatusPanel && mainView.smallStatusPanel.fail) {
+                        mainView.smallStatusPanel.fail('mainView.fail')
+                    }
+                }
+                
+                // 璁剧疆1鍒嗛挓鍚庨噸缃敤鎴稶I鐨勫畾鏃跺櫒
+                resetTimerId = std.setTimeout(() => {
+                    logger.info('[mainView]: 1鍒嗛挓瀹氭椂鍣ㄨЕ鍙戯紝閲嶇疆鐢ㄦ埛UI')
+                    // 瑙﹀彂閫氳瑙i攣瀹屾垚浜嬩欢锛岄�氱煡UI閲嶇疆
+                    bus.fire("accessUnlockComplete")
+                }, 60000) // 60000姣 = 1鍒嗛挓
+                logger.info('[mainView]: 璁剧疆1鍒嗛挓鍚庨噸缃敤鎴稶I鐨勫畾鏃跺櫒')
+            })
+            
+            // 鐘舵�佷俊鎭洿鏂颁簨浠剁洃鍚�
+            bus.on('statusInfoUpdated', (data) => {
+                // 鍙鐞嗗畨鍏ㄥ叆浠撴帶鍒剁殑鍝嶅簲锛屽拷鐣ラ潪瀹夊叏鍏ヤ粨鎺у埗鐨勫搷搴�
+                const safeInputControlFunctionId = config['functionId.safeInputControl'] || '2000'
+                if (data.functionId && data.functionId !== safeInputControlFunctionId) {
+                    logger.info(`[mainView]: 蹇界暐闈炲畨鍏ㄥ叆浠撴帶鍒剁殑鍝嶅簲锛宖unctionId=${data.functionId}`)
+                    return
+                }
+                
+                // 杩欓噷鍙互鏍规嵁瀹為檯鐨勭姸鎬佷俊鎭暟鎹粨鏋勬潵鏇存柊UI
+                logger.info(`[mainView]: 鐘舵�佷俊鎭洿鏂�: ${JSON.stringify(data)}`)
+                
+                // 妫�鏌ヨ繑鍥炵殑mode鍜宐tn鍙傛暟
+                if (data.data) {
+                    const mode = parseInt(data.data.mode) // 灏嗗瓧绗︿覆杞崲涓烘暟瀛�
+                    const btn = parseInt(data.data.btn) // 灏嗗瓧绗︿覆杞崲涓烘暟瀛�
+                    
+                    logger.info(`[mainView]: 鎺ユ敹鍒癿ode=${mode}, btn=${btn}`)
+                    
+                    // 閲嶇疆鎵�鏈夋寜閽负钃濊壊鑳屾櫙
+                    if (mainView.mode1Btn) mainView.mode1Btn.bgColor(0x017FEB)
+                    if (mainView.inBtn) mainView.inBtn.bgColor(0x017FEB)
+                    if (mainView.outBtn) mainView.outBtn.bgColor(0x017FEB)
+                    if (mainView.mode2Btn) mainView.mode2Btn.bgColor(0x017FEB)
+                    if (mainView.startBtn) mainView.startBtn.bgColor(0x017FEB)
+                    if (mainView.stopBtn) mainView.stopBtn.bgColor(0x017FEB)
+                    if (mainView.mode3Btn) mainView.mode3Btn.bgColor(0x017FEB)
+                    if (mainView.emergencyInBtn) mainView.emergencyInBtn.bgColor(0x017FEB)
+                    if (mainView.emergencyOutBtn) mainView.emergencyOutBtn.bgColor(0x017FEB)
+                    
+                    // 鏍规嵁mode鍜宐tn鏇存柊鎸夐挳鐘舵��
+                    if (mode === 1) {
+                        // 鍏佽杩涗粨妯″紡
+                        if (mainView.mode1Btn) mainView.mode1Btn.bgColor(0x037D41) // 鍏佽杩涗粨妯″紡鎸夐挳璁句负缁胯壊
+                        if (btn === 1) {
+                            // 鍏ヤ粨
+                            if (mainView.inBtn) mainView.inBtn.bgColor(0x037D41) // 鍏ヤ粨鎸夐挳璁句负缁胯壊
+                        } else if (btn === 2) {
+                            // 鍑轰粨
+                            if (mainView.outBtn) mainView.outBtn.bgColor(0x037D41) // 鍑轰粨鎸夐挳璁句负缁胯壊
+                        }
+                    } else if (mode === 2) {
+                        // 鍐閫氶妯″紡
+                        if (mainView.mode2Btn) mainView.mode2Btn.bgColor(0x037D41) // 鍐閫氶妯″紡鎸夐挳璁句负缁胯壊
+                        if (btn === 1) {
+                            // 鍚姩
+                            if (mainView.startBtn) mainView.startBtn.bgColor(0x037D41) // 鍚姩鎸夐挳璁句负缁胯壊
+                        } else if (btn === 2) {
+                            // 鍏抽棴
+                            if (mainView.stopBtn) mainView.stopBtn.bgColor(0x037D41) // 鍏抽棴鎸夐挳璁句负缁胯壊
+                        }
+                    } else if (mode === 3) {
+                        // 绂佹杩涗粨妯″紡
+                        if (mainView.mode3Btn) mainView.mode3Btn.bgColor(0x037D41) // 绂佹杩涗粨妯″紡鎸夐挳璁句负缁胯壊
+                        if (btn === 1) {
+                            // 绱ф�ュ叆浠�
+                            if (mainView.emergencyInBtn) mainView.emergencyInBtn.bgColor(0x037D41) // 绱ф�ュ叆浠撴寜閽涓虹豢鑹�
+                        } else if (btn === 2) {
+                            // 鍑轰粨
+                            if (mainView.emergencyOutBtn) mainView.emergencyOutBtn.bgColor(0x037D41) // 鍑轰粨鎸夐挳璁句负缁胯壊
+                        }
+                    }
+                } else if (data.safeInput) {
+                    // 浼犵粺鏂瑰紡鏇存柊鎸夐挳鐘舵�侊紙0-钃濊壊锛�1-缁胯壊锛�
+                    // 鍏佽杩涗粨妯″紡鐩稿叧鎸夐挳
+                    if (mainView.mode1Btn) {
+                        mainView.mode1Btn.bgColor(data.safeInput.A === '1' ? 0x037D41 : 0x017FEB)
+                    }
+                    if (mainView.inBtn) {
+                        mainView.inBtn.bgColor(data.safeInput.A1 === '1' ? 0x037D41 : 0x017FEB)
+                    }
+                    if (mainView.outBtn) {
+                        mainView.outBtn.bgColor(data.safeInput.A2 === '1' ? 0x037D41 : 0x017FEB)
+                    }
+                    
+                    // 鍐閫氶妯″紡鐩稿叧鎸夐挳
+                    if (mainView.mode2Btn) {
+                        mainView.mode2Btn.bgColor(data.safeInput.B === '1' ? 0x037D41 : 0x017FEB)
+                    }
+                    if (mainView.startBtn) {
+                        mainView.startBtn.bgColor(data.safeInput.B1 === '1' ? 0x037D41 : 0x017FEB)
+                    }
+                    if (mainView.stopBtn) {
+                        mainView.stopBtn.bgColor(data.safeInput.B2 === '1' ? 0x037D41 : 0x017FEB)
+                    }
+                    
+                    // 绂佹杩涗粨妯″紡鐩稿叧鎸夐挳
+                    if (mainView.mode3Btn) {
+                        mainView.mode3Btn.bgColor(data.safeInput.C === '1' ? 0x037D41 : 0x017FEB)
+                    }
+                    if (mainView.emergencyInBtn) {
+                        mainView.emergencyInBtn.bgColor(data.safeInput.C1 === '1' ? 0x037D41 : 0x017FEB)
+                    }
+                    if (mainView.emergencyOutBtn) {
+                        mainView.emergencyOutBtn.bgColor(data.safeInput.C2 === '1' ? 0x037D41 : 0x017FEB)
+                    }
+                }
+            })
+            
+            // 閫氳瑙i攣瀹屾垚浜嬩欢鐩戝惉锛岄噸缃敤鎴稶I
+            bus.on('accessUnlockComplete', () => {
+                logger.info('[mainView]: accessUnlockComplete浜嬩欢瑙﹀彂锛岄噸缃敤鎴稶I')
+                
+                // 閲嶇疆璁よ瘉瀹屾垚鏍囧織
+                mainView.authComplete = false
+                // 閲嶇疆宸叉牳楠岀敤鎴蜂俊鎭�
+                mainView.verifiedUsers = {}
+                
+                // 閲嶇疆鐢ㄦ埛1鐨刄I
+                if (mainView.user1Name) {
+                    mainView.user1Name.text('xx')
+                }
+                if (mainView.user1Role) {
+                    mainView.user1Role.text('淇濈鍛�')
+                }
+                if (mainView.user1Box && mainView.user1StatusLbl) {
+                    mainView.user1Box.source('/app/code/resource/image/user_w.png') // 寰呮牳楠岃儗鏅浘
+                    mainView.user1StatusLbl.text('寰呮牳楠�')
+                }
+                
+                // 閲嶇疆鐢ㄦ埛2鐨刄I
+                if (mainView.user2Name) {
+                    mainView.user2Name.text('xx')
+                }
+                if (mainView.user2Role) {
+                    mainView.user2Role.text('淇濈鍛�')
+                }
+                if (mainView.user2Box && mainView.user2StatusLbl) {
+                    mainView.user2Box.source('/app/code/resource/image/user_w.png') // 寰呮牳楠岃儗鏅浘
+                    mainView.user2StatusLbl.text('寰呮牳楠�')
+                }
+    
+                
+                // 鎭㈠浜鸿劯璁よ瘉鍔熻兘
+                try {
+                    driver.face.status(true)
+                    logger.info('[mainView]: 鎭㈠浜鸿劯璁よ瘉鍔熻兘')
+                } catch (error) {
+                    logger.error('[mainView]: 鎭㈠浜鸿劯璁よ瘉鍔熻兘澶辫触: ' + error.message)
+                }
+                
+                logger.info('[mainView]: 鐢ㄦ埛UI宸查噸缃�')
+            })
+            
+            // 浜鸿劯璇嗗埆缁撴灉浜嬩欢鐩戝惉锛堢Щ鍒癓V_EVENT_SCREEN_LOADED鍥炶皟涓級
+            if (!mainView.trackResultListenerRegistered) {
+                logger.info('[mainView]: 寮�濮嬫敞鍐宼rackResult浜嬩欢鐩戝惉鍣�')
+                bus.on('trackResult', (data) => {
+                    logger.info('[mainView]: trackResult浜嬩欢瑙﹀彂, data=' + JSON.stringify(data))
+                    logger.info('[mainView]: authComplete=' + mainView.authComplete + ', data.result=' + data.result + ', data.userId=' + data.userId + ', data.userIndex=' + data.userIndex + ', data.fileName=' + data.fileName)
+                    
+                    // 鍙湪浜鸿劯璁よ瘉鎴愬姛鏃跺瓨鍌ㄧ敤鎴蜂俊鎭�
+                    if (data.result === true && data.userId) {
+                        // 瀛樺偍宸叉牳楠屾垚鍔熺殑鐢ㄦ埛淇℃伅锛堟棤璁烘槸鍚︽湁鏉冮檺閮藉瓨鍌級
+                        mainView.verifiedUsers[data.userIndex] = data.userId
+                        logger.info('[mainView]: 瀛樺偍宸叉牳楠屾垚鍔熺殑鐢ㄦ埛淇℃伅, userIndex=' + data.userIndex + ', userId=' + data.userId)
+                        
+                        // 璋冪敤updateUserUI鏂规硶鏇存柊鐢ㄦ埛UI锛屼紶閫掍汉鑴稿浘鐗囪矾寰�
+                        mainView.updateUserUI(data.userIndex, data.userId, false, data.fileName)
+                    }
+                })
+                mainView.trackResultListenerRegistered = true
+                logger.info('[mainView]: trackResult浜嬩欢鐩戝惉鍣ㄦ敞鍐屽畬鎴�')
+            }
+            
+            mainView.eventListenersRegistered = true
+            logger.info('[mainView]: 浜嬩欢鐩戝惉鍣ㄦ敞鍐屽畬鎴�')
+        }
+
+        // 瀛樺偍瀹氭椂鍣↖D
+        let resetTimerId = null
+
+        // 鑾峰彇姘斾綋娴撳害鍜岀姸鎬佷俊鎭�
+        grainService.checkGasConcentration()
+        grainService.checkDevConcentration()
+
+        // screen.trackUpdate()
+        screen.appMode(screen.getConfig()["base.appMode"])
+        
+        // 寮�濮嬩汉鑴歌瘑鍒紙绉诲埌灞忓箷鍔犺浇瀹屾垚鍚庯級
+        screen.faceRecgStart()
+    })
+
+
+
+    screenMain.on(dxui.Utils.ENUM.LV_EVENT_SCREEN_UNLOADED, () => {
+        screen.faceRecgPause()
+    })
+
+    mainView.trackFaces = []
+    for (let i = 0; i < 10; i++) {
+        let item = {}
+        const trackFace = dxui.View.build('trackFace' + i, screenMain)
+        item.trackFace = trackFace
+        viewUtils._clearStyle(trackFace)
+        trackFace.setSize(200, 200)
+        trackFace.borderWidth(5)
+        trackFace.setBorderColor(0xffffff)
+        trackFace.bgOpa(0)
+        trackFace.hide()
+
+        const trackFaceName = dxui.Label.build('trackFaceName' + i, trackFace)
+        item.trackFaceName = trackFaceName
+        trackFaceName.textFont(viewUtils.font(30))
+        trackFaceName.textColor(0xffffff)
+        trackFaceName.text(" ")
+        trackFaceName.align(dxui.Utils.ALIGN.BOTTOM_MID, 0, 0)
+        // trackFaceName.hide()
+
+
+        mainView.trackFaces.push(item)
+    }
+
+    // const trackFace = dxui.View.build('trackFace', screenMain)
+    // mainView.trackFace = trackFace
+    // viewUtils._clearStyle(trackFace)
+    // trackFace.setSize(200, 200)
+    // trackFace.borderWidth(5)
+    // trackFace.bgOpa(0)
+    // trackFace.hide()
+
+    // const trackFaceName = dxui.Label.build('trackFaceName', trackFace)
+    // mainView.trackFaceName = trackFaceName
+    // trackFaceName.textFont(viewUtils.font(30))
+    // trackFaceName.textColor(0xffffff)
+    // trackFaceName.text(" ")
+    // trackFaceName.align(dxui.Utils.ALIGN.BOTTOM_MID, 0, 0)
+
+    const bottomBox = dxui.Image.build('bottomBox', screenMain)
+    mainView.bottomBox = bottomBox
+    bottomBox.source('/app/code/resource/image/rectangle.png')
+    bottomBox.align(dxui.Utils.ALIGN.BOTTOM_MID, 0, 0)
+    bottomBox.hide() // 闅愯棌bottomBox
+    const bottomSnBtn = dxui.Button.build('bottomSnBtn', bottomBox)
+    mainView.bottomSnBtn = bottomSnBtn
+    bottomSnBtn.bgColor(0xffffff)
+    bottomSnBtn.bgOpa(20)
+    bottomSnBtn.setSize(204, 36)
+    bottomSnBtn.shadow(0, 0, 0, 0, 0xffffff, 100)
+    bottomSnBtn.align(dxui.Utils.ALIGN.BOTTOM_LEFT, 13, -18)
+    bottomSnBtn.on(dxui.Utils.EVENT.CLICK, () => {
+        // 绉婚櫎浜岀淮鐮佹樉绀哄姛鑳�
+    })
+    bottomSnBtn.flexFlow(dxui.Utils.FLEX_FLOW.ROW)
+    bottomSnBtn.flexAlign(dxui.Utils.FLEX_ALIGN.CENTER, dxui.Utils.FLEX_ALIGN.CENTER, dxui.Utils.FLEX_ALIGN.CENTER)
+    bottomSnBtn.obj.lvObjSetStylePadGap(5, dxui.Utils.ENUM._LV_STYLE_STATE_CMP_SAME)
+
+    // 娣诲姞鍗婇�忔槑瑕嗙洊鍥惧眰
+    const overlayBox = dxui.View.build('overlayBox', screenMain)
+    mainView.overlayBox = overlayBox
+    viewUtils._clearStyle(overlayBox)
+    overlayBox.setSize(screen.screenSize.width, screen.screenSize.height)
+    overlayBox.align(dxui.Utils.ALIGN.TOP_MID, 0, 0)
+    overlayBox.bgColor(0xffffff)
+    overlayBox.bgOpa(50) // 鍗婇�忔槑鏁堟灉
+    overlayBox.clickable(false) // 涓嶆嫤鎴偣鍑讳簨浠讹紝璁╃偣鍑诲彲浠ョ┛閫�
+    overlayBox.scroll(false) // 绂佺敤婊氬姩鍔熻兘
+    overlayBox.show() // 纭繚overlayBox鏄剧ず
+    logger.info('[mainView]: overlayBox宸插垱寤哄苟鏄剧ず')
+
+    // 鍦╫verlayBox涓婂垱寤鸿璇佺粨鏋滃睍绀哄尯鍩燂紙浣嶄簬userBox鍜宑ontrolBox涔嬮棿锛�
+    // 鍒濆鍖栧皬鍨嬬姸鎬侀潰鏉�
+    mainView.smallStatusPanel = viewUtils.smallStatusPanel(overlayBox, 'mainView.success', 'mainView.fail')
+    // 璋冩暣灏忓瀷鐘舵�侀潰鏉夸綅缃�
+    if (mainView.smallStatusPanel.successBg) {
+        mainView.smallStatusPanel.successBg.align(dxui.Utils.ALIGN.TOP_MID, 0, 450)
+    }
+    if (mainView.smallStatusPanel.failBg) {
+        mainView.smallStatusPanel.failBg.align(dxui.Utils.ALIGN.TOP_MID, 0, 450)
+    }
+
+    // 璁惧淇℃伅鏄剧ず锛圫N鍜孖P锛�- 鎻愬墠瀹氫箟锛岀‘淇濆湪鍥炶皟涓彲鐢�
+    const mainDeviceInfoBox = dxui.View.build('mainDeviceInfoBox', overlayBox)
+    viewUtils._clearStyle(mainDeviceInfoBox)
+    mainDeviceInfoBox.setSize(screen.screenSize.width, 40)
+    mainDeviceInfoBox.align(dxui.Utils.ALIGN.BOTTOM_MID, 0, 20) // 璋冩暣浣嶇疆锛岃窛绂诲簳閮�20px
+    mainDeviceInfoBox.bgOpa(0)
+    mainDeviceInfoBox.flexFlow(dxui.Utils.FLEX_FLOW.ROW)
+    mainDeviceInfoBox.flexAlign(dxui.Utils.FLEX_ALIGN.SPACE_BETWEEN, dxui.Utils.FLEX_ALIGN.CENTER, dxui.Utils.FLEX_ALIGN.CENTER)
+
+    // SN淇℃伅
+    const overlaySnLbl = dxui.Label.build('overlaySnLbl', mainDeviceInfoBox)
+    overlaySnLbl.text("SN:")
+    overlaySnLbl.textFont(viewUtils.font(16)) // 澧炲ぇ瀛椾綋
+    overlaySnLbl.textColor(0x000000)
+    overlaySnLbl.width(220)
+    overlaySnLbl.longMode(dxui.Utils.LABEL_LONG_MODE.SCROLL_CIRCULAR)
+    overlaySnLbl.align(dxui.Utils.ALIGN.BOTTOM_LEFT, 30, 0) // 璋冩暣浣嶇疆锛岃窛绂诲乏渚�30px
+
+    // IP淇℃伅
+    const overlayIpLbl = dxui.Label.build('overlayIpLbl', mainDeviceInfoBox)
+    mainView.overlayIpLbl = overlayIpLbl
+    mainView.overlaySnLbl = overlaySnLbl
+    overlayIpLbl.text("IP:")
+    overlayIpLbl.textFont(viewUtils.font(16)) // 澧炲ぇ瀛椾綋
+    overlayIpLbl.textColor(0x000000)
+    overlayIpLbl.align(dxui.Utils.ALIGN.BOTTOM_RIGHT, -30, 0) // 璋冩暣浣嶇疆锛岃窛绂诲彸渚�30px
+
+    // 椤堕儴鏍囬鏍�
+    const headerBox = dxui.View.build('headerBox', overlayBox)
+    viewUtils._clearStyle(headerBox)
+    headerBox.setSize(screen.screenSize.width, 63) // 澧炲ぇ楂樺害
+    headerBox.align(dxui.Utils.ALIGN.TOP_MID, 0, 0)
+    headerBox.bgColor(0x037D41)
+    headerBox.flexFlow(dxui.Utils.FLEX_FLOW.ROW)
+    headerBox.flexAlign(dxui.Utils.FLEX_ALIGN.CENTER, dxui.Utils.FLEX_ALIGN.CENTER, dxui.Utils.FLEX_ALIGN.CENTER)
+    headerBox.obj.lvObjSetStylePadGap(10, dxui.Utils.ENUM._LV_STYLE_STATE_CMP_SAME)
+    
+    // 娣诲姞logo鍥炬爣
+    const logoImg = dxui.Image.build('logoImg', headerBox)
+    logoImg.source('/app/code/resource/image/logo.png')
+    logoImg.setSize(34, 37)
+    
+    const headerLbl = dxui.Label.build('headerLbl', headerBox)
+    mainView.headerLbl = headerLbl
+    // 浠庨厤缃腑鑾峰彇搴撳尯鍚嶇О
+    const config = screen.getConfig()
+    const GranaryName = config['GranaryName'] || '涓ぎ鍌ㄥ绮煇鏌愮洿灞炲簱'
+    headerLbl.text(GranaryName)
+    headerLbl.textFont(viewUtils.font(34)) // 澧炲ぇ瀛椾綋
+    headerLbl.textColor(0xffffff)
+
+    // 浠撳彿鏄剧ず
+    const warehouseLbl = dxui.Label.build('warehouseLbl', overlayBox)
+    mainView.warehouseLbl = warehouseLbl
+    // 浠庨厤缃腑鑾峰彇浠撳彿淇℃伅
+    const houseName = config['houseName'] || '01鍙蜂粨'
+    warehouseLbl.text(houseName)
+    warehouseLbl.textFont(viewUtils.font(34, dxui.Utils.FONT_STYLE.BOLD))
+    warehouseLbl.textColor(0x000000)
+    warehouseLbl.align(dxui.Utils.ALIGN.TOP_MID, 0, 80)
+
+    // 姘斾綋娴撳害鏄剧ず
+    const gasBox = dxui.View.build('gasBox', overlayBox)
+    viewUtils._clearStyle(gasBox)
+    gasBox.setSize(screen.screenSize.width, 180)
+    gasBox.align(dxui.Utils.ALIGN.TOP_MID, 11, 140)
+    gasBox.bgOpa(0)
+    gasBox.flexFlow(dxui.Utils.FLEX_FLOW.ROW)
+    gasBox.flexAlign(dxui.Utils.FLEX_ALIGN.FLEX_START, dxui.Utils.FLEX_ALIGN.CENTER, dxui.Utils.FLEX_ALIGN.CENTER)
+    gasBox.obj.lvObjSetStylePadGap(30, dxui.Utils.ENUM._LV_STYLE_STATE_CMP_SAME) // 璁剧疆姘斾綋妗嗛棿璺�
+
+    // 姘ф皵娴撳害
+    const oxygenBox = dxui.Image.build('oxygenBox', gasBox)
+    viewUtils._clearStyle(oxygenBox)
+    oxygenBox.setSize(239, 166)
+    oxygenBox.source('/app/code/resource/image/o2_s.png') // 榛樿浣跨敤鍚堟牸鑳屾櫙鍥�
+    mainView.oxygenBox = oxygenBox // 璁剧疆涓簃ainView灞炴��
+    
+    const oxygenTitle = dxui.Label.build('oxygenTitle', oxygenBox)
+    oxygenTitle.text('姘ф皵')
+    oxygenTitle.textFont(viewUtils.font(24))
+    oxygenTitle.textColor(0xffffff)
+    oxygenTitle.align(dxui.Utils.ALIGN.TOP_MID, 0, 18)
+    
+    // 姘ф皵鏁板�煎拰鍗曚綅瀹瑰櫒
+    const oxygenValueContainer = dxui.View.build('oxygenValueContainer', oxygenBox)
+    viewUtils._clearStyle(oxygenValueContainer)
+    oxygenValueContainer.setSize(100, 40)
+    oxygenValueContainer.bgOpa(0)
+    oxygenValueContainer.align(dxui.Utils.ALIGN.CENTER, 0, 0)
+    oxygenValueContainer.flexFlow(dxui.Utils.FLEX_FLOW.ROW)
+    oxygenValueContainer.flexAlign(dxui.Utils.FLEX_ALIGN.CENTER, dxui.Utils.FLEX_ALIGN.CENTER, dxui.Utils.FLEX_ALIGN.CENTER)
+    oxygenValueContainer.obj.lvObjSetStylePadGap(5, dxui.Utils.ENUM._LV_STYLE_STATE_CMP_SAME)
+    
+    // 姘ф皵鏁板�奸儴鍒�
+    const oxygenValue = dxui.Label.build('oxygenValue', oxygenValueContainer)
+    oxygenValue.text('20')
+    oxygenValue.textFont(viewUtils.font(26, dxui.Utils.FONT_STYLE.BOLD))
+    oxygenValue.textColor(0xffffff)
+    mainView.oxygenValue = oxygenValue // 璁剧疆涓簃ainView灞炴��
+    
+    // 姘ф皵鍗曚綅閮ㄥ垎
+    const oxygenUnit = dxui.Label.build('oxygenUnit', oxygenValueContainer)
+    oxygenUnit.text('%')
+    oxygenUnit.textFont(viewUtils.font(14))
+    oxygenUnit.textColor(0xffffff)
+    mainView.oxygenUnit = oxygenUnit // 璁剧疆涓簃ainView灞炴��
+    
+    const oxygenStatus = dxui.Label.build('oxygenStatus', oxygenBox)
+    oxygenStatus.text('鍚堟牸')
+    oxygenStatus.textFont(viewUtils.font(24, dxui.Utils.FONT_STYLE.BOLD))
+    oxygenStatus.textColor(0xffffff)
+    oxygenStatus.align(dxui.Utils.ALIGN.BOTTOM_MID, 0, -20)
+    mainView.oxygenStatus = oxygenStatus // 璁剧疆涓簃ainView灞炴��
+
+    // 纾峰寲姘㈡祿搴�
+    const ph3Box = dxui.Image.build('ph3Box', gasBox)
+    viewUtils._clearStyle(ph3Box)
+    ph3Box.setSize(239, 166)
+    ph3Box.source('/app/code/resource/image/ph3_s.png') // 榛樿浣跨敤鍚堟牸鑳屾櫙鍥�
+    mainView.ph3Box = ph3Box // 璁剧疆涓簃ainView灞炴��
+    
+    const ph3Title = dxui.Label.build('ph3Title', ph3Box)
+    ph3Title.text('纾峰寲姘�')
+    ph3Title.textFont(viewUtils.font(24))
+    ph3Title.textColor(0xffffff)
+    ph3Title.align(dxui.Utils.ALIGN.TOP_MID, 0, 18)
+    
+    // 纾峰寲姘㈡暟鍊煎拰鍗曚綅瀹瑰櫒
+    const ph3ValueContainer = dxui.View.build('ph3ValueContainer', ph3Box)
+    viewUtils._clearStyle(ph3ValueContainer)
+    ph3ValueContainer.setSize(100, 40)
+    ph3ValueContainer.bgOpa(0)
+    ph3ValueContainer.align(dxui.Utils.ALIGN.CENTER, 0, 0)
+    ph3ValueContainer.flexFlow(dxui.Utils.FLEX_FLOW.ROW)
+    ph3ValueContainer.flexAlign(dxui.Utils.FLEX_ALIGN.CENTER, dxui.Utils.FLEX_ALIGN.CENTER, dxui.Utils.FLEX_ALIGN.CENTER)
+    ph3ValueContainer.obj.lvObjSetStylePadGap(5, dxui.Utils.ENUM._LV_STYLE_STATE_CMP_SAME)
+    
+    // 纾峰寲姘㈡暟鍊奸儴鍒�
+    const ph3Value = dxui.Label.build('ph3Value', ph3ValueContainer)
+    ph3Value.text('0')
+    ph3Value.textFont(viewUtils.font(26, dxui.Utils.FONT_STYLE.BOLD))
+    ph3Value.textColor(0xffffff)
+    mainView.ph3Value = ph3Value // 璁剧疆涓簃ainView灞炴��
+    
+    // 纾峰寲姘㈠崟浣嶉儴鍒�
+    const ph3Unit = dxui.Label.build('ph3Unit', ph3ValueContainer)
+    ph3Unit.text('PPM')
+    ph3Unit.textFont(viewUtils.font(14))
+    ph3Unit.textColor(0xffffff)
+    mainView.ph3Unit = ph3Unit // 璁剧疆涓簃ainView灞炴��
+    
+    const ph3Status = dxui.Label.build('ph3Status', ph3Box)
+    ph3Status.text('鍚堟牸')
+    ph3Status.textFont(viewUtils.font(24, dxui.Utils.FONT_STYLE.BOLD))
+    ph3Status.textColor(0xffffff)
+    ph3Status.align(dxui.Utils.ALIGN.BOTTOM_MID, 0, -20)
+    mainView.ph3Status = ph3Status // 璁剧疆涓簃ainView灞炴��
+
+    // 浜屾哀鍖栫⒊娴撳害
+    const co2Box = dxui.Image.build('co2Box', gasBox)
+    viewUtils._clearStyle(co2Box)
+    co2Box.setSize(239, 166)
+    co2Box.source('/app/code/resource/image/co2_s.png') // 榛樿浣跨敤鍚堟牸鑳屾櫙鍥�
+    mainView.co2Box = co2Box // 璁剧疆涓簃ainView灞炴��
+    
+    const co2Title = dxui.Label.build('co2Title', co2Box)
+    co2Title.text('浜屾哀鍖栫⒊')
+    co2Title.textFont(viewUtils.font(24))
+    co2Title.textColor(0xffffff)
+    co2Title.align(dxui.Utils.ALIGN.TOP_MID, 0, 18)
+    
+    // 浜屾哀鍖栫⒊鏁板�煎拰鍗曚綅瀹瑰櫒
+    const co2ValueContainer = dxui.View.build('co2ValueContainer', co2Box)
+    viewUtils._clearStyle(co2ValueContainer)
+    co2ValueContainer.setSize(100, 40)
+    co2ValueContainer.bgOpa(0)
+    co2ValueContainer.align(dxui.Utils.ALIGN.CENTER, 0, 0)
+    co2ValueContainer.flexFlow(dxui.Utils.FLEX_FLOW.ROW)
+    co2ValueContainer.flexAlign(dxui.Utils.FLEX_ALIGN.CENTER, dxui.Utils.FLEX_ALIGN.CENTER, dxui.Utils.FLEX_ALIGN.CENTER)
+    co2ValueContainer.obj.lvObjSetStylePadGap(5, dxui.Utils.ENUM._LV_STYLE_STATE_CMP_SAME)
+    
+    // 浜屾哀鍖栫⒊鏁板�奸儴鍒�
+    const co2Value = dxui.Label.build('co2Value', co2ValueContainer)
+    co2Value.text('400')
+    co2Value.textFont(viewUtils.font(26, dxui.Utils.FONT_STYLE.BOLD))
+    co2Value.textColor(0xffffff)
+    mainView.co2Value = co2Value // 璁剧疆涓簃ainView灞炴��
+    
+    // 浜屾哀鍖栫⒊鍗曚綅閮ㄥ垎
+    const co2Unit = dxui.Label.build('co2Unit', co2ValueContainer)
+    co2Unit.text('PPM')
+    co2Unit.textFont(viewUtils.font(14))
+    co2Unit.textColor(0xffffff)
+    mainView.co2Unit = co2Unit // 璁剧疆涓簃ainView灞炴��
+    
+    const co2Status = dxui.Label.build('co2Status', co2Box)
+    co2Status.text('鍚堟牸')
+    co2Status.textFont(viewUtils.font(24, dxui.Utils.FONT_STYLE.BOLD))
+    co2Status.textColor(0xffffff)
+    co2Status.align(dxui.Utils.ALIGN.BOTTOM_MID, 0, -20)
+    mainView.co2Status = co2Status // 璁剧疆涓簃ainView灞炴��
+
+    // 鏃堕棿鏄剧ず
+    const timeLbl = dxui.Label.build('timeLbl', overlayBox)
+    timeLbl.text('12:30:30')
+    timeLbl.textFont(viewUtils.font(36))
+    timeLbl.textColor(0x000000)
+    timeLbl.align(dxui.Utils.ALIGN.TOP_MID, 0, 310)
+    
+    const overlayDateLbl = dxui.Label.build('overlayDateLbl', overlayBox)
+    overlayDateLbl.text('2026/02/01')
+    overlayDateLbl.textFont(viewUtils.font(20))
+    overlayDateLbl.textColor(0x000000)
+    overlayDateLbl.align(dxui.Utils.ALIGN.TOP_MID, 0, 360)
+    
+    // 瀹炴椂鏇存柊鏃堕棿鍜屾棩鏈�
+    std.setInterval(() => {
+        const t = new Date()
+        const pad = (n) => n < 10 ? `0${n}` : n
+        timeLbl.text(`${pad(t.getHours())}:${pad(t.getMinutes())}:${pad(t.getSeconds())}`)
+        overlayDateLbl.text(`${t.getFullYear()}/${pad(t.getMonth() + 1)}/${pad(t.getDate())}`)
+    }, 1000, true)
+
+    // 鐢ㄦ埛淇℃伅鏄剧ず
+    const userBox = dxui.View.build('userBox', overlayBox)
+    viewUtils._clearStyle(userBox)
+    userBox.setSize(screen.screenSize.width - 40, 193) // 鍑忓幓宸﹀彸鍚�20px鐨勮竟璺�
+    userBox.align(dxui.Utils.ALIGN.TOP_MID, 0, 620) 
+    userBox.bgColor(0x000000) // 璁剧疆鑳屾櫙棰滆壊涓洪粦鑹�
+    userBox.bgOpa(0) // 璁剧疆鑳屾櫙閫忔槑搴�
+    userBox.flexFlow(dxui.Utils.FLEX_FLOW.ROW)
+    userBox.flexAlign(dxui.Utils.FLEX_ALIGN.SPACE_BETWEEN, dxui.Utils.FLEX_ALIGN.CENTER, dxui.Utils.FLEX_ALIGN.CENTER)
+    userBox.show() // 纭繚鐢ㄦ埛UI鏄剧ず
+    mainView.userBox = userBox // 璁剧疆涓簃ainView灞炴��
+    logger.info('[mainView]: userBox宸插垱寤哄苟鏄剧ず鍦ㄩ《閮ㄤ笅鏂�580鍍忕礌浣嶇疆')
+
+    
+    // 鐢ㄦ埛1
+    const user1Box = dxui.Image.build('user1Box', userBox)
+    viewUtils._clearStyle(user1Box)
+    user1Box.setSize(239, 193) // 浣跨敤姝g‘鐨勮儗鏅浘鐗囧昂瀵�
+    user1Box.source('/app/code/resource/image/user_w.png') // 榛樿浣跨敤寰呮牳楠岃儗鏅浘
+    mainView.user1Box = user1Box // 璁剧疆涓簃ainView灞炴��
+    
+    // 濮撳悕
+    const user1Name = dxui.Label.build('user1Name', user1Box)
+    user1Name.text('xx')  //濮撳悕
+    user1Name.textFont(viewUtils.font(21, dxui.Utils.FONT_STYLE.BOLD))
+    user1Name.textColor(0xffffff)
+    user1Name.align(dxui.Utils.ALIGN.TOP_LEFT, 122, 25)
+    mainView.user1Name = user1Name // 璁剧疆涓簃ainView灞炴��
+    
+    // 鏉冮檺
+    const user1Role = dxui.Label.build('user1Role', user1Box)
+    user1Role.text('淇濈鍛�')
+    user1Role.textFont(viewUtils.font(19))
+    user1Role.textColor(0xffffff)
+    user1Role.align(dxui.Utils.ALIGN.TOP_LEFT, 122, 50)
+    mainView.user1Role = user1Role // 璁剧疆涓簃ainView灞炴��
+    
+    // 鏍搁獙鐘舵��
+    const user1StatusLbl = dxui.Label.build('user1StatusLbl', user1Box)
+    user1StatusLbl.text('寰呮牳楠�')
+    user1StatusLbl.textFont(viewUtils.font(22, dxui.Utils.FONT_STYLE.BOLD))
+    user1StatusLbl.textColor(0xffffff)
+    user1StatusLbl.align(dxui.Utils.ALIGN.BOTTOM_MID, 0, -45)
+    mainView.user1StatusLbl = user1StatusLbl // 璁剧疆涓簃ainView灞炴��
+
+    // 鐢ㄦ埛2
+    const user2Box = dxui.Image.build('user2Box', userBox)
+    viewUtils._clearStyle(user2Box)
+    user2Box.setSize(239, 193) // 浣跨敤姝g‘鐨勮儗鏅浘鐗囧昂瀵�
+    user2Box.source('/app/code/resource/image/user_w.png') // 榛樿浣跨敤寰呮牳楠岃儗鏅浘
+    mainView.user2Box = user2Box // 璁剧疆涓簃ainView灞炴��
+    
+    // 濮撳悕
+    const user2Name = dxui.Label.build('user2Name', user2Box)
+    user2Name.text('xx')
+    user2Name.textFont(viewUtils.font(21, dxui.Utils.FONT_STYLE.BOLD))
+    user2Name.textColor(0xffffff)
+    user2Name.align(dxui.Utils.ALIGN.TOP_LEFT, 122, 25)
+    mainView.user2Name = user2Name // 璁剧疆涓簃ainView灞炴��
+    
+    // 鏉冮檺
+    const user2Role = dxui.Label.build('user2Role', user2Box)
+    user2Role.text('淇濈鍛�')
+    user2Role.textFont(viewUtils.font(19))
+    user2Role.textColor(0xffffff)
+    user2Role.align(dxui.Utils.ALIGN.TOP_LEFT, 122, 50)
+    mainView.user2Role = user2Role // 璁剧疆涓簃ainView灞炴��
+    
+    // 鏍搁獙鐘舵��
+    const user2StatusLbl = dxui.Label.build('user2StatusLbl', user2Box)
+    user2StatusLbl.text('寰呮牳楠�')
+    user2StatusLbl.textFont(viewUtils.font(22, dxui.Utils.FONT_STYLE.BOLD))
+    user2StatusLbl.textColor(0xffffff)
+    user2StatusLbl.align(dxui.Utils.ALIGN.BOTTOM_MID, 0, -45)
+    mainView.user2StatusLbl = user2StatusLbl // 璁剧疆涓簃ainView灞炴��
+
+    // 鏇存柊鐢ㄦ埛UI鐨勬柟娉�
+    mainView.updateUserUI = function(userIndex, userId, forceUpdate = false, fileName = null) {
+        // 鍙湪璁よ瘉鏈畬鎴愭垨寮哄埗鏇存柊鏃舵洿鏂扮敤鎴稶I
+        if (!mainView.authComplete || forceUpdate) {
+            logger.info('[mainView]: 鍑嗗鏇存柊鐢ㄦ埛UI, userIndex=' + userIndex + ', userId=' + userId + ', forceUpdate=' + forceUpdate + ', fileName=' + fileName)
+            
+            // 鏌ヨ鐢ㄦ埛淇℃伅
+            let ret = sqliteService.d1_person.find({ userId: userId })
+            logger.info('[mainView]: 鏌ヨ鐢ㄦ埛缁撴灉, ret=' + JSON.stringify(ret))
+            
+            if (ret && ret.length > 0) {
+                let userName = ret[0].name
+                let userType = 0
+                try {
+                    userType = JSON.parse(ret[0].extra).type || 0
+                } catch (error) {
+                    logger.error("瑙f瀽鐢ㄦ埛绫诲瀷澶辫触")
+                }
+                
+                // 妫�鏌ョ敤鎴锋潈闄�
+                let hasPermission = false
+                let permissions = sqliteService.d1_permission.find({ userId: userId })
+                if (permissions && permissions.length > 0) {
+                    hasPermission = true
+                }
+                
+                // 鏍规嵁鐢ㄦ埛搴忓彿鏇存柊瀵瑰簲鐨刄I
+                if (userIndex === 1) {
+                    // 绗竴涓敤鎴凤紝鏇存柊鐢ㄦ埛1鐨刄I
+                    if (mainView.user1Name) {
+                        mainView.user1Name.text(userName)
+                    }
+                    if (mainView.user1Role) {
+                        mainView.user1Role.text(userType === 1 ? '绉戦暱' : '淇濈鍛�')
+                    }
+                    if (mainView.user1StatusLbl) {
+                        if (hasPermission) {
+                            mainView.user1Box.source('/app/code/resource/image/user_s.png') // 鏍搁獙鎴愬姛鑳屾櫙鍥�
+                            mainView.user1StatusLbl.text('鏍搁獙鎴愬姛')
+                        } else {
+                            mainView.user1Box.source('/app/code/resource/image/user_f.png') // 鏍搁獙澶辫触鑳屾櫙鍥�
+                            mainView.user1StatusLbl.text('鏍搁獙澶辫触')
+                        }
+                    }
+                    // 鏇存柊鐢ㄦ埛1鍥炬爣涓轰汉鑴歌璇佸浘鐗� - 宸叉敞閲婏紝浣跨敤鑳屾櫙鍥剧墖
+                    // if (fileName && mainView.user1Icon) {
+                    //     logger.info('[mainView]: 鏇存柊鐢ㄦ埛1鍥炬爣涓�: ' + fileName)
+                    //     try {
+                    //         // 鍏堣缃浘鏍囧ぇ灏忥紝纭繚瀹瑰櫒鍑嗗灏辩华
+                    //         mainView.user1Icon.setSize(160, 160)
+                    //         // 纭繚鍥剧墖灞呬腑鏄剧ず
+                    //         mainView.user1Icon.align(dxui.Utils.ALIGN.CENTER, 0, 0)
+                    //         
+                    //         // 鍏堟竻闄ゆ棫鍥剧墖锛岀‘淇濋噸鏂板姞杞�
+                    //         mainView.user1Icon.source('')
+                    //         mainView.user1Icon.update()
+                    //         mainView.user1Icon.invalidate()
+                    //         
+                    //         // 浣跨敤capturer璋冩暣鍥剧墖澶у皬
+                    //         // 娉ㄦ剰锛氫负閬垮厤鍐呭瓨閿欒锛屾殏鏃朵笉閿�姣佸浘鍍忓璞�
+                    //         try {
+                    //             // 灏嗗浘鐗囨枃浠惰浆鎹负鍥惧儚瀵硅薄
+                    //             const imageId = capturer.pictureFileToImage(fileName, 1) // 1琛ㄧずIMAGE_YUV420SP
+                    //             if (imageId) {
+                    //                 logger.info('[mainView]: 鍥剧墖杞崲鎴愬姛锛宨mageId=' + imageId)
+                    //                 // 璋冩暣鍥惧儚澶у皬涓�160x160
+                    //                 const resizedImageId = capturer.imageResizeResolution(imageId, 160, 160, 3) // 3琛ㄧずFILTER_MODE_BOX
+                    //                 if (resizedImageId) {
+                    //                     logger.info('[mainView]: 鍥剧墖璋冩暣鎴愬姛锛宺esizedImageId=' + resizedImageId)
+                    //                     // 淇濆瓨璋冩暣鍚庣殑鍥惧儚涓轰复鏃舵枃浠讹紙浣跨敤鍥哄畾璺緞锛屾瘡娆¤鐩栵級
+                    //                     const tempFileName = '/app/data/user/temp/user1_resized.jpg'
+                    //                     const saveResult = capturer.imageToPictureFile(resizedImageId, 1, 0, 80, tempFileName) // 0琛ㄧずTYPE_JPEG
+                    //                     if (saveResult) {
+                    //                         logger.info('[mainView]: 鍥剧墖淇濆瓨鎴愬姛锛宼empFileName=' + tempFileName)
+                    //                         // 浣跨敤璋冩暣鍚庣殑鍥剧墖浣滀负鍥炬爣婧�
+                    //                         mainView.user1Icon.source(tempFileName)
+                    //                     } else {
+                    //                         logger.error('[mainView]: 淇濆瓨璋冩暣鍚庣殑鍥剧墖澶辫触')
+                    //                         // 淇濆瓨澶辫触鏃朵娇鐢ㄥ師濮嬪浘鐗�
+                    //                         mainView.user1Icon.source(fileName)
+                    //                     }
+                    //                 } else {
+                    //                     logger.error('[mainView]: 璋冩暣鍥剧墖澶у皬澶辫触')
+                    //                     // 璋冩暣澶辫触鏃朵娇鐢ㄥ師濮嬪浘鐗�
+                    //                     mainView.user1Icon.source(fileName)
+                    //                 }
+                    //             } else {
+                    //                 logger.error('[mainView]: 杞崲鍥剧墖鏂囦欢澶辫触')
+                    //                 // 杞崲澶辫触鏃朵娇鐢ㄥ師濮嬪浘鐗�
+                    //                 mainView.user1Icon.source(fileName)
+                    //             }
+                    //         } catch (e) {
+                    //             logger.error('[mainView]: 澶勭悊鍥剧墖鏃跺嚭閿�: ' + e.message)
+                    //             // 鍑洪敊鏃朵娇鐢ㄥ師濮嬪浘鐗�
+                    //             mainView.user1Icon.source(fileName)
+                    //         }
+                    //         
+                    //         // 寮哄埗鏇存柊鍜岄噸缁�
+                    //         mainView.user1Icon.update()
+                    //         mainView.user1Icon.invalidate()
+                    //         logger.info('[mainView]: 鐢ㄦ埛1鍥炬爣鏇存柊鎴愬姛')
+                    //     } catch (error) {
+                    //         logger.error('[mainView]: 澶勭悊鍥剧墖鏃跺嚭閿�: ' + error.message)
+                    //         // 鍑洪敊鏃朵娇鐢ㄥ師濮嬪浘鐗�
+                    //         mainView.user1Icon.setSize(160, 160)
+                    //         mainView.user1Icon.align(dxui.Utils.ALIGN.CENTER, 0, 0)
+                    //         mainView.user1Icon.source(fileName)
+                    //         mainView.user1Icon.update()
+                    //         mainView.user1Icon.invalidate()
+                    //         logger.info('[mainView]: 鐢ㄦ埛1鍥炬爣鏇存柊澶辫触锛屼娇鐢ㄥ師濮嬪浘鐗�')
+                    //     }
+                    // } else {
+                    //     logger.error('[mainView]: 鏇存柊鐢ㄦ埛1鍥炬爣澶辫触锛宖ileName=' + fileName + ', user1Icon=' + mainView.user1Icon)
+                    // }
+                    logger.info('[mainView]: 鐢ㄦ埛1淇℃伅宸叉洿鏂帮細' + userName + ', ' + (userType === 1 ? '绉戦暱' : '淇濈鍛�') + ', ' + (hasPermission ? '鏍搁獙鎴愬姛' : '鏍搁獙澶辫触'))
+                } else if (userIndex === 2) {
+                    // 绗簩涓敤鎴凤紝鏇存柊鐢ㄦ埛2鐨刄I
+                    if (mainView.user2Name) {
+                        mainView.user2Name.text(userName)
+                    }
+                    if (mainView.user2Role) {
+                        mainView.user2Role.text(userType === 1 ? '绉戦暱' : '淇濈鍛�')
+                    }
+                    if (mainView.user2StatusLbl) {
+                        if (hasPermission) {
+                            mainView.user2Box.source('/app/code/resource/image/user_s.png') // 鏍搁獙鎴愬姛鑳屾櫙鍥�
+                            mainView.user2StatusLbl.text('鏍搁獙鎴愬姛')
+                        } else {
+                            mainView.user2Box.source('/app/code/resource/image/user_f.png') // 鏍搁獙澶辫触鑳屾櫙鍥�
+                            mainView.user2StatusLbl.text('鏍搁獙澶辫触')
+                        }
+                    }
+                    // 鏇存柊鐢ㄦ埛2鍥炬爣涓轰汉鑴歌璇佸浘鐗� - 宸叉敞閲婏紝浣跨敤鑳屾櫙鍥剧墖
+                    // if (fileName && mainView.user2Icon) {
+                    //     logger.info('[mainView]: 鏇存柊鐢ㄦ埛2鍥炬爣涓�: ' + fileName)
+                    //     try {
+                    //         // 鍏堣缃浘鏍囧ぇ灏忥紝纭繚瀹瑰櫒鍑嗗灏辩华
+                    //         mainView.user2Icon.setSize(160, 160)
+                    //         // 纭繚鍥剧墖灞呬腑鏄剧ず
+                    //         mainView.user2Icon.align(dxui.Utils.ALIGN.CENTER, 0, 0)
+                    //         
+                    //         // 鍏堟竻闄ゆ棫鍥剧墖锛岀‘淇濋噸鏂板姞杞�
+                    //         mainView.user2Icon.source('')
+                    //         mainView.user2Icon.update()
+                    //         mainView.user2Icon.invalidate()
+                    //         
+                    //         // 浣跨敤鍥剧墖澶勭悊娴佺▼锛岀‘淇濆浘鐗囨纭樉绀�
+                    //         logger.info('[mainView]: 寮�濮嬪鐞嗙敤鎴�2鍥剧墖: ' + fileName)
+                    //         // 杞崲鍥剧墖涓哄唴閮ㄦ牸寮�
+                    //         const imageId = capturer.pictureFileToImage(fileName, 1) // 1琛ㄧずIMAGE_YUV420SP
+                    //         if (imageId) {
+                    //             logger.info('[mainView]: 鍥剧墖杞崲鎴愬姛锛宨mageId=' + imageId)
+                    //             // 璋冩暣鍥惧儚澶у皬涓�160x160
+                    //             const resizedImageId = capturer.imageResizeResolution(imageId, 160, 160, 3) // 3琛ㄧずFILTER_MODE_BOX
+                    //             if (resizedImageId) {
+                    //                 logger.info('[mainView]: 鍥剧墖璋冩暣鎴愬姛锛宺esizedImageId=' + resizedImageId)
+                    //                 // 淇濆瓨璋冩暣鍚庣殑鍥惧儚涓轰复鏃舵枃浠讹紙浣跨敤鍥哄畾璺緞锛屾瘡娆¤鐩栵級
+                    //                 const tempFileName = '/app/data/user/temp/user2_resized.jpg'
+                    //                 
+                    //                 const saveResult = capturer.imageToPictureFile(resizedImageId, 1, 0, 80, tempFileName) // 0琛ㄧずTYPE_JPEG
+                    //                 if (saveResult) {
+                    //                     logger.info('[mainView]: 鍥剧墖淇濆瓨鎴愬姛锛宼empFileName=' + tempFileName)
+                    //                     
+                    //                     // 浣跨敤璋冩暣鍚庣殑鍥剧墖浣滀负鍥炬爣婧�
+                    //                     mainView.user2Icon.source(tempFileName)
+                    //                 } else {
+                    //                     logger.error('[mainView]: 淇濆瓨璋冩暣鍚庣殑鍥剧墖澶辫触')
+                    //                     // 淇濆瓨澶辫触鏃朵娇鐢ㄥ師濮嬪浘鐗�
+                    //                     mainView.user2Icon.source(fileName)
+                    //                 }
+                    //             } else {
+                    //                 logger.error('[mainView]: 璋冩暣鍥剧墖澶у皬澶辫触')
+                    //                 // 璋冩暣澶辫触鏃朵娇鐢ㄥ師濮嬪浘鐗�
+                    //                 mainView.user2Icon.source(fileName)
+                    //             }
+                    //         } else {
+                    //             logger.error('[mainView]: 杞崲鍥剧墖澶辫触')
+                    //             // 杞崲澶辫触鏃朵娇鐢ㄥ師濮嬪浘鐗�
+                    //             mainView.user2Icon.source(fileName)
+                    //         }
+                    //         
+                    //         // 寮哄埗鏇存柊鍜岄噸缁�
+                    //         mainView.user2Icon.update()
+                    //         mainView.user2Icon.invalidate()
+                    //         logger.info('[mainView]: 鐢ㄦ埛2鍥炬爣鏇存柊鎴愬姛')
+                    //     } catch (error) {
+                    //         logger.error('[mainView]: 澶勭悊鍥剧墖鏃跺嚭閿�: ' + error.message)
+                    //         // 鍑洪敊鏃朵娇鐢ㄩ粯璁ゅ浘鏍�
+                    //         mainView.user2Icon.setSize(160, 160)
+                    //         mainView.user2Icon.align(dxui.Utils.ALIGN.CENTER, 0, 0)
+                    //         mainView.user2Icon.source('/app/code/resource/image/user_1.png')
+                    //         mainView.user2Icon.update()
+                    //         mainView.user2Icon.invalidate()
+                    //         logger.info('[mainView]: 鐢ㄦ埛2鍥炬爣鏇存柊澶辫触锛屼娇鐢ㄩ粯璁ゅ浘鏍�')
+                    //     }
+                    // } else {
+                    //     logger.error('[mainView]: 鏇存柊鐢ㄦ埛2鍥炬爣澶辫触锛宖ileName=' + fileName + ', user2Icon=' + mainView.user2Icon)
+                    // }
+                    logger.info('[mainView]: 鐢ㄦ埛2淇℃伅宸叉洿鏂帮細' + userName + ', ' + (userType === 1 ? '绉戦暱' : '淇濈鍛�') + ', ' + (hasPermission ? '鏍搁獙鎴愬姛' : '鏍搁獙澶辫触'))
+                } else {
+                    // 鏈煡鐢ㄦ埛搴忓彿锛岄粯璁ゆ洿鏂扮敤鎴�1鐨刄I
+                    if (mainView.user1Name) {
+                        mainView.user1Name.text(userName)
+                    }
+                    if (mainView.user1Role) {
+                        mainView.user1Role.text(userType === 1 ? '绉戦暱' : '淇濈鍛�')
+                    }
+                    if (mainView.user1StatusLbl) {
+                        if (hasPermission) {
+                            mainView.user1Box.source('/app/code/resource/image/user_s.png') // 鏍搁獙鎴愬姛鑳屾櫙鍥�
+                            mainView.user1StatusLbl.text('鏍搁獙鎴愬姛')
+                        } else {
+                            mainView.user1Box.source('/app/code/resource/image/user_f.png') // 鏍搁獙澶辫触鑳屾櫙鍥�
+                            mainView.user1StatusLbl.text('鏍搁獙澶辫触')
+                        }
+                    }
+                    logger.info('[mainView]: 鐢ㄦ埛1淇℃伅宸叉洿鏂帮紙榛樿锛夛細' + userName + ', ' + (userType === 1 ? '绉戦暱' : '淇濈鍛�') + ', ' + (hasPermission ? '鏍搁獙鎴愬姛' : '鏍搁獙澶辫触'))
+                }
+            } else {
+                logger.warn('[mainView]: 鏈壘鍒扮敤鎴蜂俊鎭�, userId=' + userId)
+            }
+        }
+    }
+
+    // 鎺у埗鎸夐挳鍖哄煙
+    const controlBox = dxui.Image.build('controlBox', overlayBox)
+    viewUtils._clearStyle(controlBox)
+    controlBox.setSize(779, 343)
+    controlBox.align(dxui.Utils.ALIGN.BOTTOM_LEFT, 11, -120)
+    controlBox.source('/app/code/resource/image/input_bg.png') // 浣跨敤鑳屾櫙鍥�
+    controlBox.borderWidth(0) // 鍘绘帀杈圭嚎
+    controlBox.radius(15) // 澧炲ぇ鍦嗚寮у害
+
+    const controlTitle = dxui.Label.build('controlTitle', controlBox)
+    controlTitle.text('瀹夊叏鍏ヤ粨鑱斿姩鎺у埗')
+    controlTitle.textFont(viewUtils.font(26, dxui.Utils.FONT_STYLE.BOLD)) // 澧炲ぇ瀛椾綋
+    controlTitle.textColor(0x283248)
+    controlTitle.align(dxui.Utils.ALIGN.TOP_LEFT, 50, 15)
+
+    // 鍏佽杩涗粨妯″紡
+    const mode1Box = dxui.View.build('mode1Box', controlBox)
+    viewUtils._clearStyle(mode1Box)
+    mode1Box.setSize(760, 80)
+    mode1Box.align(dxui.Utils.ALIGN.TOP_LEFT, 43, 50)
+    mode1Box.bgOpa(0)
+    mode1Box.flexFlow(dxui.Utils.FLEX_FLOW.ROW)
+    mode1Box.flexAlign(dxui.Utils.FLEX_ALIGN.FLEX_START, dxui.Utils.FLEX_ALIGN.CENTER, dxui.Utils.FLEX_ALIGN.CENTER)
+    mode1Box.obj.lvObjSetStylePadGap(32, dxui.Utils.ENUM._LV_STYLE_STATE_CMP_SAME) // 璁剧疆鎸夐挳闂磋窛
+    
+    const mode1Btn = dxui.Button.build('mode1Btn', mode1Box)
+    mode1Btn.setSize(301, 68) // 澧炲ぇ鎸夐挳楂樺害
+    mode1Btn.bgColor(0x017FEB)
+    mode1Btn.radius(10) // 璋冩暣鍦嗚寮у害
+    mainView.mode1Btn = mode1Btn // 璁剧疆涓簃ainView灞炴��
+    
+    const mode1Lbl = dxui.Label.build('mode1Lbl', mode1Btn)
+    mode1Lbl.text('鍏佽杩涗粨妯″紡')
+    mode1Lbl.textFont(viewUtils.font(22, dxui.Utils.FONT_STYLE.BOLD)) // 绋嶅井澧炲ぇ瀛椾綋澶у皬
+    mode1Lbl.textColor(0xffffff)
+    mode1Lbl.align(dxui.Utils.ALIGN.CENTER, 0, -12)
+    
+    const mode1SubLbl = dxui.Label.build('mode1SubLbl', mode1Btn)
+    mode1SubLbl.text('(姝e父淇濈/鍏ョ伯鍚庢湡)')
+    mode1SubLbl.textFont(viewUtils.font(21))
+    mode1SubLbl.textColor(0xffffff)
+    mode1SubLbl.align(dxui.Utils.ALIGN.CENTER, 0, 12)
+    
+    const inBtn = dxui.Button.build('inBtn', mode1Box)
+    inBtn.setSize(161, 68) // 澧炲ぇ鎸夐挳楂樺害
+    inBtn.bgColor(0x017FEB)
+    inBtn.radius(10) // 璋冩暣鍦嗚寮у害
+    mainView.inBtn = inBtn // 璁剧疆涓簃ainView灞炴��
+    
+    const inLbl = dxui.Label.build('inLbl', inBtn)
+    inLbl.text('鍏ヤ粨')
+    inLbl.textFont(viewUtils.font(23, dxui.Utils.FONT_STYLE.BOLD)) // 澧炲ぇ瀛椾綋
+    inLbl.textColor(0xffffff)
+    inLbl.align(dxui.Utils.ALIGN.CENTER, 0, 0)
+    
+    const outBtn = dxui.Button.build('outBtn', mode1Box)
+    outBtn.setSize(161, 68) // 澧炲ぇ鎸夐挳楂樺害
+    outBtn.bgColor(0x017FEB)
+    outBtn.radius(10) // 璋冩暣鍦嗚寮у害
+    mainView.outBtn = outBtn // 璁剧疆涓簃ainView灞炴��
+    
+    const outLbl = dxui.Label.build('outLbl', outBtn)
+    outLbl.text('鍑轰粨')
+    outLbl.textFont(viewUtils.font(23, dxui.Utils.FONT_STYLE.BOLD)) // 澧炲ぇ瀛椾綋
+    outLbl.textColor(0xffffff)
+    outLbl.align(dxui.Utils.ALIGN.CENTER, 0, 0)
+
+    // 鍐閫氶妯″紡
+    const mode2Box = dxui.View.build('mode2Box', controlBox)
+    viewUtils._clearStyle(mode2Box)
+    mode2Box.setSize(760, 80)
+    mode2Box.align(dxui.Utils.ALIGN.TOP_LEFT, 43, 145)
+    mode2Box.bgOpa(0)
+    mode2Box.flexFlow(dxui.Utils.FLEX_FLOW.ROW)
+    mode2Box.flexAlign(dxui.Utils.FLEX_ALIGN.FLEX_START, dxui.Utils.FLEX_ALIGN.CENTER, dxui.Utils.FLEX_ALIGN.CENTER)
+    mode2Box.obj.lvObjSetStylePadGap(32, dxui.Utils.ENUM._LV_STYLE_STATE_CMP_SAME) // 璁剧疆鎸夐挳闂磋窛
+    
+    const mode2Btn = dxui.Button.build('mode2Btn', mode2Box)
+    mode2Btn.setSize(301, 68) // 澧炲ぇ鎸夐挳楂樺害
+    mode2Btn.bgColor(0x017FEB)
+    mode2Btn.radius(10) // 璋冩暣鍦嗚寮у害
+    mainView.mode2Btn = mode2Btn // 璁剧疆涓簃ainView灞炴��
+    
+    const mode2Lbl = dxui.Label.build('mode2Lbl', mode2Btn)
+    mode2Lbl.text('鍐閫氶妯″紡')
+    mode2Lbl.textFont(viewUtils.font(22, dxui.Utils.FONT_STYLE.BOLD)) // 绋嶅井澧炲ぇ瀛椾綋澶у皬
+    mode2Lbl.textColor(0xffffff)
+    mode2Lbl.align(dxui.Utils.ALIGN.CENTER, 0, -12)
+    
+    const mode2SubLbl = dxui.Label.build('mode2SubLbl', mode2Btn)
+    mode2SubLbl.text('(闇�绉戦暱鏉冮檺)')
+    mode2SubLbl.textFont(viewUtils.font(21))
+    mode2SubLbl.textColor(0xffffff)
+    mode2SubLbl.align(dxui.Utils.ALIGN.CENTER, 0, 12)
+    
+    const startBtn = dxui.Button.build('startBtn', mode2Box)
+    startBtn.setSize(161, 68) // 澧炲ぇ鎸夐挳楂樺害
+    startBtn.bgColor(0x017FEB)
+    startBtn.radius(10) // 璋冩暣鍦嗚寮у害
+    mainView.startBtn = startBtn // 璁剧疆涓簃ainView灞炴��
+    
+    const startLbl = dxui.Label.build('startLbl', startBtn)
+    startLbl.text('鍚姩')
+    startLbl.textFont(viewUtils.font(23, dxui.Utils.FONT_STYLE.BOLD)) // 澧炲ぇ瀛椾綋
+    startLbl.textColor(0xffffff)
+    startLbl.align(dxui.Utils.ALIGN.CENTER, 0, 0)
+    
+    const stopBtn = dxui.Button.build('stopBtn', mode2Box)
+    stopBtn.setSize(161, 68) // 澧炲ぇ鎸夐挳楂樺害
+    stopBtn.bgColor(0x017FEB)
+    stopBtn.radius(10) // 璋冩暣鍦嗚寮у害
+    mainView.stopBtn = stopBtn // 璁剧疆涓簃ainView灞炴��
+    
+    const stopLbl = dxui.Label.build('stopLbl', stopBtn)
+    stopLbl.text('鍏抽棴')
+    stopLbl.textFont(viewUtils.font(23, dxui.Utils.FONT_STYLE.BOLD)) // 澧炲ぇ瀛椾綋
+    stopLbl.textColor(0xffffff)
+    stopLbl.align(dxui.Utils.ALIGN.CENTER, 0, 0)
+
+    // 绂佹杩涗粨妯″紡
+    const mode3Box = dxui.View.build('mode3Box', controlBox)
+    viewUtils._clearStyle(mode3Box)
+    mode3Box.setSize(760, 80)
+    mode3Box.align(dxui.Utils.ALIGN.TOP_LEFT, 43, 240)
+    mode3Box.bgOpa(0)
+    mode3Box.flexFlow(dxui.Utils.FLEX_FLOW.ROW)
+    mode3Box.flexAlign(dxui.Utils.FLEX_ALIGN.FLEX_START, dxui.Utils.FLEX_ALIGN.CENTER, dxui.Utils.FLEX_ALIGN.CENTER)
+    mode3Box.obj.lvObjSetStylePadGap(32, dxui.Utils.ENUM._LV_STYLE_STATE_CMP_SAME) // 璁剧疆鎸夐挳闂磋窛
+    
+    const mode3Btn = dxui.Button.build('mode3Btn', mode3Box)
+    mode3Btn.setSize(301, 68) // 澧炲ぇ鎸夐挳楂樺害
+    mode3Btn.bgColor(0x017FEB)
+    mode3Btn.radius(10) // 璋冩暣鍦嗚寮у害
+    mainView.mode3Btn = mode3Btn // 璁剧疆涓簃ainView灞炴��
+    
+    const mode3Lbl = dxui.Label.build('mode3Lbl', mode3Btn)
+    mode3Lbl.text('绂佹杩涗粨妯″紡')
+    mode3Lbl.textFont(viewUtils.font(22, dxui.Utils.FONT_STYLE.BOLD)) // 绋嶅井澧炲ぇ瀛椾綋澶у皬
+    mode3Lbl.textColor(0xffffff)
+    mode3Lbl.align(dxui.Utils.ALIGN.CENTER, 0, -12)
+    
+    const mode3SubLbl = dxui.Label.build('mode3SubLbl', mode3Btn)
+    mode3SubLbl.text('(闇�绉戦暱鏉冮檺)')
+    mode3SubLbl.textFont(viewUtils.font(21))
+    mode3SubLbl.textColor(0xffffff)
+    mode3SubLbl.align(dxui.Utils.ALIGN.CENTER, 0, 12)
+    
+    const emergencyInBtn = dxui.Button.build('emergencyInBtn', mode3Box)
+    emergencyInBtn.setSize(161, 68) // 澧炲ぇ鎸夐挳楂樺害
+    emergencyInBtn.bgColor(0x017FEB)
+    emergencyInBtn.radius(10) // 璋冩暣鍦嗚寮у害
+    mainView.emergencyInBtn = emergencyInBtn // 璁剧疆涓簃ainView灞炴��
+    
+    const emergencyInLbl = dxui.Label.build('emergencyInLbl', emergencyInBtn)
+    emergencyInLbl.text('绱ф�ュ叆浠�')
+    emergencyInLbl.textFont(viewUtils.font(23, dxui.Utils.FONT_STYLE.BOLD)) // 澧炲ぇ瀛椾綋
+    emergencyInLbl.textColor(0xffffff)
+    emergencyInLbl.align(dxui.Utils.ALIGN.CENTER, 0, 0)
+    
+    const emergencyOutBtn = dxui.Button.build('emergencyOutBtn', mode3Box)
+    emergencyOutBtn.setSize(161, 68) // 澧炲ぇ鎸夐挳楂樺害
+    emergencyOutBtn.bgColor(0x017FEB)
+    emergencyOutBtn.radius(10) // 璋冩暣鍦嗚寮у害
+    mainView.emergencyOutBtn = emergencyOutBtn // 璁剧疆涓簃ainView灞炴��
+    
+    const emergencyOutLbl = dxui.Label.build('emergencyOutLbl', emergencyOutBtn)
+    emergencyOutLbl.text('鍑轰粨')
+    emergencyOutLbl.textFont(viewUtils.font(23, dxui.Utils.FONT_STYLE.BOLD)) // 澧炲ぇ瀛椾綋
+    emergencyOutLbl.textColor(0xffffff)
+    emergencyOutLbl.align(dxui.Utils.ALIGN.CENTER, 0, 0)
+
+    // 搴曢儴鎺у埗鎸夐挳
+    const bottomControlBox = dxui.View.build('bottomControlBox', overlayBox)
+    viewUtils._clearStyle(bottomControlBox)
+    bottomControlBox.setSize(screen.screenSize.width, 80)
+    bottomControlBox.align(dxui.Utils.ALIGN.BOTTOM_LEFT, 20, -40)
+    bottomControlBox.bgOpa(0)
+    bottomControlBox.flexFlow(dxui.Utils.FLEX_FLOW.ROW)
+    bottomControlBox.flexAlign(dxui.Utils.FLEX_ALIGN.FLEX_START, dxui.Utils.FLEX_ALIGN.CENTER, dxui.Utils.FLEX_ALIGN.CENTER)
+    bottomControlBox.obj.lvObjSetStylePadGap(20, dxui.Utils.ENUM._LV_STYLE_STATE_CMP_SAME) // 璁剧疆鎸夐挳闂磋窛
+
+    // 寮�鐏寜閽�
+    const lightOnBtn = viewUtils.imageBtn(bottomControlBox, 'lightOnBtn', '/app/code/resource/image/light_open.png')
+    lightOnBtn.setSize(240, 68)
+    mainView.lightOnBtn = lightOnBtn // 璁剧疆涓簃ainView灞炴��
+    
+    const lightOnLbl = dxui.Label.build('lightOnLbl', lightOnBtn)
+    lightOnLbl.text('寮�鐏�')
+    lightOnLbl.textFont(viewUtils.font(23, dxui.Utils.FONT_STYLE.BOLD)) // 澧炲ぇ瀛椾綋
+    lightOnLbl.textColor(0xffffff)
+    lightOnLbl.align(dxui.Utils.ALIGN.CENTER, 20, 0)
+
+    // 鍏崇伅鎸夐挳
+    const lightOffBtn = viewUtils.imageBtn(bottomControlBox, 'lightOffBtn', '/app/code/resource/image/light_close.png')
+    lightOffBtn.setSize(240, 68)
+    mainView.lightOffBtn = lightOffBtn // 璁剧疆涓簃ainView灞炴��
+    
+    const lightOffLbl = dxui.Label.build('lightOffLbl', lightOffBtn)
+    lightOffLbl.text('鍏崇伅')
+    lightOffLbl.textFont(viewUtils.font(23, dxui.Utils.FONT_STYLE.BOLD)) // 澧炲ぇ瀛椾綋
+    lightOffLbl.textColor(0xffffff)
+    lightOffLbl.align(dxui.Utils.ALIGN.CENTER, 20, 0)
+
+    // 搴旀�ュ紑浠撴寜閽�
+    const emergencyBtn = viewUtils.imageBtn(bottomControlBox, 'emergencyBtn', '/app/code/resource/image/emergencyOpen.png')
+    emergencyBtn.setSize(240, 68)
+    mainView.emergencyBtn = emergencyBtn // 璁剧疆涓簃ainView灞炴��
+    
+    const emergencyLbl = dxui.Label.build('emergencyLbl', emergencyBtn)
+    emergencyLbl.text('搴旀�ュ紑浠�')
+    emergencyLbl.textFont(viewUtils.font(23, dxui.Utils.FONT_STYLE.BOLD)) // 澧炲ぇ瀛椾綋
+    emergencyLbl.textColor(0xffffff)
+    emergencyLbl.align(dxui.Utils.ALIGN.CENTER, 20, 0)
+
+    // 搴曢儴淇℃伅鏍�
+    const infoBox = dxui.View.build('infoBox', overlayBox)
+    viewUtils._clearStyle(infoBox)
+    infoBox.setSize(screen.screenSize.width, 30)
+    infoBox.align(dxui.Utils.ALIGN.BOTTOM_MID, 0, 0)
+    infoBox.bgColor(0x808080)
+
+    const snInfoLbl = dxui.Label.build('snInfoLbl', infoBox)
+    mainView.snInfoLbl = snInfoLbl
+    snInfoLbl.text('SN: ')
+    snInfoLbl.textFont(viewUtils.font(14))
+    snInfoLbl.textColor(0xffffff)
+    snInfoLbl.align(dxui.Utils.ALIGN.BOTTOM_LEFT, 20, -5)
+
+
+
+    const ipInfoLbl = dxui.Label.build('ipInfoLbl', infoBox)
+    mainView.ipInfoLbl = ipInfoLbl
+    ipInfoLbl.text('IP: ')
+    ipInfoLbl.textFont(viewUtils.font(14))
+    ipInfoLbl.textColor(0xffffff)
+    ipInfoLbl.align(dxui.Utils.ALIGN.BOTTOM_RIGHT, -20, -5)
+
+    // 璁剧疆鎸夐挳鐐瑰嚮浜嬩欢
+    mode1Btn.on(dxui.Utils.EVENT.CLICK, () => {
+        logger.info('鍏佽杩涗粨妯″紡鎸夐挳鐐瑰嚮')
+        // 妫�鏌ユ槸鍚︽湁鐢ㄦ埛宸叉牳楠屾垚鍔�
+        if (!mainView.verifiedUsers[1] && !mainView.verifiedUsers[2]) {
+            // 鏄剧ず寮圭獥閫氱煡
+            bus.fire('showAccessResult', {
+                faceAuth: false,
+                gasConcentration: true,
+                accessAllowed: false,
+                message: "*鑱斿姩鎺у埗鎿嶄綔鏃犳潈闄�*"
+            })
+            // 鎾斁璇煶鎻愮ず
+            driver.alsa.play('/app/code/resource/CN/wav/control_f.wav')
+            return
+        }
+        // 鑾峰彇姘斾綋娴撳害淇℃伅
+        grainService.checkGasConcentration()
+        // 鍙戦�佸畨鍏ㄥ叆浠撹仈鍔ㄦ帶鍒惰姹�
+        grainService.checkDevConcentration({
+            mode: 1, // 鍏佽鍏ヤ粨妯″紡
+            user1: mainView.verifiedUsers[1] || mainView.verifiedUsers[2], // 浣跨敤宸叉牳楠屾垚鍔熺殑鐢ㄦ埛
+            user2: mainView.verifiedUsers[2] && mainView.verifiedUsers[1] ? mainView.verifiedUsers[2] : undefined // 濡傛灉鏈変袱涓敤鎴凤紝閮戒紶閫�
+        })
+    })
+
+    inBtn.on(dxui.Utils.EVENT.CLICK, () => {
+        logger.info('鍏ヤ粨鎸夐挳鐐瑰嚮')
+        // 妫�鏌ユ槸鍚︽湁鐢ㄦ埛宸叉牳楠屾垚鍔�
+        if (!mainView.verifiedUsers[1] && !mainView.verifiedUsers[2]) {
+            // 鏄剧ず寮圭獥閫氱煡
+            bus.fire('showAccessResult', {
+                faceAuth: false,
+                gasConcentration: true,
+                accessAllowed: false,
+                message: "*鑱斿姩鎺у埗鎿嶄綔鏃犳潈闄�*"
+            })
+            // 鎾斁璇煶鎻愮ず
+            driver.alsa.play('/app/code/resource/CN/wav/control_f.wav')
+            return
+        }
+        // 鑾峰彇姘斾綋娴撳害淇℃伅
+        grainService.checkGasConcentration()
+        // 鍙戦�佸畨鍏ㄥ叆浠撹仈鍔ㄦ帶鍒惰姹�
+        grainService.checkDevConcentration({
+            mode: 1, // 鍏佽鍏ヤ粨妯″紡
+            btn: 1, // 鍏ヤ粨
+            user1: mainView.verifiedUsers[1] || mainView.verifiedUsers[2], // 浣跨敤宸叉牳楠屾垚鍔熺殑鐢ㄦ埛
+            user2: mainView.verifiedUsers[2] && mainView.verifiedUsers[1] ? mainView.verifiedUsers[2] : undefined // 濡傛灉鏈変袱涓敤鎴凤紝閮戒紶閫�
+        })
+    })
+
+    outBtn.on(dxui.Utils.EVENT.CLICK, () => {
+        logger.info('鍑轰粨鎸夐挳鐐瑰嚮')
+        // 妫�鏌ユ槸鍚︽湁鐢ㄦ埛宸叉牳楠屾垚鍔�
+        if (!mainView.verifiedUsers[1] && !mainView.verifiedUsers[2]) {
+            // 鏄剧ず寮圭獥閫氱煡
+            bus.fire('showAccessResult', {
+                faceAuth: false,
+                gasConcentration: true,
+                accessAllowed: false,
+                message: "*鑱斿姩鎺у埗鎿嶄綔鏃犳潈闄�*"
+            })
+            // 鎾斁璇煶鎻愮ず
+            driver.alsa.play('/app/code/resource/CN/wav/control_f.wav')
+            return
+        }
+        // 鑾峰彇姘斾綋娴撳害淇℃伅
+        grainService.checkGasConcentration()
+        // 鍙戦�佸畨鍏ㄥ叆浠撹仈鍔ㄦ帶鍒惰姹�
+        grainService.checkDevConcentration({
+            mode: 1, // 鍏佽鍏ヤ粨妯″紡
+            btn: 2, // 鍑轰粨
+            user1: mainView.verifiedUsers[1] || mainView.verifiedUsers[2], // 浣跨敤宸叉牳楠屾垚鍔熺殑鐢ㄦ埛
+            user2: mainView.verifiedUsers[2] && mainView.verifiedUsers[1] ? mainView.verifiedUsers[2] : undefined // 濡傛灉鏈変袱涓敤鎴凤紝閮戒紶閫�
+        })
+    })
+
+    mode2Btn.on(dxui.Utils.EVENT.CLICK, () => {
+        logger.info('鍐閫氶妯″紡鎸夐挳鐐瑰嚮')
+        // 妫�鏌ユ槸鍚︽湁鐢ㄦ埛宸叉牳楠屾垚鍔�
+        if (!mainView.verifiedUsers[1] && !mainView.verifiedUsers[2]) {
+            // 鏄剧ず寮圭獥閫氱煡
+            bus.fire('showAccessResult', {
+                faceAuth: false,
+                gasConcentration: true,
+                accessAllowed: false,
+                message: "*鑱斿姩鎺у埗鎿嶄綔鏃犳潈闄�*"
+            })
+            // 鎾斁璇煶鎻愮ず
+            driver.alsa.play('/app/code/resource/CN/wav/control_f.wav')
+            return
+        }
+        // 鑾峰彇姘斾綋娴撳害淇℃伅
+        grainService.checkGasConcentration()
+        // 鍙戦�佸畨鍏ㄥ叆浠撹仈鍔ㄦ帶鍒惰姹�
+        grainService.checkDevConcentration({
+            mode: 2, // 鍐閫氶妯″紡
+            user1: mainView.verifiedUsers[1] || mainView.verifiedUsers[2], // 浣跨敤宸叉牳楠屾垚鍔熺殑鐢ㄦ埛
+            user2: mainView.verifiedUsers[2] && mainView.verifiedUsers[1] ? mainView.verifiedUsers[2] : undefined // 濡傛灉鏈変袱涓敤鎴凤紝閮戒紶閫�
+        })
+    })
+
+    startBtn.on(dxui.Utils.EVENT.CLICK, () => {
+        logger.info('鍚姩鎸夐挳鐐瑰嚮')
+        // 妫�鏌ユ槸鍚︽湁鐢ㄦ埛宸叉牳楠屾垚鍔�
+        if (!mainView.verifiedUsers[1] && !mainView.verifiedUsers[2]) {
+            // 鏄剧ず寮圭獥閫氱煡
+            bus.fire('showAccessResult', {
+                faceAuth: false,
+                gasConcentration: true,
+                accessAllowed: false,
+                message: "*鑱斿姩鎺у埗鎿嶄綔鏃犳潈闄�*"
+            })
+            // 鎾斁璇煶鎻愮ず
+            driver.alsa.play('/app/code/resource/CN/wav/control_f.wav')
+            return
+        }
+        // 鑾峰彇姘斾綋娴撳害淇℃伅
+        grainService.checkGasConcentration()
+        // 鍙戦�佸畨鍏ㄥ叆浠撹仈鍔ㄦ帶鍒惰姹�
+        grainService.checkDevConcentration({
+            mode: 2, // 鍐閫氶妯″紡
+            btn: 1, // 寮�鍚�
+            user1: mainView.verifiedUsers[1] || mainView.verifiedUsers[2], // 浣跨敤宸叉牳楠屾垚鍔熺殑鐢ㄦ埛
+            user2: mainView.verifiedUsers[2] && mainView.verifiedUsers[1] ? mainView.verifiedUsers[2] : undefined // 濡傛灉鏈変袱涓敤鎴凤紝閮戒紶閫�
+        })
+    })
+
+    stopBtn.on(dxui.Utils.EVENT.CLICK, () => {
+        logger.info('鍏抽棴鎸夐挳鐐瑰嚮')
+        // 妫�鏌ユ槸鍚︽湁鐢ㄦ埛宸叉牳楠屾垚鍔�
+        if (!mainView.verifiedUsers[1] && !mainView.verifiedUsers[2]) {
+            // 鏄剧ず寮圭獥閫氱煡
+            bus.fire('showAccessResult', {
+                faceAuth: false,
+                gasConcentration: true,
+                accessAllowed: false,
+                message: "*鑱斿姩鎺у埗鎿嶄綔鏃犳潈闄�*"
+            })
+            // 鎾斁璇煶鎻愮ず
+            driver.alsa.play('/app/code/resource/CN/wav/control_f.wav')
+            return
+        }
+        // 鑾峰彇姘斾綋娴撳害淇℃伅
+        grainService.checkGasConcentration()
+        // 鍙戦�佸畨鍏ㄥ叆浠撹仈鍔ㄦ帶鍒惰姹�
+        grainService.checkDevConcentration({
+            mode: 2, // 鍐閫氶妯″紡
+            btn: 2, // 鍏抽棴
+            user1: mainView.verifiedUsers[1] || mainView.verifiedUsers[2], // 浣跨敤宸叉牳楠屾垚鍔熺殑鐢ㄦ埛
+            user2: mainView.verifiedUsers[2] && mainView.verifiedUsers[1] ? mainView.verifiedUsers[2] : undefined // 濡傛灉鏈変袱涓敤鎴凤紝閮戒紶閫�
+        })
+    })
+
+    mode3Btn.on(dxui.Utils.EVENT.CLICK, () => {
+        logger.info('绂佹杩涗粨妯″紡鎸夐挳鐐瑰嚮')
+        // 妫�鏌ユ槸鍚︽湁鐢ㄦ埛宸叉牳楠屾垚鍔�
+        if (!mainView.verifiedUsers[1] && !mainView.verifiedUsers[2]) {
+            // 鏄剧ず寮圭獥閫氱煡
+            bus.fire('showAccessResult', {
+                faceAuth: false,
+                gasConcentration: true,
+                accessAllowed: false,
+                message: "*鑱斿姩鎺у埗鎿嶄綔鏃犳潈闄�*"
+            })
+            // 鎾斁璇煶鎻愮ず
+            driver.alsa.play('/app/code/resource/CN/wav/control_f.wav')
+            return
+        }
+        // 鑾峰彇姘斾綋娴撳害淇℃伅
+        grainService.checkGasConcentration()
+        // 鍙戦�佸畨鍏ㄥ叆浠撹仈鍔ㄦ帶鍒惰姹�
+        grainService.checkDevConcentration({
+            mode: 3, // 绂佹鍏ヤ粨妯″紡
+            user1: mainView.verifiedUsers[1] || mainView.verifiedUsers[2], // 浣跨敤宸叉牳楠屾垚鍔熺殑鐢ㄦ埛
+            user2: mainView.verifiedUsers[2] && mainView.verifiedUsers[1] ? mainView.verifiedUsers[2] : undefined // 濡傛灉鏈変袱涓敤鎴凤紝閮戒紶閫�
+        })
+    })
+
+    emergencyInBtn.on(dxui.Utils.EVENT.CLICK, () => {
+        logger.info('绱ф�ュ叆浠撴寜閽偣鍑�')
+        // 妫�鏌ユ槸鍚︽湁鐢ㄦ埛宸叉牳楠屾垚鍔�
+        if (!mainView.verifiedUsers[1] && !mainView.verifiedUsers[2]) {
+            // 鏄剧ず寮圭獥閫氱煡
+            bus.fire('showAccessResult', {
+                faceAuth: false,
+                gasConcentration: true,
+                accessAllowed: false,
+                message: "*鑱斿姩鎺у埗鎿嶄綔鏃犳潈闄�*"
+            })
+            // 鎾斁璇煶鎻愮ず
+            driver.alsa.play('/app/code/resource/CN/wav/control_f.wav')
+            return
+        }
+        // 鑾峰彇姘斾綋娴撳害淇℃伅
+        grainService.checkGasConcentration()
+        // 鍙戦�佸畨鍏ㄥ叆浠撹仈鍔ㄦ帶鍒惰姹�
+        grainService.checkDevConcentration({
+            mode: 3, // 绂佹鍏ヤ粨妯″紡
+            btn: 1, // 绱ф�ュ叆浠�
+            user1: mainView.verifiedUsers[1] || mainView.verifiedUsers[2], // 浣跨敤宸叉牳楠屾垚鍔熺殑鐢ㄦ埛
+            user2: mainView.verifiedUsers[2] && mainView.verifiedUsers[1] ? mainView.verifiedUsers[2] : undefined // 濡傛灉鏈変袱涓敤鎴凤紝閮戒紶閫�
+        })
+    })
+
+    emergencyOutBtn.on(dxui.Utils.EVENT.CLICK, () => {
+        logger.info('鍑轰粨鎸夐挳鐐瑰嚮')
+        // 妫�鏌ユ槸鍚︽湁鐢ㄦ埛宸叉牳楠屾垚鍔�
+        if (!mainView.verifiedUsers[1] && !mainView.verifiedUsers[2]) {
+            // 鏄剧ず寮圭獥閫氱煡
+            bus.fire('showAccessResult', {
+                faceAuth: false,
+                gasConcentration: true,
+                accessAllowed: false,
+                message: "*鑱斿姩鎺у埗鎿嶄綔鏃犳潈闄�*"
+            })
+            // 鎾斁璇煶鎻愮ず
+            driver.alsa.play('/app/code/resource/CN/wav/control_f.wav')
+            return
+        }
+        // 鑾峰彇姘斾綋娴撳害淇℃伅
+        grainService.checkGasConcentration()
+        // 鍙戦�佸畨鍏ㄥ叆浠撹仈鍔ㄦ帶鍒惰姹�
+        grainService.checkDevConcentration({
+            mode: 3, // 绂佹鍏ヤ粨妯″紡
+            btn: 2, // 鍑轰粨
+            user1: mainView.verifiedUsers[1] || mainView.verifiedUsers[2], // 浣跨敤宸叉牳楠屾垚鍔熺殑鐢ㄦ埛
+            user2: mainView.verifiedUsers[2] && mainView.verifiedUsers[1] ? mainView.verifiedUsers[2] : undefined // 濡傛灉鏈変袱涓敤鎴凤紝閮戒紶閫�
+        })
+    })
+
+    lightOnBtn.on(dxui.Utils.EVENT.CLICK, () => {
+        logger.info('寮�鐏寜閽偣鍑�')
+        // 妫�鏌ユ槸鍚︽湁鐢ㄦ埛宸叉牳楠屾垚鍔�
+        if (!mainView.verifiedUsers[1] && !mainView.verifiedUsers[2]) {
+            // 鏄剧ず寮圭獥閫氱煡
+            bus.fire('showAccessResult', {
+                faceAuth: false,
+                gasConcentration: true,
+                accessAllowed: false,
+                message: "*鑱斿姩鎺у埗鎿嶄綔鏃犳潈闄�*"
+            })
+            // 鎾斁璇煶鎻愮ず
+            driver.alsa.play('/app/code/resource/CN/wav/control_f.wav')
+            return
+        }
+        // 鑾峰彇姘斾綋娴撳害鍜岀姸鎬佷俊鎭�
+        grainService.checkGasConcentration()
+        grainService.checkDevConcentration()
+        // 鍙戦�佷粨鍐呯収鏄庤仈鍔ㄦ帶鍒惰姹�
+        grainService.controlLight({
+            btn: 1, // 寮�鐏�
+            user1: mainView.verifiedUsers[1] || mainView.verifiedUsers[2], // 浣跨敤宸叉牳楠屾垚鍔熺殑鐢ㄦ埛
+            user2: mainView.verifiedUsers[2] && mainView.verifiedUsers[1] ? mainView.verifiedUsers[2] : undefined // 濡傛灉鏈変袱涓敤鎴凤紝閮戒紶閫�
+        })
+    })
+
+    lightOffBtn.on(dxui.Utils.EVENT.CLICK, () => {
+        logger.info('鍏崇伅鎸夐挳鐐瑰嚮')
+        // 妫�鏌ユ槸鍚︽湁鐢ㄦ埛宸叉牳楠屾垚鍔�
+        if (!mainView.verifiedUsers[1] && !mainView.verifiedUsers[2]) {
+            // 鏄剧ず寮圭獥閫氱煡
+            bus.fire('showAccessResult', {
+                faceAuth: false,
+                gasConcentration: true,
+                accessAllowed: false,
+                message: "*鑱斿姩鎺у埗鎿嶄綔鏃犳潈闄�*"
+            })
+            // 鎾斁璇煶鎻愮ず
+            driver.alsa.play('/app/code/resource/CN/wav/control_f.wav')
+            return
+        }
+        // 鑾峰彇姘斾綋娴撳害鍜岀姸鎬佷俊鎭�
+        grainService.checkGasConcentration()
+        grainService.checkDevConcentration()
+        // 鍙戦�佷粨鍐呯収鏄庤仈鍔ㄦ帶鍒惰姹�
+        grainService.controlLight({
+            btn: 2, // 鍏崇伅
+            user1: mainView.verifiedUsers[1] || mainView.verifiedUsers[2], // 浣跨敤宸叉牳楠屾垚鍔熺殑鐢ㄦ埛
+            user2: mainView.verifiedUsers[2] && mainView.verifiedUsers[1] ? mainView.verifiedUsers[2] : undefined // 濡傛灉鏈変袱涓敤鎴凤紝閮戒紶閫�
+        })
+    })
+
+    emergencyBtn.on(dxui.Utils.EVENT.CLICK, () => {
+        logger.info('搴旀�ュ紑浠撴寜閽偣鍑�')
+        dxui.loadMain(emergencyPwdView.screenMain)
+    })
+
+}
+
+export default mainView
diff --git a/vf205_access/src/view/pinyin/dict.js b/vf205_access/src/view/pinyin/dict.js
new file mode 100644
index 0000000..00dca5b
--- /dev/null
+++ b/vf205_access/src/view/pinyin/dict.js
@@ -0,0 +1,410 @@
+const dict = {
+    "a": "鍟婇樋鍚栧梽鑵岄敃",
+    "ai": "鍩冩尐鍝庡攭鍝�鐨戠檶钄肩煯鑹剧鐖遍殬鎹卞棾鍡屽櫕瀚掔懛鏆х牴閿块湱",
+    "an": "闉嶆皑瀹変亢鎸夋殫宀歌兒妗堣皺鍩彏鐘村旱妗夐摰楣岄化",
+    "ang": "鑲槀鐩�",
+    "ao": "鍑规晼鐔勘琚勫偛濂ユ噴婢冲澇鎷楀椃宀欏粧閬ㄥ楠滅崚鐕犺伇铻強槌岄彇",
+    "ba": "鑺崒鎵掑彮鍚х瑔鍏枻宸存嫈璺嬮澏鎶婅�欏潩闇哥舰鐖镐集鑼囪彎钀嗘嵀宀滅仦閽矐椴呴瓋",
+    "bai": "鐧芥煆鐧炬憜浣拌触鎷滅浼枩鎹憲鎺�",
+    "ban": "鏂戠彮鎼壋鑸鏉跨増鎵媽浼寸摚鍗婂姙缁婇槳鍧傝背閽g槩鐧嶈埁",
+    "bang": "閭﹀府姊嗘鑶�缁戞纾呰殞闀戝倣璋よ挕娴�",
+    "bao": "鑻炶優鍖呰鍓ヨ杽闆逛繚鍫¢ケ瀹濇姳鎶ユ毚璞归矋鐖嗗埁鏇濆嫻钁嗗鐓查辅瑜撹兜榫�",
+    "bei": "鏉鎮插崙鍖楄緢鑳岃礉閽″�嶇媹澶囨儷鐒欒鑷傚煿瀛涢檪閭惰悊钃撳憲鎮栫楣庤閻鹃灤",
+    "ben": "濂旇嫰鏈澶暁鍧岃床閿�",
+    "beng": "铓屽穿缁风敪娉佃功杩稿爧鍞槪鐢�",
+    "bi": "閫奸蓟姣旈剻绗斿郊纰ц摉钄芥瘯姣欐瘱甯佸簢鐥归棴鏁濆紛蹇呰緹澹佽噦閬块櫅鎷傜娉屽寱浠充烤鑺樿崪鑽歌悊钖滄嵀鍚″摂鐙村撼鎰庢粭婵炲技濡e瀣栫挧璐茬潵鐣�閾嬬瑁ㄧ瓪绠呯鑸璺搁珋",
+    "bian": "闉竟缂栬船鎵佷究鍙樺崬杈ㄨ京杈亶鍖惧紒鑻勫凯姹寸紡鐓哥牠纰ョü绐嗚铦欑槌�",
+    "biao": "鏍囧姜鑶樿〃濠婇獱椋戦椋氱伂闀栭暢鐦1槌旈珶",
+    "bie": "鎹岄硸鎲嬪埆鐦供",
+    "bin": "褰枌婵掓花瀹炬憟鍌ц背缂ゆ娈¤啈闀旈珜楝�",
+    "bing": "鍏靛啺鏌勪笝绉夐ゼ鐐崇梾骞跺睆绂�鍐偞鎽掓鐕�",
+    "bo": "鏌忕櫨鑸墺钖勭幓鑿犳挱鎷ㄩ挼娉㈠崥鍕冩悘閾傜當浼笡鑸惰剸鑶婃袱娉婇┏鍗滀撼钑冭枩鎿楀暤楗借壌妾楁摌绀撮捁楣佺案瓒佃窙韪�",
+    "bu": "鍫℃崟鍗滃摵琛ュ煚涓嶅竷姝ョ翱閮ㄦ�栧煍鍗熼�嬬摽鏅¢挌閽搁啳",
+    "ca": "鎿﹀殦绀�",
+    "cai": "鐚滆鏉愭墠璐㈢潿韪╅噰褰╄彍钄�",
+    "can": "椁愬弬铓曟畫鎯儴鐏垮楠栫挩绮查华",
+    "cang": "鑻嶈埍浠撴钵钘�",
+    "cao": "鎿嶇硻妲芥浌鑽夎壒鍢堟紩灞灛鑹�",
+    "ce": "鍘曠瓥渚у唽娴嬫伝",
+    "cen": "鍙傚矐娑�",
+    "ceng": "灞傝弓鏇惧檶",
+    "cha": "鎻掑弶鑼尪鏌ョ⒋鎼藉療宀斿樊璇у埞鍠冲殦鐚归姹婂Ч鏉堟妾敻闀茶々",
+    "chai": "宸媶鏌磋焙渚挆鐦ヨ櫩",
+    "chan": "鎼�鎺鸿潐棣嬭皸缂犻摬浜ч槓棰ゅ崟鍐佽皠钂囧粵蹇忔胶婢跺缇煎┑楠h绂呴暋锜捐簲",
+    "chang": "鏄岀寲鍦哄皾甯搁暱鍋胯偁鍘傛暈鐣呭敱鍊¤3鍊樹讥楝媽鑿栧緶鎬呮儩闃婂瀚︽樁姘呴渤",
+    "chao": "瓒呮妱閽炴湞鍢叉疆宸㈠惖鐐掑壙鎬婃檨鐒��",
+    "che": "杞︽壇鎾ゆ帲褰绘緢灏哄澕灞牀",
+    "chen": "閮磋嚕杈板皹鏅ㄥ勘娌夐檲瓒佽‖绉版矆浼ц皩璋舵娀鍡斿鐞涙鑲滅榫�",
+    "cheng": "鎾戠О鍩庢鎴愬憟涔樼▼鎯╂緞璇氭壙閫為獘绉ょ洓涓炲煏鏋ㄦ熃妯樻櫉濉嶇灎閾栭摏瑁庤洀閰�",
+    "chi": "鍚冪棿鎸佸寵姹犺繜寮涢┌鑰婚娇渚堝昂璧ょ繀鏂ョ偨鍌洪儣澧�鑼屽彵鍝у暬鍡ゅ匠楗鏁曠湹楦辩槢瑜毄铻瑸绡眽韪熼瓚",
+    "chong": "鍏呭啿铏磭瀹犳秾閲嶈尯蹇℃啩閾宠垈鑹�",
+    "chou": "鎶介叕鐣磋笇绋犳剚绛逛粐缁哥瀰涓戣嚟淇﹀副鎯嗙槼闆�",
+    "chu": "鍒濆嚭姗卞帹韬囬攧闆忔粊闄ゆ纭�鍌ㄧ煑鎼愯Е澶勭暅浜嶅垗鎬垫喎缁屾澋妤瑜氳湇韫伴粶",
+    "chuai": "鎻f悑鍟愬槵鑶腹",
+    "chuan": "宸濈┛妞戒紶鑸瑰枠涓叉幘鑸涢亜宸涙皻閽忚垺韪�",
+    "chuang": "鐤獥骞㈠簥闂垱鎬�",
+    "chui": "鍚圭倞鎹堕敜鍨傞櫜妫版",
+    "chun": "鏄ユた閱囧攪娣崇函锠㈣幖鑲箲铦�",
+    "chuo": "鎴崇话缂�鍟滆径杈嶇劘瓒佃笖榫�",
+    "ci": "宸柕鑼ㄧ闆岃緸鎱堢摲璇嶆鍒鸿祼娆′己鍏硅寛鍛插弹绁犻箽绮㈢硩",
+    "cong": "鑱懕鍥卞寙浠庝笡鑻佹窓楠㈢惍鐠佹灋",
+    "cou": "鍑戞ケ杈忚厾",
+    "cu": "绮楅唻绨囦績鍗掕敓寰傜対娈傞參韫欒勾",
+    "cuan": "韫跨绐滄敀姹嗘捄鐖ㄩ暕",
+    "cui": "鎽у磾鍌剢鐦佺补娣繝钀冨晲鎮寸拃姒辨闅�",
+    "cun": "鏉戝瓨瀵稿繓鐨�",
+    "cuo": "纾嬫挳鎼撴帾鎸敊鍘濆弹鑴為攭鐭棨鐦ラ咕韫�",
+    "da": "鎼揪绛旂槱鎵撳ぇ鑰峰搾鍡掓�涘Σ鐤歌ぁ绗澕闉�",
+    "dai": "澶у憜姝瑰偅鎴村甫娈嗕唬璐疯寰呴��犲煭鐢欏脖杩ㄩ�獉缁愮幊榛�",
+    "dan": "鑰芥媴涓瑰崟閮告幐鑳嗘棪姘絾鎯贰璇炲脊铔嬬煶鐐稿剫钀忓晼婢规径娈氳禃鐪堢柛鐦呰亙绠�",
+    "dang": "褰撴尅鍏氳崱妗h盃鍑艰彧瀹曠爛閾涜",
+    "dao": "鍒�鎹h箞鍊掑矝绁峰鍒扮ɑ鎮奸亾鐩楀垈鍙ㄥ副蹇夋皹鐒樼簺",
+    "de": "寰峰緱鐨勫湴閿�",
+    "dei": "寰�",
+    "deng": "婢勮宫鐏櫥绛夌灙鍑抽倱鍣斿稘鎴ョ4闀唉",
+    "di": "鐨勫牑浣庢淮杩晫绗涚媱娑ょ繜瀚℃姷搴曞湴钂傜甯濆紵閫掔紨缁︽彁姘愮贝璇嬭皼閭稿澔鑽诲榾濞f煝妫h鐮ョ⒉鐫囬暆缇濋",
+    "dia": "鍡�",
+    "dian": "棰犳巶婊囩鐐瑰吀闈涘灚鐢典絻鐢稿簵鎯﹀娣�娈块樈鍧煗宸呯幏閽跨櫆鐧盁韪�",
+    "diao": "纰夊徏闆曞噵鍒佹帀鍚婇挀璋冮笩閾為摣铚╄矀椴�",
+    "die": "璺岀埞纰熻澏杩皪鍙犲灓鍫炴彶鍠嬪棽鐗掔摓鑰嬭箑椴�",
+    "ding": "涓佺洴鍙拤椤堕紟閿畾璁粌钁跺暥鐜庤厷纰囩敽鐤旇�甸厞",
+    "diu": "涓㈤摜",
+    "dong": "涓滃啲钁f噦鍔ㄦ爧渚楁伀鍐绘礊鍨屽挌宀藉硳姘¤儴鑳寸楦�",
+    "dou": "鍏滄姈鏂楅櫋璞嗛�楃棙閮借钄搁挱绐︾铓",
+    "du": "閮界潱姣掔妸鐙鍫电澒璧屾潨闀�鑲氬害娓″鑺忓槦娓庢鐗嶈牴绗冪簺楂戦哗",
+    "duan": "绔煭閿绘鏂紟妞寸厖绨栬腹",
+    "dui": "鍫嗗厬闃熷鎬兼啙纰撻暒",
+    "dun": "澧╁惃韫叉暒椤块挐鐩鹃亖娌岀倴鐮樼鐩归暒瓒�",
+    "duo": "搴︽巼鍝嗗澶哄灈韬叉湹璺鸿埖鍓佹儼鍫曢┊鍜勫摎缂嶆焷閾庤0閰¤副",
+    "e": "闃胯浘宄ㄩ箙淇勯璁瑰ē鎭跺巹鎵奸亸閯傞タ鍝﹂鍣╄皵鍨╄媻鑾惣鍛冨晲鎰曢槒灞欏﹢杞浄鑵攪閿烽箺棰氳毜槌�",
+    "ei": "宸ヨ",
+    "EN": "鎭╄捊鎽佸棷",
+    "er": "鑰屽効鑰冲皵楗垫幢浜岃窗浣磋咯鐝ラ搾楦搁矔",
+    "fa": "鍙戠綒绛忎紣涔忛榾娉曠彁鍨$牆",
+    "fan": "钘╁竼鐣炕妯婄熅閽掔箒鍑$儲鍙嶈繑鑼冭穿鐘キ娉涜晝铇╁埂姊电嚁鐣堣ⅱ韫�",
+    "fang": "鍧婅姵鏂硅偑鎴块槻濡ㄤ豢璁跨汉鏀惧寶閭″椒鏋嬮挮鑸矀",
+    "fei": "鑿查潪鍟¢鑲ュ尓璇藉悹鑲哄簾娌歌垂鑺捐寚鐙掓偙娣濆缁Η鑵撴枑鎵夌牘闀勭棻铚氱瘹缈¢湉椴�",
+    "fen": "鑺厷鍚╂皼鍒嗙悍鍧熺剼姹剧矇濂嬩唤蹇挎劋绮伨鐎电帰妫肩嚁鎰嶉布榧�",
+    "feng": "涓板皝鏋渹宄伴攱椋庣柉鐑介�㈠啹缂濊濂夊嚖淇搁厗钁戝敧娌i�勭牅",
+    "fo": "浣�",
+    "fou": "鍚︾级",
+    "fu": "浣涘か鏁疯偆瀛垫壎鎷傝緪骞呮盁绗︿紡淇樻湇娴丢绂忚⒈寮楃敨鎶氳緟淇嚋鏂ц劘鑵戝簻鑵愯荡鍓璧嬪鍌呬粯闃滅埗鑵硅礋瀵岃闄勫缂氬拹鍖愬嚝闃濋儧鑺欒娋鑻昏尟鑿旀媻鎺婂憢骞炴�粡瀹撹壌瀛氶└缁傜粙妗磋禉绁撶牘榛婚患缃樼▋棣ヨ毃",
+    "ga": "鍣跺槑鑳冲す浠风晫鍜栦冀灏懛灏曞皽鏃拞",
+    "gai": "璇ユ敼姒傞挋鐩栨簤鑺ヤ笎闄斿灀鎴よ祬鑳�",
+    "gan": "骞茬敇鏉嗘煈绔胯倽璧舵劅绉嗘暍璧i棿鍧╄嫹灏存搥娉旀乏婢夌粈姗勬棸鐭哥柍閰�",
+    "gang": "鍐堝垰閽㈢几鑲涚翰宀楁腐鏉犳垎缃$",
+    "gao": "绡欑殝楂樿啅缇旂硶鎼為晲绋垮憡鐫捐閮滆梺缂熸妲佹澆閿�",
+    "ge": "鐩栧摜姝屾悂鎴堥附鑳崇枡鍓查潻钁涙牸铔ら榿闅旈摤涓悇鍚堝挴楝蹭弧鍝垮湭濉ュ棟鎼胯唸纭岄晧琚艰櫦鑸搁",
+    "gei": "缁�",
+    "gen": "鏍硅窡浜樿寷鍝忚壆",
+    "geng": "鑰曟洿搴氱竟鍩傝�挎棰堝摻璧撶粻椴�",
+    "gong": "宸ユ敾鍔熸伃榫氫緵韬叕瀹紦宸╂睘鎷辫础鍏辩孩寤剧彊鑲辫殻铔╄Д",
+    "gou": "閽╁嬀娌熻嫙鐙楀灑鏋勮喘澶熷彞浣濊療宀i仒濯剧紤鏋歌褰�绗辩瘽闉�",
+    "gu": "杈滆弴鍜曠畭浼版步瀛ゅ榧撳彜铔婇璋疯偂鏁呴【鍥洪泧瀹惰淳鍢忚瘋鑿板串姹╂杞辩壇鐗胯儘鑷屾瘋鐬界綗閽撮敘楦箘鐥艰泟閰よ椴�",
+    "gua": "鍓插埉鐡滃墣瀵℃寕瑜傛嫭鍗﹀垐璇栧懕鑳嶉腹",
+    "guai": "涔栨嫄鎬幋",
+    "guan": "妫哄叧瀹樺啝瑙傜棣嗙綈鎯亴璐�岃帪鎺兼东鐩ラ钩槌�",
+    "guang": "鍏夊箍閫涘挘鐘锋鑳�",
+    "gui": "鐟拌鍦褰掗緹闂鸿建楝艰鐧告鏌滆藩璐靛埥鍖﹀尞鍒块殫搴嬪畡濡¨鐐呮櫡鐨堢皨瑙栭矐槌�",
+    "gun": "杈婃粴妫嶄辅琛徊纾欓钵",
+    "guo": "閿呴儹鍥芥灉瑁硅繃娑¢锠冨煔鍛欏洍甯煎礊鐚撴铏㈣亽铚捐潏",
+    "ha": "铔ゅ搱铏鹃摢",
+    "hai": "楠稿娴锋唉浜ュ楠囪繕鍜村棬鑳查啟",
+    "han": "閰f啫閭煩鍚兜瀵掑嚱鍠婄綍缈版捈鎹嶆棻鎲炬倣鐒婃睏姹夐倵鑿℃挅鐘撮槡娣︽緣鐎氭櫁鐒撻「棰旇毝榧�",
+    "hang": "澶澀鑸惌琛屾矄缁楃彥妗侀閰�",
+    "hao": "闀愬鍤庤豹姣儩濂借�楀彿娴╄矇钂胯枀鍡ュ殕婵犵亸鏄婄殦棰㈣殱",
+    "he": "鍛靛枬鑽疯弿鏍哥鍜屼綍鍚堢洅璨夐槀娌虫陡璧楣よ春鍚撹瘍鍔惧鍡槚绾ユ浄鐩嶉缈�",
+    "hei": "鍢块粦",
+    "hen": "鐥曞緢鐙犳仺",
+    "heng": "鍝间酣妯 鎭掕铇呯彥妗�",
+    "hong": "杞板搫鐑樿櫣楦挎椽瀹忓紭绾㈤粔瑷囪鑽暬钖ㄩ棾娉撴礆",
+    "hou": "鍠変警鐚村惣鍘氬�欏悗鍫犲緦閫呯槉绡岀硣椴庨",
+    "hu": "鏍稿拰鍛间箮蹇界憵澹惰懌鑳¤澊鐙愮硦婀栧姬铏庡敩鎶や簰娌埛鍐辫姶鍞垮洬宀电將鎬欐儦娴掓还鐞ユР杞疯儘瑙崇儉鐓虫埥鎵堢鐡犻箘楣曢贡铏嶇瑥閱愭枦楣�",
+    "hua": "鑺卞摋鍗庣尵婊戠敾鍒掑寲璇濊眮楠呮ˇ鐮夐摟",
+    "huai": "妲愬緤鎬�娣潖韪�",
+    "huan": "娆㈢幆妗撹繕缂撴崲鎮e敜鐥雹鐒曟叮瀹﹀够濂傚灨钀戞搻鍦滅嵕娲规担婕跺閫汲鐟楄剺閿鹃博楝�",
+    "huang": "鑽掓厡榛勭:铦楃哀鐨囧嚢鎯剁厡鏅冨箤鎭嶈皫鍙岄殟寰ㄦ篃娼㈤亼鐠滆倱鐧�锜ョ瘉槌�",
+    "hui": "鐏版尌杈夊窘鎭㈣洈鍥炴瘉鎮旀収鍗夋儬鏅﹁纯绉戒細鐑╂眹璁宠缁樻簝璇欒尨鑽熻暀鍜村摃鍠欓毘娲勬祶褰楃紜妗ф櫀鎭氱湱铏鸿煪楹�",
+    "hun": "鑽ゆ槒濠氶瓊娴戞贩璇ㄩ闃嶆悍鐝�",
+    "huo": "鍜岃眮娲讳紮鐏幏鎴栨儜闇嶈揣绁稿姁钘挎攭鍤ぅ鐏爥閽敧闀�犺爾",
+    "i": "浣犵埍灏煎�摝鎷熷Ξ娉ラ��",
+    "ji": "缁欏嚮鍦惧熀鏈虹暩绋界Н绠曡倢楗ヨ抗婵�璁ラ浮濮哗缂夊悏鏋佹杈戠睄闆嗗強鎬ョ柧姹插嵆瀚夌骇鎸ゅ嚑鑴婂繁钃熸妧鍐�瀛d紟绁墏鎮告祹瀵勫瘋璁¤鏃㈠繉闄呭缁х邯钘夊鑸岀郴涓屼簾涔╁墳浣跺亪澧艰姩鑺拌崰钂鸿暫鎺庡徑鍜摐鍞у矊宓�",
+    "jia": "鍢夋灧澶逛匠瀹跺姞鑽氶璐剧敳閽惧亣绋间环鏋堕┚瀚佽寗鍢忎冀閮忚懎宀祪杩︾張鏌欐垱鑳涙仢閾楅晸鐥傜槙琚疯洷绗宠璺忛",
+    "jian": "姝肩洃鍧氬皷绗洪棿鐓庡吋鑲╄壈濂哥紕鑼ф鏌⒈纭锋嫞鎹$畝淇壀鍑忚崘妲涢壌璺佃幢瑙侀敭绠欢鍋ヨ埌鍓戦ク娓愭簠娑у缓鍍皬璋弲钂规悰鍥濈姶婀旇箛璎囩迹鏋ф鎴嬫埇鐗妽姣借叡鐫戦攺楣h%绗曠喀瓒艰负椴i灟",
+    "jiang": "鍍靛灏嗘祮姹熺枂钂嬫〃濂栬鍖犻叡闄嶅己鑼虫礆缁涚及鐘熺鑰╃敞璞�",
+    "jiao": "钑夋绀佺劍鑳朵氦閮婃祰楠勫▏鍤兼悈閾扮煫渚ヨ剼鐙¤楗虹即缁炲壙鏁欓叺杞胯緝鍙獤瑙夋牎浣煎儸鑹借尛鎸㈠檷宄ゅ炯婀В鏁垵鐨庨躬铔熼啴璺ら矝",
+    "jie": "鎻帴鐨嗙Ц琛楅樁鎴姭鑺傛鏉版嵎鐫娲佺粨瑙e鎴掕棄鑺ョ晫鍊熶粙鐤ヨ灞婂亪璁﹁瘶鍗╂嫯鍠堝棢濠曞瓚鏍夋纰g枛棰夎毀缇矑楠�",
+    "jin": "宸剧瓔鏂ら噾浠婃触瑗熺揣閿︿粎璋ㄨ繘闈虫檵绂佽繎鐑蹈灏藉姴鍗鸿崺鍫囧櫎棣戝缂欑懢妲胯祮瑙愰拝琛跨煖",
+    "jing": "鍔茶崋鍏㈣寧鐫涙櫠椴镐含鎯婄簿绮崇粡浜曡鏅闈欏鏁暅寰勭棄闈栫珶绔炲噣鍒剢闃辫弫鐛嶆啲娉捐砍寮┃妾犳櫉鑲艰儷鑵堟棇闈�",
+    "jiong": "鐐獦鍐傚灖杩ョ倕鎵�",
+    "jiu": "鎻┒绾犵帠闊箙鐏镐節閰掑帺鏁戞棫鑷艰垍鍜庡氨鐤氬儲鍟鹃槃婀煩妗曢笭楣潳璧抽瑥",
+    "ju": "杞︽闉犳嫎鐙欑柦灞呴┕鑿婂眬鍜�鐭╀妇娌仛鎷掓嵁宸ㄥ叿璺濊笧閿勘鍙ユ儳鐐墽鍊ㄨ閯硅嫞鑻磋帓鎺伣灞︾悮鏋告姒樻姗樼妺椋撻挏閿旂瑁捐秳閱佃附榫冮泿闉�",
+    "juan": "鎹愰箖濞熷�︾湻鍗风虎鍦堥剟鎿愮嫹娉稉妗婅牪閿╅晫闅�",
+    "jue": "鍤艰鎾呮敨鎶夋帢鍊旂埖瑙夊喅璇�缁濆帴鍔傝安鐭嶈暔钑炲櫂宕涚崡瀛撶弿鏌芥》姗涚垵闀㈣苟瑙�",
+    "jun": "榫熷潎鑿岄挧鍐涘悰宄讳繆绔f禋閮¢獜鎹冪嫽鐨查毥",
+    "ka": "鍠�鍜栧崱浣у挃鑳�",
+    "kai": "寮�鎻╂シ鍑叏鍓�鍨茶拡蹇炬伜閾犻攷閿�",
+    "kan": "妲涘垔鍫嫎鍧庣爫鐪嬪祵渚冨嚨鑾伴槡鎴¢緵鐬�",
+    "kang": "搴锋叿绯犳墰鎶椾孩鐐曚級闂堕挭",
+    "kao": "鑰冩嫹鐑ら潬灏绘牪鐘掗搻",
+    "ke": "鍧疯嫑鏌5纾曢绉戝3鍜冲彲娓村厠鍒诲璇惧棏宀㈡仾婧橀獟缂傜弬杞叉蔼鐬岀泹閽堕敒绋炵柎绐犻铓佃潓楂�",
+    "ken": "鑲晝鍨︽伋瑁�",
+    "keng": "鍧戝惌纭庨摽",
+    "kong": "绌烘亹瀛旀帶鍊ュ磫绠�",
+    "kou": "鎶犲彛鎵e瘒鍒充綕鑺よ敾鍙╃湇绛�",
+    "ku": "鏋摥绐熻嫤閰峰簱瑁ゅ埑鍫�鍠剧粩楠�",
+    "kua": "澶稿灝鎸庤法鑳緣楂�",
+    "kuai": "浼氬潡绛蜂京蹇挴閮愬摍鐙祶鑴�",
+    "kuan": "瀹芥楂�",
+    "kuang": "鍖$瓙鐙傛鐭跨湺鏃峰喌璇撹閭濆湽澶煎搻绾╄炊",
+    "kui": "浜忕洈宀跨钁靛榄佸個棣堟劎婧冮鍖闅楄拤鎻嗗柟鍠熸倽鎰﹂�垫殞鐫借仼铦扮瘧璺",
+    "kun": "鍧ゆ槅鎹嗗洶鎮冮槂鐞ㄩ敓閱岄膊楂�",
+    "kuo": "鎷墿寤撻様閫傛牆铔�",
+    "la": "鍨冩媺鍠囪湣鑵婅荆鍟﹁惤鍓岄倠鏃牞鐦�",
+    "lai": "鑾辨潵璧栧磧寰曟稙婵戣祲鐫愰摷鐧炵眮",
+    "lan": "钃濆┆鏍忔嫤绡槕鍏版緶璋版徑瑙堟噿缂嗙儌婊ュ矚鎳旀激姒勬枔缃遍暓瑜�",
+    "lang": "鐞呮鐙煎粖閮庢湕娴帹钂楀暦闃嗛敀绋傝瀭",
+    "lao": "鎹炲姵鐗㈣�佷浆濮ラ叒鐑欐稘涔愯惤鍞犲磦鏍抽搼閾圭棬鑰㈤啰",
+    "le": "鍕掍箰浜嗕粋鍙诲槥娉愰硴",
+    "lei": "鍕掗浄闀暰纾婄疮鍎″瀿鎿傝倠绫绘唱缇歌瘮鍢炲珮缂ф獞鑰掗吂",
+    "leng": "妫辨鍐峰紕濉勬劊",
+    "li": "鍘樻ⅷ鐘侀粠绡辩嫺绂绘紦鐞嗘潕閲岄菠绀艰帀鑽斿悘鏍椾附鍘夊姳鐮惧巻鍒╁倛渚嬩繍鐥㈢珛绮掓播闅跺姏鐠冨摡楝蹭开淇氶儲鍧滆媹鑾呰摖钘滃憱鍞冲柋鐚佹骇婢ч�﹀▽瀚犻獖缂℃灔鏍庤焦鎴剧牶纭岃﹫缃归攤楣傜枲鐤泿铚婅牎绗犵绮濋喆璺為洺椴¢尝",
+    "lia": "淇�",
+    "lian": "鑱旇幉杩為暟寤夋�滄稛甯樻暃鑴搁摼鎭嬬偧缁冭敼濂佹悰娼嬫總鐞忔娈撹噥鑶︾灥瑁㈣#锠婇并",
+    "liang": "淇╃伯鍑夋绮辫壇涓よ締閲忔櫨浜皡澧氭韪夐潛榄�",
+    "liao": "鎾╄亰鍍氱枟鐕庡杈芥溅浜嗘拏闀e粬鏂欒摷灏ュ樄鐛犲缂拰楣�",
+    "lie": "鍒楄鐑堝姡鐚庡喗鍩掓崺鍜ф磳瓒旇簮楝�",
+    "lin": "鐞虫灄纾烽湒涓撮偦槌炴穻鍑涜祦鍚濇嫀钄哄晧宥欏华鎳旈伌妾╄練鑶︾灥绮艰簭楹�",
+    "ling": "妫辩幉鑿遍浂榫勯搩浼剁練鍑岀伒闄靛箔棰嗗彟浠ら厓鑻撳懁鍥规碃缁焹妫傜摯鑱嗚泬缈庨伯",
+    "liu": "婧滅悏姒寸~棣忕暀鍒樼槫娴佹煶鍏娉栨祻閬涢獫缁烘棐鐔橀攳闀忛龚閹�",
+    "long": "榫欒亱鍜欑绐块殕鍨勬嫝闄囧紕鍨呰審娉风彂鏍婅儳鐮荤檭",
+    "lou": "妤煎▌鎼傜瘬婕忛檵闇插伝钂屽柦宓濋晜鐦樿�ц澕楂�",
+    "lu": "鍏姦鍗㈤搴愮倝鎺冲崵铏忛瞾楹撶闇茶矾璧傞箍娼炵褰曢檰鎴豢鍨嗘捀鍣滄掣娓屾級閫拹鏍屾┕杞宠緜杈樻皣鑳暐楦弓鐦崇皬鑸婚矆",
+    "luan": "宄︽寷瀛沪鍗典贡鑴斿▓鏍鹃妇閵�",
+    "lun": "鎶¤疆浼︿粦娌︾憾璁哄浀",
+    "luo": "鍜彛閰悵铻虹綏閫婚敚绠╅瑁歌惤娲涢獑缁滃�爟鑽︽崑鎽炵寭鐚℃澈婕彏妞よ劧纭岄暀鐦拌溇璺為洅",
+    "lv": "椹村悤閾濅荆鏃呭饱灞$紩铏戞隘寰嬬巼婊ょ豢闂炬鑶傜▎瑜�",
+    "lve": "鎺犵暐閿�",
+    "m": "鍛�",
+    "ma": "濡堥夯鐜涚爜铓傞┈楠傚槢鍚椾箞鎽╂姽鐘稿鏉╄焼",
+    "mai": "鍩嬩拱楹﹀崠杩堣剦缇庡姠鑽敍闇�",
+    "man": "鍩嬬瀿棣掕洰婊¤敁鏇兼參婕癌澧佸箶缂︾喅闀橀铻ㄩ硹闉�",
+    "mang": "鑺掕尗鐩叉皳蹇欒幗閭欑灑婕…锜�",
+    "mao": "鐚寘閿氭瘺鐭涢搯鍗寕鍐掑附璨岃锤渚旇ⅳ鍕栬寙宄佹硸鐟佹槾鐗﹁�勬梽鎳嬬瀫铔戣潵锜婇",
+    "me": "涔堟湯楹�",
+    "mei": "鐜灇姊呴叾闇夌叅娌$湁濯掗晛姣忕編鏄у瘣濡瑰獨璋滃澏鑾撳祴鐚告导婀勬ィ闀呴箾琚傞瓍",
+    "men": "闂ㄩ椃浠壀鐒栨噾閽旈灁",
+    "meng": "姘撹悓钂欐鐩熼敯鐚涙ⅵ瀛熷嫄鐢嶇灑鎳垫湨绀炶櫥铚㈣爴鑹嬭墾榛�",
+    "mi": "鐪啔闈$硿杩疯皽寮ョ背绉樿娉岃湝瀵嗗箓鑺堝問璋ц樇鍜槯鐚曟报瀹撳辑鑴掔ア鏁夌掣绺婚簨",
+    "mian": "妫夌湢缁靛啎鍏嶅媺濞╃紖闈㈡矓娓戞箮瀹�鑵肩渼榛�",
+    "miao": "鑻楁弿鐬勮棎绉掓负搴欏鍠甸倛缂堟潽娣肩渿楣�",
+    "mie": "钄戠伃涔滃挬锠涚",
+    "min": "姘戞娍鐨挎晱鎮椊鑻犲卜闂垫朝缂楃弶鎰嶉痪槌�",
+    "ming": "鏄庤灍楦i摥鍚嶅懡鍐ヨ寳婧熸殱鐬戦叐",
+    "miu": "璋吉",
+    "mo": "鑴変箞娌℃懜鎽硅槕妯¤啘纾ㄦ懇榄旀姽鏈帿澧ㄩ粯娌紶瀵為檶涓囨棤璋熻寜钃﹂瀚娈侀晢绉g樇鑰辫矈璨橀航",
+    "mou": "璋嬬墴鏌愪緮鍘跺摓缂湼铔戦崻",
+    "mu": "濮ユā鐗熸媷鐗′憨濮嗘瘝澧撴毊骞曞嫙鎱曟湪鐩潶鐗х﹩浠澏鑻滄矏姣捈",
+    "na": "鎷垮摢鍛愰挔閭e绾冲崡鎹鸿偔闀庤〔绠�",
+    "nai": "姘栦箖濂惰�愬榧愪酱鑹胯悩鏌�",
+    "nan": "鍗楃敺闅惧杻鍥℃鑵╃奖铦昏掸",
+    "nang": "鍥婃敭鍥旈鏇�",
+    "nao": "鎸犺剳鎭奸椆娣栧鍨村懚鐚辩憴纭囬摍铔�",
+    "ne": "鍝憿璁风枓",
+    "nei": "棣佸唴",
+    "nen": "瀚�",
+    "neng": "鑳�",
+    "ni": "鍛㈠Ξ闇撳�偿灏兼嫙浣犲尶鑵婚�嗘汉浼插澀鐚婃�╂樀鏃庣ア鎱濈潹閾岄驳",
+    "nian": "钄媹骞寸⒕鎾垫嵒蹇电矘寤垮煗杈囬粡椴囬捕",
+    "niang": "濞橀吙",
+    "niao": "婧洪笩灏胯寫瀣茶劜琚�",
+    "nie": "鎹忚亗瀛藉暜闀婇晬娑呴櫑鍩濊槚鍡鑷箲",
+    "nin": "鎮�",
+    "ning": "鏌犵嫗鍑濆畞鎷ф碁浣炲挍鐢亶",
+    "niu": "鐗涙壄閽航鎷楃媰蹇稿",
+    "nong": "鑴撴祿鍐滃紕渚摑",
+    "nou": "鑰�",
+    "nu": "濂村姫鎬掑缉鑳椹�",
+    "nuan": "鏆�",
+    "nuo": "濞滄尓鎳︾朝璇哄偐鎼﹀枏閿�",
+    "nv": "濂崇媰鎭ч挄琛�",
+    "nve": "铏愮枱",
+    "o": "鍠斿櫌",
+    "ou": "娆ч弗娈磋棔鍛曞伓娌よ鎬勭摨鑰�",
+    "pa": "鎵掕�欏暘瓒寸埇甯曟�曠惗钁╂澐绛�",
+    "pai": "鎷嶆帓鐗屽緲婀冩淳杩砍钂庡搶",
+    "pan": "鑸崬鐣攢娼樼洏纾愮浖鐣斿垽鍙涜儢寮佹嫐鐖挎钞鐨よⅱ瑗昏煚韫�",
+    "pang": "鑶�纾呬箵搴炴梺鑰儢褰锋粋閫勮瀮",
+    "pao": "鎶涘拞鍒ㄧ偖琚嶈窇娉″審鐙嶅簴鑴柋瓒�",
+    "pei": "鍛歌儦鍩硅4璧旈櫔閰嶄僵娌涜寚鎺婅緮甯旀窢鑹存梿閿唴闇�",
+    "pen": "鍠风泦婀�",
+    "peng": "鐮版姩鐑规編褰摤妫氱〖绡疯啫鏈嬮箯鎹х鍫嬪槶鎬﹁煕",
+    "pi": "杈熷惁鍧爳闇规壒鎶妶鐞垫瘲鍟よ劸鐤茬毊鍖圭棡鍍诲眮璀笗浠抽檪闄撮偝閮湲鍩ら紮鑺樿悊钖滄摋鍣煎笖搴�搴虫窢濯茬喊鏋囩敁缃撮搷鐧栫枊铓嶈湵璨�",
+    "pian": "鎵佷究绡囧亸鐗囬獥璋濋獔缂忕姀鑳肩咯韫�",
+    "piao": "椋樻紓鐡㈢エ鏈村壗鑾╁槍瀚栭獱缂ユ畭鐬熻灥楂�",
+    "pie": "鎾囩灔涓胯嫟姘�",
+    "pin": "鎷奸璐搧鑱樻嫐濮樺珨姒�鐗濋ⅵ",
+    "ping": "鍐箳鍧嫻钀嶅钩鍑摱璇勫睆淇滃爧濞夋灠椴�",
+    "po": "娉婂潯娉奸濠嗙牬榄勮揩绮曟湸鍙甸檪閯辨澈鐝�閽嬮挿鐨ょ",
+    "pou": "鍓栬鎺�",
+    "pu": "鍫℃毚鑴墤閾轰粏鑾嗚憽鑿╄挷鍩旀湸鍦冩櫘娴﹁氨鏇濈�戝實鍣楁亥婵挒鏀存皢鏀甸暏闀ㄨ辜",
+    "qi": "绋芥湡娆烘爾鎴氬涓冨噭婕嗘煉娌忓叾妫嬪姝х暒宕庤剱榻愭棗绁堢楠戣捣宀備篂浼佸惎濂戠爩鍣ㄦ皵杩勫純姹芥常璁笇浜撲繜鍋堝溁鑺戣姫鑽犺悂钀嬭懞钑插榿灞哄矏姹旀穱楠愮划鐞惁鏉炴·妲�嗘绁烘仢鎲╃棰�铔磋湠缍︾懂韫婇硩楹�",
+    "qia": "鍗℃帎鎭版唇钁滈珎",
+    "qian": "鐗垫墻閽庨搮鍗冭縼绛句粺璋︿咕榛旈挶閽冲墠娼滈仯娴呰按鍫戝祵娆犳瓑绾ゅ�╀渐闃″嚨鑺婅姟鑼滆崹鎺挅宀嶆偔鎱婃稊楠炴惔瑜扮急妞犵妽鑲锋剢閽よ檾绠�",
+    "qiang": "灏嗘灙鍛涜厰缇屽钄峰己鎶脯鐖挎垥瀚辨ǒ鎴楃倽閿栭數闀铚g緹璺穭",
+    "qiao": "钑夊3姗囬敼鏁叉倓妗ョ灖涔斾鲸宸ч灅鎾繕宄繌绐嶉泙鍔佽璋崬宄ゆ剙鎲旂疾妯垫鏁璺烽瀿",
+    "qie": "娌忕爩鍒囪寗涓旀�獌浼介儎鍞兼儸鎱婂濠曟寛鑴為敳绠ц秳",
+    "qin": "閽︿镜浜茬Е鐞村嫟鑺规搾绂藉瘽娌佽姪钃佹徔鍚e棯鍣欏粦婧辨獛閿撹】铻撹【",
+    "qing": "浜查潚杞绘阿鍊惧嵖娓呮搸鏅存鞍鎯呴》璇峰簡鑻樺湂妾犵,铚荤絼绠愮懂璎﹂箔榛�",
+    "qiong": "鐞肩┓閭涜妿鑼曠┕铔╃瓏璺妿",
+    "qiu": "榫熺涓橀偙鐞冩眰鍥氶厠娉呬繀宸姲鎰�婀�戦亽妤歌祰铏毌铦よ绯楅硡榧�",
+    "qu": "瓒嬪尯铔嗘洸韬眻椹辨笭鍙栧ǘ榫嬭叮鍘绘垖璇庡姮鑻h晼铇у矕琛㈤槖鐠╄姘嶆湊绁涚2楦茬櫙铔愯牸楹寸灴闉虎",
+    "quan": "鍦堥ⅶ鏉冮啗娉夊叏鐥婃嫵鐘埜鍔濊癄鑽冪姯鎮涚换妗婅緛鐣庨摠铚风瓕楝�",
+    "que": "缂虹倲鐦稿嵈楣婃Ψ纭泙鑺嶉槙闃欐偒",
+    "qun": "瑁欑兢閫¢簢",
+    "ran": "鐒剁噧鍐夋煋鑻掕毢楂�",
+    "rang": "鐡ゅ¥鏀樺毞璁╃Τ绌�",
+    "rao": "楗舵壈缁曡崨濞嗘 ",
+    "re": "鎯圭儹鑻ュ枏",
+    "ren": "澹粊浜哄繊闊т换璁ゅ垉濡婄韩浜讳粸鑽忛オ杞亖绋旇〗",
+    "reng": "鎵斾粛",
+    "ri": "鏃�",
+    "rong": "鎴庤尭钃夎崳铻嶇啍婧跺缁掑啑宓樼嫧姒曡倻铦�",
+    "rou": "鎻夋煍鑲夌硡韫傞灒",
+    "ru": "鑼硅爼鍎掑濡傝颈涔虫睗鍏ヨぅ钃愯柗鍤呮闯婧芥俊缂涢摲瑗﹂ⅴ",
+    "ruan": "杞槷鏈�",
+    "rui": "钑婄憺閿愯姰钑ゆ灅鐫胯殝",
+    "run": "闂版鼎",
+    "ruo": "鑻ュ急鍋岀",
+    "sa": "鎾掓磼钀ㄥ崊浠ㄦ鎸茶剮椋�",
+    "sai": "鑵硟濉炶禌鍣�",
+    "san": "涓夊弫浼炴暎棣撴绯�",
+    "sang": "妗戝棑涓ф悺纾夐ⅰ",
+    "sao": "鎼旈獨鎵珎鍩界极缂茶噴鐦欓硧",
+    "se": "濉炵憻鑹叉订鍟摨绌�",
+    "sen": "妫�",
+    "seng": "鍍�",
+    "sha": "鑾庣爞鏉�鍒规矙绾卞偦鍟ョ厼鍘﹀敿鍡勬瓋閾╃棫瑁熼湈椴�",
+    "shai": "鑹茬瓫鏅掗吘",
+    "shan": "鍗曟幐鐝婅嫬鏉夊北鍒犵吔琛棯闄曟搮璧¤喅鍠勬睍鎵囩籍鏍呭墶璁劘鍩忚姛褰℃礁濮楀瑮楠熻喕绂呴拹鐤濊煯鑸㈣窔槌濋珶",
+    "shang": "澧掍激鍟嗚祻鏅屼笂灏氳3鍨х槐娈囩喌瑙�",
+    "shao": "姊㈡崕绋嶇儳鑺嶅嫼闊跺皯鍝ㄩ偟缁嶅彫鍔嫊娼叉潛铔哥鑹�",
+    "she": "濂㈣祳铔囪垖鑸嶈郸鎽勫皠鎱戞秹绀捐鎷炬姌鍘嶄綐鎻茬尀婊犳瓩鐣查簼",
+    "shei": "璋�",
+    "shen": "鍙傜牱鐢冲懟浼歌韩娣卞缁呯娌堝濠剁敋鑲炬厧娓椾粈璇滆皞鑾樿憵鍝傛笘妞硅儌鐭ц渻",
+    "sheng": "涔樿韩澹扮敓鐢ョ壊鍗囩怀鐪佺洓鍓╄儨鍦e祳鏅熺湚绗�",
+    "shi": "鍖欏笀澶辩嫯鏂芥箍璇楀案铏卞崄鐭虫嬀鏃朵粈椋熻殌瀹炶瘑鍙茬煝浣垮睅椹跺寮忕ず澹笘鏌夸簨鎷獡閫濆娍鏄棞鍣�備粫渚嶉噴楗版皬甯傛亙瀹よ璇曚技娈栧硻璋ュ煒鑾宠搷寮戦ィ杞艰闯鐐荤せ閾堣垚绛吘璞曢播椴�",
+    "shou": "鏀舵墜棣栧畧瀵挎巿鍞彈鐦﹀吔鐔熸墝鐙╃欢鑹�",
+    "shu": "钄灑姊虫畩鎶掕緭鍙旇垝娣戠枏涔﹁祹瀛扮啛钖殤鏇欑讲铚�榛嶉紶灞炴湳杩版爲鏉熸垗绔栧搴舵暟婕辨仌淇炲�忓【鑿芥憛娌稇婢嶅绾炬鑵ф绉枊",
+    "shua": "鍒疯�嶅敯",
+    "shuai": "鐜囨憯琛扮敥甯呰焵",
+    "shuan": "鏍撴嫶闂╂懂韪�",
+    "shuang": "闇滃弻鐖芥撤娣欏瓈",
+    "shui": "璋佹按鐫$◣璇存暗",
+    "shun": "鍚灛椤鸿垳鎭傚窙",
+    "shuo": "鏁拌纭曟湐鐑佽挻鎼犲棈濡佹閾�",
+    "si": "鍘曟柉鎾曞樁鎬濈鍙镐笣姝昏倖瀵哄棧鍥涗己浼奸ゲ宸冲幃淇熷厱鍘跺挐姹滄硹婢屽椹风簾缂岀閿堕付鑰滆洺绗ョ掣",
+    "song": "鏉捐�告�傞閫佸畫璁艰鍑囪彉宕у旦蹇倸娣炵",
+    "sou": "鎼滆墭鎿炲椊鍙熻柈鍡栧椌棣婃稇婧查鐬嶉敿铻�",
+    "su": "鑻忛叆淇楃礌閫熺矡鍍冲婧璇夎們澶欒啊钄屽棄鎰稇绨岃Й绋�",
+    "suan": "閰歌挏绠楃嫽",
+    "sui": "灏胯櫧闅嬮殢缁ラ珦纰庡瞾绌楅亗闅х璋囪嵔婵夐們鐕х湱鐫�",
+    "sun": "瀛欐崯绗嬭崻鐙查'姒毤",
+    "suo": "鑾庤搼姊攩缂╃悙绱㈤攣鎵�鍞㈠棪鍡嶅☉妗尣鐫冪晶",
+    "ta": "濉屼粬瀹冨ス濉旂嵀鎸炶箣韪忔嫇鍡掗椉婧婚仮姒绘矒閾婅犊槌�",
+    "tai": "鑳庤嫈鎶彴娉伴厼澶�佹卑閭拌柟鍛旈獉鑲界偙閽涜穯椴�",
+    "tan": "寮瑰潔鎽婅椽鐦哗鍧涙獉鐥版江璋皥鍧︽琚掔⒊鎺㈠徆鐐儻鏄欏繍閽介敩闀¤",
+    "tang": "姹ゅ鎼爞妫犺啗鍞愮硸鍊樿汉娣岃稛鐑偉甯戞簭鐟閾撮晽鑰ヨ灄铻崇景閱�",
+    "tao": "鎺忔稕婊旂沪钀勬閫冩窐闄惰濂楅紬鍙ㄥ晻娲煬鐒橀",
+    "te": "鐗瑰繏蹇戞厺閾�",
+    "teng": "钘よ吘鐤艰獖婊�",
+    "ti": "鍫ゅ紵姊墧韪㈤攽鎻愰韫勫暭浣撴浛鍤忔儠娑曞墐灞夊�滆崙鎮岄�栫花缂囬箞閱�",
+    "tian": "澶╂坊濉敯鐢滄伂鑸旇厗鎺繚闃楁畡鑵肩晪閽�",
+    "tiao": "璋冩寫鏉¤竣鐪鸿烦浣昏嫊绁х獣铚╃绮滈締椴﹂",
+    "tie": "璐撮搧甯栬悳椁�",
+    "ting": "鍘呭惉鐑冩眬寤峰仠浜涵鎸鸿墖鑾涜懚濠锋鐢洪摛铚撻渾",
+    "tong": "渚楁礊閫氭閰灣鍚岄摐褰ょ妗舵崊绛掔粺鐥涗綗鍍粷鍨岃尲鍡靛硳鎭告郊鐮�",
+    "tou": "鍋锋姇澶撮�忎籂閽",
+    "tu": "鍑哥绐佸浘寰掗�旀秱灞犲湡鍚愬厰鍫嶈嵓鑿熼拲閰�",
+    "tuan": "婀嶅洟鎶熷綎鐤�",
+    "tui": "鍫嗘帹棰撹吙铚曡お閫�鐓�",
+    "tun": "鍥よお鍚炲悲鑷�姘介エ鏆捐偒璞�",
+    "tuo": "鎷栨墭鑴遍傅闄�椹┘妞Ε鎷撳斁涔囦綏鍧ㄥ汗娌叉脖鏌濇焷姗愮牐閾婄閰¤穾榧�",
+    "u": "鍘讳笉涓庨洦楸�",
+    "v": "鍚冩墠杞﹀嚭闄�",
+    "wa": "鍑规寲鍝囪洐娲煎▋鐡﹁浣ゅú鑵�",
+    "wai": "姝宕�",
+    "wan": "璞屽集婀剧帺椤戒父鐑峰畬纰楁尳鏅氱殩鎯嬪疀濠変竾鑵曞墱鑺勮帪鑿�绾ㄧ痪鐞剺鐣硅溈",
+    "wang": "姹帇浜℃瀴缃戝線鏃烘湜蹇樺缃斿阿鎯樿緥榄�",
+    "wei": "濞佸穽寰嵄闊﹁繚妗呭洿鍞儫涓烘綅缁磋媷钀庡浼熶吉灏剧含鏈敋鍛崇晱鑳冨杺榄忎綅娓皳灏夋叞鍗亷璇块殘闅楀湬鑺熻懗钖囧洍甯忓阜宓尌鐚棻娌╂揣娑犻�跺〒鐜煪杌庣倻鐓ㄧ湱鐥胯墘闅归矓",
+    "wen": "鐦熸俯铓婃枃闂荤汗鍚荤ǔ绱婇棶鍒庨槍姹剁師鐠烘畞绗忛洴",
+    "weng": "鍡$縼鐡搳钑�",
+    "wo": "鎸濊湕娑$獫鎴戞枴鍗ф彙娌冨�幋鍠斿棇骞勬弗濯偀纭緦",
+    "wu": "鎭跺帆鍛滈挩涔屾薄璇眿鏃犺姕姊у惥鍚存瘚姝︿簲鎹傚崍鑸炰紞渚潪鎴婇浘鏅ょ墿鍕垮姟鎮熻鍏�浠甸槩閭湰鑺村憭鍞斿枖搴戞�冨郡娴杩曞Ι濠洪獩鏉岀壘鏂肩剱楣夐箿鐥﹁湀绗忛媹榧�",
+    "xi": "鏍栨様鐔欐瀽瑗跨鐭芥櫚鍢诲惛閿$壓绋�鎭笇鎮夎啙澶曟儨鐔勭儻婧睈鐘�妾勮甯範濯冲枩閾f礂绯婚殭鎴忕粏鍍栧叜闅伴儎閮楄寽鑿ヨ懜钃板鍜﹀攺寰欓ォ闃嬫禒娣呭保瀣夌幒妯ㄦ洣瑙嬫鐔圭绂у祰鐨欑└瑁艰湧铻呰煁鑸勮埦缇茬矠缈曢啹韫�",
+    "xia": "鐬庤櫨鍖i湠杈栨殗宄′緺鐙笅鍘﹀鍚撹懎鍡勭嫀閬愮憰鏌欐纭栫槙缃呴粻",
+    "xian": "瑙侀摚娲楁巰閿ㄥ厛浠欓矞绾ゅ捀璐よ鑸烽棽娑庡鸡瀚屾樉闄╃幇鐚幙鑵洪缇″闄烽檺绾挎兂鍐艰媼鑾惰棑宀樺健鐚冩厞鏆瑰ù姘欑嚬绁嗛还閿箛鐥毈绛呯奔閰拌罚璺归湴",
+    "xiang": "闄嶇浉鍘㈤暥棣欑瑗勬箻涔$繑绁ヨ鎯冲搷浜」宸锋鍍忓悜璞¤姉钁欓シ搴犻缂冭煋鑸¢矠椋�",
+    "xiao": "钀х闇勫墛鍝殻閿�娑堝娣嗘檽灏忓瓭鏍¤倴鍟哥瑧鏁堢埢鍝撳搐娼囬�嶅В楠佺弧鏋灥铔哥绠瓐",
+    "xie": "瑙f浜涙瓏铦庨瀷鍗忔専鎼洪偑鏂滆儊璋愬啓姊板嵏锜规噲娉勬郴璋㈠睉琛�鍙跺仌浜靛嫲鐕枻鎾峰枅鐛花娓�i倐缁佺棘姒鐪番韬為",
+    "xin": "钖姱閿屾杈涙柊蹇诲績淇¤鍥熼Θ鑾樺縿鏄曟瓎闀¢懌",
+    "xing": "鐪佹槦鑵ョ尒鎯哄叴鍒戝瀷褰㈤偄琛岄啋骞告潖鎬у鍏勯檳鑽囪崶鎿らェ鎮荤",
+    "xiong": "鍏勫嚩鑳稿寛姹归泟鐔婅妿",
+    "xiu": "鑷浼戜慨缇炴溄鍡呴攬绉�琚栫唬鍜诲搏棣愬亥婧撮负璨呴",
+    "xu": "澧熸垖闇�铏氬槝椤诲緪璁歌搫閰楀彊鏃簭鐣滄仱绲┛缁画鍚佽鍕栧湬钃挎传婧嗛〖鏍╄偡鐓︾爥鐩辫儱绯堥啈闆�",
+    "xuan": "杞╁枾瀹f偓鏃嬬巹閫夌櫍鐪╃粴鍎囪皷钀辨弾鎿愭倡娓叉缉鐠囨ウ鏄曟殑鐐厞纰归搲闀熺梼",
+    "xue": "鍓婇澊钖涘绌撮洩琛�璋戝櫛鍤扯韪呴硶",
+    "xun": "鑽ゆ禋鍕嬬啅寰棳璇㈠椹贰娈夋睕璁閫婅繀宸介儑鍩欒崁鑽ㄨ晥钖板硧寰囩嫽鐛亗娲垫禂鏇涢喓椴�",
+    "ya": "鍘嬫娂楦﹂腑鍛�涓娊鐗欒殰宕栬娑泤鍝戜簹璁惰涧浼㈠灜鎻犲矆杩撳▍鐞婃姘╃爲鐫氱棖鐤�",
+    "yan": "淇洪搮鐒夊捊闃夌儫娣圭洂涓ョ爺铚掑博寤惰█棰滈槑鐐庢部濂勬帺鐪艰婕旇壋鍫扮嚂鍘岀牃闆佸攣褰︾劙瀹磋皻楠屾鍘h禎鍓′卡鍋冨厲璁犺俺闃介兙閯㈠煆鍩姭鑿告彏宕︽伖闂槒婀粺濡嶅鐞版獝鏅忚儹鑵岀劚缃ㄧ閰介瓏椁嶉脊",
+    "yang": "娈冨ぎ楦Ё鏉ㄦ壃浣枴缇婃磱闃虫哀浠扮棐鍏绘牱婕惧緣鎬忔潮鐐�鐑婃仚铔橀瀰",
+    "yao": "渚ョ枱閭�鑵板鐟舵憞灏ч仴绐戣埃濮氬挰鑸�鑽鑰�绾﹂挜澶埢鍚嗗搐宕惧经鐎瑰购鐝ф澇杞烘洔鑲撮摣楣炵獔绻囬硱",
+    "ye": "鍜芥ぐ鍣庤�剁埛閲庡喍涔熼〉鎺栦笟鍙舵洺鑵嬪娑叉嫿闈ヨ皰閭烘彾鎻叉彏鏅旂儴閾�",
+    "yi": "鑹捐泧灏句竴澹瑰尰鎻栭摫渚濅紛琛i澶烽仐绉讳华鑳扮枒娌傚疁濮ㄥ綕妞呰殎鍊氬凡涔欑煟浠ヨ壓鎶戞槗閭戝惫浜垮焦鑷嗛�歌倓鐤害瑁旀剰姣呭繂涔夌泭婧㈣璁皧璇戝紓缈肩繉缁庝缚鍒堝姄浣氫骄璇掑湳鍩告嚳鑻¤枏寮堝鎸规帋寮嬪憮鍜﹀捒鍡屽櫕",
+    "yin": "鑼佃崼鍥犳闊抽槾濮诲悷閾舵帆瀵呴ギ灏瑰紩闅愬嵃鑳ら劄寤村灎鍫欒姪鑼氬惒鍠戠嫼澶ゆ磭婀挨閾熺樉绐ㄨ殦闇緢",
+    "ying": "鑻辨ū濠撮拱搴旂绩鑾硅悿钀ヨ崸铦囪繋璧㈢泩褰遍纭槧瀣撮儮鑼旇崶鑾鸿惁钃ユ拕鍢よ喓婊㈡絾鐎涚憶鐠庢ス濯甸功鐦块缃�",
+    "yo": "鍝熷敺",
+    "yong": "鎷ヤ剑鑷冪棃搴搁泹韪婅浌鍜忔吵娑屾案鎭垮媷鐢ㄤ繎澹呭鍠佹叺閭曢暃鐢硻楗�",
+    "you": "骞戒紭鎮犲咖灏ょ敱閭搥鐘规补娓搁厜鏈夊弸鍙充綉閲夎鍙堝辜鍗f敻渚戣帬鑾滆幐灏㈠懄鍥垮鏌氱尫鐗栭摃鐤h伇铓拌毚铦h潳绻囬笨榛濋棘",
+    "yu": "璋疯敋灏夎總娣や簬鐩傛铏炴剼鑸嗕綑淇為�鹃奔鎰夋笣娓旈殔浜堝ū闆ㄤ笌灞跨瀹囪缇界帀鍩熻妺閮佸悂閬囧柣宄尽鎰堟鐙辫偛瑾夋荡瀵撹棰勮鲍椹播绂烘瘬浼涗浚璋�璋曞湬钀歌摚鎻勫渼鍦夊禌鐙抽カ棣�搴鹃槇楝诲Κ濡ょ骸鐟滄槺瑙庢鑵存",
+    "yuan": "瀹涢赋娓婂啢鍏冨灒琚佸師鎻磋緯鍥憳鍦嗙尶婧愮紭杩滆嫅鎰挎�ㄩ櫌鍨稿‖鑺幘娌呭獩鐟楁┘鐖扮湤楦㈣瀳绠㈤紜",
+    "yue": "涔愭洶绾﹁秺璺冮挜宀崇菠鏈堟偊闃呴緺鍝曠�规ň鍒栭捄",
+    "yun": "鑰樹簯閮у寑闄ㄥ厑杩愯暣閰濇檿闊靛瓡閮撹姼鐙佹伣鎰犲绾煫娈掓榾姘茬啫绛�",
+    "za": "鍖濈牳鏉傚挶鎵庡拫绫村拏鍟�",
+    "zai": "鏍藉搲鐏惧杞藉啀鍦ㄤ粩宕界斁",
+    "zan": "鍜辨敀鏆傝禐鎷舵稊鐡掓槤绨硨瓒遍尵",
+    "zang": "钘忚祪鑴忚懍濂橀┑鑷�",
+    "zao": "閬碂鍑胯椈鏋f棭婢¤殼韬佸櫔閫犵殏鐏剁嚗鍞�",
+    "ze": "璐f嫨鍒欐辰浠勮禍鍟у富杩槂绗鑸�",
+    "zei": "璐�",
+    "zen": "鎬庤爱",
+    "zeng": "澧炴啂鏇捐禒缂攽缃鹃攦",
+    "zha": "鐖嗘煡鎵庡柍娓f湱杞ч摗闂哥湪鏍呮Θ鍜嬩箥鐐歌瘓鏌炴徃鍚掑挙鍝抽妤傜牊鐥勮毐绗絼",
+    "zhai": "缈熸嫨鎽樻枊瀹呯獎鍊哄鐮︾樀",
+    "zhan": "棰ょ灮姣¤┕绮樻簿鐩忔柀杈楀喘灞曡樃鏍堝崰鎴樼珯婀涚唤璋垫悓婢舵梼",
+    "zhang": "闀挎绔犲桨婕冲紶鎺屾定鏉栦笀甯愯处浠楄儉鐦撮殰浠夐劊骞涘秱鐛愬珳鐠嬭煈",
+    "zhao": "鏈濆槻鎷涙槶鎵炬布璧电収缃╁厗鑲囧彫鐖潃璇忓晛妫规檨閽婄瑠",
+    "zhe": "閬姌鍝茶洶杈欒�呴敆钄楄繖娴欑潃涔囪蔼闄懞鏌樿緞纾旈恭瑜惰渿铻淡",
+    "zhen": "鐝嶆枱鐪熺攧鐮ц嚮璐為拡渚︽灂鐤硅瘖闇囨尟闀囬樀甯у湷钃佹祱婧辩紲妗㈡す姒涜礁鎴¤祱鑳楁湑绁暃绋归俯绠�",
+    "zheng": "涓佽捀鎸g潄寰佺嫲浜夋�旀暣鎷鏀跨棁閮戣瘉璇ゅ偿閽查摦绛�",
+    "zhi": "璇嗘皬鑺濇灊鏀惐铚樼煡鑲㈣剛姹佷箣缁囪亴鐩存娈栨墽鍊间緞鍧�鎸囨瓒惧彧鏃ㄧ焊蹇楁寶鎺疯嚦鑷寸疆甯滃硻鍒舵櫤绉╃璐ㄧ倷鐥旀粸娌荤獟鍗皭闄熼儏鍩磋姺鎽笝寰靛蹇綐鍜獦鏍夋灣鏍�妗庤降杞捐唇鑳濊啠绁夌榛归泬楦风棧铔捣閰窎韪腐璞歌Н",
+    "zhong": "涓泤蹇犻挓琛风粓绉嶈偪閲嶄徊浼楀啟澶傚开閿鸿灲鑸傅",
+    "zhou": "鑸熷懆宸炴床璇岀播杞磋倶甯氬拻鐨卞畽鏄奸鑽晛濡海缁夎儎纰$眬鑸抽厧",
+    "zhu": "灞炴湳鐝犳牚铔涙湵鐚璇涢�愮鐑涚叜鎷勭灘鍢变富钁楁煴鍔╄泙璐摳绛戜綇娉ㄧ椹绘涓朵极渚忛偩鑻庤尡娲欐笟娼存緧鏉兼姗ョ偡閾㈢柊鐦冪绠歌埑缈ヨ簠楹�",
+    "zhua": "鎶撶埅",
+    "zhuai": "鎷借浆",
+    "zhuan": "浼犱笓鐮栬浆鎾拌禋绡嗗暛棣旈",
+    "zhuang": "妗╁簞瑁呭鎾炲.鐘跺儺",
+    "zhui": "妞庨敟杩借禈鍧犵紑钀戞兇楠撶紥闅�",
+    "zhun": "灞皢鍑嗚偒鑳楃獉",
+    "zhuo": "钁楁崏鎷欏崜妗岀悽鑼侀厡鍟勭潃鐏兼祳鍊钑炴摙娴炴犊婵9鑲劘绂氭柅闀兜",
+    "zi": "鍚卞吂鍜ㄨ祫濮挎粙娣勫瓬绱粩绫芥粨瀛愯嚜娓嶅瓧璋樺懖宓瀛崇紒姊撹編璧�鎭g湨閿辩Л鑰旂绮㈣稇瑙滆ň榫囬不楂�",
+    "zong": "楝冩韪畻缁兼�荤旱鍋灋鑵欑步",
+    "zou": "閭硅蛋濂忔弽璇归櫖閯归┖妤遍舶",
+    "zu": "绉熻冻鍗掓棌绁栬瘏闃荤粍淇庤徆鍟愰暈",
+    "zuan": "閽荤簜鏀ョ嫉韬�",
+    "zui": "鍜�鍢撮唹鏈�缃暈瑙�",
+    "zun": "灏婇伒鎾欐ń槌�",
+    "zuo": "鍑跨悽鏄ㄥ乏浣愭煘鍋氫綔鍧愬骇闃煎攽鍢�嶈儥绁氱牊绗參"
+}
+export default dict
diff --git a/vf205_access/src/view/pinyin/pinyin.js b/vf205_access/src/view/pinyin/pinyin.js
new file mode 100644
index 0000000..4a2003d
--- /dev/null
+++ b/vf205_access/src/view/pinyin/pinyin.js
@@ -0,0 +1,1049 @@
+import dxui from '../../../dxmodules/dxUi.js'
+import dict from './dict.js'
+const pinyin = {}
+
+// 閿洏澶у皬
+let width = 800
+let height = 400
+// 鏄惁閿佸畾閿洏
+let isLock = false
+// 鏄惁鏀寔鎷奸煶杈撳叆
+let enablePinyin = true
+// 鍒濆鍖栧鍣�
+pinyin.init = function (w, h) {
+    width = w
+    height = h
+
+    // 鍙厑璁稿垵濮嬪寲涓�娆�
+    if (pinyin.inited) {
+        return
+    }
+    pinyin.inited = true
+    // 鍏ㄥ眬瀛椾綋
+    pinyin.font24 = dxui.Font.build('/app/code/resource/font/AlibabaPuHuiTi-2-65-Medium.ttf', 24, dxui.Utils.FONT_STYLE.NORMAL)
+    let container = dxui.View.build('container', dxui.Utils.LAYER.TOP)
+    pinyin.container = container
+    clearStyle(container)
+    container.obj.lvObjAddFlag(dxui.Utils.ENUM.LV_OBJ_FLAG_OVERFLOW_VISIBLE)
+    container.setSize(width, height)
+    container.align(dxui.Utils.ALIGN.BOTTOM_MID, 0, 0)
+    container.textFont(pinyin.font24)
+    // 瀹瑰櫒鍒濆鍖�
+    container.bgOpa(0)
+    container.update()
+    container.hide()
+    // 鍒涘缓涓夌閿洏妯″紡
+    pinyin.englishPanel = createEnglish()
+    pinyin.pinyinPanel = createPinyin()
+    pinyin.numPanel = createNum()
+    pinyin.symbolPanel = createSymbol()
+}
+pinyin.getSize = function () {
+    return { width: width, height: height }
+}
+/**
+ * 鏄剧ず閿洏锛岄渶瑕佸厛鍒濆鍖�
+ * @param {number} mode 閿洏妯″紡锛�0锛氳嫳鏂囬敭鐩橈紝1锛氭嫾闊抽敭鐩橈紝2锛氭暟瀛楅敭鐩橈紝3锛氱鍙烽敭鐩�
+ * @param {function} cb 鎸夐敭鍐呭鍥炶皟
+ */
+pinyin.show = function (mode, cb) {
+    if (![0, 1, 2, 3].includes(mode)) {
+        return
+    }
+    this.unlock()
+    this.hide()
+    // 鎸夐敭鍐呭鍥炶皟
+    pinyin.cb = cb
+    pinyin.container.show()
+    pinyin.container.moveForeground()
+    switch (mode) {
+        case 0:
+            pinyin.englishPanel.show()
+            break;
+        case 1:
+            pinyin.pinyinPanel.show()
+            break;
+        case 2:
+            pinyin.numPanel.show()
+            break;
+        case 3:
+            pinyin.symbolPanel.show()
+            break;
+        default:
+            break;
+    }
+}
+// 鑾峰彇褰撳墠閿洏妯″紡
+pinyin.getMode = function () {
+    if (!pinyin.englishPanel.isHide()) {
+        return 0
+    } else if (!pinyin.pinyinPanel.isHide()) {
+        return 1
+    } else if (!pinyin.numPanel.isHide()) {
+        return 2
+    } else if (!pinyin.symbolPanel.isHide()) {
+        return 3
+    } else {
+        return 0
+    }
+}
+// 闅愯棌閿洏
+pinyin.hide = function () {
+    pinyin.englishPanel.hide()
+    pinyin.pinyinPanel.hide()
+    pinyin.numPanel.hide()
+    pinyin.symbolPanel.hide()
+    pinyin.container.hide()
+    if (pinyin.callback) {
+        pinyin.callback()
+        pinyin.callback = null
+    }
+}
+// 闅愯棌鍥炶皟锛屽崟娆℃湁鏁�
+pinyin.hideCb = function (cb) {
+    pinyin.callback = cb
+}
+// 閿佸畾閿洏锛屼笉鍏佽鍒囨崲妯″紡
+pinyin.lock = function () {
+    isLock = true
+}
+// 瑙i櫎閿佸畾閿洏
+pinyin.unlock = function () {
+    isLock = false
+}
+pinyin.pinyinSupport = function (bool) {
+    enablePinyin = bool
+}
+
+// 鑻辨枃閿洏
+function createEnglish() {
+    let englishPanel = dxui.View.build(pinyin.container.id + 'englishPanel', pinyin.container)
+    clearStyle(englishPanel)
+    englishPanel.setSize(pinyin.container.width(), pinyin.container.height())
+    englishPanel.update()
+    // 鍒涘缓澶у皬鍐欑殑鑻辨枃閿洏
+    function createKeyboard(capital) {
+        let englishKeyboard = dxui.Buttons.build(englishPanel.id + 'englishKeyboard' + (capital ? "Big" : "Small"), englishPanel)
+        clearStyle(englishKeyboard)
+        englishKeyboard.obj.lvObjSetStylePadGap(10, dxui.Utils.ENUM._LV_STYLE_STATE_CMP_SAME)
+        englishKeyboard.padAll(10)
+        englishKeyboard.bgColor(0xffffff, dxui.Utils.STYLE_PART.ITEMS)
+        englishKeyboard.bgColor(0xe6e6e6)
+        englishKeyboard.setSize(englishPanel.width(), englishPanel.height())
+        englishKeyboard.align(dxui.Utils.ALIGN.BOTTOM_MID, 0, 0)
+        if (capital) {
+            englishKeyboard.data([
+                "Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P", "\n",
+                " ", "A", "S", "D", "F", "G", "H", "J", "K", "L", " ", "\n",
+                "鈫�", "Z", "X", "C", "V", "B", "N", "M", " ", "\n",
+                "!?#", "123", ",", " ", ".", "EN", " ",
+                ""])
+        } else {
+            englishKeyboard.data([
+                "q", "w", "e", "r", "t", "y", "u", "i", "o", "p", "\n",
+                " ", "a", "s", "d", "f", "g", "h", "j", "k", "l", " ", "\n",
+                "鈫�", "z", "x", "c", "v", "b", "n", "m", " ", "\n",
+                "!?#", "123", ",", " ", ".", "EN", " ",
+                ""])
+        }
+        // 璁剧疆鎸夐挳瀹藉害
+        englishKeyboard.setBtnWidth(10, 1)
+        for (let i = 11; i < 20; i++) {
+            englishKeyboard.setBtnWidth(i, 2)
+        }
+        englishKeyboard.setBtnWidth(20, 1)
+        englishKeyboard.setBtnWidth(21, 3)
+        for (let i = 22; i < 29; i++) {
+            englishKeyboard.setBtnWidth(i, 2)
+        }
+        englishKeyboard.setBtnWidth(29, 3)
+        englishKeyboard.obj.addEventCb((e) => {
+            let dsc = e.lvEventGetDrawPartDsc()
+            if (dsc.class_p == englishKeyboard.obj.ClassP && dsc.type == dxui.Utils.ENUM.LV_BTNMATRIX_DRAW_PART_BTN) {
+                // 闅愯棌鏃犵敤鎸夐挳
+                if (dsc.id == 10 || dsc.id == 20) {
+                    dxui.Utils.GG.NativeDraw.lvDrawRectReset(dsc.rect_dsc, { bg_opa: 0, shadow_opa: 0 })
+                }
+                // 鍔犳繁涓�浜涘姛鑳芥寜閽�
+                if (dsc.id == 21 || dsc.id == 29 || dsc.id == 30 || dsc.id == 31 || dsc.id == 35) {
+                    if (englishKeyboard.obj.lvBtnmatrixGetSelectedBtn() == dsc.id && e.lvEventGetTarget().hasState(dxui.Utils.ENUM.LV_STATE_PRESSED)) {
+                        dxui.Utils.GG.NativeDraw.lvDrawRectReset(dsc.rect_dsc, { bg_color: 0xcdcdcd })
+                    } else {
+                        dxui.Utils.GG.NativeDraw.lvDrawRectReset(dsc.rect_dsc, { bg_color: 0xdbdbdb })
+                    }
+                }
+                // 鍥炶溅鎸夐挳钃濊壊
+                if (dsc.id == 36) {
+                    if (englishKeyboard.obj.lvBtnmatrixGetSelectedBtn() == dsc.id && e.lvEventGetTarget().hasState(dxui.Utils.ENUM.LV_STATE_PRESSED)) {
+                        dxui.Utils.GG.NativeDraw.lvDrawRectReset(dsc.rect_dsc, { bg_color: 0x0C6CE4 })
+                    } else {
+                        dxui.Utils.GG.NativeDraw.lvDrawRectReset(dsc.rect_dsc, { bg_color: 0x0C78FE })
+                    }
+                }
+            }
+        }, dxui.Utils.ENUM.LV_EVENT_DRAW_PART_BEGIN)
+        englishKeyboard.obj.addEventCb((e) => {
+            let dsc = e.lvEventGetDrawPartDsc()
+            if (dsc.class_p == englishKeyboard.obj.ClassP && dsc.type == dxui.Utils.ENUM.LV_BTNMATRIX_DRAW_PART_BTN) {
+                // 鍒犻櫎鎸夐挳鍥炬娣诲姞
+                if (dsc.id == 29) {
+                    let src = '/app/code/resource/image/backspace.png'
+                    // 鑾峰彇鍥剧墖淇℃伅
+                    let header = dxui.Utils.GG.NativeDraw.lvImgDecoderGetInfo(src)
+                    // 瀹氫箟涓�鍧楀尯鍩燂紝灞呬腑鏄剧ず锛屾敞鎰忥細灏哄杞琣rea闇�瑕�-1锛宎rea杞昂瀵搁渶瑕�+1
+                    let x1 = dsc.draw_area.x1 + (dsc.draw_area.x2 - dsc.draw_area.x1 + 1 - header.w) / 2;
+                    let y1 = dsc.draw_area.y1 + (dsc.draw_area.y2 - dsc.draw_area.y1 + 1 - header.h) / 2;
+                    let x2 = x1 + header.w - 1;
+                    let y2 = y1 + header.h - 1;
+                    let area = dxui.Utils.GG.NativeArea.lvAreaSet(x1, y1, x2, y2)
+                    // 缁樺埗鍥剧墖淇℃伅
+                    let img_draw_dsc = dxui.Utils.GG.NativeDraw.lvDrawImgDscInit()
+                    // 缁樺埗鍥剧墖
+                    dxui.Utils.GG.NativeDraw.lvDrawImg(dsc.dsc, img_draw_dsc, area, src)
+                }
+                // 鍥炶溅鎸夐挳鍥炬娣诲姞
+                if (dsc.id == 36) {
+                    let src = '/app/code/resource/image/enter.png'
+                    // 鑾峰彇鍥剧墖淇℃伅
+                    let header = dxui.Utils.GG.NativeDraw.lvImgDecoderGetInfo(src)
+                    // 瀹氫箟涓�鍧楀尯鍩燂紝灞呬腑鏄剧ず锛屾敞鎰忥細灏哄杞琣rea闇�瑕�-1锛宎rea杞昂瀵搁渶瑕�+1
+                    let x1 = dsc.draw_area.x1 + (dsc.draw_area.x2 - dsc.draw_area.x1 + 1 - header.w) / 2;
+                    let y1 = dsc.draw_area.y1 + (dsc.draw_area.y2 - dsc.draw_area.y1 + 1 - header.h) / 2;
+                    let x2 = x1 + header.w - 1;
+                    let y2 = y1 + header.h - 1;
+                    let area = dxui.Utils.GG.NativeArea.lvAreaSet(x1, y1, x2, y2)
+                    // 缁樺埗鍥剧墖淇℃伅
+                    let img_draw_dsc = dxui.Utils.GG.NativeDraw.lvDrawImgDscInit()
+                    // 缁樺埗鍥剧墖
+                    dxui.Utils.GG.NativeDraw.lvDrawImg(dsc.dsc, img_draw_dsc, area, src)
+                }
+                // 绌烘牸鎸夐挳鍥炬娣诲姞
+                if (dsc.id == 33) {
+                    let src = '/app/code/resource/image/space.png'
+                    // 鑾峰彇鍥剧墖淇℃伅
+                    let header = dxui.Utils.GG.NativeDraw.lvImgDecoderGetInfo(src)
+                    // 瀹氫箟涓�鍧楀尯鍩燂紝灞呬腑鏄剧ず锛屾敞鎰忥細灏哄杞琣rea闇�瑕�-1锛宎rea杞昂瀵搁渶瑕�+1
+                    let x1 = dsc.draw_area.x1 + (dsc.draw_area.x2 - dsc.draw_area.x1 + 1 - header.w) / 2;
+                    let y1 = dsc.draw_area.y1 + (dsc.draw_area.y2 - dsc.draw_area.y1 + 1 - header.h) / 2;
+                    let x2 = x1 + header.w - 1;
+                    let y2 = y1 + header.h - 1;
+                    y1 += 10
+                    y2 += 10
+                    let area = dxui.Utils.GG.NativeArea.lvAreaSet(x1, y1, x2, y2)
+                    // 缁樺埗鍥剧墖淇℃伅
+                    let img_draw_dsc = dxui.Utils.GG.NativeDraw.lvDrawImgDscInit()
+                    // 缁樺埗鍥剧墖
+                    dxui.Utils.GG.NativeDraw.lvDrawImg(dsc.dsc, img_draw_dsc, area, src)
+                }
+            }
+        }, dxui.Utils.ENUM.LV_EVENT_DRAW_PART_END)
+        englishKeyboard.on(dxui.Utils.ENUM.LV_EVENT_LONG_PRESSED_REPEAT, () => {
+            let clickBtn = englishKeyboard.clickedButton()
+            let id = clickBtn.id
+            switch (id) {
+                case 29:
+                    // 閫�鏍�
+                    pinyin.cb({ cmd: "backspace" })
+                    break;
+            }
+        })
+        englishKeyboard.on(dxui.Utils.ENUM.LV_EVENT_PRESSED, () => {
+            let clickBtn = englishKeyboard.clickedButton()
+            let id = clickBtn.id
+            let text = clickBtn.text
+            switch (id) {
+                case 21:
+                    // 澶у皬鍐欏垏鎹�
+                    if (englishKeyboardBig.isHide()) {
+                        englishKeyboardBig.show()
+                        englishKeyboardSmall.hide()
+                    } else {
+                        englishKeyboardBig.hide()
+                        englishKeyboardSmall.show()
+                    }
+                    break;
+                case 29:
+                    // 閫�鏍�
+                    pinyin.cb({ cmd: "backspace" })
+                    break;
+                case 30:
+                    if (isLock) {
+                        break;
+                    }
+                    // 鍒囨崲绗﹀彿閿洏
+                    pinyin.symbolPanel.show()
+                    pinyin.englishPanel.hide()
+                    break;
+                case 31:
+                    if (isLock) {
+                        break;
+                    }
+                    // 鍒囨崲鏁板瓧閿洏
+                    pinyin.numPanel.show()
+                    pinyin.englishPanel.hide()
+                    break;
+                case 33:
+                    // 绌烘牸
+                    pinyin.cb(" ")
+                    break;
+                case 35:
+                    if (isLock || !enablePinyin) {
+                        break;
+                    }
+                    // 鍒囨崲鎷奸煶閿洏
+                    pinyin.pinyinPanel.show()
+                    pinyin.englishPanel.hide()
+                    break;
+                case 36:
+                    // 鍥炶溅
+                    pinyin.cb({ cmd: "enter" })
+                    break;
+                default:
+                    break;
+            }
+            // 鎵撳嵃瀛楃
+            if (["q", "w", "e", "r", "t", "y", "u", "i", "o", "p",
+                "a", "s", "d", "f", "g", "h", "j", "k", "l",
+                "z", "x", "c", "v", "b", "n", "m",
+                ",", "."].includes(text) || [
+                    "Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P",
+                    "A", "S", "D", "F", "G", "H", "J", "K", "L",
+                    "Z", "X", "C", "V", "B", "N", "M",
+                    ",", "."].includes(text)) {
+                pinyin.cb(text)
+            }
+        })
+        return englishKeyboard
+    }
+    // 鍒涘缓澶у皬鍐欓敭鐩�
+    let englishKeyboardBig = createKeyboard(true)
+    let englishKeyboardSmall = createKeyboard(false)
+    // 榛樿鏄皬鍐�
+    englishKeyboardBig.hide()
+    englishKeyboardSmall.show()
+    englishPanel.hide()
+    return englishPanel
+}
+
+// 鎷奸煶閿洏
+function createPinyin() {
+    let pinyinPanel = dxui.View.build(pinyin.container.id + 'pinyinPanel', pinyin.container)
+    clearStyle(pinyinPanel)
+    pinyinPanel.setSize(pinyin.container.width(), pinyin.container.height())
+    pinyinPanel.obj.lvObjAddFlag(dxui.Utils.ENUM.LV_OBJ_FLAG_OVERFLOW_VISIBLE)
+    pinyinPanel.update()
+    // 鍒涘缓姹夊瓧棰勮妗�
+    let previewBox = dxui.View.build(pinyinPanel.id + 'previewBox', pinyinPanel)
+    clearStyle(previewBox)
+    previewBox.setSize(pinyinPanel.width(), 70)
+    previewBox.align(dxui.Utils.ALIGN.TOP_LEFT, 0, -70)
+    previewBox.padLeft(20)
+    previewBox.flexFlow(dxui.Utils.FLEX_FLOW.ROW)
+    previewBox.flexAlign(dxui.Utils.FLEX_ALIGN.SPACE_AROUND, dxui.Utils.FLEX_ALIGN.CENTER, dxui.Utils.FLEX_ALIGN.CENTER)
+    previewBox.labels = []
+    // 8涓瑙堟枃瀛�
+    for (let i = 0; i < 8; i++) {
+        let labelBox = dxui.View.build(previewBox.id + 'labelBox' + i, previewBox)
+        clearStyle(labelBox)
+        labelBox.setSize(50, 70)
+        labelBox.on(dxui.Utils.ENUM.LV_EVENT_PRESSED, () => {
+            if (label.text() != " ") {
+                labelBox.bgColor(0xe6e6e6)
+            }
+        })
+        labelBox.on(dxui.Utils.ENUM.LV_EVENT_RELEASED, () => {
+            if (label.text() != " ") {
+                labelBox.bgColor(0xffffff)
+                pinyin.cb(label.text())
+                // 娓呯┖鎷奸煶锛岃繕鍘熺姸鎬�
+                phrase.text("")
+                previewBox.fillData()
+            }
+        })
+        let label = dxui.Label.build(labelBox.id + 'label' + i, labelBox)
+        label.align(dxui.Utils.ALIGN.CENTER, 0, 0)
+        label.text(" ")
+        previewBox.labels.push(label)
+    }
+    // 濉厖棰勮鏂囧瓧
+    previewBox.fillData = (str) => {
+        if (!str) {
+            // str = "寰厜浜掕仈"
+            str = ""
+        }
+        previewBox.characters = str
+        for (let i = 0; i < 8; i++) {
+            if (str.charAt(i)) {
+                previewBox.labels[i].text(str.charAt(i))
+            } else {
+                previewBox.labels[i].text(" ")
+            }
+        }
+        if (str.length > 8) {
+            // 鏂囧瓧澶氫簬8涓紝灞曠ず鏇村鏂囧瓧鎸夐挳
+            morePreview.show()
+        } else {
+            morePreview.hide()
+        }
+    }
+    // 鏇村姹夊瓧棰勮鎸夐挳
+    let morePreview = dxui.View.build(pinyinPanel.id + 'morePreview', pinyinPanel)
+    clearStyle(morePreview)
+    morePreview.setSize(70, 70)
+    morePreview.align(dxui.Utils.ALIGN.TOP_RIGHT, 0, -70)
+    morePreview.hide()
+    let rightBtn = dxui.Image.build(morePreview.id + 'rightBtn', morePreview)
+    rightBtn.source('/app/code/resource/image/right.png')
+    rightBtn.align(dxui.Utils.ALIGN.CENTER, 0, 0)
+    morePreview.on(dxui.Utils.ENUM.LV_EVENT_PRESSED, () => {
+        morePreview.bgColor(0xe6e6e6)
+    })
+    morePreview.on(dxui.Utils.ENUM.LV_EVENT_RELEASED, () => {
+        morePreview.bgColor(0xffffff)
+        morePreviewKeyboard.moveForeground()
+        morePreviewKeyboard.fillData(0)
+        morePreviewKeyboard.show()
+    })
+    // 鍒濆鐘舵��
+    previewBox.fillData()
+    // 鏇村姹夊瓧闈㈡澘
+    let morePreviewKeyboard = dxui.Buttons.build(pinyinPanel.id + 'morePreviewKeyboard', pinyinPanel)
+    clearStyle(morePreviewKeyboard)
+    morePreviewKeyboard.setSize(pinyinPanel.width(), pinyinPanel.height())
+    morePreviewKeyboard.hide()
+    morePreviewKeyboard.obj.lvObjSetStylePadGap(10, dxui.Utils.ENUM._LV_STYLE_STATE_CMP_SAME)
+    morePreviewKeyboard.padAll(10)
+    morePreviewKeyboard.bgColor(0xffffff, dxui.Utils.STYLE_PART.ITEMS)
+    morePreviewKeyboard.bgColor(0xe6e6e6)
+    morePreviewKeyboard.align(dxui.Utils.ALIGN.BOTTOM_MID, 0, 0)
+    morePreviewKeyboard.data([
+        " ", " ", " ", " ", " ", " ", " ", " ", "\n",
+        " ", " ", " ", " ", " ", " ", " ", " ", "\n",
+        " ", " ", " ", " ", " ", " ", " ", " ", "\n",
+        " ", " ", " ", " ", " ", " ", " ", " ", "\n",
+        "涓婁竴椤�", "杩斿洖", "涓嬩竴椤�",
+        ""])
+    morePreviewKeyboard.index = 0
+    // index:0绗竴椤碉紝1涓嬩竴椤碉紝-1涓婁竴椤�
+    morePreviewKeyboard.fillData = (index) => {
+        if (index == 1 && previewBox.characters.charAt((morePreviewKeyboard.index + 1) * 32)) {
+            morePreviewKeyboard.index += 1
+        } else if (index == -1 && morePreviewKeyboard.index > 0) {
+            morePreviewKeyboard.index -= 1
+        } else {
+            morePreviewKeyboard.index = 0
+        }
+        let temp = []
+        for (let i = 0; i < 32; i++) {
+            let character = previewBox.characters.charAt(i + morePreviewKeyboard.index * 32)
+            if (character) {
+                temp.push(character)
+            } else {
+                if (i == 0) {
+                    // 鏃犳暟鎹�
+                    return
+                }
+                temp.push(" ")
+            }
+            if ((i + 1) % 8 == 0) {
+                temp.push("\n")
+            }
+        }
+        temp.push("涓婁竴椤�")
+        temp.push("杩斿洖")
+        temp.push("涓嬩竴椤�")
+        temp.push("")
+        morePreviewKeyboard.data(temp)
+    }
+    morePreviewKeyboard.obj.addEventCb((e) => {
+        let dsc = e.lvEventGetDrawPartDsc()
+        if (dsc.class_p == morePreviewKeyboard.obj.ClassP && dsc.type == dxui.Utils.ENUM.LV_BTNMATRIX_DRAW_PART_BTN) {
+            // 鍔犳繁涓や釜鍔熻兘鎸夐挳
+            if ([32, 33, 34].includes(dsc.id)) {
+                if (morePreviewKeyboard.obj.lvBtnmatrixGetSelectedBtn() == dsc.id && e.lvEventGetTarget().hasState(dxui.Utils.ENUM.LV_STATE_PRESSED)) {
+                    dxui.Utils.GG.NativeDraw.lvDrawRectReset(dsc.rect_dsc, { bg_color: 0xcdcdcd })
+                } else {
+                    dxui.Utils.GG.NativeDraw.lvDrawRectReset(dsc.rect_dsc, { bg_color: 0xdbdbdb })
+                }
+            }
+        }
+    }, dxui.Utils.ENUM.LV_EVENT_DRAW_PART_BEGIN)
+    morePreviewKeyboard.on(dxui.Utils.ENUM.LV_EVENT_PRESSED, () => {
+        let clickBtn = morePreviewKeyboard.clickedButton()
+        let id = clickBtn.id
+        let text = clickBtn.text
+        if (text == "杩斿洖") {
+            morePreviewKeyboard.hide()
+        } else if (text == "涓婁竴椤�") {
+            morePreviewKeyboard.fillData(-1)
+        } else if (text == "涓嬩竴椤�") {
+            morePreviewKeyboard.fillData(1)
+        } else if (text != " ") {
+            pinyin.cb(text)
+            // 娓呯┖鎷奸煶锛岃繕鍘熺姸鎬�
+            phrase.text("")
+            previewBox.fillData()
+            morePreviewKeyboard.hide()
+        }
+    })
+    // 璇嶇粍棰勮
+    let phrasePreview = dxui.View.build(pinyinPanel.id + 'phrasePreview', pinyinPanel)
+    clearStyle(phrasePreview)
+    phrasePreview.setSize(70, 35)
+    phrasePreview.align(dxui.Utils.ALIGN.TOP_LEFT, 0, -105)
+    phrasePreview.bgColor(0xe6e6e6)
+    phrasePreview.hide()
+    let phrase = dxui.Label.build(phrasePreview.id + 'phrase', phrasePreview)
+    phrase.align(dxui.Utils.ALIGN.CENTER, 0, 0)
+    let overwrite = phrase.text
+    phrase.text = (v) => {
+        if (typeof v != 'string') {
+            // 鑾峰彇璇嶇粍
+            let temp = overwrite.call(phrase, v)
+            temp = temp == "Text" ? "" : temp
+            return temp
+        }
+        if (v.length == 0) {
+            // 璇嶇粍闀垮害涓�0灏遍殣钘�
+            overwrite.call(phrase, "Text")
+            return phrasePreview.hide()
+        }
+        if (v.length > 10) {
+            // 璇嶇粍棰勮闀垮害涓嶈秴杩�10瀛楃
+            return
+        }
+        phrasePreview.show()
+        overwrite.call(phrase, v)
+        phrase.update()
+        phrasePreview.width(phrase.width() + 40)
+    }
+    let overwrite1 = pinyinPanel.show
+    pinyinPanel.show = () => {
+        // 閲嶅啓鏄剧ず鏂规硶锛屾樉绀烘眽瀛楅瑙堟
+        previewBox.align(dxui.Utils.ALIGN.TOP_LEFT, 0, -70)
+        morePreview.align(dxui.Utils.ALIGN.TOP_RIGHT, 0, -70)
+        phrasePreview.align(dxui.Utils.ALIGN.TOP_LEFT, 0, -105)
+        overwrite1.call(pinyinPanel)
+    }
+    let overwrite2 = pinyinPanel.hide
+    pinyinPanel.hide = () => {
+        // 閲嶅啓闅愯棌鏂规硶锛岄殣钘忔眽瀛楅瑙堟
+        previewBox.align(dxui.Utils.ALIGN.TOP_LEFT, 0, 0)
+        morePreview.align(dxui.Utils.ALIGN.TOP_RIGHT, 0, 0)
+        phrasePreview.align(dxui.Utils.ALIGN.TOP_LEFT, 0, 0)
+        overwrite2.call(pinyinPanel)
+    }
+    // 鍒涘缓鎷奸煶閿洏
+    let pinyinKeyboard = dxui.Buttons.build(pinyinPanel.id + 'pinyinKeyboard', pinyinPanel)
+    clearStyle(pinyinKeyboard)
+    pinyinKeyboard.obj.lvObjSetStylePadGap(10, dxui.Utils.ENUM._LV_STYLE_STATE_CMP_SAME)
+    pinyinKeyboard.padAll(10)
+    pinyinKeyboard.bgColor(0xffffff, dxui.Utils.STYLE_PART.ITEMS)
+    pinyinKeyboard.bgColor(0xe6e6e6)
+    pinyinKeyboard.setSize(pinyinPanel.width(), pinyinPanel.height())
+    pinyinKeyboard.align(dxui.Utils.ALIGN.BOTTOM_MID, 0, 0)
+    pinyinKeyboard.data([
+        "q", "w", "e", "r", "t", "y", "u", "i", "o", "p", "\n",
+        " ", "a", "s", "d", "f", "g", "h", "j", "k", "l", " ", "\n",
+        "鍒嗚瘝", "z", "x", "c", "v", "b", "n", "m", " ", "\n",
+        "!?#", "123", "锛�", " ", "銆�", "涓�", " ",
+        ""])
+    // 璁剧疆鎸夐挳瀹藉害
+    pinyinKeyboard.setBtnWidth(10, 1)
+    for (let i = 11; i < 20; i++) {
+        pinyinKeyboard.setBtnWidth(i, 2)
+    }
+    pinyinKeyboard.setBtnWidth(20, 1)
+    pinyinKeyboard.setBtnWidth(21, 3)
+    for (let i = 22; i < 29; i++) {
+        pinyinKeyboard.setBtnWidth(i, 2)
+    }
+    pinyinKeyboard.setBtnWidth(29, 3)
+    pinyinKeyboard.obj.addEventCb((e) => {
+        let dsc = e.lvEventGetDrawPartDsc()
+        if (dsc.class_p == pinyinKeyboard.obj.ClassP && dsc.type == dxui.Utils.ENUM.LV_BTNMATRIX_DRAW_PART_BTN) {
+            // 闅愯棌鏃犵敤鎸夐挳
+            if (dsc.id == 10 || dsc.id == 20) {
+                dxui.Utils.GG.NativeDraw.lvDrawRectReset(dsc.rect_dsc, { bg_opa: 0, shadow_opa: 0 })
+            }
+            // 鍔犳繁涓�浜涘姛鑳芥寜閽�
+            if (dsc.id == 21 || dsc.id == 29 || dsc.id == 30 || dsc.id == 31 || dsc.id == 35) {
+                if (pinyinKeyboard.obj.lvBtnmatrixGetSelectedBtn() == dsc.id && e.lvEventGetTarget().hasState(dxui.Utils.ENUM.LV_STATE_PRESSED)) {
+                    dxui.Utils.GG.NativeDraw.lvDrawRectReset(dsc.rect_dsc, { bg_color: 0xcdcdcd })
+                } else {
+                    dxui.Utils.GG.NativeDraw.lvDrawRectReset(dsc.rect_dsc, { bg_color: 0xdbdbdb })
+                }
+            }
+            // 鍥炶溅鎸夐挳钃濊壊
+            if (dsc.id == 36) {
+                if (pinyinKeyboard.obj.lvBtnmatrixGetSelectedBtn() == dsc.id && e.lvEventGetTarget().hasState(dxui.Utils.ENUM.LV_STATE_PRESSED)) {
+                    dxui.Utils.GG.NativeDraw.lvDrawRectReset(dsc.rect_dsc, { bg_color: 0x0C6CE4 })
+                } else {
+                    dxui.Utils.GG.NativeDraw.lvDrawRectReset(dsc.rect_dsc, { bg_color: 0x0C78FE })
+                }
+            }
+        }
+    }, dxui.Utils.ENUM.LV_EVENT_DRAW_PART_BEGIN)
+    pinyinKeyboard.obj.addEventCb((e) => {
+        let dsc = e.lvEventGetDrawPartDsc()
+        if (dsc.class_p == pinyinKeyboard.obj.ClassP && dsc.type == dxui.Utils.ENUM.LV_BTNMATRIX_DRAW_PART_BTN) {
+            // 鍒犻櫎鎸夐挳鍥炬娣诲姞
+            if (dsc.id == 29) {
+                let src = '/app/code/resource/image/backspace.png'
+                // 鑾峰彇鍥剧墖淇℃伅
+                let header = dxui.Utils.GG.NativeDraw.lvImgDecoderGetInfo(src)
+                // 瀹氫箟涓�鍧楀尯鍩燂紝灞呬腑鏄剧ず锛屾敞鎰忥細灏哄杞琣rea闇�瑕�-1锛宎rea杞昂瀵搁渶瑕�+1
+                let x1 = dsc.draw_area.x1 + (dsc.draw_area.x2 - dsc.draw_area.x1 + 1 - header.w) / 2;
+                let y1 = dsc.draw_area.y1 + (dsc.draw_area.y2 - dsc.draw_area.y1 + 1 - header.h) / 2;
+                let x2 = x1 + header.w - 1;
+                let y2 = y1 + header.h - 1;
+                let area = dxui.Utils.GG.NativeArea.lvAreaSet(x1, y1, x2, y2)
+                // 缁樺埗鍥剧墖淇℃伅
+                let img_draw_dsc = dxui.Utils.GG.NativeDraw.lvDrawImgDscInit()
+                // 缁樺埗鍥剧墖
+                dxui.Utils.GG.NativeDraw.lvDrawImg(dsc.dsc, img_draw_dsc, area, src)
+            }
+            // 鍥炶溅鎸夐挳鍥炬娣诲姞
+            if (dsc.id == 36) {
+                let src = '/app/code/resource/image/enter.png'
+                // 鑾峰彇鍥剧墖淇℃伅
+                let header = dxui.Utils.GG.NativeDraw.lvImgDecoderGetInfo(src)
+                // 瀹氫箟涓�鍧楀尯鍩燂紝灞呬腑鏄剧ず锛屾敞鎰忥細灏哄杞琣rea闇�瑕�-1锛宎rea杞昂瀵搁渶瑕�+1
+                let x1 = dsc.draw_area.x1 + (dsc.draw_area.x2 - dsc.draw_area.x1 + 1 - header.w) / 2;
+                let y1 = dsc.draw_area.y1 + (dsc.draw_area.y2 - dsc.draw_area.y1 + 1 - header.h) / 2;
+                let x2 = x1 + header.w - 1;
+                let y2 = y1 + header.h - 1;
+                let area = dxui.Utils.GG.NativeArea.lvAreaSet(x1, y1, x2, y2)
+                // 缁樺埗鍥剧墖淇℃伅
+                let img_draw_dsc = dxui.Utils.GG.NativeDraw.lvDrawImgDscInit()
+                // 缁樺埗鍥剧墖
+                dxui.Utils.GG.NativeDraw.lvDrawImg(dsc.dsc, img_draw_dsc, area, src)
+            }
+            // 绌烘牸鎸夐挳鍥炬娣诲姞
+            if (dsc.id == 33) {
+                let src = '/app/code/resource/image/space.png'
+                // 鑾峰彇鍥剧墖淇℃伅
+                let header = dxui.Utils.GG.NativeDraw.lvImgDecoderGetInfo(src)
+                // 瀹氫箟涓�鍧楀尯鍩燂紝灞呬腑鏄剧ず锛屾敞鎰忥細灏哄杞琣rea闇�瑕�-1锛宎rea杞昂瀵搁渶瑕�+1
+                let x1 = dsc.draw_area.x1 + (dsc.draw_area.x2 - dsc.draw_area.x1 + 1 - header.w) / 2;
+                let y1 = dsc.draw_area.y1 + (dsc.draw_area.y2 - dsc.draw_area.y1 + 1 - header.h) / 2;
+                let x2 = x1 + header.w - 1;
+                let y2 = y1 + header.h - 1;
+                y1 += 10
+                y2 += 10
+                let area = dxui.Utils.GG.NativeArea.lvAreaSet(x1, y1, x2, y2)
+                // 缁樺埗鍥剧墖淇℃伅
+                let img_draw_dsc = dxui.Utils.GG.NativeDraw.lvDrawImgDscInit()
+                // 缁樺埗鍥剧墖
+                dxui.Utils.GG.NativeDraw.lvDrawImg(dsc.dsc, img_draw_dsc, area, src)
+            }
+        }
+    }, dxui.Utils.ENUM.LV_EVENT_DRAW_PART_END)
+    // 鏌ュ瓧鍏革紝鏍规嵁杈撳叆鍐呭鏌ユ壘
+    function search() {
+        // 杈撳叆鐨勬嫾闊�
+        let searchStr = phrase.text()
+        if (searchStr.indexOf("'") >= 0) {
+            searchStr = searchStr.substring(0, searchStr.indexOf("'"))
+        }
+        if (searchStr.length <= 0) {
+            // 杈撳叆鐨勬嫾闊充负绌�
+            previewBox.fillData()
+            return
+        }
+        let characters = ""
+        let res = Object.keys(dict).filter(v => v.startsWith(searchStr))
+        if (res.length > 0) {
+            res.forEach(v => {
+                characters += dict[v]
+            })
+        }
+        previewBox.fillData(characters)
+    }
+    pinyinKeyboard.on(dxui.Utils.ENUM.LV_EVENT_LONG_PRESSED_REPEAT, () => {
+        let clickBtn = pinyinKeyboard.clickedButton()
+        let id = clickBtn.id
+        switch (id) {
+            case 29:
+                // 閫�鏍硷紝鏈夎瘝缁勫厛鍒犻櫎璇嶇粍
+                let temp = phrase.text()
+                if (temp.length > 0) {
+                    phrase.text(temp.substring(0, temp.length - 1))
+                } else {
+                    pinyin.cb({ cmd: "backspace" })
+                }
+                break;
+        }
+    })
+    pinyinKeyboard.on(dxui.Utils.ENUM.LV_EVENT_PRESSED, () => {
+        let clickBtn = pinyinKeyboard.clickedButton()
+        let id = clickBtn.id
+        let text = clickBtn.text
+        switch (id) {
+            case 21:
+                // 鍒嗚瘝
+                if (phrase.text().length != 0 && phrase.text().indexOf("'") < 0) {
+                    phrase.text(phrase.text() + "'")
+                }
+                break;
+            case 29:
+                // 閫�鏍硷紝鏈夎瘝缁勫厛鍒犻櫎璇嶇粍
+                let temp = phrase.text()
+                if (temp.length > 0) {
+                    phrase.text(temp.substring(0, temp.length - 1))
+                } else {
+                    pinyin.cb({ cmd: "backspace" })
+                }
+                break;
+            case 30:
+                if (isLock) {
+                    break;
+                }
+                // 鍒囨崲绗﹀彿閿洏
+                pinyin.symbolPanel.show()
+                pinyin.pinyinPanel.hide()
+                break;
+            case 31:
+                if (isLock) {
+                    break;
+                }
+                // 鍒囨崲鏁板瓧閿洏
+                pinyin.numPanel.show()
+                pinyin.pinyinPanel.hide()
+                break;
+            case 33:
+                // 绌烘牸
+                pinyin.cb(" ")
+                break;
+            case 35:
+                if (isLock) {
+                    break;
+                }
+                // 鍒囨崲鑻辨枃閿洏
+                pinyin.englishPanel.show()
+                pinyin.pinyinPanel.hide()
+                break;
+            case 36:
+                if (phrase.text().length > 0) {
+                    pinyin.cb(phrase.text())
+                    phrase.text("")
+                    previewBox.fillData()
+                    break;
+                }
+                // 鍥炶溅
+                pinyin.cb({ cmd: "enter" })
+                break;
+            default:
+                break;
+        }
+        // 鎵撳嵃瀛楃
+        if (["锛�", "銆�"].includes(text)) {
+            pinyin.cb(text)
+        }
+        if (["q", "w", "e", "r", "t", "y", "u", "i", "o", "p",
+            "a", "s", "d", "f", "g", "h", "j", "k", "l",
+            "z", "x", "c", "v", "b", "n", "m"].includes(text) && phrase.text().indexOf("'") < 0) {
+            phrase.text(phrase.text() + text)
+        }
+        search()
+    })
+    pinyinPanel.hide()
+    return pinyinPanel
+}
+
+// 鏁板瓧閿洏
+function createNum() {
+    let numPanel = dxui.View.build(pinyin.container.id + 'numPanel', pinyin.container)
+    clearStyle(numPanel)
+    numPanel.setSize(pinyin.container.width(), pinyin.container.height())
+    numPanel.update()
+    // 鍒涘缓鏁板瓧閿洏
+    let numKeyboard = dxui.Buttons.build(numPanel.id + 'numKeyboard', numPanel)
+    clearStyle(numKeyboard)
+    numKeyboard.obj.lvObjSetStylePadGap(10, dxui.Utils.ENUM._LV_STYLE_STATE_CMP_SAME)
+    numKeyboard.padAll(10)
+    numKeyboard.bgColor(0xffffff, dxui.Utils.STYLE_PART.ITEMS)
+    numKeyboard.bgColor(0xe6e6e6)
+    numKeyboard.setSize(numPanel.width(), numPanel.height())
+    numKeyboard.data([
+        "1", "2", "3", " ", "\n",
+        "4", "5", "6", "+", "\n",
+        "7", "8", "9", "-", "\n",
+        "ABC", "0", ".", " ", "",
+    ])
+    numKeyboard.obj.addEventCb((e) => {
+        let dsc = e.lvEventGetDrawPartDsc()
+        if (dsc.class_p == numKeyboard.obj.ClassP && dsc.type == dxui.Utils.ENUM.LV_BTNMATRIX_DRAW_PART_BTN) {
+            // 鍔犳繁涓や釜鍔熻兘鎸夐挳
+            if ([3, 7, 11, 12, 14].includes(dsc.id)) {
+                if (numKeyboard.obj.lvBtnmatrixGetSelectedBtn() == dsc.id && e.lvEventGetTarget().hasState(dxui.Utils.ENUM.LV_STATE_PRESSED)) {
+                    dxui.Utils.GG.NativeDraw.lvDrawRectReset(dsc.rect_dsc, { bg_color: 0xcdcdcd })
+                } else {
+                    dxui.Utils.GG.NativeDraw.lvDrawRectReset(dsc.rect_dsc, { bg_color: 0xdbdbdb })
+                }
+            }
+            // 鍥炶溅鎸夐挳钃濊壊
+            if (dsc.id == 15) {
+                if (numKeyboard.obj.lvBtnmatrixGetSelectedBtn() == dsc.id && e.lvEventGetTarget().hasState(dxui.Utils.ENUM.LV_STATE_PRESSED)) {
+                    dxui.Utils.GG.NativeDraw.lvDrawRectReset(dsc.rect_dsc, { bg_color: 0x0C6CE4 })
+                } else {
+                    dxui.Utils.GG.NativeDraw.lvDrawRectReset(dsc.rect_dsc, { bg_color: 0x0C78FE })
+                }
+            }
+        }
+    }, dxui.Utils.ENUM.LV_EVENT_DRAW_PART_BEGIN)
+    numKeyboard.obj.addEventCb((e) => {
+        let dsc = e.lvEventGetDrawPartDsc()
+        if (dsc.class_p == numKeyboard.obj.ClassP && dsc.type == dxui.Utils.ENUM.LV_BTNMATRIX_DRAW_PART_BTN) {
+            // 鍒犻櫎鎸夐挳鍥炬
+            if (dsc.id == 3) {
+                let src = '/app/code/resource/image/backspace.png'
+                // 鑾峰彇鍥剧墖淇℃伅
+                let header = dxui.Utils.GG.NativeDraw.lvImgDecoderGetInfo(src)
+                // 瀹氫箟涓�鍧楀尯鍩燂紝灞呬腑鏄剧ず锛屾敞鎰忥細灏哄杞琣rea闇�瑕�-1锛宎rea杞昂瀵搁渶瑕�+1
+                let x1 = dsc.draw_area.x1 + (dsc.draw_area.x2 - dsc.draw_area.x1 + 1 - header.w) / 2;
+                let y1 = dsc.draw_area.y1 + (dsc.draw_area.y2 - dsc.draw_area.y1 + 1 - header.h) / 2;
+                let x2 = x1 + header.w - 1;
+                let y2 = y1 + header.h - 1;
+                let area = dxui.Utils.GG.NativeArea.lvAreaSet(x1, y1, x2, y2)
+                // 缁樺埗鍥剧墖淇℃伅
+                let img_draw_dsc = dxui.Utils.GG.NativeDraw.lvDrawImgDscInit()
+                // 缁樺埗鍥剧墖
+                dxui.Utils.GG.NativeDraw.lvDrawImg(dsc.dsc, img_draw_dsc, area, src)
+            }
+            if (dsc.id == 15) {
+                let src = '/app/code/resource/image/enter.png'
+                // 鑾峰彇鍥剧墖淇℃伅
+                let header = dxui.Utils.GG.NativeDraw.lvImgDecoderGetInfo(src)
+                // 瀹氫箟涓�鍧楀尯鍩燂紝灞呬腑鏄剧ず锛屾敞鎰忥細灏哄杞琣rea闇�瑕�-1锛宎rea杞昂瀵搁渶瑕�+1
+                let x1 = dsc.draw_area.x1 + (dsc.draw_area.x2 - dsc.draw_area.x1 + 1 - header.w) / 2;
+                let y1 = dsc.draw_area.y1 + (dsc.draw_area.y2 - dsc.draw_area.y1 + 1 - header.h) / 2;
+                let x2 = x1 + header.w - 1;
+                let y2 = y1 + header.h - 1;
+                let area = dxui.Utils.GG.NativeArea.lvAreaSet(x1, y1, x2, y2)
+                // 缁樺埗鍥剧墖淇℃伅
+                let img_draw_dsc = dxui.Utils.GG.NativeDraw.lvDrawImgDscInit()
+                // 缁樺埗鍥剧墖
+                dxui.Utils.GG.NativeDraw.lvDrawImg(dsc.dsc, img_draw_dsc, area, src)
+            }
+        }
+    }, dxui.Utils.ENUM.LV_EVENT_DRAW_PART_END)
+    numKeyboard.on(dxui.Utils.ENUM.LV_EVENT_LONG_PRESSED_REPEAT, () => {
+        let clickBtn = numKeyboard.clickedButton()
+        let id = clickBtn.id
+        switch (id) {
+            case 3:
+                // 閫�鏍�
+                pinyin.cb({ cmd: "backspace" })
+                break;
+        }
+    })
+    numKeyboard.on(dxui.Utils.ENUM.LV_EVENT_PRESSED, () => {
+        let clickBtn = numKeyboard.clickedButton()
+        let id = clickBtn.id
+        let text = clickBtn.text
+        switch (id) {
+            case 3:
+                // 閫�鏍�
+                pinyin.cb({ cmd: "backspace" })
+                break;
+            case 12:
+                if (isLock) {
+                    break;
+                }
+                // 鍒囨崲鑻辨枃閿洏
+                pinyin.englishPanel.show()
+                pinyin.numPanel.hide()
+                break;
+            case 15:
+                // 鍥炶溅
+                pinyin.cb({ cmd: "enter" })
+                break;
+            default:
+                break;
+        }
+        // 鎵撳嵃瀛楃
+        if (["1", "2", "3",
+            "4", "5", "6", "+",
+            "7", "8", "9", "-",
+            "0", "."].includes(text)) {
+            pinyin.cb(text)
+        }
+    })
+    numPanel.hide()
+    return numPanel
+}
+
+// 绗﹀彿閿洏
+function createSymbol() {
+    let symbolPanel = dxui.View.build(pinyin.container.id + 'symbolPanel', pinyin.container)
+    clearStyle(symbolPanel)
+    symbolPanel.setSize(pinyin.container.width(), pinyin.container.height())
+    symbolPanel.update()
+    // 鍒涘缓绗﹀彿閿洏
+    let symbolKeyboard = dxui.Buttons.build(symbolPanel.id + 'symbolKeyboard', symbolPanel)
+    clearStyle(symbolKeyboard)
+    symbolKeyboard.obj.lvObjSetStylePadGap(10, dxui.Utils.ENUM._LV_STYLE_STATE_CMP_SAME)
+    symbolKeyboard.padAll(10)
+    symbolKeyboard.bgColor(0xffffff, dxui.Utils.STYLE_PART.ITEMS)
+    symbolKeyboard.bgColor(0xe6e6e6)
+    symbolKeyboard.setSize(symbolPanel.width(), symbolPanel.height())
+    symbolKeyboard.data([
+        "^", "\\", "|", "<", ">", "垄", "拢", "鈧�", "楼", "鈧�", "\n",
+        "[", "]", "{", "}", "#", "%", "+", "=", "~", "_", "\n",
+        " ", "-", "/", ":", ";", "(", ")", "$", "&", "\"", " ", "\n",
+        "123", "`", "?", "!", "*", "@", ",", "'", " ", "\n",
+        "ABC", " ", " ", ""
+    ])
+    symbolKeyboard.setBtnWidth(20, 1)
+    for (let i = 21; i < 30; i++) {
+        symbolKeyboard.setBtnWidth(i, 2)
+    }
+    symbolKeyboard.setBtnWidth(30, 1)
+    symbolKeyboard.setBtnWidth(31, 3)
+    for (let i = 32; i < 39; i++) {
+        symbolKeyboard.setBtnWidth(i, 2)
+    }
+    symbolKeyboard.setBtnWidth(39, 3)
+    symbolKeyboard.setBtnWidth(41, 2)
+    symbolKeyboard.obj.addEventCb((e) => {
+        let dsc = e.lvEventGetDrawPartDsc()
+        if (dsc.class_p == symbolKeyboard.obj.ClassP && dsc.type == dxui.Utils.ENUM.LV_BTNMATRIX_DRAW_PART_BTN) {
+            // 闅愯棌鏃犵敤鎸夐挳
+            if (dsc.id == 20 || dsc.id == 30) {
+                dxui.Utils.GG.NativeDraw.lvDrawRectReset(dsc.rect_dsc, { bg_opa: 0, shadow_opa: 0 })
+            }
+            // 鍔犳繁涓�浜涘姛鑳芥寜閽�
+            if (dsc.id == 31 || dsc.id == 39 || dsc.id == 40 || dsc.id == 41 || dsc.id == 45) {
+                if (symbolKeyboard.obj.lvBtnmatrixGetSelectedBtn() == dsc.id && e.lvEventGetTarget().hasState(dxui.Utils.ENUM.LV_STATE_PRESSED)) {
+                    dxui.Utils.GG.NativeDraw.lvDrawRectReset(dsc.rect_dsc, { bg_color: 0xcdcdcd })
+                } else {
+                    dxui.Utils.GG.NativeDraw.lvDrawRectReset(dsc.rect_dsc, { bg_color: 0xdbdbdb })
+                }
+            }
+            // 鍥炶溅鎸夐挳钃濊壊
+            if (dsc.id == 42) {
+                if (symbolKeyboard.obj.lvBtnmatrixGetSelectedBtn() == dsc.id && e.lvEventGetTarget().hasState(dxui.Utils.ENUM.LV_STATE_PRESSED)) {
+                    dxui.Utils.GG.NativeDraw.lvDrawRectReset(dsc.rect_dsc, { bg_color: 0x0C6CE4 })
+                } else {
+                    dxui.Utils.GG.NativeDraw.lvDrawRectReset(dsc.rect_dsc, { bg_color: 0x0C78FE })
+                }
+            }
+        }
+    }, dxui.Utils.ENUM.LV_EVENT_DRAW_PART_BEGIN)
+    symbolKeyboard.obj.addEventCb((e) => {
+        let dsc = e.lvEventGetDrawPartDsc()
+        if (dsc.class_p == symbolKeyboard.obj.ClassP && dsc.type == dxui.Utils.ENUM.LV_BTNMATRIX_DRAW_PART_BTN) {
+            if (dsc.id == 39) {
+                let src = '/app/code/resource/image/backspace.png'
+                // 鑾峰彇鍥剧墖淇℃伅
+                let header = dxui.Utils.GG.NativeDraw.lvImgDecoderGetInfo(src)
+                // 瀹氫箟涓�鍧楀尯鍩燂紝灞呬腑鏄剧ず锛屾敞鎰忥細灏哄杞琣rea闇�瑕�-1锛宎rea杞昂瀵搁渶瑕�+1
+                let x1 = dsc.draw_area.x1 + (dsc.draw_area.x2 - dsc.draw_area.x1 + 1 - header.w) / 2;
+                let y1 = dsc.draw_area.y1 + (dsc.draw_area.y2 - dsc.draw_area.y1 + 1 - header.h) / 2;
+                let x2 = x1 + header.w - 1;
+                let y2 = y1 + header.h - 1;
+                let area = dxui.Utils.GG.NativeArea.lvAreaSet(x1, y1, x2, y2)
+                // 缁樺埗鍥剧墖淇℃伅
+                let img_draw_dsc = dxui.Utils.GG.NativeDraw.lvDrawImgDscInit()
+                // 缁樺埗鍥剧墖
+                dxui.Utils.GG.NativeDraw.lvDrawImg(dsc.dsc, img_draw_dsc, area, src)
+            }
+            if (dsc.id == 42) {
+                let src = '/app/code/resource/image/enter.png'
+                // 鑾峰彇鍥剧墖淇℃伅
+                let header = dxui.Utils.GG.NativeDraw.lvImgDecoderGetInfo(src)
+                // 瀹氫箟涓�鍧楀尯鍩燂紝灞呬腑鏄剧ず锛屾敞鎰忥細灏哄杞琣rea闇�瑕�-1锛宎rea杞昂瀵搁渶瑕�+1
+                let x1 = dsc.draw_area.x1 + (dsc.draw_area.x2 - dsc.draw_area.x1 + 1 - header.w) / 2;
+                let y1 = dsc.draw_area.y1 + (dsc.draw_area.y2 - dsc.draw_area.y1 + 1 - header.h) / 2;
+                let x2 = x1 + header.w - 1;
+                let y2 = y1 + header.h - 1;
+                let area = dxui.Utils.GG.NativeArea.lvAreaSet(x1, y1, x2, y2)
+                // 缁樺埗鍥剧墖淇℃伅
+                let img_draw_dsc = dxui.Utils.GG.NativeDraw.lvDrawImgDscInit()
+                // 缁樺埗鍥剧墖
+                dxui.Utils.GG.NativeDraw.lvDrawImg(dsc.dsc, img_draw_dsc, area, src)
+            }
+            if (dsc.id == 41) {
+                let src = '/app/code/resource/image/space.png'
+                // 鑾峰彇鍥剧墖淇℃伅
+                let header = dxui.Utils.GG.NativeDraw.lvImgDecoderGetInfo(src)
+                // 瀹氫箟涓�鍧楀尯鍩燂紝灞呬腑鏄剧ず锛屾敞鎰忥細灏哄杞琣rea闇�瑕�-1锛宎rea杞昂瀵搁渶瑕�+1
+                let x1 = dsc.draw_area.x1 + (dsc.draw_area.x2 - dsc.draw_area.x1 + 1 - header.w) / 2;
+                let y1 = dsc.draw_area.y1 + (dsc.draw_area.y2 - dsc.draw_area.y1 + 1 - header.h) / 2;
+                let x2 = x1 + header.w - 1;
+                let y2 = y1 + header.h - 1;
+                y1 += 10
+                y2 += 10
+                let area = dxui.Utils.GG.NativeArea.lvAreaSet(x1, y1, x2, y2)
+                // 缁樺埗鍥剧墖淇℃伅
+                let img_draw_dsc = dxui.Utils.GG.NativeDraw.lvDrawImgDscInit()
+                // 缁樺埗鍥剧墖
+                dxui.Utils.GG.NativeDraw.lvDrawImg(dsc.dsc, img_draw_dsc, area, src)
+            }
+        }
+    }, dxui.Utils.ENUM.LV_EVENT_DRAW_PART_END)
+    symbolKeyboard.on(dxui.Utils.ENUM.LV_EVENT_LONG_PRESSED_REPEAT, () => {
+        let clickBtn = symbolKeyboard.clickedButton()
+        let id = clickBtn.id
+        switch (id) {
+            case 39:
+                // 閫�鏍�
+                pinyin.cb({ cmd: "backspace" })
+                break;
+        }
+    })
+    symbolKeyboard.on(dxui.Utils.ENUM.LV_EVENT_PRESSED, () => {
+        let clickBtn = symbolKeyboard.clickedButton()
+        let id = clickBtn.id
+        let text = clickBtn.text
+        switch (id) {
+            case 31:
+                if (isLock) {
+                    break;
+                }
+                // 鍒囨崲鏁板瓧閿洏
+                pinyin.numPanel.show()
+                pinyin.symbolPanel.hide()
+                break;
+            case 39:
+                // 閫�鏍�
+                pinyin.cb({ cmd: "backspace" })
+                break;
+            case 40:
+                if (isLock) {
+                    break;
+                }
+                // 鍒囨崲鑻辨枃閿洏
+                pinyin.englishPanel.show()
+                pinyin.symbolPanel.hide()
+                break;
+            case 41:
+                // 绌烘牸
+                pinyin.cb(" ")
+                break;
+            case 42:
+                // 鍥炶溅
+                pinyin.cb({ cmd: "enter" })
+                break;
+            default:
+                break;
+        }
+        // 鎵撳嵃瀛楃
+        if (["^", "\\", "|", "<", ">", "垄", "拢", "鈧�", "楼", "鈧�",
+            "[", "]", "{", "}", "#", "%", "+", "=", "~", "_",
+            "-", "/", ":", ";", "(", ")", "$", "&", "\"",
+            "`", "?", "!", "*", "@", ",", "'"].includes(text)) {
+            pinyin.cb(text)
+        }
+    })
+    symbolPanel.hide()
+    return symbolPanel
+}
+// 娓呴櫎鏍峰紡
+function clearStyle(obj) {
+    obj.radius(0)
+    obj.borderWidth(0)
+    obj.padAll(0)
+}
+export default pinyin
diff --git a/vf205_access/src/view/pwdView.js b/vf205_access/src/view/pwdView.js
new file mode 100644
index 0000000..56c142d
--- /dev/null
+++ b/vf205_access/src/view/pwdView.js
@@ -0,0 +1,72 @@
+import dxui from '../../dxmodules/dxUi.js'
+import std from '../../dxmodules/dxStd.js'
+import viewUtils from "./viewUtils.js"
+import topView from './topView.js'
+import mainView from './mainView.js'
+import i18n from './i18n.js'
+import screen from '../screen.js'
+
+const pwdView = {}
+pwdView.init = function () {
+    /**************************************************鍒涘缓灞忓箷*****************************************************/
+    const screenMain = dxui.View.build('pwdView', dxui.Utils.LAYER.MAIN)
+    pwdView.screenMain = screenMain
+    screenMain.scroll(false)
+    screenMain.bgColor(0xffffff)
+    screenMain.on(dxui.Utils.ENUM.LV_EVENT_SCREEN_LOADED, () => {
+        topView.changeTheme(true)
+
+        const configAll = screen.getConfig()
+        pwdAccessBtn.disable(configAll['sys.pwd'] == 0)
+        
+        pwdView.timer = std.setInterval(() => {
+            let count = dxui.Utils.GG.NativeDisp.lvDispGetInactiveTime()
+            if (count > 15 * 1000) {
+                std.clearInterval(pwdView.timer)
+                pwdView.timer = null
+                dxui.loadMain(mainView.screenMain)
+            }
+        }, 1000)
+
+        pwdInput.send(dxui.Utils.EVENT.CLICK)
+        pwdInput.send(dxui.Utils.EVENT.FOCUSED)
+    })
+    screenMain.on(dxui.Utils.ENUM.LV_EVENT_SCREEN_UNLOADED, () => {
+        if (pwdView.timer) {
+            std.clearInterval(pwdView.timer)
+        }
+    })
+
+    const titleBox = viewUtils.title(screenMain, mainView.screenMain, 'pwdViewTitle', 'pwdView.title')
+    titleBox.align(dxui.Utils.ALIGN.TOP_MID, 0, 70)
+
+    const pwdInput = viewUtils.input(screenMain, 'pwdInput', 2, undefined, 'pwdView.pwd')
+    pwdInput.align(dxui.Utils.ALIGN.TOP_MID, 0, 211)
+    pwdInput.setPasswordMode(true)
+
+    const eyeFill = viewUtils.imageBtn(screenMain, screenMain.id + 'eye_fill', '/app/code/resource/image/eye-fill.png')
+    eyeFill.alignTo(pwdInput, dxui.Utils.ALIGN.RIGHT_MID, 0, 0)
+    eyeFill.on(dxui.Utils.EVENT.CLICK, () => {
+        pwdInput.setPasswordMode(true)
+        eyeFill.hide()
+        eyeOff.show()
+    })
+    eyeFill.hide()
+
+    const eyeOff = viewUtils.imageBtn(screenMain, screenMain.id + 'eye_off', '/app/code/resource/image/eye-off.png')
+    eyeOff.alignTo(pwdInput, dxui.Utils.ALIGN.RIGHT_MID, 0, 0)
+    eyeOff.on(dxui.Utils.EVENT.CLICK, () => {
+        pwdInput.setPasswordMode(false)
+        eyeFill.show()
+        eyeOff.hide()
+    })
+
+    const pwdAccessBtn = viewUtils.bottomBtn(screenMain, 'pwdAccessBtn', 'pwdView.pwdAccess', () => {
+        // 纭瀵嗙爜
+        screen.pwdAccess(pwdInput.text())
+        dxui.loadMain(mainView.screenMain)
+    })
+    pwdAccessBtn.align(dxui.Utils.ALIGN.BOTTOM_MID, 0, -83)
+}
+
+export default pwdView
\ No newline at end of file
diff --git a/vf205_access/src/view/topView.js b/vf205_access/src/view/topView.js
new file mode 100644
index 0000000..db0f041
--- /dev/null
+++ b/vf205_access/src/view/topView.js
@@ -0,0 +1,170 @@
+import dxui from '../../dxmodules/dxUi.js'
+import std from '../../dxmodules/dxStd.js'
+import viewUtils from './viewUtils.js'
+import screen from '../screen.js'
+import newPwdView from './config/newPwdView.js'
+import logger from '../../dxmodules/dxLogger.js'
+
+// 涓昏鏄剧ず绯荤粺鏃堕棿鍜岀姸鎬佸浘鏍�
+const topView = {}
+topView.init = function () {
+    const screenMain = dxui.View.build('topView', dxui.Utils.LAYER.TOP)
+    topView.screenMain = screenMain
+    viewUtils._clearStyle(screenMain)
+    screenMain.scroll(false)
+    screenMain.width(screen.screenSize.width)
+    screenMain.height(screen.screenSize.height)
+    screenMain.bgOpa(0)
+    screenMain.clickable(false)
+
+    const topBox = dxui.View.build('topBox', screenMain)
+    viewUtils._clearStyle(topBox)
+    topBox.width(screen.screenSize.width)
+    topBox.height(70)
+    topBox.bgOpa(0)
+    topBox.clickable(false)
+
+    topBox.flexFlow(dxui.Utils.FLEX_FLOW.ROW)
+    topBox.flexAlign(dxui.Utils.FLEX_ALIGN.SPACE_BETWEEN, dxui.Utils.FLEX_ALIGN.CENTER, dxui.Utils.FLEX_ALIGN.CENTER)
+
+    const topBoxLeft = dxui.View.build('topBoxLeft', topBox)
+    viewUtils._clearStyle(topBoxLeft)
+    topBoxLeft.width(400)
+    topBoxLeft.height(70)
+    topBoxLeft.padLeft(38)
+    topBoxLeft.bgOpa(0)
+    topBoxLeft.clickable(false)
+
+    const topBoxRight = dxui.View.build('topBoxRight', topBox)
+    viewUtils._clearStyle(topBoxRight)
+    topBoxRight.width(400)
+    topBoxRight.height(70)
+    topBoxRight.padRight(38)
+    topBoxRight.bgOpa(0)
+    topBoxRight.clickable(false)
+    topBoxRight.flexFlow(dxui.Utils.FLEX_FLOW.ROW)
+    topBoxRight.flexAlign(dxui.Utils.FLEX_ALIGN.END, dxui.Utils.FLEX_ALIGN.CENTER, dxui.Utils.FLEX_ALIGN.CENTER)
+
+    const ethShow = dxui.Image.build('ethShow', topBoxRight)
+    topView.ethShow = ethShow
+    ethShow.source('/app/code/resource/image/ethernet.png')
+    ethShow.clickable(false)
+    ethShow.hide()
+
+    const wifiShow = dxui.Image.build('wifiShow', topBoxRight)
+    topView.wifiShow = wifiShow
+    wifiShow.source('/app/code/resource/image/wifi.png')
+    wifiShow.clickable(false)
+    wifiShow.hide()
+
+    const _4gShow = dxui.Image.build('4gShow', topBoxRight)
+    topView._4gShow = _4gShow
+    _4gShow.source('/app/code/resource/image/4g.png')
+    _4gShow.clickable(false)
+    _4gShow.hide()
+
+    const mqttShow = dxui.Image.build('mqttShow', topBoxRight)
+    topView.mqttShow = mqttShow
+    mqttShow.source('/app/code/resource/image/mqtt.png')
+    mqttShow.clickable(false)
+    mqttShow.hide()
+
+    // 娣诲姞闀挎寜杩涘叆绠$悊椤甸潰鐨勫尯鍩�
+    const adminArea = dxui.View.build('adminArea', screenMain)
+    viewUtils._clearStyle(adminArea)
+    adminArea.setSize(120, 120)
+    adminArea.align(dxui.Utils.ALIGN.TOP_RIGHT, 0, 0)
+    adminArea.bgOpa(0)
+    adminArea.clickable(true)
+    
+    logger.info('[topView]: 闀挎寜鍖哄煙宸插垱寤猴紝浣嶇疆锛氬彸涓婅')
+    
+    let pressStartTime = 0
+    let isPressing = false
+    let longPressTimer = null
+    
+    // 浣跨敤PRESSING浜嬩欢妫�娴嬫寜浣忕姸鎬�
+    adminArea.on(dxui.Utils.EVENT.PRESSING, () => {
+        if (!isPressing) {
+            // 绗竴娆℃娴嬪埌鎸変綇
+            isPressing = true
+            pressStartTime = Date.now()
+            logger.info('[topView]: 寮�濮嬫寜浣�')
+            
+            // 鍚姩闀挎寜璁℃椂鍣�
+            longPressTimer = std.setTimeout(() => {
+                const pressDuration = Date.now() - pressStartTime
+                logger.info(`[topView]: 鎸変綇涓嶆斁${pressDuration}ms鎴愬姛锛岃繘鍏ョ鐞嗛〉闈)
+                dxui.loadMain(newPwdView.screenMain)
+                longPressTimer = null
+            }, 3000)
+        }
+    })
+    
+    // 浣跨敤CLICK浜嬩欢妫�娴嬮噴鏀撅紙褰撶敤鎴烽噴鏀炬椂锛孭RESSING浜嬩欢浼氬仠姝級
+    adminArea.on(dxui.Utils.EVENT.CLICK, () => {
+        if (isPressing) {
+            const pressDuration = Date.now() - pressStartTime
+            logger.info(`[topView]: 鎸変綇鏃堕棿${pressDuration}ms锛岄噴鏀綻)
+            
+            // 娓呴櫎璁℃椂鍣�
+            if (longPressTimer) {
+                std.clearTimeout(longPressTimer)
+                longPressTimer = null
+            }
+            
+            isPressing = false
+        } else {
+            logger.info('[topView]: 闀挎寜鍖哄煙妫�娴嬪埌鐐瑰嚮浜嬩欢')
+        }
+    })
+
+}
+
+// 鍒囨崲涓婚锛屼袱濂楀浘鏍囷紝涓�濂楃櫧鑹诧紝涓�濂楅粦鑹�
+topView.changeTheme = function (dark) {
+    if (dark) {
+        topView.ethShow.source('/app/code/resource/image/ethernet_dark.png')
+        topView.mqttShow.source('/app/code/resource/image/mqtt_dark.png')
+        topView.wifiShow.source('/app/code/resource/image/wifi_dark.png')
+        topView._4gShow.source('/app/code/resource/image/4g_dark.png')
+    } else {
+        topView.ethShow.source('/app/code/resource/image/ethernet.png')
+        topView.mqttShow.source('/app/code/resource/image/mqtt.png')
+        topView.wifiShow.source('/app/code/resource/image/wifi.png')
+        topView._4gShow.source('/app/code/resource/image/4g.png')
+    }
+}
+
+// mqtt杩炴帴鐘舵��
+topView.mqttConnectState = function (connected) {
+    if (connected) {
+        topView.mqttShow.show()
+    } else {
+        topView.mqttShow.hide()
+    }
+}
+
+// eth杩炴帴鐘舵��
+topView.ethConnectState = function (connected, type) {
+    if (connected) {
+        if (type == 1) {
+            topView.ethShow.show()
+            topView.wifiShow.hide()
+            topView._4gShow.hide()
+        } else if (type == 2) {
+            topView.wifiShow.show()
+            topView.ethShow.hide()
+            topView._4gShow.hide()
+        } else if (type == 4) {
+            topView._4gShow.show()
+            topView.ethShow.hide()
+            topView.wifiShow.hide()
+        }
+    } else {
+        topView.ethShow.hide()
+        topView.wifiShow.hide()
+        topView._4gShow.hide()
+    }
+}
+export default topView
diff --git a/vf205_access/src/view/viewUtils.js b/vf205_access/src/view/viewUtils.js
new file mode 100644
index 0000000..9d3c90d
--- /dev/null
+++ b/vf205_access/src/view/viewUtils.js
@@ -0,0 +1,475 @@
+import * as os from "os"
+import dxui from '../../dxmodules/dxUi.js'
+import dxMap from '../../dxmodules/dxMap.js'
+import screen from '../screen.js'
+import pinyin from './pinyin/pinyin.js'
+// import utils from "../common/utils/utils.js"
+import i18n from "./i18n.js"
+import std from '../../dxmodules/dxStd.js'
+
+const viewUtils = {}
+
+viewUtils.font = function (size, style) {
+    return dxui.Font.build('/app/code/resource/font/AlibabaPuHuiTi-2-65-Medium.ttf', size || 14, style || dxui.Utils.FONT_STYLE.NORMAL)
+}
+
+// 璇箟鍖栭鑹�
+viewUtils.color = {
+    // 鎴愬姛锛岀豢鑹�
+    success: 0x00BF8A,
+    // 澶辫触锛岀孩鑹�
+    fail: 0xFF0000,
+    // 璀﹀憡锛岄粍鑹�
+    warning: 0xFFA800,
+    // 榛樿锛氳摑鑹�
+    default: 0x00a8ff
+}
+
+// 娓呴櫎鏍峰紡
+viewUtils._clearStyle = function (obj) {
+    obj.radius(0)
+    obj.borderWidth(0)
+    obj.padAll(0)
+}
+
+// 鍥剧墖鎸夐挳灏佽锛屾寜閽牴鎹浘鐗囧ぇ灏忚缃紝鐭╁舰
+viewUtils.imageBtn = function (parent, id, src, dataI18n, textColor) {
+    const zoom = 1.02
+
+    const imageBox = dxui.View.build(id, parent)
+    viewUtils._clearStyle(imageBox)
+    imageBox.bgOpa(0)
+
+    const image = dxui.Image.build(id + 'image', imageBox)
+    image.source(src)
+    image.update()
+    const width = image.width()
+    const height = image.height()
+    imageBox.setSize(width * zoom + 5, height * zoom + 5)
+    imageBox.scroll(false)
+    image.align(dxui.Utils.ALIGN.CENTER, 0, 0)
+
+    if (dataI18n) {
+        const textLbl = dxui.Label.build(id + 'text', image)
+        textLbl.textFont(viewUtils.font(Math.round(height / 3)))
+        if (textColor !== undefined && textColor !== null) {
+            textLbl.textColor(textColor)
+        } else {
+            textLbl.textColor(0xffffff)
+        }
+        textLbl.align(dxui.Utils.ALIGN.CENTER, 0, 0)
+        textLbl.dataI18n = dataI18n
+    }
+
+    imageBox.on(dxui.Utils.ENUM.LV_EVENT_PRESSED, () => {
+        image.obj.lvImgSetZoom(256 * zoom)
+    })
+
+    imageBox.on(dxui.Utils.ENUM.LV_EVENT_RELEASED, () => {
+        image.obj.lvImgSetZoom(256)
+    })
+
+    return imageBox
+}
+
+// 鍒涘缓鏍囬鏍�
+viewUtils.title = function (parent, backScreen, id, dataI18n, backCb) {
+    const titleBox = dxui.View.build(id, parent)
+    viewUtils._clearStyle(titleBox)
+    titleBox.setSize(800, 70)
+    titleBox.bgColor(0xffffff)
+
+    if (dataI18n) {
+        const titleLbl = dxui.Label.build(id + 'title', titleBox)
+        titleLbl.textFont(viewUtils.font(32))
+        titleLbl.align(dxui.Utils.ALIGN.CENTER, 0, 0)
+        titleLbl.dataI18n = dataI18n
+    }
+
+    const back = viewUtils.imageBtn(titleBox, id + 'back', '/app/code/resource/image/back.png')
+    back.setSize(80, 70)
+    back.align(dxui.Utils.ALIGN.LEFT_MID, 0, 0)
+
+    back.on(dxui.Utils.EVENT.CLICK, () => {
+        if (backScreen) {
+            dxui.loadMain(backScreen)
+        }
+        if (backCb) {
+            backCb()
+        }
+    })
+
+    return titleBox
+}
+
+// 杈撳叆妗�
+viewUtils.input = function (parent, id, mode, enter = () => { }, dataI18n) {
+    const input = dxui.Textarea.build(id + 'input', parent)
+    viewUtils._clearStyle(input)
+    input.align(dxui.Utils.ALIGN.TOP_MID, 0, 100)
+    input.textAlign(dxui.Utils.TEXT_ALIGN.LEFT_MID)
+    input.setOneLine(true)
+    input.borderWidth(2)
+    input.setBorderColor(0xE7E7E7)
+    const font = viewUtils.font(26)
+    const superSetSize = input.setSize
+    input.setSize = (width, height) => {
+        superSetSize.call(input, width, height)
+        input.padAll((height - 4 - font.obj.lvFontGetLineHeight()) / 2)
+        input.padLeft(30)
+        input.padRight(30)
+    }
+    input.setSize(650, 100)
+    input.radius(13)
+    input.textFont(font)
+    if (dataI18n) {
+        // 鍙湁鍦╠xui.all涓紝鎵嶈兘浣跨敤dataI18n
+        dxui.all[id + 'input' + 'obj'] = input.obj
+        input.obj.dataI18n = dataI18n
+        input.obj.text = (text) => {
+            input.obj.lvTextareaSetPlaceholderText(text)
+        }
+    }
+
+    input.on(dxui.Utils.EVENT.CLICK, () => {
+        input.setBorderColor(0x3670f7)
+        pinyin.show(mode || pinyin.getMode(), (data) => {
+            if (typeof data == 'string') {
+                input.lvTextareaAddText(data)
+            } else if (typeof data == 'object') {
+                switch (data.cmd) {
+                    case 'enter':
+                        enter()
+                        pinyin.hide()
+                        break
+                    case 'backspace':
+                        input.lvTextareaDelChar()
+                        break
+                }
+            }
+        })
+        if (mode) {
+            pinyin.lock()
+        }
+    })
+    input.on(dxui.Utils.EVENT.DEFOCUSED, () => {
+        dxMap.get("INPUT_KEYBOARD").put("defocus", "defocus")
+    })
+
+    let root = parent
+    let rootId = parent.id
+    while ((rootId = dxui.all[rootId].parent) != "0") {
+        root = dxui.all[rootId]
+    }
+
+    root.on(dxui.Utils.EVENT.CLICK, () => {
+        input.setBorderColor(0xE7E7E7)
+        // pinyin.hide()
+    })
+
+    root.on(dxui.Utils.ENUM.LV_EVENT_SCREEN_UNLOADED, () => {
+        input.setBorderColor(0xE7E7E7)
+        // pinyin.hide()
+        input.text('')
+    })
+    return input
+}
+
+// 纭寮圭獥
+viewUtils.confirmInit = function () {
+    const confirm = dxui.View.build('confirm', dxui.Utils.LAYER.TOP)
+    viewUtils._clearStyle(confirm)
+    confirm.setSize(screen.screenSize.width, screen.screenSize.height)
+    confirm.bgColor(0x0)
+    confirm.bgOpa(50)
+    confirm.hide()
+
+    const box = dxui.View.build('confirmBox', confirm)
+    viewUtils._clearStyle(box)
+    box.setSize(500, 300)
+    box.radius(20)
+    box.align(dxui.Utils.ALIGN.CENTER, 0, 0)
+    box.bgColor(0xffffff)
+
+    const title = dxui.Label.build('confirmTitle', box)
+    title.align(dxui.Utils.ALIGN.TOP_MID, 0, 22)
+    title.textFont(viewUtils.font(30))
+    title.text("Confirm")
+
+    const close = viewUtils.imageBtn(box, 'confirmClose', '/app/code/resource/image/close_small.png')
+    close.align(dxui.Utils.ALIGN.TOP_RIGHT, -28, 18)
+
+    const content = dxui.Label.build('confirmContent', box)
+    content.align(dxui.Utils.ALIGN.TOP_MID, 0, 114)
+    content.textFont(viewUtils.font(24))
+    content.textColor(0x767676)
+    content.text("Are you sure you want to exit?")
+    content.textAlign(dxui.Utils.TEXT_ALIGN.CENTER)
+
+    const ok = dxui.Button.build('okBtn', box)
+    ok.align(dxui.Utils.ALIGN.BOTTOM_LEFT, 69, -31)
+    ok.bgColor(0x0)
+    ok.radius(10)
+    ok.setSize(150, 50)
+    const okLbl = dxui.Label.build('okLbl', ok)
+    okLbl.textFont(viewUtils.font(26))
+    okLbl.dataI18n = 'confirm.ok'
+    okLbl.textColor(0xffffff)
+    okLbl.align(dxui.Utils.ALIGN.CENTER, 0, 0)
+    ok.on(dxui.Utils.EVENT.CLICK, () => {
+        confirm.hide()
+        if (typeof viewUtils.confirm.okFunc == 'function') {
+            viewUtils.confirm.okFunc()
+        }
+    })
+
+    const no = dxui.Button.build('noBtn', box)
+    no.align(dxui.Utils.ALIGN.BOTTOM_RIGHT, -69, -31)
+    no.bgColor(0xF3F3F3)
+    no.radius(10)
+    no.setSize(150, 50)
+    const noLbl = dxui.Label.build('noLbl', no)
+    noLbl.textFont(viewUtils.font(26))
+    noLbl.dataI18n = 'confirm.no'
+    noLbl.align(dxui.Utils.ALIGN.CENTER, 0, 0)
+    noLbl.textColor(0x0)
+    no.on(dxui.Utils.EVENT.CLICK, () => {
+        confirm.hide()
+    })
+
+    close.on(dxui.Utils.EVENT.CLICK, () => {
+        confirm.hide()
+        if (typeof viewUtils.confirm.noFunc == 'function') {
+            viewUtils.confirm.noFunc()
+        }
+    })
+    viewUtils.confirm = { confirm, box, title, close, content, ok, no, okLbl, noLbl }
+}
+
+viewUtils.confirmClose = function () {
+    viewUtils.confirm.confirm.hide()
+}
+
+viewUtils.confirmOpen = function (title, content, ok, no) {
+    viewUtils.confirm.confirm.moveForeground()
+    viewUtils.confirm.title.dataI18n = title
+    viewUtils.confirm.content.dataI18n = content
+    if (ok) {
+        viewUtils.confirm.ok.show()
+        viewUtils.confirm.okFunc = ok
+    } else {
+        viewUtils.confirm.ok.hide()
+    }
+    if (no) {
+        viewUtils.confirm.no.show()
+        viewUtils.confirm.noFunc = no
+    } else {
+        viewUtils.confirm.no.hide()
+    }
+    viewUtils.confirm.confirm.show()
+    i18n.refreshObj(viewUtils.confirm.title)
+    i18n.refreshObj(viewUtils.confirm.content)
+    viewUtils.confirm.content.update()
+    viewUtils.confirm.box.height(viewUtils.confirm.content.height() + 257)
+}
+
+
+viewUtils.bottomBtn = function (parent, id, dataI18n, click, btnColor = 0x000000, textColor = 0xffffff, fontSize = 28) {
+    const btn = dxui.Button.build(id, parent)
+    btn.align(dxui.Utils.ALIGN.BOTTOM_MID, 0, -124)
+    btn.bgColor(btnColor)
+    btn.setSize(620, 100)
+    btn.radius(60)
+    const btnLbl = dxui.Label.build(id + 'lbl', btn)
+    btnLbl.dataI18n = dataI18n
+    btnLbl.textFont(viewUtils.font(fontSize))
+    btnLbl.textColor(textColor)
+    btnLbl.align(dxui.Utils.ALIGN.CENTER, 0, 0)
+    btn.on(dxui.Utils.EVENT.CLICK, click)
+    return btn
+}
+
+// 寰幆婊氬姩
+viewUtils.cycleList = function (parent, id, size, maxNum, template = () => { }, update = () => { }) {
+    const cycleList = dxui.View.build(id, parent)
+    viewUtils._clearStyle(cycleList)
+    cycleList.setSize(size[0], size[1])
+    cycleList.cycleList = []
+    cycleList.cycleIndex = 0
+    for (let i = -1; i < (maxNum + 1); i++) {
+        const cycleItem = dxui.View.build(id + 'item' + i, cycleList)
+        viewUtils._clearStyle(cycleItem)
+        cycleItem.setSize(size[0], size[1] / maxNum)
+        cycleItem.bgOpa(0)
+        cycleItem.borderWidth(1)
+        cycleItem.setBorderColor(0xDEDEDE)
+        cycleItem.obj.setStyleBorderSide(dxui.Utils.ENUM.LV_BORDER_SIDE_BOTTOM, 0)
+        cycleItem.userdata = template(cycleItem)
+        cycleList.cycleIndex = i
+        update(cycleItem.userdata, i)
+        if (cycleList.cycleList.length > 0) {
+            cycleItem.alignTo(cycleList.cycleList[cycleList.cycleList.length - 1], dxui.Utils.ALIGN.OUT_BOTTOM_MID, 0, 0)
+        } else {
+            cycleItem.align(dxui.Utils.ALIGN.TOP_MID, 0, 0)
+        }
+        cycleList.cycleList.push(cycleItem)
+    }
+    cycleList.scrollToY(size[1] / maxNum, false)
+
+    cycleList.on(dxui.Utils.ENUM.LV_EVENT_SCROLL, () => {
+        if (cycleList.scrollTop() >= size[1] / maxNum * 2) {
+            const cycleItem = cycleList.cycleList.shift()
+            cycleList.cycleList.push(cycleItem)
+            for (let i = 0; i < cycleList.cycleList.length; i++) {
+                const item = cycleList.cycleList[i]
+                if (i == 0) {
+                    item.align(dxui.Utils.ALIGN.TOP_MID, 0, 0)
+                } else {
+                    item.alignTo(cycleList.cycleList[i - 1], dxui.Utils.ALIGN.OUT_BOTTOM_MID, 0, 0)
+                }
+            }
+            cycleList.cycleIndex += 1
+            update(cycleItem.userdata, cycleList.cycleIndex)
+            cycleList.scrollToY(size[1] / maxNum, false)
+        } else if (cycleList.scrollTop() <= 0) {
+            const cycleItem = cycleList.cycleList.pop()
+            cycleList.cycleList.unshift(cycleItem)
+            for (let i = 0; i < cycleList.cycleList.length; i++) {
+                const item = cycleList.cycleList[i]
+                if (i == 0) {
+                    item.align(dxui.Utils.ALIGN.TOP_MID, 0, 0)
+                } else {
+                    item.alignTo(cycleList.cycleList[i - 1], dxui.Utils.ALIGN.OUT_BOTTOM_MID, 0, 0)
+                }
+            }
+            cycleList.cycleIndex -= 1
+            update(cycleItem.userdata, cycleList.cycleIndex)
+            cycleList.scrollToY(size[1] / maxNum, false)
+        }
+    })
+    cycleList.refresh = () => {
+        cycleList.cycleList.forEach((item, index) => {
+            update(item.userdata, index)
+        })
+    }
+    return cycleList
+}
+
+viewUtils.statusPanel = function (parent, successI18n, failI18n) {
+    const successBg = dxui.Image.build(parent.id + 'successBg', parent)
+    successBg.source('/app/code/resource/image/successBg.png')
+    successBg.align(dxui.Utils.ALIGN.BOTTOM_MID, 0, 0)
+    successBg.hide()
+
+    const successIcon = dxui.Image.build(parent.id + 'successIcon', successBg)
+    successIcon.source('/app/code/resource/image/success_fill.png')
+    successIcon.align(dxui.Utils.ALIGN.CENTER, 0, 0)
+
+    const successLbl = dxui.Label.build(parent.id + 'successLbl', successBg)
+    successLbl.textFont(viewUtils.font(38))
+    successLbl.textColor(0xffffff)
+    successLbl.dataI18n = successI18n
+    successLbl.textAlign(dxui.Utils.TEXT_ALIGN.CENTER)
+    successLbl.align(dxui.Utils.ALIGN.TOP_MID, 0, 244)
+
+    const failBg = dxui.Image.build(parent.id + 'failBg', parent)
+    failBg.source('/app/code/resource/image/failBg.png')
+    failBg.align(dxui.Utils.ALIGN.BOTTOM_MID, 0, 0)
+    failBg.hide()
+
+    const failIcon = dxui.Image.build(parent.id + 'failIcon', failBg)
+    failIcon.source('/app/code/resource/image/delete_fill.png')
+    failIcon.align(dxui.Utils.ALIGN.CENTER, 0, 0)
+
+    const failLbl = dxui.Label.build(parent.id + 'failLbl', failBg)
+    failLbl.textFont(viewUtils.font(38))
+    failLbl.textColor(0xffffff)
+    failLbl.dataI18n = failI18n
+    failLbl.textAlign(dxui.Utils.TEXT_ALIGN.CENTER)
+    failLbl.align(dxui.Utils.ALIGN.TOP_MID, 0, 244)
+
+    return {
+        success: (dataI18n) => {
+            if (dataI18n) {
+                successLbl.dataI18n = dataI18n
+                i18n.refreshObj(successLbl)
+            }
+            successBg.show()
+            failBg.hide()
+            std.setTimeout(() => {
+                successBg.hide()
+            }, 3000)
+        },
+        fail: (dataI18n) => {
+            if (dataI18n) {
+                failLbl.dataI18n = dataI18n
+                i18n.refreshObj(failLbl)
+            }
+            failBg.show()
+            successBg.hide()
+            std.setTimeout(() => {
+                failBg.hide()
+            }, 3000)
+        },
+        successBg: successBg,
+        failBg: failBg
+    }
+}
+
+// 鏂板寮圭獥甯冨眬 - 灏忓瀷鐘舵�侀潰鏉�
+viewUtils.smallStatusPanel = function (parent, successI18n, failI18n) {
+    const successBg = dxui.Image.build(parent.id + 'smallSuccessBg', parent)
+    successBg.source('/app/code/resource/image/view_s.png') // 鎴愬姛鑳屾櫙鍥�
+    successBg.setSize(499, 97) // 璁剧疆灏哄
+    successBg.align(dxui.Utils.ALIGN.BOTTOM_MID, 0, 0)
+    successBg.hide()
+
+    const successLbl = dxui.Label.build(parent.id + 'smallSuccessLbl', successBg)
+    successLbl.textFont(viewUtils.font(24, dxui.Utils.FONT_STYLE.BOLD))
+    successLbl.textColor(0xffffff)
+    successLbl.dataI18n = successI18n
+    successLbl.textAlign(dxui.Utils.TEXT_ALIGN.CENTER)
+    successLbl.align(dxui.Utils.ALIGN.CENTER, 0, 0)
+
+    const failBg = dxui.Image.build(parent.id + 'smallFailBg', parent)
+    failBg.source('/app/code/resource/image/view_f.png') // 澶辫触鑳屾櫙鍥�
+    failBg.setSize(499, 97) // 璁剧疆灏哄
+    failBg.align(dxui.Utils.ALIGN.BOTTOM_MID, 0, 0)
+    failBg.hide()
+
+    const failLbl = dxui.Label.build(parent.id + 'smallFailLbl', failBg)
+    failLbl.textFont(viewUtils.font(24, dxui.Utils.FONT_STYLE.BOLD))
+    failLbl.textColor(0xffffff)
+    failLbl.dataI18n = failI18n
+    failLbl.textAlign(dxui.Utils.TEXT_ALIGN.CENTER)
+    failLbl.align(dxui.Utils.ALIGN.CENTER, 0, 0)
+
+    return {
+        success: (dataI18n) => {
+            if (dataI18n) {
+                successLbl.dataI18n = dataI18n
+                i18n.refreshObj(successLbl)
+            }
+            successBg.show()
+            failBg.hide()
+            std.setTimeout(() => {
+                successBg.hide()
+            }, 3000)
+        },
+        fail: (dataI18n) => {
+            if (dataI18n) {
+                failLbl.dataI18n = dataI18n
+                i18n.refreshObj(failLbl)
+            }
+            failBg.show()
+            successBg.hide()
+            std.setTimeout(() => {
+                failBg.hide()
+            }, 3000)
+        },
+        successBg: successBg,
+        failBg: failBg
+    }
+}
+
+export default viewUtils
\ No newline at end of file

--
Gitblit v1.9.3