From 683b1595260e638d1d3c6cc0d6543a72f6d6f925 Mon Sep 17 00:00:00 2001
From: yy1717 <fctom1215@outlook.com>
Date: 星期二, 12 一月 2021 14:36:42 +0800
Subject: [PATCH] 扣分码标准化

---
 lib/src/main/java/com/anyun/exam/lib/InstallUtil.java   |   90 ++
 lib/src/main/cpp/driver_test.cpp                        |   96 ++
 lib/src/main/cpp/native-lib.h                           |    2 
 lib/src/main/cpp/test_items/stop_and_start.cpp          |   18 
 lib/src/main/cpp/test_items2/car_start.cpp              |   12 
 lib/src/main/cpp/test_items2/prepare.cpp                |  100 +++
 lib/src/main/cpp/CMakeLists.txt                         |    1 
 lib/src/main/cpp/rtk_module/rtk.cpp                     |  193 ++++--
 lib/src/main/cpp/test_items2/change_lane.cpp            |    2 
 lib/src/main/cpp/test_items2/operate_gear.cpp           |    6 
 lib/src/main/cpp/test_items/park_bottom.cpp             |   18 
 lib/src/main/cpp/test_items2/prepare.h                  |   14 
 lib/src/main/cpp/test_items/park_edge.cpp               |   16 
 lib/src/main/cpp/mcu/mcu_if.h                           |    2 
 lib/src/main/cpp/test_items2/overtake.cpp               |    6 
 lib/src/main/cpp/master/comm_if.cpp                     |   65 ++
 lib/src/main/cpp/native-lib.cpp                         |   32 
 lib/src/main/cpp/test_items2/through_something.cpp      |   18 
 lib/src/main/cpp/defs.h                                 |    4 
 lib/src/main/cpp/test_items2/road_exam.cpp              |   56 +
 lib/src/main/cpp/test_items2/dummy_light.h              |   11 
 lib/src/main/cpp/rtk_platform/platform.cpp              |  606 ++++++++++---------
 lib/src/main/cpp/test_items/driving_curve.cpp           |    4 
 lib/src/main/cpp/rtk_module/rtk.h                       |    2 
 lib/src/main/cpp/rtk_platform/parse_net.cpp             |    2 
 lib/src/main/java/com/anyun/exam/lib/Upgrade.java       |   11 
 lib/src/main/cpp/test_items2/dummy_light.cpp            |  199 +----
 lib/src/main/cpp/test_items2/stop_car.cpp               |   23 
 lib/src/main/cpp/driver_test.h                          |   10 
 lib/src/main/cpp/master/comm_if.h                       |    1 
 lib/src/main/cpp/test_items/turn_a90.cpp                |    6 
 lib/src/main/cpp/test_items2/drive_straight.cpp         |    2 
 lib/src/main/cpp/rtk_platform/platform.h                |   34 
 lib/src/main/cpp/test_common/car_sensor.cpp             |   17 
 lib/src/main/cpp/mcu/mcu_if.cpp                         |   62 +
 lib/src/main/cpp/rtk_module/virtual_rtk.cpp             |    8 
 lib/src/main/java/com/anyun/exam/lib/RemoteService.java |   47 +
 37 files changed, 1,102 insertions(+), 694 deletions(-)

diff --git a/lib/src/main/cpp/CMakeLists.txt b/lib/src/main/cpp/CMakeLists.txt
index ccc572d..125e4eb 100644
--- a/lib/src/main/cpp/CMakeLists.txt
+++ b/lib/src/main/cpp/CMakeLists.txt
@@ -38,6 +38,7 @@
         test_items/turn_a90.cpp
         test_items/area_exam.cpp
 
+        test_items2/prepare.cpp
         test_items2/common_check.cpp
         test_items2/dummy_light.cpp
         test_items2/road_exam.cpp
diff --git a/lib/src/main/cpp/defs.h b/lib/src/main/cpp/defs.h
index fba169e..017fa15 100644
--- a/lib/src/main/cpp/defs.h
+++ b/lib/src/main/cpp/defs.h
@@ -1,8 +1,8 @@
 #ifndef _DEFS_H_
 #define _DEFS_H_
 
-#include <stdint.h>
-#include <stdbool.h>
+#include <cstdint>
+#include <cstdbool>
 
 #define ENABLE_DEBUG
 
diff --git a/lib/src/main/cpp/driver_test.cpp b/lib/src/main/cpp/driver_test.cpp
index b90ea78..e1df9bb 100644
--- a/lib/src/main/cpp/driver_test.cpp
+++ b/lib/src/main/cpp/driver_test.cpp
@@ -37,6 +37,7 @@
 #include "test_common/car_sensor.h"
 #include "test_items2/road_exam.h"
 #include "test_items/area_exam.h"
+#include "test_items2/prepare.h"
 
 #define DEBUG(fmt, args...)     LOGD("<driver_test> <%s>: " fmt, __func__, ##args)
 
@@ -86,6 +87,12 @@
 static const int DEFAULT_START_CAR_MAX_RMP = 2500;
 static const int DEFAULT_START_CAR_DISTANCE = 10;
 static const double DEFAULT_START_CAR_OPEN_DOOR_DISTANCE = 1.0;
+static const char DEFAULT_PREPARE_TTS[] = "璇峰紑濮嬩笂杞﹀噯澶�";
+static const char DEFAULT_TOUCH_LEFT_FRONT[] = "瀛﹀憳閫氳繃宸﹀墠鏂�";
+static const char DEFAULT_TOUCH_LEFT_REAR[] = "瀛﹀憳閫氳繃宸﹀悗鏂�";
+static const char DEFAULT_TOUCH_RIGHT_FRONT[] = "瀛﹀憳閫氳繃鍙冲墠鏂�";
+static const char DEFAULT_TOUCH_RIGHT_REAR[] = "瀛﹀憳閫氳繃鍙冲悗鏂�";
+static const char DEFAULT_START_ENGINE[] = "璇峰惎鍔ㄥ彂鍔ㄦ満";
 static const char DEFAULT_START_CAR_BEGIN_TTS[] = "璇疯捣姝ワ紝缁х画瀹屾垚鑰冭瘯";
 static const char DEFAULT_START_CAR_END_TTS[] = "璧锋瀹屾垚";
 static const int CHANGE_LANE_MAX_DISTANCE = 100;
@@ -235,6 +242,14 @@
     examParam.start_car_max_rpm = DEFAULT_START_CAR_MAX_RMP;
     examParam.start_car_limit_distance = DEFAULT_START_CAR_DISTANCE;
     examParam.open_door_drive_allow_distance = DEFAULT_START_CAR_OPEN_DOOR_DISTANCE;
+
+    examParam.prepare_tts = DEFAULT_PREPARE_TTS;
+    examParam.touch_leftfront_tts = DEFAULT_TOUCH_LEFT_FRONT;
+    examParam.touch_leftrear_tts = DEFAULT_TOUCH_LEFT_REAR;
+    examParam.touch_rightfront_tts = DEFAULT_TOUCH_RIGHT_FRONT;
+    examParam.touch_rightrear_tts = DEFAULT_TOUCH_RIGHT_REAR;
+    examParam.start_engine_tts = DEFAULT_START_ENGINE;
+
     examParam.start_car_begin_tts = DEFAULT_START_CAR_BEGIN_TTS;
     examParam.start_car_end_tts = DEFAULT_START_CAR_END_TTS;
     examParam.change_lane_limit_distance = CHANGE_LANE_MAX_DISTANCE;
@@ -371,7 +386,7 @@
 
     RoadMap.examScheme.assign(scheme.begin(), scheme.end());
 
-    DEBUG("寰楀埌鏂扮殑璺�冨湴鍥� 椤圭洰鏁伴噺 %d", RoadMap.examScheme.size());
+    DEBUG("寰楀埌璺�冮」鐩柟妗� 椤圭洰鏁伴噺 %d", RoadMap.examScheme.size());
 }
 
 void SetCarMeasurePoint(double *basePoint, int *axial, int *left_front_tire,
@@ -505,18 +520,38 @@
 {
     DEBUG("鑾峰彇妯℃嫙璺�冪伅鍏夋祴璇曢」鐩� N = %d %d", n, ExamStart);
 
+    static const int cov[] = {0,
+                              (DIPPED_BEAM_LAMP<<8)+DIPPED_BEAM_LIGHT,
+                              (MAIN_BEAM_LAMP<<8)+MAIN_BEAM_LIGHT,
+                              (CLEARANCE_LAMP<<8)+CLEARANCE_LIGHT,
+                              (FOG_LAMP<<8)+FOG_LIGHT,
+                              (TURN_SIGNAL_LAMP<<8)+LEFT_TURN_LIGHT,
+                              (TURN_SIGNAL_LAMP<<8)+RIGHT_TURN_LIGHT,
+                              (TURN_SIGNAL_LAMP<<8)+HAZARD_LIGHTS,
+                              (FLASH_BEAM_LAMP<<8)+FLASH_BEAM_LIGHT};
+
     if (ExamStart) return;
 
     if (DummyLightContent != NULL) {
-        free(DummyLightContent);
+        delete []DummyLightContent;
         DummyLightContent = NULL;
+        DummyLightContentSize = 0;
     }
 
-    DummyLightContent = (struct dummy_light_exam *)malloc(n * sizeof(struct dummy_light_exam));
+    DummyLightContent = new struct dummy_light_exam[n];
     DummyLightContentSize = n;
 
     for (int i = 0; i < n; i++) {
-        DummyLightContent[i] = cfg[i];
+        DummyLightContent[i].item = cfg[i].item;
+        DummyLightContent[i].tts = cfg[i].tts;
+        DummyLightContent[i].wrongCode = cfg[i].wrongCode;
+        // Sensor Name<<8 + Sensor Status
+        for (int j = 0; j < cfg[i].process.size(); ++j) {
+            DummyLightContent[i].process[j] = cov[cfg[i].process[j]];
+        }
+        for (int j = 0; j < cfg[i].solution.size(); ++j) {
+            DummyLightContent[i].solution[j] = cov[cfg[i].solution[j]];
+        }
     }
 }
 
@@ -688,8 +723,6 @@
     }
 }
 
-
-
 static void PrintObdInfo(struct RtkTime *rtkTime, double speed) {
     static struct RtkTime cTime = *rtkTime;
 
@@ -791,9 +824,9 @@
             engineRuning = false;
             if (ExamType == TEST_TYPE_AREA) {
                 // 鐔勭伀1娆★紝鎵�10鍒�
-                AddExamFault(5, rtkTime);
+                AddExamFault(10210, rtkTime);
             } else {
-                AddExamFault(20, rtkTime);
+                AddExamFault(30208, rtkTime);
             }
         }
     } else {
@@ -806,9 +839,9 @@
             if (ReadCarStatus(GEAR) != GEAR_N) {
                 // 涓嶆槸绌烘尅鐐圭伀锛屼笉鍚堟牸
                 if (ExamType == TEST_TYPE_AREA)
-                    AddExamFault(3, rtkTime);
+                    AddExamFault(10105, rtkTime);
                 else
-                    AddExamFault(4, rtkTime);
+                    AddExamFault(30105, rtkTime);
             }
             AppTimer_delete(EngineStartHold);
             AppTimer_add(EngineStartHold, examParam.hold_start_key_limit_time);
@@ -823,19 +856,23 @@
 
         // 涓嶅強鏃舵澗寮�鍚姩寮�鍏筹紝鎵�10鍒�
         if (ExamType == TEST_TYPE_AREA)
-            AddExamFault(4, rtkTime);
+            AddExamFault(10201, rtkTime);
     }
 
     if (ExamType == TEST_TYPE_ROAD_DUMMY_LIGHT) {
         if (exam_dummy_light == 0) {
-            StartDummyLightExam(DummyLightContent, DummyLightContentSize, rtkTime);
+            StartPrepare();
+//            StartDummyLightExam(DummyLightContent, DummyLightContentSize, rtkTime);
             exam_dummy_light = 1;
-            // 姹囨姤鐏厜鑰冭瘯寮�濮�
-            DEBUG("鐏厜鑰冭瘯寮�濮�");
-        } else if (exam_dummy_light == 1) {
-            exam_dummy_light = ExecuteDummyLightExam(rtkTime);
-            // 姹囨姤鐏厜鑰冭瘯缁撴潫
-            if (exam_dummy_light == 2) {
+            DEBUG("寮�濮嬩笂杞﹀噯澶�");
+        } else if (exam_dummy_light == 2) {
+            DEBUG("寮�濮嬬伅鍏夎�冭瘯");
+            StartDummyLightExam(DummyLightContent, DummyLightContentSize, rtkTime);
+            exam_dummy_light = 3;
+        } else if (exam_dummy_light == 3) {
+            if (!ExecuteDummyLightExam(rtkTime)) {
+                exam_dummy_light = 4;
+                // 姹囨姤鐏厜鑰冭瘯缁撴潫
                 DEBUG("鐏厜鑰冭瘯缁撴潫");
                 InitRoadExam(RoadMap);
             }
@@ -849,12 +886,12 @@
         if (ReadCarStatus(SEATBELT) == EJECT_SEATBELT && !reportSeatbeltEject) {
             DEBUG("涓嶇郴瀹夊叏甯�");
             reportSeatbeltEject = true;
-            AddExamFault(1, rtkTime);
+            AddExamFault(ExamType == TEST_TYPE_AREA? 10101: 30101, rtkTime);
         }
     }
 
     if (ExamType != TEST_TYPE_AREA) {
-        if (exam_dummy_light == 2 || ExamType == TEST_TYPE_ROAD_TRUE_LIGHT || ExamType == TEST_TYPE_ROAD_CALIBRATE) {
+        if (exam_dummy_light == 4 || ExamType == TEST_TYPE_ROAD_TRUE_LIGHT || ExamType == TEST_TYPE_ROAD_CALIBRATE) {
             TestRoadGeneral(RoadMap, CarModel, CarModelList, speed, move, rtkTime);
         }
     } else {
@@ -1089,13 +1126,13 @@
     sprintf(fault.utc, "%04d%02d%02d%02d%02d%02d.%02d", 2000 + rtkTime->YY,
             rtkTime->MM, rtkTime->DD, rtkTime->hh, rtkTime->mm, rtkTime->ss, rtkTime->mss);
 
-    if (ExamType != TEST_TYPE_AREA) {
-        wrong += 1000;
-    }
+//    if (ExamType != TEST_TYPE_AREA) {
+//        wrong += 1000;
+//    }
 
     fault.wrong_id = wrong;
 
-    DEBUG("鑰冭瘯鍙戠敓閿欒 %d %s", wrong, fault.utc);
+    DEBUG("鑰冭瘯鍙戠敓閿欒 code = %d %s", wrong, fault.utc);
 
     ExamFaultList.push_back(fault);
 
@@ -1204,3 +1241,14 @@
 
     }
 }
+
+void SensorXChanged(uint16_t id, int value)
+{
+    handlePrepare(id, value);
+    handleLigthExam(id, value);
+}
+
+void PrepareOver(int res)
+{
+    exam_dummy_light = 2;
+}
diff --git a/lib/src/main/cpp/driver_test.h b/lib/src/main/cpp/driver_test.h
index a4e609e..878dafd 100644
--- a/lib/src/main/cpp/driver_test.h
+++ b/lib/src/main/cpp/driver_test.h
@@ -247,6 +247,14 @@
     int start_car_max_rpm;
     int start_car_limit_distance;
     double open_door_drive_allow_distance;
+
+    string prepare_tts;
+    string touch_leftfront_tts;
+    string touch_leftrear_tts;
+    string touch_rightfront_tts;
+    string touch_rightrear_tts;
+    string start_engine_tts;
+
     string start_car_begin_tts;
     string start_car_end_tts;
 
@@ -325,4 +333,6 @@
 
 int CorrectPauseCriteria(int src);
 
+void SensorXChanged(uint16_t id, int value);
+
 #endif //RTKDRIVERTEST_DRIVER_TEST_H
diff --git a/lib/src/main/cpp/master/comm_if.cpp b/lib/src/main/cpp/master/comm_if.cpp
index 1af9356..b1898f6 100644
--- a/lib/src/main/cpp/master/comm_if.cpp
+++ b/lib/src/main/cpp/master/comm_if.cpp
@@ -22,6 +22,7 @@
 #include <vector>
 #include <list>
 #include <semaphore.h>
+#include <unistd.h>
 
 #define DEBUG(fmt, args...)     LOGD("<comm_if> <%s>: " fmt, __func__, ##args)
 
@@ -74,6 +75,8 @@
 #define ID_SM_CAN_BRIEF         0x0021
 #define ID_SM_BLUETOOTH_BRIEF   0x0022
 
+#define ID_SM_RTK_STATUS_BRIEF  0x0023
+
 #define MA_OUT_GPS_BRIEF        0x0001
 #define MA_OUT_RTK_BRIEF        0x0002
 #define MA_OUT_CAR_BRIEF        0x0004
@@ -121,16 +124,26 @@
 
         if (MessageBuffer.size() > 0) {
             struct msg_2_main_t msg;
+            int success;
 
             pthread_mutex_lock(&msg_mutex);
             msg = MessageBuffer.back();
-            MessageBuffer.pop_back();
             pthread_mutex_unlock(&msg_mutex);
 
             if (msg.value.length() > 0)
-                SendMsgToMainProc(msg.cmd, msg.value.c_str());
+                success = SendMsgToMainProc(msg.cmd, msg.value.c_str());
             else
-                SendMsgToMainProc(msg.cmd, NULL);
+                success = SendMsgToMainProc(msg.cmd, NULL);
+
+            if (success == 0) {
+                pthread_mutex_lock(&msg_mutex);
+                MessageBuffer.pop_back();
+                pthread_mutex_unlock(&msg_mutex);
+            } else {
+                // 寤惰繜閲嶅彂
+                usleep(500000);
+                sem_post(&sem_msg_income);
+            }
         }
     }
 }
@@ -646,6 +659,7 @@
 {
     switch (cmd) {
         case ID_MS_RTK_PLAT_CFG: {
+            DEBUG("骞冲彴淇℃伅 %s", value);
             if (OnOff == 0) OnOff = MA_OUT_GPS_BRIEF + MA_OUT_RTK_BRIEF + MA_OUT_CAR_BRIEF;
 
             rtk_platform_cfg_t cfg;
@@ -1971,9 +1985,28 @@
                                 const Value &s2 = (*itr)["tts"];
 
                                 content[n].item = s1.GetInt();
-                                strcpy(content[n].tts, s2.GetString());
-                                n++;
+                                content[n].tts = s2.GetString();
                             }
+
+                            if (itr->HasMember("wrong_code")) {
+                                const Value &s = (*itr)["wrong_code"];
+
+                                content[n].wrongCode = s.GetInt();
+                            }
+
+                            if (itr->HasMember("process")) {
+                                const Value& s = doc["process"];
+                                for(Value::ConstValueIterator itr2 = s.Begin(); itr2 != s.End(); ++itr2) {
+                                    content[n].process.push_back(itr2->GetInt());
+                                }
+                            }
+                            if (itr->HasMember("solution")) {
+                                const Value& s = doc["solution"];
+                                for(Value::ConstValueIterator itr2 = s.Begin(); itr2 != s.End(); ++itr2) {
+                                    content[n].solution.push_back(itr2->GetInt());
+                                }
+                            }
+                            n++;
                         }
 
                         SetDummyLightExam(n, content);
@@ -2063,3 +2096,25 @@
 
     SendMsgToMainProcIndep(ID_SM_BLUETOOTH_BRIEF, sb.GetString());
 }
+
+void MA_SendRtkStatus(const char *model, int status)
+{
+    StringBuffer sb;
+    Writer<StringBuffer> writer(sb);
+
+    writer.StartObject();
+
+    writer.Key("model");
+    if (model == NULL || model[0] == 0) {
+        writer.String("Unknown");
+    } else {
+        writer.String(model);
+    }
+
+    writer.Key("status");
+    writer.Int(status);
+
+    writer.EndObject();
+
+    SendMsgToMainProcIndep(ID_SM_RTK_STATUS_BRIEF, sb.GetString());
+}
diff --git a/lib/src/main/cpp/master/comm_if.h b/lib/src/main/cpp/master/comm_if.h
index 4989c21..fd378ae 100644
--- a/lib/src/main/cpp/master/comm_if.h
+++ b/lib/src/main/cpp/master/comm_if.h
@@ -154,5 +154,6 @@
 void MA_SendCanStatus(const struct canBrief *brief);
 
 void MA_SendBlueStatus(const char *name, const char *addr, int status);
+void MA_SendRtkStatus(const char *type, int status);
 
 #endif //MYAPPLICATION2_COMM_IF_H
diff --git a/lib/src/main/cpp/mcu/mcu_if.cpp b/lib/src/main/cpp/mcu/mcu_if.cpp
index 080f233..b5924d6 100644
--- a/lib/src/main/cpp/mcu/mcu_if.cpp
+++ b/lib/src/main/cpp/mcu/mcu_if.cpp
@@ -14,6 +14,7 @@
 #include "../rtk_platform/platform.h"
 #include "../rtk_module/parse_gps.h"
 #include "../native-lib.h"
+#include "../rtk_module/virtual_rtk.h"
 
 #define DEBUG(fmt, args...)     LOGD("<mcu_if> <%s>: " fmt, __func__, ##args)
 
@@ -277,25 +278,29 @@
     WriteMcu(MCU_UART, buffer, x);
 }
 
-void ConfigMCU(void)
+void ConfigMCU(bool ayDevice)
 {
-    McuCommModeSel(1);
+    if (ayDevice) {
+        McuCommModeSel(0);
 
-    // TODO
-  /*  static struct serial_config serialConfig;
+        // TODO
+        static struct serial_config serialConfig;
 
-    strcpy(serialConfig.name, "/dev/ttyHSL1");
-    serialConfig.baud = 115200;
-    serialConfig.data_bit = 8;
-    serialConfig.verify_bit = 'N';
-    serialConfig.stop_bit = 1;
-    serialConfig.flow_ctrl = 0;
+        strcpy(serialConfig.name, "/dev/ttyHSL1");
+        serialConfig.baud = 115200;
+        serialConfig.data_bit = 8;
+        serialConfig.verify_bit = 'N';
+        serialConfig.stop_bit = 1;
+        serialConfig.flow_ctrl = 0;
 
-    pthread_t pid;
-    pthread_attr_t attr;
-    pthread_attr_init(&attr);
-    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);//detached
-    pthread_create(&pid, &attr, UartThread1, &serialConfig);*/
+        pthread_t pid;
+        pthread_attr_t attr;
+        pthread_attr_init(&attr);
+        pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);//detached
+        pthread_create(&pid, &attr, UartThread1, &serialConfig);
+    } else {
+        McuCommModeSel(1);
+    }
 }
 
 void SendRtkToMcu(const uint8_t *data, int length)
@@ -417,14 +422,29 @@
 
             memcpy(GnssBuf + GnssBufLen, data, length);
             GnssBufLen += length;
+
             if (GnssBufLen > 0) {
-                const uint8_t *ptr = parseGPS(GnssBuf, GnssBuf + GnssBufLen);
-                if (ptr != GnssBuf) {
-                    memcpy(GnssBuf, ptr, GnssBufLen - (ptr - GnssBuf));
-                    GnssBufLen -= ptr - GnssBuf;
-                } else if (GnssBufLen == PARSE_BUFF_SIZE) {        //濉弧浜嗭紝涓旀病鏈変竴涓猏r锛岄兘鎶涘純
-                    DEBUG("Parse GPS error");
+                if (VirtualIsConnected()) {     //PC妯℃嫙鐢ㄦ椂
+                    static bool first = false;
+
+                    if (!first) {
+                        first = true;
+
+                        uint8_t buff[33] = "emulator";
+                        buff[32] = 1;
+                        PlatformStatusChanged(RTK_STATUS_EVT, buff, 33);
+                    }
+
                     GnssBufLen = 0;
+                } else {
+                    const uint8_t *ptr = parseGPS(GnssBuf, GnssBuf + GnssBufLen);
+                    if (ptr != GnssBuf) {
+                        memcpy(GnssBuf, ptr, GnssBufLen - (ptr - GnssBuf));
+                        GnssBufLen -= ptr - GnssBuf;
+                    } else if (GnssBufLen == PARSE_BUFF_SIZE) {        //濉弧浜嗭紝涓旀病鏈変竴涓猏r锛岄兘鎶涘純
+                        DEBUG("Parse GPS error");
+                        GnssBufLen = 0;
+                    }
                 }
             }
             break;
diff --git a/lib/src/main/cpp/mcu/mcu_if.h b/lib/src/main/cpp/mcu/mcu_if.h
index 7f451b1..0ab43ab 100644
--- a/lib/src/main/cpp/mcu/mcu_if.h
+++ b/lib/src/main/cpp/mcu/mcu_if.h
@@ -8,7 +8,7 @@
 #include <cstdint>
 
 void McuCommModeSel(int mode);
-void ConfigMCU(void);
+void ConfigMCU(bool ayDevice);
 void SendRtkToMcu(const uint8_t *data, int length);
 void ParseMcuInit(void);
 void ParseMcu(const uint8_t *data, int length);
diff --git a/lib/src/main/cpp/native-lib.cpp b/lib/src/main/cpp/native-lib.cpp
index f0d0390..49d9e4e 100644
--- a/lib/src/main/cpp/native-lib.cpp
+++ b/lib/src/main/cpp/native-lib.cpp
@@ -35,8 +35,6 @@
 
 static int ttsSeq = 1;
 
-static void SendBootIndicate(union sigval sig);
-
 static std::map<int, void (*)(int)> TTSCallBack;
 
 int DESEncrypt(const uint8_t *key, int key_length,
@@ -173,25 +171,26 @@
     }
 }
 
-void SendMsgToMainProc(int cmd, const char *value)
+int SendMsgToMainProc(int cmd, const char *value)
 {
     JNIEnv *env;
     bool ready_in_java_env = false;
+    int ret;
 
     if (sg_jvm->GetEnv((void **)&env, JNI_VERSION_1_6) != JNI_OK) {
         // Attach涓荤嚎绋�
         if (sg_jvm->AttachCurrentThread(&env, NULL) != JNI_OK) {
             LOGE("%s: AttachCurrentThread() failed", __FUNCTION__);
-            return;
+            return -3;
         }
     } else {
         ready_in_java_env = true;
     }
 
     jclass cls = env->GetObjectClass(sg_obj);
-    jmethodID fun = env->GetMethodID(cls, "SendMsgToMainProc", "(ILjava/lang/String;)V");
+    jmethodID fun = env->GetMethodID(cls, "SendMsgToMainProc", "(ILjava/lang/String;)I");
 
-    env->CallVoidMethod(sg_obj, fun, cmd, value != NULL ? env->NewStringUTF(value) : NULL);
+    ret = env->CallIntMethod(sg_obj, fun, cmd, value != NULL ? env->NewStringUTF(value) : NULL);
 
     env->DeleteLocalRef(cls);
 
@@ -201,6 +200,8 @@
             LOGE("%s: DetachCurrentThread() failed", __FUNCTION__);
         }
     }
+
+    return ret;
 }
 
 static int GetTtsSeq(void)
@@ -384,7 +385,7 @@
 
 extern "C"
 JNIEXPORT void JNICALL
-Java_com_anyun_exam_lib_RemoteService_startNative(JNIEnv *env, jobject thiz) {
+Java_com_anyun_exam_lib_RemoteService_startNative(JNIEnv *env, jobject thiz, jboolean ayDevice) {
     // TODO: implement startNative()
     // 淇濆瓨鍏ㄥ眬JVM浠ヤ究鍦ㄥ瓙绾跨▼涓娇鐢�
     DEBUG("鍚姩Native");
@@ -395,28 +396,17 @@
     srand(time(NULL));
 
     AppTimer_Init();
-    ConfigMCU();
+    ConfigMCU(ayDevice);
     DriverTestInit();
-    ConfigRTKModule();
+    ConfigRTKModule(ayDevice);
     MA_Init();
-    InitPlatform(phone, RTK_PLATFORM_IP, RTK_PLATFORM_PORT);
-    AppTimer_add(SendBootIndicate, D_SEC(1));
+    InitPlatform(ayDevice, phone, RTK_PLATFORM_IP, RTK_PLATFORM_PORT);
 
     InitVirtualDevice(VIRTUAL_RTK_IP, VIRTUAL_RTK_PORT);
 
     pthread_mutex_init(&tts_mutex, NULL);
-}
 
-static void SendBootIndicate(union sigval sig) {
-    static int n = 0;
-    AppTimer_delete(SendBootIndicate);
     MA_NdkStart();
-
-    n++;
-
-    if (n < 3) {
-        AppTimer_add(SendBootIndicate, D_SEC(1));
-    }
 }
 
 extern "C"
diff --git a/lib/src/main/cpp/native-lib.h b/lib/src/main/cpp/native-lib.h
index 1ff9046..456f068 100644
--- a/lib/src/main/cpp/native-lib.h
+++ b/lib/src/main/cpp/native-lib.h
@@ -24,7 +24,7 @@
 
 void TextOsd(int type, const char *text);
 void DrawScreen(const Polygon *map, const Polygon *car);
-void SendMsgToMainProc(int cmd, const char *value);
+int SendMsgToMainProc(int cmd, const char *value);
 int PlayTTS(const char *string, void (*callback)(int));
 int PlayTTS(std::string &tts, void (*callback)(int));
 void PlayRing(void);
diff --git a/lib/src/main/cpp/rtk_module/rtk.cpp b/lib/src/main/cpp/rtk_module/rtk.cpp
index 244c0b3..82eab51 100644
--- a/lib/src/main/cpp/rtk_module/rtk.cpp
+++ b/lib/src/main/cpp/rtk_module/rtk.cpp
@@ -36,17 +36,24 @@
 const static char SAVECONFIG[] = "saveconfig\r\n";
 const static char *PJKITEMS[] = {"gptra", "ptnlpjk"};
 const static char *GPSITEMS[] = {"gpgga", "gprmc", "gpvtg"};
+const char CMD_VERSION[] = "log version\r\n";
 
 static gpsStatus_t gpsStatus;
+static char rtkModel[32] = {0};
 
 static int (*WriteRtk)(int id, const void *buf, int len);
 
 static rtk_info CurrRTKInfo;
 static bool needSetPjk = false;
+static int lostCnt;
 
 static void CheckPjkParam(void);
 static void CheckPjkParamTimeout(union sigval sig);
 static int WriteBluetooth(int id, const void *buf, int len);
+static void GetModuleVersion(void);
+
+static void VersionTimeout(union sigval sig);
+static void GpsDataTimeout(union sigval sig);
 
 static void *UartThread(void *p);
 
@@ -59,7 +66,7 @@
     }
 }
 
-void ConfigRTKModule(void)
+void ConfigRTKModule(bool ayDevice)
 {
     // TODO
     DEBUG("ConfigRTKModule");
@@ -70,26 +77,34 @@
     memset(&gpsStatus, 0, sizeof(gpsStatus));
     gpsStatus.hh = -1;
 
-    RtkCommModeSel(1);
+    if (ayDevice) {
+        RtkCommModeSel(0);
 
-    /*static struct serial_config serialConfig;
+        static struct serial_config serialConfig;
 
-    strcpy(serialConfig.name, "/dev/ttyHSL0");
-    serialConfig.baud = 115200;
-    serialConfig.data_bit = 8;
-    serialConfig.verify_bit = 'N';
-    serialConfig.stop_bit = 1;
-    serialConfig.flow_ctrl = 0;
+        strcpy(serialConfig.name, "/dev/ttyHSL0");
+        serialConfig.baud = 115200;
+        serialConfig.data_bit = 8;
+        serialConfig.verify_bit = 'N';
+        serialConfig.stop_bit = 1;
+        serialConfig.flow_ctrl = 0;
 
-    pthread_t pid;
-    pthread_attr_t attr;
-    pthread_attr_init(&attr);
-    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);//detached
-    pthread_create(&pid, &attr, UartThread, &serialConfig);*/
+        pthread_t pid;
+        pthread_attr_t attr;
+        pthread_attr_init(&attr);
+        pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);//detached
+        pthread_create(&pid, &attr, UartThread, &serialConfig);
+    } else {
+        RtkCommModeSel(1);
+        // 绛夊緟钃濈墮杩炴帴
+    }
 }
 
+// 钃濈墮杩炴帴鍚�
 void ConfigRTKModuleLater(void)
 {
+    AppTimer_delete(GpsDataTimeout);
+    AppTimer_delete(VersionTimeout);
     AppTimer_delete(CheckPjkParamTimeout);
     AppTimer_add(CheckPjkParamTimeout, D_SEC(1));
 }
@@ -107,59 +122,27 @@
 void handleRTKRebootComp(const struct nmea *s)
 {
     DEBUG("RTK Reboot complete!!");
-    CheckPjkParam();
+//    CheckPjkParam();
+    GetModuleVersion();
 }
 
 void handlePJKParam(const struct nmea *s) {
     DEBUG("handlePJKParam");
-//PJK Parameter: A:6378137.000, 1/F:298.257223563, B0:0.000000deg, L0:120.000000, N0:0.000, E0:500000.000.
-//PJK Parameter: A:6378137.000, 1/F:298.257223563, B0:29.512453deg, L0:106.455336, N0:0.000, E0:0.000.
-//    bool setparam = true;
-//
-//    const char DP1[] = "A:6378137.000";
-//    const char DP2[] = "1/F:298.257223563";
-//    const char DP3[] = "B0:29.512453deg";
-//    const char DP4[] = "L0:106.455336";
-//    const char DP5[] = "N0:0.000";
-//    const char DP6[] = "E0:0.000";
 
     AppTimer_delete(CheckPjkParamTimeout);
 
-//    for (int i = 0; i < s->nmea_num; ++i) {
-//        char out[64] = {0};
-//
-//        memcpy(out, s->nmea_value[i].data, s->nmea_value[i].length);
-//
-//        DEBUG("handlePJKParam = %s", out);
-//    }
-//
-//    if (s->nmea_num != 6) return;
-//
-//    if (memcmp(s->nmea_value[0].data, DP1, strlen(DP1))) {
-//        setparam = true;
-//    }
-//    if (memcmp(s->nmea_value[1].data, DP2, strlen(DP2))) {
-//        setparam = true;
-//    }
-//    if (memcmp(s->nmea_value[2].data, DP3, strlen(DP3))) {
-//        setparam = true;
-//    }
-//    if (memcmp(s->nmea_value[3].data, DP4, strlen(DP4))) {
-//        setparam = true;
-//    }
-//    if (memcmp(s->nmea_value[4].data, DP5, strlen(DP5))) {
-//        setparam = true;
-//    }
-//    if (memcmp(s->nmea_value[5].data, DP6, strlen(DP6))) {
-//        setparam = true;
-//    }
-//
-//    if (setparam) {
-//        SetAYFactoryParam(5);
-//    }
-
     SetAYFactoryParam(5);
     needSetPjk = true;
+
+    lostCnt = 0;
+    AppTimer_delete(GpsDataTimeout);
+    AppTimer_add(GpsDataTimeout, D_SEC(5));
+
+    uint8_t buff[33];
+
+    memcpy(buff, rtkModel, 32);
+    buff[32] = 1;
+    PlatformStatusChanged(RTK_STATUS_EVT, buff, 33);
 }
 
 void SetAYFactoryParam(int freq)
@@ -211,7 +194,8 @@
     int RxBufLen = 0;
 
     if (res == 0) {
-        CheckPjkParam();
+//        CheckPjkParam();
+        GetModuleVersion();
     }
 
     while (res == 0) {
@@ -240,6 +224,15 @@
         if (RxBufLen > 0) {
 #if 1
             if (VirtualIsConnected()) {     //PC妯℃嫙鐢ㄦ椂
+                static bool first = false;
+
+                if (!first) {
+                    first = true;
+
+                    uint8_t buff[33] = "emulator";
+                    buff[32] = 1;
+                    PlatformStatusChanged(RTK_STATUS_EVT, buff, 33);
+                }
                 RxBufLen = 0;
             } else {
                 const uint8_t *ptr = parseGPS(RxBuf, RxBuf + RxBufLen);
@@ -263,17 +256,41 @@
 }
 
 void handleUnrecognisedNMEA(const uint8_t *data, uint16_t length) {
-//    char buff[4096] = {0};
-//    memcpy(buff, data, MIN(length, 3000));
+    char buff[4096] = {0};
+    memcpy(buff, data, MIN(length, 4000));
 //    DEBUG("handleUnrecognisedNMEA: %s", buff);
+
+    if (length >= 100) {
+        string cs(buff);
+
+        if (cs.find("K708") != string::npos) {
+            // 鏈�鍒濈殑鏍囧噯鍩虹珯妯″潡
+            DEBUG("K708 妯″潡");
+            strcpy(rtkModel, "K708");
+
+            AppTimer_delete(VersionTimeout);
+            CheckPjkParam();
+        } else if (cs.find("K726") != string::npos) {
+            // 绉诲姩绔欐ā鍧楋紝涔熷彲浠ョ敤鍋氬熀绔欏姛鑳�
+            DEBUG("K726 妯″潡");
+            strcpy(rtkModel, "K726");
+
+            AppTimer_delete(VersionTimeout);
+            CheckPjkParam();
+        }
+    }
 }
 
 void handleGPGGA(const struct nmea *s)
 {
     static uint32_t qfCnt = 0;
 
-    DEBUG("handleGPGGA num = %d", s->nmea_num);
+//    DEBUG("handleGPGGA num = %d", s->nmea_num);
     if (s->nmea_num >= 10) {
+        lostCnt = 0;
+        AppTimer_delete(GpsDataTimeout);
+        AppTimer_add(GpsDataTimeout, D_SEC(5));
+
         gpsStatus.gps_status = str2int(s->nmea_value[5].data, s->nmea_value[5].length);
 
         int hh = str2int(s->nmea_value[0].data, 2);
@@ -331,7 +348,7 @@
 
 void handleGPRMC(const struct nmea *s)
 {
-    DEBUG("handleGPRMC num = %d", s->nmea_num);
+//    DEBUG("handleGPRMC num = %d", s->nmea_num);
 
     if (s->nmea_num >= 9) {
         int hh = str2int(s->nmea_value[0].data, 2);
@@ -397,7 +414,7 @@
 }
 
 void handlePJK(const struct nmea *s) {
-    DEBUG("handlePJK num = %d", s->nmea_num);
+//    DEBUG("handlePJK num = %d", s->nmea_num);
 
     int hh = str2int(s->nmea_value[0].data, 2);
     int mm = str2int(s->nmea_value[0].data + 2, 2);
@@ -457,7 +474,7 @@
 }
 
 void handleGPTRA(const struct nmea *s) {
-    DEBUG("handleGPTRA num = %d", s->nmea_num);
+//    DEBUG("handleGPTRA num = %d", s->nmea_num);
 
     int hh = str2int(s->nmea_value[0].data, 2);
     int mm = str2int(s->nmea_value[0].data + 2, 2);
@@ -491,8 +508,8 @@
 
 static void CheckPjkParam(void)
 {
-    int n = WriteRtk(RTK_MODULE_UART, INQ_PJK_PARAM, strlen(INQ_PJK_PARAM));
-    DEBUG("CN = %d", n);
+    WriteRtk(RTK_MODULE_UART, INQ_PJK_PARAM, strlen(INQ_PJK_PARAM));
+    DEBUG("鑾峰彇PJK鍙傛暟...");
     AppTimer_delete(CheckPjkParamTimeout);
     AppTimer_add(CheckPjkParamTimeout, D_SEC(3));
 }
@@ -500,11 +517,14 @@
 static void CheckPjkParamTimeout(union sigval sig) {
     AppTimer_delete(CheckPjkParamTimeout);
 
-    DEBUG("RTK Module failure!!");
+    DEBUG("鑾峰彇PJK鍙傛暟瓒呮椂");
 
-//    PlayTTS("RTK妯″潡鏃犳硶閫氳", NULL);
+    uint8_t buff[33];
+    memcpy(buff, rtkModel, 32);
+    buff[32] = 0;
+    PlatformStatusChanged(RTK_STATUS_EVT, buff, 33);
 
-    CheckPjkParam();
+    GetModuleVersion();
 }
 
 static int WriteBluetooth(int id, const void *buf, int len)
@@ -513,3 +533,36 @@
     SendMcuCommand(0x000B, (uint8_t *)buf, len);
     return len;
 }
+
+static void GetModuleVersion(void)
+{
+    AppTimer_delete(VersionTimeout);
+    AppTimer_add(VersionTimeout, D_SEC(3));
+    WriteRtk(RTK_MODULE_UART, CMD_VERSION, strlen(CMD_VERSION));
+
+    DEBUG("鑾峰彇鐗堟湰...");
+}
+
+static void VersionTimeout(union sigval sig)
+{
+    AppTimer_delete(VersionTimeout);
+    DEBUG("鐗堟湰鑾峰彇瓒呮椂");
+    GetModuleVersion();
+
+    uint8_t buff[33];
+    memcpy(buff, rtkModel, 32);
+    buff[32] = 0;
+    PlatformStatusChanged(RTK_STATUS_EVT, buff, 33);
+}
+
+static void GpsDataTimeout(union sigval sig)
+{
+    AppTimer_delete(GpsDataTimeout);
+
+    if (++lostCnt >= 3) {
+        DEBUG("RTK妯″潡鏀朵笉鍒癎PS鏁版嵁");
+        GetModuleVersion();
+    } else {
+        AppTimer_add(GpsDataTimeout, D_SEC(5));
+    }
+}
diff --git a/lib/src/main/cpp/rtk_module/rtk.h b/lib/src/main/cpp/rtk_module/rtk.h
index 3b81937..ae52e8d 100644
--- a/lib/src/main/cpp/rtk_module/rtk.h
+++ b/lib/src/main/cpp/rtk_module/rtk.h
@@ -40,7 +40,7 @@
 }rtk_info;
 
 void RtkCommModeSel(int mode);
-void ConfigRTKModule(void);
+void ConfigRTKModule(bool ayDevice);
 void ConfigRTKModuleLater(void);
 void FactorySettings(void);
 void RebootModule(void);
diff --git a/lib/src/main/cpp/rtk_module/virtual_rtk.cpp b/lib/src/main/cpp/rtk_module/virtual_rtk.cpp
index 83dee44..b0e62e5 100644
--- a/lib/src/main/cpp/rtk_module/virtual_rtk.cpp
+++ b/lib/src/main/cpp/rtk_module/virtual_rtk.cpp
@@ -86,7 +86,7 @@
         DEBUG("铏氭嫙骞冲彴杩炴帴鎴愬姛");
         virtRtkIsValid = true;
         connectCnt = 0;
-//        PlayTTS("妯℃嫙鍣ㄨ繛鎺�", NULL);
+        PlayTTS("妯℃嫙鍣ㄨ繛鎺�", NULL);
     } else {
         DEBUG("铏氭嫙骞冲彴杩炴帴澶辫触");
     }
@@ -110,7 +110,9 @@
                 break;
             } else if (lx > 0) {
                 RxBufLen += lx;
+
                 const uint8_t *ptr = parseGPS(RxBuf, RxBuf + RxBufLen);
+
                 if(ptr != RxBuf) {
                     memcpy(RxBuf, ptr, RxBufLen - (ptr - RxBuf));
                     RxBufLen -= ptr - RxBuf;
@@ -123,7 +125,9 @@
     }
 
     if (fd > 0) {
+        DEBUG("铏氭嫙骞冲彴鏂紑");
         DisconnectTCP(fd);
+        PlayTTS("妯℃嫙鍣ㄦ柇寮�", NULL);
     }
     virtRtkIsValid = false;
 
@@ -131,7 +135,7 @@
         AppTimer_add(ConnectLater, D_SEC(3));
     }
 
-//    PlayTTS("妯℃嫙鍣ㄦ柇寮�", NULL);
+    DEBUG("铏氭嫙骞冲彴绾跨▼閫�鍑�");
 
     pthread_exit(NULL);
 }
diff --git a/lib/src/main/cpp/rtk_platform/parse_net.cpp b/lib/src/main/cpp/rtk_platform/parse_net.cpp
index 09e2e1a..a82a7db 100644
--- a/lib/src/main/cpp/rtk_platform/parse_net.cpp
+++ b/lib/src/main/cpp/rtk_platform/parse_net.cpp
@@ -21,7 +21,7 @@
 
 #define DEBUG(fmt, args...)     LOGD("<parse_net> <%s>: " fmt, __func__, ##args)
 
-//#define ENABLE_DEBUG_PROTOCOL
+#define ENABLE_DEBUG_PROTOCOL
 
 using namespace std;
 
diff --git a/lib/src/main/cpp/rtk_platform/platform.cpp b/lib/src/main/cpp/rtk_platform/platform.cpp
index c42bdf7..1f28070 100644
--- a/lib/src/main/cpp/rtk_platform/platform.cpp
+++ b/lib/src/main/cpp/rtk_platform/platform.cpp
@@ -77,6 +77,8 @@
     struct event_queue_t *next;
 } *eventQueue;
 
+static bool mAyDevice = false;
+
 struct platformSocket exceptSocket, currSocket;
 static sem_t sem_status_changed;
 
@@ -113,6 +115,7 @@
 static void LoginPlatformTimeout(union sigval sig);
 static void TriggerHeartbeat(union sigval sig);
 static void RequestRtkNoResp(union sigval sig);
+
 
 static void AddEvnet(uint32_t event, const uint8_t *data, int length)
 {
@@ -181,9 +184,11 @@
         free(p1);
 }
 
-void InitPlatform(const uint8_t *phone, const char *domain_name, int port)
+void InitPlatform(bool ayDevice, const uint8_t *phone, const char *domain_name, int port)
 {
     DEBUG("InitPlatform");
+
+    mAyDevice = ayDevice;
 
     memset(&gbf, 0, sizeof(gbf));
     memset(&rbf, 0, sizeof(rbf));
@@ -264,7 +269,7 @@
     if (domain_name == NULL || strlen(domain_name) == 0 || port == 0)
         return;
 
-    DEBUG("ConnectPlatform %s: %d", domain_name, port);
+    DEBUG("杩炴帴RTK骞冲彴 %s: %d", domain_name, port);
     // TODO
     struct platformSocketInfo *ptr = (struct platformSocketInfo *)malloc(sizeof(struct platformSocketInfo));
 
@@ -299,334 +304,371 @@
 
 static void PlatformChangeEntry(uint32_t events, const uint8_t *data, int length)
 {
-    if (events & PLATFORM_CONNECT_EVT) {
-        DEBUG("骞冲彴杩炴帴鎴愬姛 %s:%d", currSocket.domain_name, currSocket.port);
-        MA_RtkPlatformConnect(1, currSocket.domain_name, currSocket.port);
+    switch (events) {
+        case PLATFORM_CONNECT_EVT: {
+            DEBUG("骞冲彴杩炴帴鎴愬姛 %s:%d", currSocket.domain_name, currSocket.port);
+            MA_RtkPlatformConnect(1, currSocket.domain_name, currSocket.port);
 
-        platformStatus.connected = 1;
-        if (!platformStatus.registed || platformStatus.platformKeyLength == 0) {
-            RegisterPlatform();
-        } else if (!platformStatus.login) {
-            LoginPlatform();
+            platformStatus.connected = 1;
+            if (!platformStatus.registed || platformStatus.platformKeyLength == 0) {
+                RegisterPlatform();
+            } else if (!platformStatus.login) {
+                LoginPlatform();
+            }
+
+            MA_SendBlueStatus("name", "00:1B:35:16:20:4A", 3);
+            break;
         }
-    }
 
-    if (events & PLATFORM_DISCONNECT_EVT) {
-        DEBUG("骞冲彴鏂紑 %s:%d", currSocket.domain_name, currSocket.port);
-        MA_RtkPlatformConnect(0, currSocket.domain_name, currSocket.port);
+        case PLATFORM_DISCONNECT_EVT: {
+            DEBUG("骞冲彴鏂紑 %s:%d", currSocket.domain_name, currSocket.port);
+            MA_RtkPlatformConnect(0, currSocket.domain_name, currSocket.port);
 
-        AppTimer_delete(ConnectPlatformLater);
-        AppTimer_add(ConnectPlatformLater, D_SEC(2));
+            AppTimer_delete(ConnectPlatformLater);
+            AppTimer_add(ConnectPlatformLater, D_SEC(2));
 
-        platformStatus.login = 0;
-        platformStatus.connected = 0;
+            platformStatus.login = 0;
+            platformStatus.connected = 0;
 
-        AppTimer_delete(TriggerHeartbeat);
-        AppTimer_delete(RegisterPlatformTimeout);
-        AppTimer_delete(LoginPlatformTimeout);
+            AppTimer_delete(TriggerHeartbeat);
+            AppTimer_delete(RegisterPlatformTimeout);
+            AppTimer_delete(LoginPlatformTimeout);
 
 //        PlayTTS("鍩哄噯婧愭柇寮�", NULL);
-    }
-    if (events & PLATFORM_REGISTER_EVT) {
-        DEBUG("PLATFORM_REGISTER_EVT");
-
-        platformStatus.login = 0;
-        if (data[0] == 0) {
-            platformStatus.registed = 1;
-            platformStatus.platformKeyLength = length - 1;
-            memcpy(platformStatus.platformKey, data+1, length-1);
-            LoginPlatform();
-        } else {
-            platformStatus.registed = 0;
+            break;
         }
-        MA_RtkPlatformRegister(data[0], data + 1, length - 1);
-    }
-    if (events & PLATFORM_LOGIN_EVT) {
-        DEBUG("PLATFORM_LOGIN_EVT");
+        case PLATFORM_REGISTER_EVT: {
+            DEBUG("骞冲彴娉ㄥ唽缁撴灉锛�%d", data[0]);
 
-        if (data[0] == 0) {
-            platformStatus.login = 1;
-            requestPlatformSendRtk = true;
-            AppTimer_delete(TriggerHeartbeat);
-            AppTimer_add(TriggerHeartbeat, D_SEC(30));
+            platformStatus.login = 0;
+            if (data[0] == 0) {
+                platformStatus.registed = 1;
+                platformStatus.platformKeyLength = length - 1;
+                memcpy(platformStatus.platformKey, data + 1, length - 1);
+                LoginPlatform();
+            } else {
+                platformStatus.registed = 0;
+            }
+            MA_RtkPlatformRegister(data[0], data + 1, length - 1);
+            break;
+        }
+        case PLATFORM_LOGIN_EVT: {
+            DEBUG("骞冲彴鐧诲綍缁撴灉锛�%d", data[0]);
+
+            if (data[0] == 0) {
+                platformStatus.login = 1;
+                requestPlatformSendRtk = true;
+                AppTimer_delete(TriggerHeartbeat);
+                AppTimer_add(TriggerHeartbeat, D_SEC(30));
 
 //            PlayTTS("鍩哄噯婧愬缓绔�", NULL);
-        } else {
-            platformStatus.login = 0;
+            } else {
+                platformStatus.login = 0;
+            }
+            MA_RtkPlatformLogin(data[0]);
+            break;
         }
-        MA_RtkPlatformLogin(data[0]);
-    }
-    if (events & GPS_UPDATE_EVT) {
-        DEBUG("GPS_UPDATE_EVT length %d", length);
-        const gpsStatus_t *gps = (gpsStatus_t *)data;
+        case GPS_UPDATE_EVT: {
+            const gpsStatus_t *gps = (gpsStatus_t *) data;
 
-        gbf.qf = gps->gps_status;
-        gbf.latitude = gps->latitude;
-        gbf.longitude = gps->longitude;
-        gbf.altitude = gps->altitude;
-        gbf.speed = gps->speed;
-        gbf.sat_num = gps->satNum;
-        gbf.trackTure = gps->trackTure;
-        sprintf(gbf.utc, "%04d%02d%02d%02d%02d%02d.%02d", 2000 + gps->YY, gps->MM, gps->DD, gps->hh, gps->mm, gps->ss, gps->mss);
-        if (!strcmp(rbf.utc, gbf.utc)) {
-            rbf.sat_num = gbf.sat_num;
-            rbf.latitude = gbf.latitude;
-            rbf.longitude = gbf.longitude;
-            rbf.altitude = gbf.altitude;
-            rbf.speed = gbf.speed;
-            rbf.trackTure = gbf.trackTure;
-            MA_SendRtkBrief(&rbf);
-        }
+            gbf.qf = gps->gps_status;
+            gbf.latitude = gps->latitude;
+            gbf.longitude = gps->longitude;
+            gbf.altitude = gps->altitude;
+            gbf.speed = gps->speed;
+            gbf.sat_num = gps->satNum;
+            gbf.trackTure = gps->trackTure;
+            sprintf(gbf.utc, "%04d%02d%02d%02d%02d%02d.%02d", 2000 + gps->YY, gps->MM, gps->DD,
+                    gps->hh, gps->mm, gps->ss, gps->mss);
+            if (!strcmp(rbf.utc, gbf.utc)) {
+                rbf.sat_num = gbf.sat_num;
+                rbf.latitude = gbf.latitude;
+                rbf.longitude = gbf.longitude;
+                rbf.altitude = gbf.altitude;
+                rbf.speed = gbf.speed;
+                rbf.trackTure = gbf.trackTure;
+                MA_SendRtkBrief(&rbf);
+            }
 //        MA_SendGpsBrief(&brief);
-        RequestRtkDownload(gps, 1);
-
-        DEBUG("GPS_UPDATE_EVT ================");
-    }
-    if (events & RTK_UPDATE_EVT) {
-        DEBUG("RTK_UPDATE_EVT length %d", length);
-
-//        uint32_t ost = AppTimer_GetTickCount();
-
-        const rtk_info *rtk = (rtk_info *)data;
-
-        rbf.qf = rtk->qf;
-        rbf.coord_x = rtk->y;
-        rbf.coord_y = rtk->x;
-        rbf.heading = rtk->heading;
-        rbf.pitch = rtk->pitch;
-        rbf.roll = rtk->roll;
-        rbf.coord_x_dir = 'N';
-        rbf.coord_y_dir = 'E';
-        sprintf(rbf.utc, "%04d%02d%02d%02d%02d%02d.%02d", 2000 + rtk->YY, rtk->MM, rtk->DD, rtk->hh, rtk->mm, rtk->ss, rtk->dss);
-        if (!strcmp(rbf.utc, gbf.utc)) {
-            rbf.sat_num = gbf.sat_num;
-            rbf.latitude = gbf.latitude;
-            rbf.longitude = gbf.longitude;
-            rbf.altitude = gbf.altitude;
-            rbf.speed = gbf.speed;
-            rbf.trackTure = gbf.trackTure;
-            MA_SendRtkBrief(&rbf);
+            RequestRtkDownload(gps, 1);
+            break;
         }
+        case RTK_UPDATE_EVT: {
+            uint32_t ost = AppTimer_GetTickCount();
+            uint32_t ost1 = ost;
 
-        UpdateRTKInfo(rtk);
+            const rtk_info *rtk = (rtk_info *) data;
 
-//        DEBUG("driver_test 璇勫垽鑰楁椂 %ld", AppTimer_GetTickCount() - ost);
+            rbf.qf = rtk->qf;
+            rbf.coord_x = rtk->y;
+            rbf.coord_y = rtk->x;
+            rbf.heading = rtk->heading;
+            rbf.pitch = rtk->pitch;
+            rbf.roll = rtk->roll;
+            rbf.coord_x_dir = 'N';
+            rbf.coord_y_dir = 'E';
+            sprintf(rbf.utc, "%04d%02d%02d%02d%02d%02d.%02d", 2000 + rtk->YY, rtk->MM, rtk->DD,
+                    rtk->hh, rtk->mm, rtk->ss, rtk->dss);
+            if (!strcmp(rbf.utc, gbf.utc)) {
+                rbf.sat_num = gbf.sat_num;
+                rbf.latitude = gbf.latitude;
+                rbf.longitude = gbf.longitude;
+                rbf.altitude = gbf.altitude;
+                rbf.speed = gbf.speed;
+                rbf.trackTure = gbf.trackTure;
+                MA_SendRtkBrief(&rbf);
+            }
 
-        DEBUG("RTK_UPDATE_EVT =================");
-    }
-    if (events & MCU_UPDATE_EVT) {
-        DEBUG("MCU_UPDATE_EVT length %d", length);
-        // 0-31 version
-        // 32-33 selftest
-        // 34-35 gpio
-        // 36-37 speed
-        // 38-39 engine
-        // 40-55 sn
-        struct mcuBrief brief;
+            ost1 = AppTimer_GetTickCount() - ost1;
 
-        memset(&brief, 0, sizeof(brief));
+            UpdateRTKInfo(rtk);
 
-        int x = 0;
-        while(data[x] != 0 && x < 32) x++;
+            ost = AppTimer_GetTickCount() - ost;
 
-        ConvertHex2String(brief.version, data, x);
-        brief.selftest = BUILD_UINT16(data[33], data[32]);
+            if (ost > 100)
+                DEBUG("driver_test 璇勫垽鑰楁椂 %ld %ld", ost1, ost);
+            break;
+        }
+        case RTK_STATUS_EVT: {
+            DEBUG("妯″潡淇℃伅 %02X %02X %02X %02X %02X %02X", data[0], data[1], data[2], data[3], data[4], data[5]);
+            if (length == 33)
+                MA_SendRtkStatus((char *)data, data[32]);
+            break;
+        }
+        case MCU_UPDATE_EVT: {
+            // 0-31 version
+            // 32-33 selftest
+            // 34-35 gpio
+            // 36-37 speed
+            // 38-39 engine
+            // 40-55 sn
+            struct mcuBrief brief;
+
+            memset(&brief, 0, sizeof(brief));
+
+            int x = 0;
+            while (data[x] != 0 && x < 32) x++;
+
+            ConvertHex2String(brief.version, data, x);
+            brief.selftest = BUILD_UINT16(data[33], data[32]);
 //        brief.gpio = BUILD_UINT16(data[35], data[34]);
 //        brief.speed = BUILD_UINT16(data[37], data[36]);
 //        brief.engine = BUILD_UINT16(data[39], data[38]);
 //        memcpy(brief.sn, data+40, 16);
-        memcpy(brief.sn, data+34, 16);
+            memcpy(brief.sn, data + 34, 16);
 
-        MA_SendMcuBrief(&brief);
+            MA_SendMcuBrief(&brief);
 
-        if (defaultMcuRom.more > 0) {
-            char str[64] = {0};
+            if (defaultMcuRom.more > 0) {
+                char str[64] = {0};
 
-            memcpy(str, data, 32);
+                memcpy(str, data, 32);
 
-            vector<string> ver = split(str, "_");
+                vector<string> ver = split(str, "_");
 
-            if (strlen(defaultMcuRom.verCode) > 0 && ver.size() >= 4 && strcmp(defaultMcuRom.verCode, ver[3].c_str()) != 0 && defaultMcuRom.rom != NULL) {
-                UploadDfuFile(defaultMcuRom.rom, defaultMcuRom.length);
-                delete []defaultMcuRom.rom;
-                defaultMcuRom.rom = NULL;
+                if (strlen(defaultMcuRom.verCode) > 0 && ver.size() >= 4 &&
+                    strcmp(defaultMcuRom.verCode, ver[3].c_str()) != 0 &&
+                    defaultMcuRom.rom != NULL) {
+                    UploadDfuFile(defaultMcuRom.rom, defaultMcuRom.length);
+                    delete[]defaultMcuRom.rom;
+                    defaultMcuRom.rom = NULL;
+                }
+                defaultMcuRom.more = 0;
             }
-            defaultMcuRom.more = 0;
-        }
 //        UpdateSensor(brief.gpio, brief.speed, brief.engine);
-    }
-    if (events & CAN_UPDATE_EVT) {
-        struct canBrief brief;
+            break;
+        }
+        case CAN_UPDATE_EVT: {
+            struct canBrief brief;
 
-        brief.gpio = BUILD_UINT16(data[1], data[0]);
-        brief.rpm = BUILD_UINT16(data[3], data[2]);
-        brief.speed = (double) BUILD_UINT16(data[5], data[4]) / 10.0;
-        brief.voltage = (double) BUILD_UINT16(data[7], data[6]) / 10.0;
+            brief.gpio = BUILD_UINT16(data[1], data[0]);
+            brief.rpm = BUILD_UINT16(data[3], data[2]);
+            brief.speed = (double) BUILD_UINT16(data[5], data[4]) / 10.0;
+            brief.voltage = (double) BUILD_UINT16(data[7], data[6]) / 10.0;
 
-        MA_SendCanStatus(&brief);
-    }
-    if (events & CAR_SENSOR_UPDATE_EVT) {
-        struct carSensorBrief brief;
-        int x = 20;
+            MA_SendCanStatus(&brief);
+            break;
+        }
+        case CAR_SENSOR_UPDATE_EVT: {
+            struct carSensorBrief brief;
+            int x = 20;
 
-        brief.odo = BUILD_UINT32(data[3], data[2], data[1], data[0]);
-        brief.trip = BUILD_UINT32(data[7], data[6], data[5], data[4]);
-        brief.tripTime = BUILD_UINT32(data[11], data[10], data[9], data[8]);
-        brief.cellVolt = ((double) BUILD_UINT16(data[13], data[12])) / 10.0;
-        brief.speed = ((double) BUILD_UINT16(data[15], data[14])) / 10.0;
-        brief.engine = BUILD_UINT16(data[17], data[16]);
-        brief.sas = (short)BUILD_UINT16(data[19], data[18]);
-        brief.key = data[x++];
-        brief.gear = data[x++];
-        brief.aps = data[x++];
-        brief.door = data[x++];
-        brief.seatBelt = data[x++];
-        brief.clutch = data[x++];
-        brief.horn = data[x++];
-        brief.wiper = data[x++];
-        brief.handBreak = data[x++];
-        brief.mainBreak = data[x++];
-        brief.leftTurnLamp = data[x++];
-        brief.rightTurnLamp = data[x++];
-        brief.clearanceLamp = data[x++];
-        brief.dippedBeamLamp = data[x++];
-        brief.mainBeamLamp = data[x++];
-        brief.fogLamp = data[x++];
-        brief.assBreak = data[x++];
-        brief.surround1 = data[x++];
-        brief.surround2 = data[x++];
-        brief.surround3 = data[x++];
-        brief.surround4 = data[x++];
+            brief.odo = BUILD_UINT32(data[3], data[2], data[1], data[0]);
+            brief.trip = BUILD_UINT32(data[7], data[6], data[5], data[4]);
+            brief.tripTime = BUILD_UINT32(data[11], data[10], data[9], data[8]);
+            brief.cellVolt = ((double) BUILD_UINT16(data[13], data[12])) / 10.0;
+            brief.speed = ((double) BUILD_UINT16(data[15], data[14])) / 10.0;
+            brief.engine = BUILD_UINT16(data[17], data[16]);
+            brief.sas = (short) BUILD_UINT16(data[19], data[18]);
+            brief.key = data[x++];
+            brief.gear = data[x++];
+            brief.aps = data[x++];
+            brief.door = data[x++];
+            brief.seatBelt = data[x++];
+            brief.clutch = data[x++];
+            brief.horn = data[x++];
+            brief.wiper = data[x++];
+            brief.handBreak = data[x++];
+            brief.mainBreak = data[x++];
+            brief.leftTurnLamp = data[x++];
+            brief.rightTurnLamp = data[x++];
+            brief.clearanceLamp = data[x++];
+            brief.dippedBeamLamp = data[x++];
+            brief.mainBeamLamp = data[x++];
+            brief.fogLamp = data[x++];
+            brief.assBreak = data[x++];
+            brief.surround1 = data[x++];
+            brief.surround2 = data[x++];
+            brief.surround3 = data[x++];
+            brief.surround4 = data[x++];
 
-        MA_SendCarSensorBrief(&brief);
+            MA_SendCarSensorBrief(&brief);
 
-        car_sensor_t sensor;
-        x = 20;
+            car_sensor_t sensor;
+            x = 20;
 
-        sensor.odo = BUILD_UINT32(data[3], data[2], data[1], data[0]);
-        sensor.trip = BUILD_UINT32(data[7], data[6], data[5], data[4]);
-        sensor.tripTime = BUILD_UINT32(data[11], data[10], data[9], data[8]);
-        sensor.cellVolt = (double)(BUILD_UINT16(data[13], data[12])) / 10.0;
-        sensor.speed = BUILD_UINT16(data[15], data[14]);
-        sensor.engine = BUILD_UINT16(data[17], data[16]);
-        sensor.sas = (short)BUILD_UINT16(data[19], data[18]);
-        sensor.key = data[x++];
-        sensor.gear = data[x++];
-        sensor.aps = data[x++];
-        sensor.door = data[x++];
-        sensor.seatBelt = data[x++];
-        sensor.clutch = data[x++];
-        sensor.horn = data[x++];
-        sensor.wiper = data[x++];
-        sensor.handBreak = data[x++];
-        sensor.mainBreak = data[x++];
-        sensor.leftTurnLamp = data[x++];
-        sensor.rightTurnLamp = data[x++];
-        sensor.clearanceLamp = data[x++];
-        sensor.dippedBeamLamp = data[x++];
-        sensor.mainBeamLamp = data[x++];
-        sensor.fogLamp = data[x++];
-        sensor.assBreak = data[x++];
-        sensor.surround1 = data[x++];
-        sensor.surround2 = data[x++];
-        sensor.surround3 = data[x++];
-        sensor.surround4 = data[x++];
+            sensor.odo = BUILD_UINT32(data[3], data[2], data[1], data[0]);
+            sensor.trip = BUILD_UINT32(data[7], data[6], data[5], data[4]);
+            sensor.tripTime = BUILD_UINT32(data[11], data[10], data[9], data[8]);
+            sensor.cellVolt = (double) (BUILD_UINT16(data[13], data[12])) / 10.0;
+            sensor.speed = BUILD_UINT16(data[15], data[14]);
+            sensor.engine = BUILD_UINT16(data[17], data[16]);
+            sensor.sas = (short) BUILD_UINT16(data[19], data[18]);
+            sensor.key = data[x++];
+            sensor.gear = data[x++];
+            sensor.aps = data[x++];
+            sensor.door = data[x++];
+            sensor.seatBelt = data[x++];
+            sensor.clutch = data[x++];
+            sensor.horn = data[x++];
+            sensor.wiper = data[x++];
+            sensor.handBreak = data[x++];
+            sensor.mainBreak = data[x++];
+            sensor.leftTurnLamp = data[x++];
+            sensor.rightTurnLamp = data[x++];
+            sensor.clearanceLamp = data[x++];
+            sensor.dippedBeamLamp = data[x++];
+            sensor.mainBeamLamp = data[x++];
+            sensor.fogLamp = data[x++];
+            sensor.assBreak = data[x++];
+            sensor.surround1 = data[x++];
+            sensor.surround2 = data[x++];
+            sensor.surround3 = data[x++];
+            sensor.surround4 = data[x++];
 
-        if (sensor.clutch == 1)
-            sensor.gear = 0;
+            if (sensor.clutch == 1)
+                sensor.gear = 0;
 
-        UpdateSensor(&sensor);
-    }
-    if (events & CARD_UPDATE_EVT) {
-        DEBUG("CARD_UPDATE_EVT length %d", length);
+            UpdateSensor(&sensor);
+            break;
+        }
+        case CARD_UPDATE_EVT: {
+            DEBUG("CARD_UPDATE_EVT length %d", length);
 
-        int ret = -1;
+            int ret = -1;
 
-        for (int i = 0; i < length; ++i) {
-            if (data[i] != 0) {
-                ret = 0;
-                break;
+            for (int i = 0; i < length; ++i) {
+                if (data[i] != 0) {
+                    ret = 0;
+                    break;
+                }
             }
+
+            struct cardBrief brief;
+
+            brief.result = ret;
+
+            ConvertHex2String(brief.card, data, length);
+
+            MA_SendCardBrief(&brief);
+            break;
         }
-
-        struct cardBrief brief;
-        
-        brief.result = ret;
-
-        ConvertHex2String(brief.card, data, length);
-
-        MA_SendCardBrief(&brief);
-    }
-    if (events & PLAY_TTS_DONE_EVT) {
-        tts_back_t *cb = (tts_back_t *) data;
-        if (cb->callback != NULL) {
-            cb->callback(cb->seq);
-        }
-    }
-    if (events & MASTER_COMM_EVT) {
-        union {
-            int a;
-            uint8_t b[sizeof(int)];
-        } c;
-
-        c.b[0] = data[0];
-        c.b[1] = data[1];
-        c.b[2] = data[2];
-        c.b[3] = data[3];
-
-        if (length == 4)
-            MA_MainProcMsgEntry(c.a, NULL);
-        else {
-            MA_MainProcMsgEntry(c.a, (char *) data + 4);
-        }
-    }
-    if (events & BLUETOOTH_STATUS_EVT) {
-        DEBUG("BLUETOOTH_STATUS_EVT");
-        uint8_t sta;
-
-        if (length == 128) {
-            MA_SendBlueStatus((char *)data, (char *)data+64, 3);
-            sta = 3;
-        } else if (length == 64) {
-            MA_SendBlueStatus(NULL, (char *)data, 3);
-            sta = 3;
-        } else {
-            MA_SendBlueStatus(NULL, NULL, data[0]);
-            sta = data[0];
-        }
-
-        if (sta == 3) {
-            // Connected
-            btConnected = true;
-            ParseMcuInit();
-            ConfigRTKModuleLater();
-
-            PlayTTS("钃濈墮杩炴帴", NULL);
-        } else if (sta == 2) {
-            // Disconnect
-            btConnected = false;
-            PlayTTS("钃濈墮鏂紑", NULL);
-        } else if (sta == 1) {
-            // Open
-            btEnable = true;
-
-            if (strlen(btAddr) > 0) {
-                ConnectToBluetooth(btAddr, NULL);
+        case PLAY_TTS_DONE_EVT: {
+            tts_back_t *cb = (tts_back_t *) data;
+            if (cb->callback != NULL) {
+                cb->callback(cb->seq);
             }
+            break;
+        }
+        case MASTER_COMM_EVT: {
+            union {
+                int a;
+                uint8_t b[sizeof(int)];
+            } c;
+
+            c.b[0] = data[0];
+            c.b[1] = data[1];
+            c.b[2] = data[2];
+            c.b[3] = data[3];
+
+            if (length == 4)
+                MA_MainProcMsgEntry(c.a, NULL);
+            else {
+                MA_MainProcMsgEntry(c.a, (char *) data + 4);
+            }
+            break;
+        }
+        case BLUETOOTH_STATUS_EVT: {
+            DEBUG("BLUETOOTH_STATUS_EVT");
+
+            if (!mAyDevice) {
+                uint8_t sta;
+
+                if (length == 128) {
+                    MA_SendBlueStatus((char *) data, (char *) data + 64, 3);
+                    sta = 3;
+                } else if (length == 64) {
+                    MA_SendBlueStatus(NULL, (char *) data, 3);
+                    sta = 3;
+                } else {
+                    MA_SendBlueStatus(NULL, NULL, data[0]);
+                    sta = data[0];
+                }
+
+                if (sta == 3) {
+                    // Connected
+                    btConnected = true;
+                    ParseMcuInit();
+                    ConfigRTKModuleLater();
+
+                    PlayTTS("钃濈墮杩炴帴", NULL);
+                } else if (sta == 2) {
+                    // Disconnect
+                    if (btConnected) {
+                        btConnected = false;
+                        PlayTTS("钃濈墮鏂紑", NULL);
+                    }
+                } else if (sta == 1) {
+                    // Open
+                    btEnable = true;
+
+                    if (strlen(btAddr) > 0) {
+                        ConnectToBluetooth(btAddr, NULL);
+                    }
 //            ConnectToBluetooth("00:1B:35:16:20:4A", NULL);
 //            ConnectToBluetooth("00:1B:35:16:20:4A", "3800");``
 //            ConnectToBluetooth("00:1D:43:9A:E0:79", "1900");
 //            ConnectToBluetooth("DESKTOP-IE9V7U8", "0000");
-            PlayTTS("钃濈墮鍚姩", NULL);
-        } else {
-            // Close
-            btEnable = false;
-            btConnected = false;
-            PlayTTS("钃濈墮鍏抽棴", NULL);
+                    PlayTTS("钃濈墮鍚姩", NULL);
+                } else {
+                    // Close
+                    btEnable = false;
+                    btConnected = false;
+                    PlayTTS("钃濈墮鍏抽棴", NULL);
+                }
+            }
+            break;
         }
-    }
-    if (events & BLUETOOTH_DATA_EVT) {
-        ParseMcu(data, length);
+        case BLUETOOTH_DATA_EVT: {
+            ParseMcu(data, length);
+            break;
+        }
+        case SENSOR_CHANGE_EVT: {
+            SensorXChanged(BUILD_UINT16(data[1], data[0]), BUILD_UINT32(data[5], data[4], data[3], data[2]));
+            break;
+        }
+        default:
+            break;
     }
 }
 
@@ -706,13 +748,14 @@
 
 static void RegisterPlatformTimeout(union sigval sig)
 {
-    DEBUG("RegisterPlatformTimeout");
+    DEBUG("RTK骞冲彴娉ㄥ唽瓒呮椂");
     AppTimer_delete(RegisterPlatformTimeout);
     RegisterPlatform();
 }
 
 static void RegisterPlatform(void)
 {
+    DEBUG("RTK骞冲彴娉ㄥ唽...");
     AppTimer_delete(RegisterPlatformTimeout);
     AppTimer_add(RegisterPlatformTimeout, D_SEC(15));
     SendDeviceRegister(deviceInfo.province, deviceInfo.city, deviceInfo.device_model,
@@ -730,12 +773,14 @@
 
 static void LoginPlatformTimeout(union sigval sig)
 {
+    DEBUG("RTK骞冲彴鐧诲綍瓒呮椂");
     AppTimer_delete(LoginPlatformTimeout);
     LoginPlatform();
 }
 
 static void LoginPlatform(void)
 {
+    DEBUG("RTK骞冲彴鐧诲綍...");
     uint32_t tim = time(NULL);
     uint8_t data[12];
     uint8_t *ciphertext;
@@ -748,6 +793,7 @@
     AppTimer_delete(LoginPlatformTimeout);
     AppTimer_add(LoginPlatformTimeout, D_SEC(15));
 
+
     DESEncrypt(platformStatus.platformKey, platformStatus.platformKeyLength, data, 4, &ciphertext);
 
     if (ciphertext != NULL) {
diff --git a/lib/src/main/cpp/rtk_platform/platform.h b/lib/src/main/cpp/rtk_platform/platform.h
index 8e88ffe..5c2136f 100644
--- a/lib/src/main/cpp/rtk_platform/platform.h
+++ b/lib/src/main/cpp/rtk_platform/platform.h
@@ -7,20 +7,24 @@
 
 #include "../rtk_module/rtk.h"
 
-#define PLATFORM_CONNECT_EVT                         0x0001
-#define PLATFORM_DISCONNECT_EVT                      0x0002
-#define PLATFORM_REGISTER_EVT                        0x0004
-#define PLATFORM_LOGIN_EVT                           0x0008
-#define RTK_UPDATE_EVT                               0x0010
-#define GPS_UPDATE_EVT                              0x0020
-#define MCU_UPDATE_EVT                              0x0040
-#define CARD_UPDATE_EVT                             0x0080
-#define PLAY_TTS_DONE_EVT                           0x0100
-#define CAR_SENSOR_UPDATE_EVT                       0x0200
-#define MASTER_COMM_EVT                             0x0400
-#define CAN_UPDATE_EVT                              0x0800
-#define BLUETOOTH_DATA_EVT                          0x1000
-#define BLUETOOTH_STATUS_EVT                        0x2000
+enum {
+    PLATFORM_CONNECT_EVT,
+    PLATFORM_DISCONNECT_EVT,
+    PLATFORM_REGISTER_EVT,
+    PLATFORM_LOGIN_EVT,
+    RTK_UPDATE_EVT,
+    RTK_STATUS_EVT,
+    GPS_UPDATE_EVT,
+    MCU_UPDATE_EVT,
+    CARD_UPDATE_EVT,
+    PLAY_TTS_DONE_EVT,
+    CAR_SENSOR_UPDATE_EVT,
+    MASTER_COMM_EVT,
+    CAN_UPDATE_EVT,
+    BLUETOOTH_DATA_EVT,
+    BLUETOOTH_STATUS_EVT,
+    SENSOR_CHANGE_EVT
+};
 
 typedef struct {
     char domain_name[32];
@@ -36,7 +40,7 @@
     int rtk_interval;
 } rtk_platform_cfg_t;
 
-void InitPlatform(const uint8_t *phone, const char *domain_name, int port);
+void InitPlatform(bool ayDevice, const uint8_t *phone, const char *domain_name, int port);
 void ConfigPlatform(const rtk_platform_cfg_t *p);
 
 void PlatformStatusChanged(uint32_t event, const uint8_t *data, int length);
diff --git a/lib/src/main/cpp/test_common/car_sensor.cpp b/lib/src/main/cpp/test_common/car_sensor.cpp
index 5e98de8..8caa027 100644
--- a/lib/src/main/cpp/test_common/car_sensor.cpp
+++ b/lib/src/main/cpp/test_common/car_sensor.cpp
@@ -8,6 +8,7 @@
 #include "../defs.h"
 #include "../common/apptimer.h"
 #include "../jni_log.h"
+#include "../rtk_platform/platform.h"
 
 #define DEBUG(fmt, args...)     LOGD("<car_sensor> <%s>: " fmt, __func__, ##args)
 
@@ -229,6 +230,19 @@
     pthread_mutex_lock(&status_rw_mutex);
     CarStatus[id] = value;
     pthread_mutex_unlock(&status_rw_mutex);
+
+    if (id != OBD_SPEED && id != ENGINE_RPM) {
+        uint8_t buffer[6];
+
+        buffer[0] = HI_UINT16(id);
+        buffer[1] = LO_UINT16(id);
+        buffer[2] = BREAK_UINT32(value, 3);
+        buffer[3] = BREAK_UINT32(value, 2);
+        buffer[4] = BREAK_UINT32(value, 1);
+        buffer[5] = BREAK_UINT32(value, 0);
+
+        PlatformStatusChanged(SENSOR_CHANGE_EVT, buffer, 6);
+    }
 }
 
 static void LRLightTimeout(union sigval sig)
@@ -267,7 +281,6 @@
 static void SensorChanged(int id, int value)
 {
 //    DEBUG("鐘舵�佹敼鍙� %d = %d", id, value);
-
     switch (id) {
         case SENSOR_LEFT_TURN_SIGNAL: {
             left_turn_signal = value;
@@ -432,7 +445,7 @@
 //            break;
 //        }
         default:
-            break;
+            return;
     }
 }
 
diff --git a/lib/src/main/cpp/test_items/driving_curve.cpp b/lib/src/main/cpp/test_items/driving_curve.cpp
index dd3bcc9..447ef11 100644
--- a/lib/src/main/cpp/test_items/driving_curve.cpp
+++ b/lib/src/main/cpp/test_items/driving_curve.cpp
@@ -105,7 +105,7 @@
         if (!crashRedLine) {
             crashRedLine = true;
             // 杞﹁疆鍘嬭竟绾匡紝涓嶅悎鏍�
-            AddExamFault(27, rtkTime);
+            AddExamFault(20601, rtkTime);
             DEBUG("杞﹁疆鍘嬭竟绾�");
             if (who == 1) {
                 PlayTTS("鍘嬪乏鏇茬嚎", NULL);
@@ -132,7 +132,7 @@
 
         if (tp - stopTimepoint >= CorrectPauseCriteria(examParam.curve_pause_criteria) && !reportStopCarTimeout) {
             // 鍋滆溅瓒�2绉掞紝涓嶅悎鏍�
-            AddExamFault(28, rtkTime);
+            AddExamFault(20602, rtkTime);
             DEBUG("涓�斿仠杞�");
             reportStopCarTimeout = true;
         }
diff --git a/lib/src/main/cpp/test_items/park_bottom.cpp b/lib/src/main/cpp/test_items/park_bottom.cpp
index 261e425..12e80fc 100644
--- a/lib/src/main/cpp/test_items/park_bottom.cpp
+++ b/lib/src/main/cpp/test_items/park_bottom.cpp
@@ -85,7 +85,7 @@
         if ((parkStatus[0] != 1 || parkStatus[1] != 1) && !reportParkFail && reverseCar) {
             // 鍊掑簱涓嶅叆锛屼笉鍚堟牸
             reportParkFail = true;
-            AddExamFault(8, rtkTime);
+            AddExamFault(20103, rtkTime);
             DEBUG("鍊掑簱涓嶅叆");
         }
         goto TEST_END;
@@ -111,7 +111,7 @@
         if (!occurCrashRedLine && reverseCar) {
             occurCrashRedLine = true;
             // 杞﹁韩鍑虹嚎锛屼笉鍚堟牸
-            AddExamFault(7, rtkTime);
+            AddExamFault(10116, rtkTime);
             DEBUG("杞﹁疆鍘嬬嚎");
             if (who == 1) {
                 PlayTTS("鍘嬪乏搴撲綅绾�", NULL);
@@ -131,14 +131,14 @@
         } else if (parkCount == 1) {
             if (carray[0] == crossCtrlLine) {
                 // 涓嶆寜瑙勫畾绾胯矾锛岄『搴忓舰寮忥紝涓嶅悎鏍�
-                AddExamFault(6, rtkTime);
+                AddExamFault(20101, rtkTime);
                 DEBUG("涓嶆寜瑙勫畾绾胯矾锛岄『搴忓舰寮�");
             }
             carray[1] = crossCtrlLine;
         } else if (parkCount == 2) {
             if (carray[0] != crossCtrlLine) {
                 // 涓嶆寜瑙勫畾绾胯矾锛岄『搴忓舰寮忥紝涓嶅悎鏍�
-                AddExamFault(6, rtkTime);
+                AddExamFault(20101, rtkTime);
                 DEBUG("涓嶆寜瑙勫畾绾胯矾锛岄『搴忓舰寮�");
             } else {
                 // 绂诲紑娴嬭瘯鍖猴紝鍋滄璁℃椂
@@ -154,7 +154,7 @@
         // 瀹屾垚瓒呮椂锛屼笉鍚堟牸
         if (!reportExamTimeout) {
             reportExamTimeout = true;
-            AddExamFault(10, rtkTime);
+            AddExamFault(20105, rtkTime);
             DEBUG("椤圭洰瓒呮椂");
         }
     }
@@ -177,7 +177,7 @@
                 // 鍚屾柟鍚戝啀鍚姩锛岀户缁垽鏂槸鍚﹀仠杞﹁秴鏃�
                 if (tp - stopTimepoint >= CorrectPauseCriteria(examParam.park_bottom_pause_criteria) && reverseCar) {
                     // 鍋滆溅瓒�2绉掞紝姣忔鎵�5鍒�
-                    AddExamFault(11, rtkTime);
+                    AddExamFault(20106, rtkTime);
                     DEBUG("涓�斿仠杞�");
                 }
             } else if (moveDirect == -1) {
@@ -189,7 +189,7 @@
                 if (darray[parkCount] == 0) {
                     if (!crossCtrlLineSw) {
                         // 鍊掕溅鍓嶏紝鍓嶈疆鏈┒杩囨帶鍒剁嚎
-                        AddExamFault(9, rtkTime);
+                        AddExamFault(20104, rtkTime);
                         DEBUG("鍊掕溅鍓嶏紝鍓嶈疆鏈┒杩囨帶鍒剁嚎");
                     }
                     darray[parkCount] = 1;
@@ -204,7 +204,7 @@
                         if (parkStatus[parkCount] != 1) {
                             // 鍊掑簱涓嶅叆锛屼笉鍚堟牸
                             reportParkFail = true;
-                            AddExamFault(8, rtkTime);
+                            AddExamFault(20103, rtkTime);
                             DEBUG("鍊掑簱涓嶅叆");
                         }
                     }
@@ -222,7 +222,7 @@
             // 鍒囨崲涓哄�掕溅
             if (!crossCtrlLineSw) {
                 // 鍊掕溅鍓嶏紝鍓嶈疆鏈┒杩囨帶鍒剁嚎
-                AddExamFault(9, rtkTime);
+                AddExamFault(20104, rtkTime);
                 DEBUG("鍊掕溅鍓嶏紝鍓嶈疆鏈┒杩囨帶鍒剁嚎");
             }
             darray[parkCount] = 1;
diff --git a/lib/src/main/cpp/test_items/park_edge.cpp b/lib/src/main/cpp/test_items/park_edge.cpp
index 8b33d8b..e7b9366 100644
--- a/lib/src/main/cpp/test_items/park_edge.cpp
+++ b/lib/src/main/cpp/test_items/park_edge.cpp
@@ -71,7 +71,7 @@
     if (CrashRedLine1(map, car)) {
         if (!occurCrashRedLine1 && occurMoveBack) {
             // 杞﹁疆鍘嬭竟绾匡紝姣忔鎵�10鍒�
-            AddExamFault(23, rtkTime);
+            AddExamFault(20403, rtkTime);
             DEBUG("杞﹁疆鍘嬭竟绾�");
             occurCrashRedLine1 = true;
         }
@@ -82,7 +82,7 @@
     if (CrashRedLine2(map, car)) {
         if (!occurCrashRedLine2 && occurMoveBack) {
             // 杞﹁韩鍘嬪簱浣嶇嚎锛屾瘡娆℃墸10鍒�
-            AddExamFault(24, rtkTime);
+            AddExamFault(20404, rtkTime);
             DEBUG("杞﹁韩鍘嬪簱浣嶇嚎");
             occurCrashRedLine2 = true;
         }
@@ -93,9 +93,9 @@
     if (ExitParkArea(map, car) || ExitParkArea2(map, car)) {
         if (!parkSuccess && occurMoveBack && !reportParkFail) {
             // 鐩存帴椹剁娴嬭瘯鍖猴紝璁や负绉诲簱涓嶅叆
-            AddExamFault(21, rtkTime);
+            AddExamFault(10103, rtkTime);
             reportParkFail = true;
-            DEBUG("鐩存帴椹剁娴嬭瘯鍖�,绉诲簱涓嶅叆");
+            DEBUG("鐩存帴椹剁娴嬭瘯鍖�,涓嶆寜鑰冭瘯鍛樻寚浠ら┚椹�");
         }
         testing = false;
         goto TEST_END;
@@ -122,7 +122,7 @@
 
         if (!reportExamTimeout && tp - moveBackTimePoint >= examParam.park_edge_limit_time) {
             // 瓒呮椂90绉掞紝涓嶅悎鏍�
-            AddExamFault(22, rtkTime);
+            AddExamFault(20402, rtkTime);
             reportExamTimeout = true;
             DEBUG("绉诲簱90绉掕秴鏃�");
         }
@@ -145,7 +145,7 @@
                 // 鍚屾柟鍚戝啀鍚姩锛岀户缁垽鏂槸鍚﹀仠杞﹁秴鏃�
                 if (tp - stopTimepoint >= CorrectPauseCriteria(examParam.park_edge_pause_criteria) && occurMoveBack) {
                     // 鍋滆溅瓒�2绉掞紝姣忔鎵�5鍒�
-                    AddExamFault(26, rtkTime);
+                    AddExamFault(20406, rtkTime);
                     DEBUG("鍋滆溅瓒呮椂");
                 }
             } else {
@@ -160,7 +160,7 @@
 
                     if (!parkSuccess && !reportParkFail) {
                         // 鍋滄鍚庯紝杞﹁韩鍑虹嚎锛屼笉鍚堟牸
-                        AddExamFault(21, rtkTime);
+                        AddExamFault(20401, rtkTime);
                         reportParkFail = true;
                         DEBUG("绉诲簱涓嶅叆");
                     }
@@ -168,7 +168,7 @@
                     // 鍦ㄨ繖閲屾鏌ヨ浆鍚戠伅鐘舵��
                     if (ReadCarStatus(TURN_SIGNAL_LAMP) != LEFT_TURN_LIGHT) {
                         // 涓嶅紑杞悜鐏紝鎵�10鍒�
-                        AddExamFault(25, rtkTime);
+                        AddExamFault(20405, rtkTime);
                         DEBUG("鏈紑鍚浆鍚戠伅");
                     }
                 }
diff --git a/lib/src/main/cpp/test_items/stop_and_start.cpp b/lib/src/main/cpp/test_items/stop_and_start.cpp
index 477884b..47690a2 100644
--- a/lib/src/main/cpp/test_items/stop_and_start.cpp
+++ b/lib/src/main/cpp/test_items/stop_and_start.cpp
@@ -71,7 +71,7 @@
     if (CrashRedLine(map, car)) {
         // 杞﹁疆鍘嬬嚎锛屼笉鍚堟牸
         if (!occurCrashRedLine) {
-            AddExamFault(13, rtkTime);
+            AddExamFault(10116, rtkTime);
             DEBUG("杞﹁疆鍘嬬嚎");
         }
         occurCrashRedLine = true;
@@ -102,7 +102,7 @@
         } else if (stopCar && !handBreakActive) {
             // 妫�鏌ユ槸鍚︽媺浣忔墜鍒�
             handBreakActive = true;
-            AddExamFault(19, rtkTime);
+            AddExamFault(20306, rtkTime);
             DEBUG("娌℃媺鎵嬪埞");
         }
         prevMoveDirect = moveDirect;
@@ -123,21 +123,21 @@
 
             if (dis1 > examParam.ramp_stoppoint_red_distance) {
                 // 璺濈鍋滄绾垮墠鍚庤秴鍑�50鍘樼背
-                AddExamFault(12, rtkTime);
+                AddExamFault(20301, rtkTime);
                 DEBUG("璺濈鍋滄绾垮墠鍚庤秴鍑�50鍘樼背锛屼笉鍚堟牸");
             } else if (fabs(dis1) > EPSILON) {
                 // 鍓嶄繚闄╂病鏈変綅浜庡仠姝㈠甫鍐咃紝浣嗘病鏈夎秴鍑�50鍘樼背锛屾墸10鍒�
-                AddExamFault(17, rtkTime);
+                AddExamFault(20304, rtkTime);
                 DEBUG("鍓嶄繚闄╂病鏈変綅浜庡仠姝㈠甫鍐咃紝浣嗘病鏈夎秴鍑�50鍘樼背");
             }
 
             if (dis2 > examParam.ramp_edge_red_distance) {
                 // 璺濈杈圭嚎瓒呭嚭50鍘樼背,涓嶅悎鏍�
-                AddExamFault(14, rtkTime);
+                AddExamFault(20302, rtkTime);
                 DEBUG("璺濈杈圭嚎瓒呭嚭50鍘樼背");
             } else if (dis2 > examParam.ramp_edge_yellow_distance) {
                 // 璺濈杈圭嚎瓒呭嚭30鍘樼背锛屾墸10鍒�
-                AddExamFault(18, rtkTime);
+                AddExamFault(20305, rtkTime);
                 DEBUG("璺濈杈圭嚎瓒呭嚭30鍘樼背");
             }
         }
@@ -159,7 +159,7 @@
 
             if (slideDistance > examParam.ramp_slide_red_distance && !slideLongDistance && !reportSlideFault) {
                 // 鍚庢粦瓒呰繃30鍘樼背, 涓嶅悎鏍�
-                AddExamFault(16, rtkTime);
+                AddExamFault(10106, rtkTime);
                 DEBUG("鍚庢粦瓒呰繃30鍘樼背");
                 slideLongDistance = true;
                 reportSlideFault = true;
@@ -171,7 +171,7 @@
                 DistanceOf(stopPoint, car->carXY[car->axial[AXIAL_FRONT]]) < 0.1)) {
             if (TimeMakeComposite(rtkTime->hh, rtkTime->mm, rtkTime->ss, rtkTime->mss*10) - stopCarTime > examParam.ramp_start_car_limit_time) {
                 // 璧锋鏃堕棿瓒呰繃30绉掞紝涓嶅悎鏍�
-                AddExamFault(15, rtkTime);
+                AddExamFault(20303, rtkTime);
                 DEBUG("璧锋鏃堕棿瓒呰繃30绉�");
                 reportStartTimeout = true;
             }
@@ -182,7 +182,7 @@
             if (slideNormalDistance && !slideLongDistance && !reportSlideFault) {
                 reportSlideFault = true;
                 // 鍚庢粦瓒呰繃10鍘樼背锛屼絾娌¤秴杩�30鍘樼背
-                AddExamFault(20, rtkTime);
+                AddExamFault(10204, rtkTime);
                 DEBUG("鍚庢粦瓒呰繃10鍘樼背锛屼絾娌¤秴杩�30鍘樼背");
             }
         }
diff --git a/lib/src/main/cpp/test_items/turn_a90.cpp b/lib/src/main/cpp/test_items/turn_a90.cpp
index a9443d7..e9f97f8 100644
--- a/lib/src/main/cpp/test_items/turn_a90.cpp
+++ b/lib/src/main/cpp/test_items/turn_a90.cpp
@@ -79,7 +79,7 @@
         if (!crashRedLine) {
             crashRedLine = true;
             // 纰惧帇閬撹矾杈圭紭,涓嶅悎鏍�
-            AddExamFault(29, rtkTime);
+            AddExamFault(20701, rtkTime);
             DEBUG("纰惧帇閬撹矾杈圭紭");
         }
     } else {
@@ -101,7 +101,7 @@
 
         if (tp - stopTimepoint >= CorrectPauseCriteria(examParam.turn_a90_pause_criteria) && !reportStopCarTimeout) {
             // 鍋滆溅瓒�2绉掞紝姣忔鎵�5鍒�
-            AddExamFault(31, rtkTime);
+            AddExamFault(20703, rtkTime);
             DEBUG("涓�斿仠杞�");
             reportStopCarTimeout = true;
         }
@@ -128,7 +128,7 @@
             if ((turn_direct == 'R' && ReadCarStatus(TURN_SIGNAL_LAMP) != RIGHT_TURN_LIGHT) ||
                     (turn_direct == 'L' && ReadCarStatus(TURN_SIGNAL_LAMP) != LEFT_TURN_LIGHT)) {
                 DEBUG("杞悜鐏湭寮�鍚�");
-                AddExamFault(30, rtkTime);
+                AddExamFault(20702, rtkTime);
             }
         }
         turnLeftFinished = true;
diff --git a/lib/src/main/cpp/test_items2/car_start.cpp b/lib/src/main/cpp/test_items2/car_start.cpp
index fdc3a59..31410f5 100644
--- a/lib/src/main/cpp/test_items2/car_start.cpp
+++ b/lib/src/main/cpp/test_items2/car_start.cpp
@@ -48,11 +48,11 @@
             if (sensor.value != LEFT_TURN_LIGHT) {
                 DEBUG("鍙樿皟鏈墦鐏�!!");
                 // 娌℃墦鐏紝涓嶅悎鏍�
-                AddExamFault(13, rtkTime);
+                AddExamFault(30121, rtkTime);
             } else if (TimeGetDiff(rtkTime, &sensor.time) < D_SEC(3)) {
                 DEBUG("杞悜鐏椂闂翠笉瓒�");
                 // 涓嶈冻3绉掞紝涓嶅悎鏍�
-                AddExamFault(14, rtkTime);
+                AddExamFault(30122, rtkTime);
             }
         }
     }
@@ -63,11 +63,11 @@
         if (sensor.name == HAND_BREAK && sensor.value == BREAK_ACTIVE) {
             DEBUG("Handbreak active move over 10m");
             // 鎵嬪埞鎷夎捣鐘舵�佷笅锛岃椹朵簡10绫充互涓婏紝涓嶅悎鏍�
-            AddExamFault(25, rtkTime);
+            AddExamFault(40205, rtkTime);
         } else if (handBreakActive) {
             // 鎵嬪埞鎷夎捣鐘舵�佷笅锛岃椹朵簡1绫充互涓婏紝鎵�10鍒�
             DEBUG("Handbreak active move over 1M");
-            AddExamFault(26, rtkTime);
+            AddExamFault(40206, rtkTime);
         }
 
         PlayTTS(examParam.start_car_end_tts, NULL);
@@ -82,7 +82,7 @@
             if (sensor.name == DOOR && sensor.value == DOOR_OPEN) {
                 // 杞﹂棬鏈畬鍏ㄥ叧闂紝涓嶅悎鏍�
                 DEBUG("杞﹂棬鏈叧闂�");
-                AddExamFault(23, rtkTime);
+                AddExamFault(40202, rtkTime);
             }
 
             sensor = ReadCarSensorValue(HAND_BREAK);
@@ -95,7 +95,7 @@
     if (ReadCarStatus(ENGINE_RPM) > examParam.start_car_max_rpm && !checkEngineRPM) {
         // 杞�熻秴鏍囷紝涓嶅悎鏍�
         DEBUG("杞�熻秴鏍�");
-        AddExamFault(29, rtkTime);
+        AddExamFault(40210, rtkTime);
         checkEngineRPM = true;
     }
 
diff --git a/lib/src/main/cpp/test_items2/change_lane.cpp b/lib/src/main/cpp/test_items2/change_lane.cpp
index 80053ac..c9f305c 100644
--- a/lib/src/main/cpp/test_items2/change_lane.cpp
+++ b/lib/src/main/cpp/test_items2/change_lane.cpp
@@ -43,7 +43,7 @@
     if (ReadOdo() - maxMoveDistance > examParam.change_lane_limit_distance) {
         // 瓒呰溅鏈畬鎴�
         DEBUG("鍙橀亾鍥哄畾璺濈鍐呮湭瀹屾垚 褰撳墠閲岀▼ %f", ReadOdo());
-        AddExamFault(3, rtkTime);
+        AddExamFault(30103, rtkTime);
         return false;
     }
 
diff --git a/lib/src/main/cpp/test_items2/drive_straight.cpp b/lib/src/main/cpp/test_items2/drive_straight.cpp
index 44d120a..21156f2 100644
--- a/lib/src/main/cpp/test_items2/drive_straight.cpp
+++ b/lib/src/main/cpp/test_items2/drive_straight.cpp
@@ -80,7 +80,7 @@
         if (fabs(offset2 - offsetBase) > examParam.straight_max_offset) {
             DEBUG("鐩寸嚎鍋忕Щ澶т簬30鍘樼背 offset2 = %f", fabs(offset2 - offsetBase));
             // 鍋忕Щ澶т簬30鍘樼背锛屼笉鍚堟牸
-            AddExamFault(30, rtkTime);
+            AddExamFault(40301, rtkTime);
             return false;
         }
     }
diff --git a/lib/src/main/cpp/test_items2/dummy_light.cpp b/lib/src/main/cpp/test_items2/dummy_light.cpp
index dcb3d09..144b545 100644
--- a/lib/src/main/cpp/test_items2/dummy_light.cpp
+++ b/lib/src/main/cpp/test_items2/dummy_light.cpp
@@ -11,206 +11,123 @@
 
 #define DEBUG(fmt, args...)     LOGD("<road_exam dummy_light> <%s>: " fmt, __func__, ##args)
 
-enum {
-    TTS_NOT_START,
-    TTS_DOING,
-    TTS_DONE,
-    WAIT_OPERATE,
-    CHECK_OPERATE
-};
-
 static struct RtkTime currRtkTime;
 static struct dummy_light_exam *content;
 static int contentNum;
 
-static int checkCnt;
-static bool turn_left_active, flash_beam_active;
+static int question;
 
-static int examTtsSeq = 0;
+static vector<int> process;
+
 static bool testing;
 
-static void DummyLightCheckActive(union sigval sig);
-static void ExamDummyLight(union sigval sig);
+static void CheckSolution(union sigval sig);
+static void ExamDummyLight(void);
 
 void StartDummyLightExam(struct dummy_light_exam *ptr, int num, const struct RtkTime* rtkTime)
 {
     DEBUG("StartDummyLightExam");
     content = ptr;
     contentNum = num;
+    question = 0;
 
     if (content != NULL && num > 0) {
         DEBUG("鍚姩鐏厜");
         currRtkTime = *rtkTime;
 
         for (int i = 0; i < contentNum; ++i) {
-            content[i].itemStatus = TTS_NOT_START;
-
-            DEBUG("鐏厜椤圭洰 <%d> item %d, TTS %s", i, content[i].item, content[i].tts);
+            DEBUG("鐏厜椤圭洰 <%d> item %d, TTS %s", i, content[i].item, content[i].tts.c_str());
         }
         testing = true;
 
-        AppTimer_delete(DummyLightCheckActive);
-        AppTimer_delete(ExamDummyLight);
-        AppTimer_add(ExamDummyLight, D_SEC(2));
+        AppTimer_delete(CheckSolution);
+        ExamDummyLight();
     } else {
         testing = false;
     }
 }
 
-int ExecuteDummyLightExam(const struct RtkTime* rtkTime)
+bool ExecuteDummyLightExam(const struct RtkTime* rtkTime)
 {
     currRtkTime = *rtkTime;
-    return (testing)?1:2;
+    return testing;
 }
 
 void DummyLightTTSDone(int id)
 {
     // 绛夎闊虫挱鎶ュ畬姣曞悗璁℃椂
-    if (id == examTtsSeq && testing) {
+    if (testing) {
+        vector<int>().swap(process);
 
-        for (int i = 0; i < contentNum; ++i) {
-            if (content[i].itemStatus == TTS_DOING) {
-                DEBUG("DummyLightTTSDone item %d", content[i].item);
-                content[i].itemStatus = TTS_DONE;
-                break;
+        // 棰勮鍙栨湁涓棿鎿嶄綔姝ラ鐨勭伅鍏�
+        for (int i = 0; i < content[question].process.size(); ++i) {
+            if (ReadCarStatus((content[question].process[i]>>8) & 0xFF) == content[question].process[i] & 0xFF) {
+                process.push_back(content[question].process[i]);
             }
         }
 
-        AppTimer_add(ExamDummyLight, 100);
+        AppTimer_delete(CheckSolution);
+        AppTimer_add(CheckSolution, D_SEC(5));
     }
 }
 
 void TerminateDummyLightExam(void)
 {
     testing = false;
-    AppTimer_delete(DummyLightCheckActive);
-    AppTimer_delete(ExamDummyLight);
+    AppTimer_delete(CheckSolution);
 }
 
-static void DummyLightCheckActive(union sigval sig)
+void handleLigthExam(uint16_t id, int value)
 {
-    int active = sig.sival_int;
-    AppTimer_delete(DummyLightCheckActive);
-    DEBUG("DummyLightCheckActive item = %d", active);
+    if (testing) {
+        for (int i = 0; i < content[question].process.size(); ++i) {
+            if (id == ((content[question].process[i] >> 8) & 0xFF) && value == (content[question].process[i] & 0xFF)) {
+                if (process.size() == 0 || process.back() != content[question].process[i]) {
+                    process.push_back(content[question].process[i]);
+                }
+            }
+        }
+    }
+}
 
-    switch (active) {
-        case DRIVE_AT_NIGHT:
-        case TURN_ON_MAIN_BEAM_LAMP:
-            if (ReadCarStatus(MAIN_BEAM_LAMP) != MAIN_BEAM_LIGHT) {
-                AddExamFault(58, &currRtkTime);
-            }
-            break;
-        case TURN_ON_DIPPED_LAMP:
-        case BRIDGE_MEET_CAR:
-        case FOLLOW_CAR:
-            if (ReadCarStatus(DIPPED_BEAM_LAMP) != DIPPED_BEAM_LIGHT) {
-                AddExamFault(58, &currRtkTime);
-            }
-            break;
-        case DRIVE_IN_FOG:
-            if (ReadCarStatus(FOG_LAMP) != FOG_LIGHT) {
-                AddExamFault(58, &currRtkTime);
-            }
-            break;
-        case THROUGE_CROSSWALK:
-        case THROUGE_CURVE:
-        case THROUGE_CROSSROADS:
-            if (++checkCnt < 5) {
-                if (ReadCarStatus(FLASH_BEAM_LAMP) == FLASH_BEAM_LIGHT) {
-                    flash_beam_active = true;
-                }
-                AppTimer_add(DummyLightCheckActive, D_SEC(1), active);
-                return;
-            } else {
-                if (!flash_beam_active) {
-                    AddExamFault(58, &currRtkTime);
+static void CheckSolution(union sigval sig)
+{
+    int question = sig.sival_int;
+
+    AppTimer_delete(CheckSolution);
+
+    if (content[question].process.size() > 0) {
+        if (content[question].process.size() != process.size()) {
+            AddExamFault(content[question].wrongCode, &currRtkTime);
+            goto NEXT_LIGHT;
+        } else {
+            // 鎿嶄綔椤哄簭涔熻婊¤冻
+            for (int i = 0; i < content[question].process.size(); ++i) {
+                if (process[i] != content[question].process[i]) {
+                    AddExamFault(content[question].wrongCode, &currRtkTime);
+                    goto NEXT_LIGHT;
                 }
             }
-            break;
-        case OVERTAKE:
-            if (++checkCnt < 5) {
-                if (!flash_beam_active) {
-                    if (ReadCarStatus(TURN_SIGNAL_LAMP) == LEFT_TURN_LIGHT) {
-                        turn_left_active = true;
-                    }
-                }
-                if (turn_left_active) {
-                    if (ReadCarStatus(FLASH_BEAM_LAMP) == FLASH_BEAM_LIGHT) {
-                        flash_beam_active = true;
-                    }
-                }
-                AppTimer_add(DummyLightCheckActive, D_SEC(1), OVERTAKE);
-                return;
-            } else {
-                if (!flash_beam_active || !turn_left_active) {
-                    AddExamFault(58, &currRtkTime);
-                }
-            }
-            break;
-        case CAR_FAULT:
-        case PARK_CAR_TEMP:
-            if (ReadCarStatus(TURN_SIGNAL_LAMP) != HAZARD_LIGHTS) {
-                AddExamFault(58, &currRtkTime);
-            }
-            break;
-        default:
-            break;
+        }
     }
 
-    for (int i = 0; i < contentNum; ++i) {
-        if (content[i].item == active) {
-            content[i].itemStatus = CHECK_OPERATE;
+    for (int i = 0; i < content[question].solution.size(); ++i) {
+        if (ReadCarStatus((content[question].solution[i]>>8)&0xFF) != content[question].solution[i] & 0xFF) {
+            AddExamFault(content[question].wrongCode, &currRtkTime);
             break;
         }
     }
 
-    AppTimer_add(ExamDummyLight, 500);
+NEXT_LIGHT:
+    question++;
+    ExamDummyLight();
 }
 
-static void ExamDummyLight(union sigval sig)
+static void ExamDummyLight(void)
 {
-    int i = 0;
-    AppTimer_delete(ExamDummyLight);
-
-    for (; i < contentNum; ++i) {
-        switch (content[i].itemStatus) {
-            case TTS_NOT_START:
-                DEBUG("鎻愮ず璇█ %d: %s", content[i].item, content[i].tts);
-                content[i].itemStatus = TTS_DOING;
-                examTtsSeq = PlayTTS(content[i].tts, DummyLightTTSDone);
-                // 绛夊緟TTS鎾斁瀹屾瘯
-                return;
-            case TTS_DOING:
-                return;
-            case TTS_DONE:
-                content[i].itemStatus = WAIT_OPERATE;
-
-                AppTimer_delete(DummyLightCheckActive);
-
-                DEBUG("鎻愮ず璇█瀹屾瘯 %d", content[i].item);
-
-                if (content[i].item == OVERTAKE) {
-                    checkCnt = 0;
-                    turn_left_active = flash_beam_active = false;
-                    AppTimer_add(DummyLightCheckActive, D_SEC(1), content[i].item);
-                } else if (content[i].item == THROUGE_CROSSWALK || content[i].item == THROUGE_CURVE || content[i].item == THROUGE_CROSSROADS) {
-                    checkCnt = 0;
-                    flash_beam_active = false;
-                    AppTimer_add(DummyLightCheckActive, D_SEC(1), content[i].item);
-                } else if (content[i].item >= 100)
-                    AppTimer_add(DummyLightCheckActive, D_SEC(3), content[i].item);
-                else
-                    AppTimer_add(DummyLightCheckActive, D_SEC(5), content[i].item);
-                return;
-            case WAIT_OPERATE:
-                return;
-            case CHECK_OPERATE:
-            default:
-                break;
-        }
-    }
-
-    if (i >= contentNum) {
+    if (testing && question < contentNum) {
+        PlayTTS(content[question].tts, DummyLightTTSDone);
+    } else {
         testing = false;
     }
 }
diff --git a/lib/src/main/cpp/test_items2/dummy_light.h b/lib/src/main/cpp/test_items2/dummy_light.h
index 40a5cf8..129a0f1 100644
--- a/lib/src/main/cpp/test_items2/dummy_light.h
+++ b/lib/src/main/cpp/test_items2/dummy_light.h
@@ -6,6 +6,8 @@
 #define MYAPPLICATION2_DUMMY_LIGHT_H
 
 #include "../driver_test.h"
+#include <vector>
+#include <string>
 
 enum {
     TURN_ON_DIPPED_LAMP = 1,
@@ -24,13 +26,16 @@
 
 struct dummy_light_exam {
     int item;
-    int itemStatus;
-    char tts[512];
+    int wrongCode;
+    std::vector<int> process;
+    std::vector<int> solution;
+    std::string tts;
 };
 
 void StartDummyLightExam(struct dummy_light_exam *ptr, int num, const struct RtkTime* rtkTime);
-int ExecuteDummyLightExam(const struct RtkTime* rtkTime);
+bool ExecuteDummyLightExam(const struct RtkTime* rtkTime);
 void DummyLightTTSDone(int id);
 void TerminateDummyLightExam(void);
+void handleLigthExam(uint16_t id, int value);
 
 #endif //MYAPPLICATION2_DUMMY_LIGHT_H
diff --git a/lib/src/main/cpp/test_items2/operate_gear.cpp b/lib/src/main/cpp/test_items2/operate_gear.cpp
index c403d17..f9e9fba 100644
--- a/lib/src/main/cpp/test_items2/operate_gear.cpp
+++ b/lib/src/main/cpp/test_items2/operate_gear.cpp
@@ -94,7 +94,7 @@
         } else if (sensor.value != expectGear) {
             // 鏈寜鎸囦护鎿嶄綔鎸′綅锛屼笉鍚堟牸
             DEBUG("棣栨鎹㈡尅閿欒 GEAR %d  甯屾湜 %d", sensor.value, expectGear);
-            AddExamFault(31, rtkTime);
+            AddExamFault(40401, rtkTime);
             return false;
         } else {
             // 鍦ㄦ鎸′綅琛岄┒涓�瀹氳窛绂伙紝鍐嶆墽琛屼笅涓�涓�
@@ -121,7 +121,7 @@
         } else if (sensor.value != expectGear) {
             // 鏈寜鎸囦护鎿嶄綔鎸′綅锛屼笉鍚堟牸
             DEBUG("浜屾鎹㈡尅閿欒 GEAR %d  甯屾湜 %d", sensor.value, expectGear);
-            AddExamFault(31, rtkTime);
+            AddExamFault(40401, rtkTime);
             return false;
         } else {
             // 鍦ㄦ鎸′綅琛岄┒涓�瀹氳窛绂伙紝鍐嶆墽琛屼笅涓�涓�
@@ -140,7 +140,7 @@
     if (ReadOdo() - maxMoveDistance > 120) {
         // 鏈寜鎸囦护鎿嶄綔鎸′綅锛屼笉鍚堟牸
         DEBUG("鏈寜鎸囦护鎿嶄綔鎸′綅锛岃秴鏃�");
-        AddExamFault(31, rtkTime);
+        AddExamFault(40401, rtkTime);
         return false;
     }
 
diff --git a/lib/src/main/cpp/test_items2/overtake.cpp b/lib/src/main/cpp/test_items2/overtake.cpp
index 7f9d29b..74a7b97 100644
--- a/lib/src/main/cpp/test_items2/overtake.cpp
+++ b/lib/src/main/cpp/test_items2/overtake.cpp
@@ -44,7 +44,7 @@
             originalLane = currLane;
         } else {
             DEBUG("鍙充晶瓒呰溅");
-            AddExamFault(3, rtkTime);
+            AddExamFault(30103, rtkTime);
             return false;
         }
     } else if (setup == 2) {
@@ -55,7 +55,7 @@
             return false;
         } else {
             DEBUG("瓒呰溅杩濊鍙橀亾");
-            AddExamFault(3, rtkTime);
+            AddExamFault(30103, rtkTime);
             return false;
         }
     }
@@ -63,7 +63,7 @@
     if (ReadOdo() - maxMoveDistance > examParam.overtake_limit_distance) {
         // 瓒呰溅鏈畬鎴�
         DEBUG("瓒呰溅鍥哄畾璺濈鍐呮湭瀹屾垚 褰撳墠閲岀▼ %f", ReadOdo());
-        AddExamFault(3, rtkTime);
+        AddExamFault(30103, rtkTime);
         return false;
     }
 
diff --git a/lib/src/main/cpp/test_items2/prepare.cpp b/lib/src/main/cpp/test_items2/prepare.cpp
new file mode 100644
index 0000000..79fec6c
--- /dev/null
+++ b/lib/src/main/cpp/test_items2/prepare.cpp
@@ -0,0 +1,100 @@
+//
+// Created by YY on 2020/12/16.
+//
+
+#include "prepare.h"
+#include "../native-lib.h"
+#include "../driver_test.h"
+#include "../test_common/car_sensor.h"
+#include "../common/apptimer.h"
+#include "../jni_log.h"
+
+#define DEBUG(fmt, args...)     LOGD("<prepare> <%s>: " fmt, __func__, ##args)
+
+static int touch[4];
+static int hint_cnt;
+static bool exec = false;
+
+static void TtsBack(int seq);
+static void PrepareTimeout(union sigval sig);
+static void PrepareTimeout2(union sigval sig);
+void StartPrepare(void)
+{
+    exec = true;
+    hint_cnt = 0;
+    memset(touch, 0, sizeof(touch));
+    PlayTTS(examParam.prepare_tts, TtsBack);
+    DEBUG("寮�濮嬩笂杞﹀噯澶�");
+}
+
+void handlePrepare(uint16_t sensor_id, int value)
+{
+    if (!exec)
+        return;
+    if (sensor_id == SEATBELT) {
+        if (value == INSERT_SEATBELT) {
+            AppTimer_delete(PrepareTimeout);
+            // 妫�鏌ョ粫杞︿紶鎰熷櫒鎯呭喌
+            if (touch[0] + touch[1] + touch[2] + touch[3] != 4) {
+                exec = false;
+                PrepareOver(-1);
+            } else {
+                exec = false;
+                PrepareOver(0);
+            }
+        } else {
+            // 瀹夊叏甯﹁В寮�
+            AppTimer_delete(PrepareTimeout2);
+        }
+    }
+
+    if (sensor_id == SURROUND_CAR_1 && value == SURROUND_CAR_ACTIVE && touch[0] != 1) {
+        touch[0] = 1;
+        PlayTTS(examParam.touch_leftfront_tts, NULL);
+        DEBUG("瑙︽懜浼犳劅鍣�1");
+    }
+    if (sensor_id == SURROUND_CAR_2 && value == SURROUND_CAR_ACTIVE && touch[1] != 1) {
+        touch[1] = 1;
+        PlayTTS(examParam.touch_leftrear_tts, NULL);
+        DEBUG("瑙︽懜浼犳劅鍣�2");
+    }
+    if (sensor_id == SURROUND_CAR_3 && value == SURROUND_CAR_ACTIVE && touch[2] != 1) {
+        touch[2] = 1;
+        PlayTTS(examParam.touch_rightrear_tts, NULL);
+        DEBUG("瑙︽懜浼犳劅鍣�3");
+    }
+    if (sensor_id == SURROUND_CAR_4 && value == SURROUND_CAR_ACTIVE && touch[3] != 1) {
+        touch[3] = 1;
+        PlayTTS(examParam.touch_rightfront_tts, NULL);
+        DEBUG("瑙︽懜浼犳劅鍣�4");
+    }
+}
+
+static void TtsBack(int seq)
+{
+    if (hint_cnt == 0) {
+        if (ReadCarStatus(SEATBELT) == INSERT_SEATBELT) {
+            // 鍐嶆鎻愮ず
+            AppTimer_add(PrepareTimeout2, D_SEC(10));
+            DEBUG("璁剧疆鍐嶆鎻愰啋");
+        }
+        AppTimer_add(PrepareTimeout, D_MIN(2));
+        DEBUG("璁剧疆2鍒嗛挓瓒呮椂");
+    }
+    hint_cnt++;
+}
+
+static void PrepareTimeout(union sigval sig)
+{
+    DEBUG("涓婅溅鍑嗗瓒呮椂");
+    AppTimer_delete(PrepareTimeout);
+    exec = false;
+    PrepareOver(-2);
+}
+
+static void PrepareTimeout2(union sigval sig)
+{
+    AppTimer_delete(PrepareTimeout2);
+
+    PlayTTS(examParam.prepare_tts, TtsBack);
+}
diff --git a/lib/src/main/cpp/test_items2/prepare.h b/lib/src/main/cpp/test_items2/prepare.h
new file mode 100644
index 0000000..538a015
--- /dev/null
+++ b/lib/src/main/cpp/test_items2/prepare.h
@@ -0,0 +1,14 @@
+//
+// Created by YY on 2020/12/16.
+//
+
+#ifndef MYAPPLICATION2_PREPARE_H
+#define MYAPPLICATION2_PREPARE_H
+
+#include <cstdint>
+
+void StartPrepare(void);
+void handlePrepare(uint16_t sensor_id, int value);
+void PrepareOver(int res);
+
+#endif //MYAPPLICATION2_PREPARE_H
diff --git a/lib/src/main/cpp/test_items2/road_exam.cpp b/lib/src/main/cpp/test_items2/road_exam.cpp
index 22102d0..166cbc3 100644
--- a/lib/src/main/cpp/test_items2/road_exam.cpp
+++ b/lib/src/main/cpp/test_items2/road_exam.cpp
@@ -859,17 +859,17 @@
     if (newLineType >= 100) {
         newLineType -= 100;
         DEBUG("闈炴硶璺ㄨ秺鍒嗛亾绾�");
-        AddExamFault(11, rtkTime);
+        AddExamFault(30119, rtkTime);
     }
     if (newLineType == LINE_SOLID && CrashLineType != LINE_SOLID) {
         // 杞﹁締琛岄┒涓獞杞ц溅閬撲腑蹇冨疄绾挎垨鑰呰溅閬撹竟缂樺疄绾匡紝涓嶅悎鏍�
         DEBUG("鎾為亾璺竟缂樼嚎");
-        AddExamFault(11, rtkTime);
+        AddExamFault(30119, rtkTime);
     }
     if (newLineType == LINE_BOUNDARY && CrashLineType != LINE_BOUNDARY) {
         // 杞﹁締瓒婄晫锛岄�冭窇浜嗭紝涓嶅悎鏍�
         DEBUG("杞﹁締瓒婄晫");
-        AddExamFault(3, rtkTime);
+        AddExamFault(30103, rtkTime);
     }
 
     if (newLineType == LINE_DOTTED || newLineType == LINE_HALF_SOLID_LEFT || newLineType == LINE_HALF_SOLID_RIGHT) {
@@ -896,7 +896,7 @@
                     DEBUG("闀挎椂闂村帇铏氱嚎");
                     checkCrashGreenTimeout = 2;
                     // 闀挎椂闂撮獞杞ц溅閬撳垎鐣岀嚎琛岄┒锛屼笉鍚堟牸
-                    AddExamFault(12, rtkTime);
+                    AddExamFault(30120, rtkTime);
                 }
             }
         } else {
@@ -935,7 +935,7 @@
                 if (turnSignalStatus.value != LEFT_TURN_LIGHT) {
                     DEBUG("鍙樿皟鏈墦鐏�!!");
                     // 娌℃墦鐏紝涓嶅悎鏍�
-                    AddExamFault(13, rtkTime);
+                    AddExamFault(30121, rtkTime);
                 } else if (TimeGetDiff(&crashGreenStartTime, &turnSignalStatus.time) <
                            examParam.turn_signal_min_advance) {
                     DEBUG("杞悜鐏椂闂翠笉瓒� %02d-%02d-%02d %02d:%02d:%02d.%03d  -> %02d-%02d-%02d %02d:%02d:%02d.%03d",
@@ -946,13 +946,13 @@
                           turnSignalStatus.time.mm, turnSignalStatus.time.ss, turnSignalStatus.time.mss * 10);
 
                     // 涓嶈冻3绉掞紝涓嶅悎鏍�
-                    AddExamFault(14, rtkTime);
+                    AddExamFault(30122, rtkTime);
                 }
             } else {
                 if (turnSignalStatus.value != RIGHT_TURN_LIGHT) {
                     DEBUG("鍙樿皟鏈墦鐏�!!");
                     // 娌℃墦鐏紝涓嶅悎鏍�
-                    AddExamFault(13, rtkTime);
+                    AddExamFault(30121, rtkTime);
                 } else if (TimeGetDiff(&crashGreenStartTime, &turnSignalStatus.time) <
                         examParam.turn_signal_min_advance) {
                     DEBUG("杞悜鐏椂闂翠笉瓒� %02d-%02d-%02d %02d:%02d:%02d.%03d  -> %02d-%02d-%02d %02d:%02d:%02d.%03d",
@@ -962,13 +962,13 @@
                           turnSignalStatus.time.YY, turnSignalStatus.time.MM, turnSignalStatus.time.DD, turnSignalStatus.time.hh,
                           turnSignalStatus.time.mm, turnSignalStatus.time.ss, turnSignalStatus.time.mss * 10);
                     // 涓嶈冻3绉掞紝涓嶅悎鏍�
-                    AddExamFault(14, rtkTime);
+                    AddExamFault(30122, rtkTime);
                 }
             }
 
             if (((ChangeLane.gain < 0 && gain < 0) || (ChangeLane.gain > 0 && gain > 0)) && TimeGetDiff(rtkTime, &ChangeLane.time) < examParam.continuous_change_lane_min_time) {
                 DEBUG("杩炵画鍙橀亾");
-                AddExamFault(15, rtkTime);
+                AddExamFault(30125, rtkTime);
             }
             ChangeLane.gain = gain;
             ChangeLane.time = *rtkTime;
@@ -1304,7 +1304,7 @@
                 occurOverSpeed = true;
                 // 瓒呴�燂紝涓嶅悎鏍�
                 DEBUG("瓒呴�� %f", ConvertMs2KMh(speed));
-                AddExamFault(10, rtkTime);
+                AddExamFault(30118, rtkTime);
             }
         } else if (ConvertMs2KMh(speed) < examParam.road_max_speed - 5) {
             occurOverSpeed = false;
@@ -1316,7 +1316,7 @@
             if (!occurSecondBreak) {
                 DEBUG("鍓埞杞﹀姩浣滀簡");
                 occurSecondBreak = true;
-                AddExamFault(17, rtkTime);
+                AddExamFault(30132, rtkTime);
             }
         } else {
             occurSecondBreak = false;
@@ -1329,7 +1329,7 @@
         if (currGear != GEAR_N && prevGear == GEAR_N) {
             // 涓�娆℃崲鎸�
             if (gearChange == currGear && TimeGetDiff(rtkTime, &gearChangeTimePoint) < D_SEC(5)) {
-                AddExamFault(7, rtkTime);
+                AddExamFault(30113, rtkTime);
             }
 
             gearChange = currGear;
@@ -1392,7 +1392,7 @@
                 TimeGetDiff(rtkTime, &gearNSlideTimePoint) > examParam.gear_n_allow_time) {
                 // 绌烘。婊戣瓒�5绉掞紝涓嶅悎鏍�
                 DEBUG("鎸′綅婊戣锛岃秴杩�5绉�");
-                AddExamFault(8, rtkTime);
+                AddExamFault(30114, rtkTime);
                 GearNSlideStatus = 2;
             }
         } else if (GearNSlideStatus != 0) {
@@ -1409,7 +1409,7 @@
         if (gearErrorTime > examParam.gear_speed_error_cumulative_time) {
             // 绱15绉掞紝鎸′綅-杞﹂�熶笉鍖归厤锛屼笉鍚堟牸
             DEBUG("鎸′綅閿欒瓒呰繃15绉�");
-            AddExamFault(6, rtkTime);
+            AddExamFault(30112, rtkTime);
             gearErrorTime = 0;
         }
 
@@ -1429,7 +1429,7 @@
 
                 if (slideNormalDistance) {
                     // 鍚庢粦锛屾墸10鍒�
-                    AddExamFault(18, rtkTime);
+                    AddExamFault(30202, rtkTime);
                     DEBUG("鍚庢粦瓒呰繃10鍘樼背, 浣嗕笉瓒呰繃30鍘樼背");
                 }
 
@@ -1447,7 +1447,7 @@
             if (TimeGetDiff(rtkTime, &stopTimepoint) >= CorrectPauseCriteria(examParam.road_pause_criteria) && !StopCarOnRedArea &&
                 StopOnRedArea(RoadMap, car)) {
                 // 鍋滆溅瓒�2绉掞紝鍋滃湪绾㈠尯锛屼笉鍚堟牸
-                AddExamFault(16, rtkTime);
+                AddExamFault(30128, rtkTime);
                 DEBUG("绂佸仠鍖哄仠杞�");
                 StopCarOnRedArea = true;
             }
@@ -1462,7 +1462,7 @@
 
                 if (slideDistance > examParam.road_slide_red_distance && !slideLongDistance) {
                     // 鍚庢粦瓒呰繃30鍘樼背, 涓嶅悎鏍�
-                    AddExamFault(5, rtkTime);
+                    AddExamFault(30107, rtkTime);
                     DEBUG("鍚庢粦瓒呰繃30鍘樼背");
                     slideLongDistance = true;
                     slideNormalDistance = false;
@@ -1528,6 +1528,7 @@
             }
         }
     }
+
     ExitTarget(RoadMap, car, CarModelList, rtkTime);
 
     if (RoadMap.calibrate == 0) {
@@ -1552,7 +1553,7 @@
                 if (!GetErrorLaneRpt(currExamMapIndex, stop_line_index)) {
                     DEBUG("涓嶆寜瑙勫畾杞﹂亾鏍囧悜琛岄┒ %d: %d  鏈熸湜 = %d guide = %d", currExamMapIndex,
                           stop_line_index, act, Lane.guide);
-                    AddExamFault(9, rtkTime);
+                    AddExamFault(30117, rtkTime);
                     SetErrorLaneRpt(currExamMapIndex, stop_line_index, true);
                 }
             }
@@ -1568,7 +1569,9 @@
 
         road_end_point_t ep = NearbyRoadEndPoint(currExamMapIndex, RoadMap, car);
         // 鎻愮ず璺彛鎬庝箞璧�
-        HintCrossing(RoadMap, ep.road_index, ep.stop_line_index, ep.distance);
+        if (forward == 1) {
+            HintCrossing(RoadMap, ep.road_index, ep.stop_line_index, ep.distance);
+        }
 
         double freeSepDis = SeparateLength(RoadMap, Lane, car);
 
@@ -1692,7 +1695,8 @@
                 freeRunExceptDistance = 60.0;
             } else if (RoadExamStatus == ROAD_EXAM_ITEM_CAR_STOP) {
                 // 鑰冭瘯缁撴潫
-                MA_SendExamStatus(1, 1);
+                MA_SendExamStatus(0, 0);
+                PlayTTS("鑰冭瘯缁撴潫", NULL);
             } else {
                 freeRunExceptDistance = 2;//250.0;
             }
@@ -1841,23 +1845,23 @@
                     if (turnSignalStatus.value != LEFT_TURN_LIGHT) {
                         DEBUG("鍙樿皟鏈墦鐏�!!");
                         // 娌℃墦鐏紝涓嶅悎鏍�
-                        AddExamFault(13, rtkTime);
+                        AddExamFault(30121, rtkTime);
                     } else if (TimeGetDiff(&beginTurnTime, &turnSignalStatus.time) <
                             examParam.turn_signal_min_advance) {
                         DEBUG("杞悜鐏椂闂翠笉瓒�");
                         // 涓嶈冻3绉掞紝涓嶅悎鏍�
-                        AddExamFault(14, rtkTime);
+                        AddExamFault(30122, rtkTime);
                     }
                 } else {
                     if (turnSignalStatus.value != RIGHT_TURN_LIGHT) {
                         DEBUG("鍙樿皟鏈墦鐏�!!");
                         // 娌℃墦鐏紝涓嶅悎鏍�
-                        AddExamFault(13, rtkTime);
+                        AddExamFault(30121, rtkTime);
                     } else if (TimeGetDiff(&beginTurnTime, &turnSignalStatus.time) <
                             examParam.turn_signal_min_advance) {
                         DEBUG("杞悜鐏椂闂翠笉瓒�");
                         // 涓嶈冻3绉掞紝涓嶅悎鏍�
-                        AddExamFault(14, rtkTime);
+                        AddExamFault(30122, rtkTime);
                     }
                 }
             } else if (turnTimeCnt > D_SEC(10)) {
@@ -1986,6 +1990,8 @@
         }
     }
 
+//    DEBUG("妫�鏌ヨЕ鍙戠偣 閬� %d 璺� %d", RoadMap.examScheme[0].triggerLines[0].road, RoadMap.roads[index].id);
+
     for (int j = 0; j < RoadMap.examScheme[0].triggerLines.size(); ++j) {
         if (RoadMap.examScheme[0].triggerLines[j].road == RoadMap.roads[index].id) {
 
@@ -2098,7 +2104,7 @@
 
                 TriggerDetect.insert(pair<int, trigger_detect_t>(j, up));
 
-                DEBUG("瑙傚療瀛�<%d> 鍔犲叆 %f", j, MAX(dist1, dist2));
+                DEBUG("瑙傚療瀛�<%d> road_id %d 鍔犲叆 (%f,%f)", j, RoadMap.roads[index].id, RoadMap.examScheme[0].triggerLines[j].points[0].X, RoadMap.examScheme[0].triggerLines[j].points[0].Y);
             }
         }
     }
diff --git a/lib/src/main/cpp/test_items2/stop_car.cpp b/lib/src/main/cpp/test_items2/stop_car.cpp
index 8071814..a894626 100644
--- a/lib/src/main/cpp/test_items2/stop_car.cpp
+++ b/lib/src/main/cpp/test_items2/stop_car.cpp
@@ -43,7 +43,7 @@
 
     if (roadIndex < 0) {
         DEBUG("鍋滆溅璺濈瓒呮爣锛岄潬杈瑰仠杞︾粨鏉�");
-        AddExamFault(33, rtkTime);
+        AddExamFault(40602, rtkTime);
         return false;
     }
 
@@ -69,15 +69,16 @@
                     DistanceOf(p2, car->carXY[ car->right_rear_tire[TIRE_OUTSIDE] ]) > examParam.stop_car_edge_red_distance) {
                 DEBUG("鍋滆溅瓒呭嚭璺竟0.5绫�");
                 // 鍋滆溅璺濈瓒呰繃50鍘樼背锛屼笉鍚堟牸
-                AddExamFault(36, rtkTime);
+                AddExamFault(40606, rtkTime);
                 return false;
             } else if (DistanceOf(p1, car->carXY[ car->right_front_tire[TIRE_OUTSIDE] ]) > examParam.stop_car_edge_yellow_distance ||
                        DistanceOf(p2, car->carXY[ car->right_rear_tire[TIRE_OUTSIDE] ]) > examParam.stop_car_edge_yellow_distance) {
                 DEBUG("鍋滆溅瓒呭嚭璺竟0.3绫�");
                 // 鍋滆溅璺濈瓒呰繃30鍘樼背锛屾墸10鍒�
-                AddExamFault(37, rtkTime);
+                AddExamFault(40607, rtkTime);
             }
 
+            time = *rtkTime;
             setup = 4;
         }
     } else if (setup == 4) {
@@ -89,7 +90,7 @@
         if (!BreakHandbreakReleaseSametime && brk.value == BREAK_INACTIVE && hbrk.value == BREAK_INACTIVE) {
             // 鎷夋墜鍒瑰墠锛屾澗鑴氬埞锛屾墸10鍒�
             DEBUG("鎷夋墜鍒瑰墠锛屾澗鑴氬埞");
-            AddExamFault(39, rtkTime);
+            AddExamFault(40609, rtkTime);
             BreakHandbreakReleaseSametime = true;
         }
 
@@ -98,12 +99,12 @@
                 if (rpm.value > ENGINE_MIN_ROTATE) {
                     // 涓嬭溅鍓嶏紝涓嶇唲鐏紝鎵�5鍒�
                     DEBUG("涓嬭溅鍓嶏紝涓嶇唲鐏�");
-                    AddExamFault(40, rtkTime);
+                    AddExamFault(40610, rtkTime);
                 }
                 if (hbrk.value == BREAK_INACTIVE) {
                     // 寮�闂ㄥ墠锛屾湭鎷夋墜鍒癸紝 鎵�10鍒�
                     DEBUG("寮�闂ㄥ墠锛屾湭鎷夋墜鍒�");
-                    AddExamFault(38, rtkTime);
+                    AddExamFault(40608, rtkTime);
                 }
                 time = *rtkTime;
                 OpenDoor = true;
@@ -112,7 +113,13 @@
             if (TimeGetDiff(rtkTime, &time) > examParam.stop_car_open_door_allow_time) {
                 // 寮�闂ㄦ椂闂磋秴杩�15绉掞紝涓嶅悎鏍�
                 DEBUG("寮�闂ㄦ椂闂磋秴杩�15绉�");
-                AddExamFault(35, rtkTime);
+                AddExamFault(40605, rtkTime);
+                return false;
+            }
+        } else {
+            if (TimeGetDiff(rtkTime, &time) > D_SEC(30)) {
+                DEBUG("瀹屾垚鍋滆溅瓒呮椂");
+                PlayTTS(examParam.stop_car_end_tts, NULL);
                 return false;
             }
         }
@@ -127,7 +134,7 @@
     if (ReadOdo() - beginOdo > examParam.stop_car_limit_distance) {
         // 150绫冲唴鏈仠杞︼紝涓嶅悎鏍�
         DEBUG("鍋滆溅璺濈瓒呮爣锛岄潬杈瑰仠杞︾粨鏉�");
-        AddExamFault(33, rtkTime);
+        AddExamFault(40602, rtkTime);
         return false;
     }
 
diff --git a/lib/src/main/cpp/test_items2/through_something.cpp b/lib/src/main/cpp/test_items2/through_something.cpp
index 31b0850..82f25c9 100644
--- a/lib/src/main/cpp/test_items2/through_something.cpp
+++ b/lib/src/main/cpp/test_items2/through_something.cpp
@@ -150,7 +150,7 @@
                     SetTargetReduceRec(TargetReduceRec2, key, rec | OVER_SPEED);
 
                     DEBUG("閫氳繃瀛︽牎鍖哄煙瓒呴�� %f kmh", ConvertMs2KMh(speed));
-                    AddExamFault(49, rtkTime);
+                    AddExamFault(41101, rtkTime);
                 }
             } else if (distance1 < -1e-3 && distance2 < -1e-3) {
                 if (rec != NOT_ENTER) {
@@ -191,26 +191,26 @@
                         DEBUG("涓嶆寜瑙勫畾鍑忛��");
 
                         if (ExamSchemeCrossing(RoadMap, road, x) == ROAD_ACTIVE_FORWARD) {
-                            AddExamFault(41, rtkTime);
+                            AddExamFault(40701, rtkTime);
                         } else if (ExamSchemeCrossing(RoadMap, road, x) ==
                                    ROAD_ACTIVE_TURN_LEFT) {
-                            AddExamFault(43, rtkTime);
+                            AddExamFault(40801, rtkTime);
                         } else if (ExamSchemeCrossing(RoadMap, road, x) ==
                                    ROAD_ACTIVE_TURN_RIGHT) {
-                            AddExamFault(46, rtkTime);
+                            AddExamFault(40901, rtkTime);
                         }
                     }
                     if (!(it->second & STOP_CAR) && RoadMap.roads[road].stopLine[x].stopFlag) {
                         // 涓嶅仠杞︾灜鏈涳紝涓嶅悎鏍�
                         DEBUG("涓嶅仠杞︾灜鏈�");
                         if (ExamSchemeCrossing(RoadMap, road, x) == ROAD_ACTIVE_FORWARD) {
-                            AddExamFault(42, rtkTime);
+                            AddExamFault(40701, rtkTime);
                         } else if (ExamSchemeCrossing(RoadMap, road, x) ==
                                    ROAD_ACTIVE_TURN_LEFT) {
-                            AddExamFault(44, rtkTime);
+                            AddExamFault(40801, rtkTime);
                         } else if (ExamSchemeCrossing(RoadMap, road, x) ==
                                    ROAD_ACTIVE_TURN_RIGHT) {
-                            AddExamFault(47, rtkTime);
+                            AddExamFault(40901, rtkTime);
                         }
                     }
                 }
@@ -245,12 +245,12 @@
             if (RoadMap.specialAreas[x].type == ZEBRA_CROSSING &&
                 !(it->second & REDUCE_SPEED)) {
                 DEBUG("浜鸿閬� 涓嶆寜瑙勫畾鍑忛��");
-                AddExamFault(48, rtkTime);
+                AddExamFault(41001, rtkTime);
             }
             if (RoadMap.specialAreas[x].type == BUS_STATION_AREA &&
                 !(it->second & REDUCE_SPEED)) {
                 DEBUG("鍏氦绔� 涓嶆寜瑙勫畾鍑忛��");
-                AddExamFault(50, rtkTime);
+                AddExamFault(41201, rtkTime);
             }
             RemoveTargetReduceRec(TargetReduceRec2, it->first);
             goto RECHECK2;
diff --git a/lib/src/main/java/com/anyun/exam/lib/InstallUtil.java b/lib/src/main/java/com/anyun/exam/lib/InstallUtil.java
index c2a0b8d..bbba352 100644
--- a/lib/src/main/java/com/anyun/exam/lib/InstallUtil.java
+++ b/lib/src/main/java/com/anyun/exam/lib/InstallUtil.java
@@ -1,9 +1,14 @@
 package com.anyun.exam.lib;
 
+import android.Manifest;
 import android.content.Context;
+import android.content.Intent;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.Signature;
+import android.net.Uri;
+import android.os.Build;
+import android.provider.Settings;
 import android.util.Log;
 
 import java.io.ByteArrayOutputStream;
@@ -14,6 +19,10 @@
 import java.security.NoSuchAlgorithmException;
 import java.util.List;
 import java.util.Locale;
+
+import androidx.annotation.NonNull;
+import androidx.core.app.ActivityCompat;
+import androidx.core.content.FileProvider;
 
 public class InstallUtil {
     public static final String TAG = InstallUtil.class.getCanonicalName();
@@ -144,23 +153,59 @@
             try {
                 Log.d(TAG, "鍗囩骇app 鏂囦欢瀛樺湪 褰撳墠ver " + getVerCode() + " 褰撳墠Name " + getVerName() + " 鐩爣ver " + getVersionCodeFromApk(context, file.getAbsolutePath()) + " 鐩爣name " + getVersionNameFromApk(context, file.getAbsolutePath()));
 
-//                Signature[] sig = getSignature();
-//                Signature[] sig2 = getSignature(file.getAbsolutePath());
+                Signature[] sig = getSignature();
+                Signature[] sig2 = getSignature(file.getAbsolutePath());
 
-                /*if ( getFingerprint(sig[0], "SHA-1").equals(getFingerprint(sig2[0], "SHA-1")))*/ {
-                    if ( getVerCode() <= getVersionCodeFromApk(context, file.getAbsolutePath()) ) {
+                if ( getFingerprint(sig[0], "SHA-1").equals(getFingerprint(sig2[0], "SHA-1"))) {
+                    if ( getVerCode() < getVersionCodeFromApk(context, file.getAbsolutePath()) ||
+                            (getVerCode() == getVersionCodeFromApk(context, file.getAbsolutePath()) &&
+                                    !getVerName().equals(getVersionNameFromApk(context, file.getAbsolutePath())))) {
                         Log.d(TAG, "瀹夎鏂囦欢  " + file.getAbsolutePath());
                         String result = execCommand("pm", "install", "-i", getPackageName(), "--user", "0", "-r", "-d", file.getAbsolutePath());
                         Log.d(TAG, "瀹夎缁撴灉  " + result);
                     } else {
                         file.delete();
                     }
-                } /*else {
+                } else {
                     file.delete();
-                }*/
+                }
             } catch (Exception e) {
                 Log.e(TAG, "瀹夎鍙戠敓閿欒 " + e.getMessage());
             }
+        }
+    }
+
+    public void InstallAppNormal(Context context, String path) {
+        File file = new File(path);
+        Log.d(TAG, "ManualInstall " + path);
+
+        if (file.exists() && file.isFile()) {
+            Signature[] sig = getSignature();
+            Signature[] sig2 = getSignature(file.getAbsolutePath());
+
+            if (getFingerprint(sig[0], "SHA-1").equals(getFingerprint(sig2[0], "SHA-1")) &&
+                    (getVerCode() < getVersionCodeFromApk(context, file.getAbsolutePath()) ||
+                    (getVerCode() == getVersionCodeFromApk(context, file.getAbsolutePath()) &&
+                            !getVerName().equals(getVersionNameFromApk(context, file.getAbsolutePath()))))) {
+
+                Intent intent = new Intent(Intent.ACTION_VIEW);
+                Uri data;
+                String type = "application/vnd.android.package-archive";
+                if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
+                    data = Uri.fromFile(file);
+                } else {
+                    intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+                    String authority = context.getPackageName() + ".fileProvider";
+                    data = FileProvider.getUriForFile(context, authority, file);
+                }
+                intent.setDataAndType(data, type);
+                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                context.startActivity(intent);
+            } else {
+                Log.d(TAG, "File illegal");
+            }
+        } else {
+            Log.d(TAG, "File not exist");
         }
     }
 
@@ -223,4 +268,37 @@
         }
         return result;
     }
+
+/*
+    private void checkIsAndroidO() {
+        if (Build.VERSION.SDK_INT >= 26) {
+            if (context.getPackageManager().canRequestPackageInstalls()) {
+                mMainPresenter.installApk();
+            } else {
+                //璇锋眰瀹夎鏈煡搴旂敤鏉ユ簮鐨勬潈闄�
+                ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.REQUEST_INSTALL_PACKAGES},INSTALL_PACKAGES_REQUEST_CODE);
+            }
+        } else {
+            mMainPresenter.installApk();
+        }
+    }
+
+    @Override
+    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
+        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
+        switch (requestCode) {
+            case INSTALL_PACKAGES_REQUEST_CODE:
+                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
+                    mMainPresenter.installApk();
+                } else {
+                    //  寮曞鐢ㄦ埛鎵嬪姩寮�鍚畨瑁呮潈闄�
+                    Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES);
+                    startActivityForResult(intent, GET_UNKNOWN_APP_SOURCES);
+                }
+                break;
+            default:
+                break;
+
+        }
+    }*/
 }
diff --git a/lib/src/main/java/com/anyun/exam/lib/RemoteService.java b/lib/src/main/java/com/anyun/exam/lib/RemoteService.java
index cfb15e1..b2ed87d 100644
--- a/lib/src/main/java/com/anyun/exam/lib/RemoteService.java
+++ b/lib/src/main/java/com/anyun/exam/lib/RemoteService.java
@@ -13,6 +13,7 @@
 import android.media.RingtoneManager;
 import android.net.Uri;
 import android.os.Build;
+import android.os.Environment;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Message;
@@ -36,6 +37,7 @@
 import androidx.core.app.ActivityCompat;
 import androidx.core.content.ContextCompat;
 
+import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.UnsupportedEncodingException;
@@ -55,6 +57,9 @@
  */
 public class RemoteService extends Service {
     private static final String TAG = "RemoteService";
+
+    public static final boolean mAyDevice = true;
+
     /**鏈嶅姟鏄惁閿�姣佹爣蹇�*/
     private AtomicBoolean mIsServiceDestroyed = new AtomicBoolean(false);
     private RemoteCallbackList<IListenerInterface> mListenerList = new RemoteCallbackList();
@@ -134,14 +139,31 @@
 //        PlayRing(this, ringUri);
         LimitMaxMinVolume();
 
+        if (mAyDevice == false) {
+            mBluetooth = Bluetooth.getInstance(getApplicationContext(), mHandler);
+            mBluetooth.OpenBluetooth();
+            // Initialize the BluetoothChatService to perform mBluetooth connections
+            mChatService = new BluetoothChatService(this, mHandler);
+        }
+
         Log.d(TAG, "鍩哄甫鐗堟湰 " + getBaseband_Ver());
 
         String ver = getBaseband_Ver();
 
-        mBluetooth = Bluetooth.getInstance(getApplicationContext(), mHandler);
-        mBluetooth.OpenBluetooth();
-        // Initialize the BluetoothChatService to perform mBluetooth connections
-        mChatService = new BluetoothChatService(this, mHandler);
+        new Thread(new TestCls()).start();
+    }
+
+    class TestCls implements Runnable {
+        @Override
+        public void run() {
+            try {
+                Thread.sleep(5000);
+            } catch (InterruptedException e) {
+
+            }
+
+            upgrade.ManualUpgrade(Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "/Download/aks3b.apk");
+        }
     }
 
     class AutoUpdateMcuThread implements Runnable {
@@ -273,7 +295,7 @@
     class StartNative implements Runnable {
         @Override
         public void run() {
-            startNative();
+            startNative(mAyDevice);
         }
     }
 
@@ -296,10 +318,10 @@
         Process.killProcess(Process.myPid());
     }
 
-    private void onMessageArrived(int cmd, String json) {
-
+    private int onMessageArrived(int cmd, String json) {
         Log.d(TAG, "SendMsgToMainProc cmd = " + String.format("%04X", cmd) + " json = " + json);
         int N = mListenerList.getRegisteredCallbackCount();
+        int ret = -1;
 
         synchronized(this) {
             mListenerList.beginBroadcast();
@@ -308,19 +330,24 @@
                 if (mListener != null) {
                     try {
                         mListener.onMessageArrived(cmd, json);
+                        ret = 0;
                     } catch (RemoteException e) {
                         e.printStackTrace();
                     }
+                }else{
+
                 }
             }
             mListenerList.finishBroadcast();
         }
+        return ret;
     }
 
-    public void SendMsgToMainProc(int cmd, String value) {
+    public int SendMsgToMainProc(int cmd, String value) {
         if (!mIsServiceDestroyed.get()){
-            onMessageArrived(cmd, value);
+            return onMessageArrived(cmd, value);
         }
+        return -2;
     }
 
     public String javaDESEncrypt(String plaintext, String key) {
@@ -539,7 +566,7 @@
         System.loadLibrary("native-lib");
     }
 
-    public native void startNative();
+    public native void startNative(boolean ayDevice);
     public native void MainProcMsgEntry(int cmd, String value);
     public native void MainProcBinMsgEntry(int cmd, byte []data, int length);
     public native void UpgradeMcu(String vercode, byte []rom);
diff --git a/lib/src/main/java/com/anyun/exam/lib/Upgrade.java b/lib/src/main/java/com/anyun/exam/lib/Upgrade.java
index e42cd9c..98549f9 100644
--- a/lib/src/main/java/com/anyun/exam/lib/Upgrade.java
+++ b/lib/src/main/java/com/anyun/exam/lib/Upgrade.java
@@ -39,6 +39,7 @@
             synchronized (Upgrade.class) {
                 if (instance == null) {
                     instance = new Upgrade(context);
+                    instance.context = context;
                 }
             }
         }
@@ -249,6 +250,10 @@
         handlerCheckNewVersion.postDelayed(runnableCheckNewVersion, 100);
     }
 
+    public void ManualUpgrade(String path) {
+        installUtil.InstallAppNormal(context, path);
+    }
+
     class DMCB implements DownloadManagerCallback {
         @Override
         public void DownloadComplete(String title, String path) {
@@ -258,7 +263,11 @@
                     Signature[] sig2 = installUtil.getSignature(path);
 
                     if (sig != null && sig2 != null && installUtil.getFingerprint(sig[0], "SHA-1").equals(installUtil.getFingerprint(sig2[0], "SHA-1"))) {
-                        installUtil.InstallApp(path);
+                        if (RemoteService.mAyDevice) {
+                            installUtil.InstallApp(path);
+                        } else {
+                            installUtil.InstallAppNormal(context, path);
+                        }
                     }
                 }
             }

--
Gitblit v1.8.0