yy1717
2020-11-24 6e0f29b08a040d14576d7053c1206a8439936570
坐标
24个文件已修改
6个文件已添加
1688 ■■■■■ 已修改文件
lib/src/main/AndroidManifest.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lib/src/main/cpp/driver_test.cpp 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lib/src/main/cpp/driver_test.h 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lib/src/main/cpp/master/comm_if.cpp 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lib/src/main/cpp/master/comm_if.h 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lib/src/main/cpp/mcu/mcu_if.cpp 85 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lib/src/main/cpp/mcu/mcu_if.h 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lib/src/main/cpp/native-lib.cpp 88 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lib/src/main/cpp/native-lib.h 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lib/src/main/cpp/rtk_module/rtk.cpp 56 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lib/src/main/cpp/rtk_module/rtk.h 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lib/src/main/cpp/rtk_module/virtual_rtk.cpp 48 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lib/src/main/cpp/rtk_module/virtual_rtk.h 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lib/src/main/cpp/rtk_platform/platform.cpp 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lib/src/main/cpp/rtk_platform/platform.h 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lib/src/main/cpp/test_common/Geometry.cpp 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lib/src/main/cpp/test_common/Geometry.h 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lib/src/main/cpp/test_items/driving_curve.cpp 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
lib/src/main/cpp/test_items/park_bottom.cpp 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
lib/src/main/cpp/test_items/park_edge.cpp 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
lib/src/main/cpp/test_items/turn_a90.cpp 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
lib/src/main/cpp/test_items2/road_exam.cpp 165 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lib/src/main/cpp/test_items2/through_something.cpp 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lib/src/main/java/com/anyun/exam/lib/Ota.java 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lib/src/main/java/com/anyun/exam/lib/RemoteService.java 165 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lib/src/main/java/com/anyun/exam/lib/util/Bluetooth.java 152 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lib/src/main/java/com/anyun/exam/lib/util/BluetoothChatService.java 540 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lib/src/main/java/com/anyun/exam/lib/util/BluetoothChatServiceCallback.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lib/src/main/java/com/anyun/exam/lib/util/ClsUtils.java 138 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lib/src/main/java/com/anyun/exam/lib/util/Constants.java 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lib/src/main/AndroidManifest.xml
@@ -1,6 +1,11 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.anyun.exam.lib" >
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
    <uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <application>
        <service android:name=".RemoteService"  android:process=":reomte" android:exported="true"/>
    </application>
lib/src/main/cpp/driver_test.cpp
@@ -1133,6 +1133,16 @@
    MA_SendCrossingStatus(&brief2);
}
/***************************************************************
 * 车速判断需要1秒前后的对比,实测停车确认需要1.5秒左右,固减去这个时间
 * @param src
 * @return
 */
int CorrectPauseCriteria(int src)
{
    return (src > 1500) ? src - 1500 : 0;
}
/*******************************************************************
 * @brief 由主天线坐标计算车身点坐标
 * @param azimuth
lib/src/main/cpp/driver_test.h
@@ -323,4 +323,6 @@
void MasterInqRoadStatus(void);
int CorrectPauseCriteria(int src);
#endif //RTKDRIVERTEST_DRIVER_TEST_H
lib/src/main/cpp/master/comm_if.cpp
@@ -41,6 +41,7 @@
#define ID_MS_ROAD_MAP2         0x8013
#define ID_MS_SCHEME            0x8017
#define ID_MS_EXAM_PARAM        0x8019
#define ID_MS_BLUETOOTH_NAME    0x8020
#define ID_SM_READ_CAR          0x0007
#define ID_MS_CAR               0x8007
@@ -71,6 +72,7 @@
#define ID_MS_INQ_ROAD_CROSSING 0x8018              // Master查询当前路段和路口
#define ID_SM_CAN_BRIEF         0x0021
#define ID_SM_BLUETOOTH_BRIEF   0x0022
#define MA_OUT_GPS_BRIEF        0x0001
#define MA_OUT_RTK_BRIEF        0x0002
@@ -1290,6 +1292,9 @@
        case ID_MS_SCHEME: {
            Document doc;
            doc.Parse(value);
            DEBUG("方案 %s", value);
            if (!doc.HasParseError()) {
                DEBUG("开始解析路考方案");
                vector<scheme_t> schemes;
@@ -1379,87 +1384,104 @@
                if (doc.HasMember("hold_start_key_limit_time")) {
                    const Value &a = doc["hold_start_key_limit_time"];
                    examParam.hold_start_key_limit_time = a.GetInt();
                    DEBUG("hold_start_key_limit_time = %d", examParam.hold_start_key_limit_time);
                }
                if (doc.HasMember("curve_pause_criteria")) {
                    const Value &a = doc["curve_pause_criteria"];
                    examParam.curve_pause_criteria = a.GetInt();
                    DEBUG("curve_pause_criteria = %d", examParam.curve_pause_criteria);
                }
                if (doc.HasMember("park_bottom_pause_criteria")) {
                    const Value &a = doc["park_bottom_pause_criteria"];
                    examParam.park_bottom_pause_criteria = a.GetInt();
                    DEBUG("park_bottom_pause_criteria = %d", examParam.park_bottom_pause_criteria);
                }
                if (doc.HasMember("park_bottom_limit_time")) {
                    const Value &a = doc["park_bottom_limit_time"];
                    examParam.park_bottom_limit_time = D_SEC(a.GetInt());
                    DEBUG("park_bottom_limit_time = %d", examParam.park_bottom_limit_time);
                }
                if (doc.HasMember("park_edge_pause_criteria")) {
                    const Value &a = doc["park_edge_pause_criteria"];
                    examParam.park_edge_pause_criteria = a.GetInt();
                    DEBUG("park_edge_pause_criteria = %d", examParam.park_edge_pause_criteria);
                }
                if (doc.HasMember("park_edge_limit_time")) {
                    const Value &a = doc["park_edge_limit_time"];
                    examParam.park_edge_limit_time = D_SEC(a.GetInt());
                    DEBUG("park_edge_limit_time = %d", examParam.park_edge_limit_time);
                }
                if (doc.HasMember("turn_a90_pause_criteria")) {
                    const Value &a = doc["turn_a90_pause_criteria"];
                    examParam.turn_a90_pause_criteria = a.GetInt();
                    DEBUG("turn_a90_pause_criteria = %d", examParam.turn_a90_pause_criteria);
                }
                if (doc.HasMember("ramp_stoppoint_red_distance")) {
                    const Value &a = doc["ramp_stoppoint_red_distance"];
                    examParam.ramp_stoppoint_red_distance = a.GetDouble();
                    DEBUG("ramp_stoppoint_red_distance = %f", examParam.ramp_stoppoint_red_distance);
                }
                if (doc.HasMember("ramp_edge_yellow_distance")) {
                    const Value &a = doc["ramp_edge_yellow_distance"];
                    examParam.ramp_edge_yellow_distance = a.GetDouble();
                    DEBUG("ramp_edge_yellow_distance = %f", examParam.ramp_edge_yellow_distance);
                }
                if (doc.HasMember("ramp_edge_red_distance")) {
                    const Value &a = doc["ramp_edge_red_distance"];
                    examParam.ramp_edge_red_distance = a.GetDouble();
                    DEBUG("ramp_edge_red_distance = %f", examParam.ramp_edge_red_distance);
                }
                if (doc.HasMember("ramp_slide_yellow_distance")) {
                    const Value &a = doc["ramp_slide_yellow_distance"];
                    examParam.ramp_slide_yellow_distance = a.GetDouble();
                    DEBUG("ramp_slide_yellow_distance = %f", examParam.ramp_slide_yellow_distance);
                }
                if (doc.HasMember("ramp_slide_red_distance")) {
                    const Value &a = doc["ramp_slide_red_distance"];
                    examParam.ramp_slide_red_distance = a.GetDouble();
                    DEBUG("ramp_slide_red_distance = %f", examParam.ramp_slide_red_distance);
                }
                if (doc.HasMember("ramp_start_car_limit_time")) {
                    const Value &a = doc["ramp_start_car_limit_time"];
                    examParam.ramp_start_car_limit_time = D_SEC(a.GetInt());
                    DEBUG("ramp_start_car_limit_time = %d", examParam.ramp_start_car_limit_time);
                }
                if (doc.HasMember("road_slide_yellow_distance")) {
                    const Value &a = doc["road_slide_yellow_distance"];
                    examParam.road_slide_yellow_distance = a.GetDouble();
                    DEBUG("road_slide_yellow_distance = %f", examParam.road_slide_yellow_distance);
                }
                double road_slide_red_distance;
                if (doc.HasMember("road_slide_red_distance")) {
                    const Value &a = doc["road_slide_red_distance"];
                    examParam.road_slide_red_distance = a.GetDouble();
                    DEBUG("road_slide_red_distance = %f", examParam.road_slide_red_distance);
                }
                if (doc.HasMember("road_total_distance")) {
                    const Value &a = doc["road_total_distance"];
                    examParam.road_total_distance = a.GetDouble();
                    examParam.road_total_distance = a.GetInt();
                    DEBUG("road_total_distance = %d", examParam.road_total_distance);
                }
                if (doc.HasMember("road_max_speed")) {
                    const Value &a = doc["road_max_speed"];
                    examParam.road_max_speed = a.GetInt();
                    DEBUG("road_max_speed = %d", examParam.road_max_speed);
                }
                if (doc.HasMember("gear_speed_table")) {
@@ -1467,12 +1489,17 @@
                    int m = 0, n = 0;
                    if (a.IsArray()) {
                    for (Value::ConstValueIterator itr = a.Begin();
                         itr != a.End() && m < 6; ++itr, ++m) {
                        n = 0;
                            if ((*itr).IsArray()) {
                        for (Value::ConstValueIterator itr2 = (*itr).Begin();
                             itr2 != (*itr).End() && n < 2; ++itr2, ++n) {
                            examParam.gear_speed_table[m][n] = (*itr2).GetInt();
                                    DEBUG("gear_speed_table[%d][%d] = %d", m, n, examParam.gear_speed_table[m][n]);
                                }
                            }
                        }
                    }
                }
@@ -1480,118 +1507,141 @@
                if (doc.HasMember("gear_n_allow_time")) {
                    const Value &a = doc["gear_n_allow_time"];
                    examParam.gear_n_allow_time = D_SEC(a.GetInt());
                    DEBUG("gear_n_allow_time = %d", examParam.gear_n_allow_time);
                }
                if (doc.HasMember("same_gear_min_time")) {
                    const Value &a = doc["same_gear_min_time"];
                    examParam.same_gear_min_time = D_SEC(a.GetInt());
                    DEBUG("same_gear_min_time = %d", examParam.same_gear_min_time);
                }
                if (doc.HasMember("gear_speed_error_cumulative_time")) {
                    const Value &a = doc["gear_speed_error_cumulative_time"];
                    examParam.gear_speed_error_cumulative_time = D_SEC(a.GetInt());
                    DEBUG("gear_speed_error_cumulative_time = %d", examParam.gear_speed_error_cumulative_time);
                }
                if (doc.HasMember("road_pause_criteria")) {
                    const Value &a = doc["road_pause_criteria"];
                    examParam.road_pause_criteria = a.GetInt();
                    DEBUG("road_pause_criteria = %d", examParam.road_pause_criteria);
                }
                if (doc.HasMember("continuous_change_lane_min_time")) {
                    const Value &a = doc["continuous_change_lane_min_time"];
                    examParam.continuous_change_lane_min_time = D_SEC(a.GetInt());
                    DEBUG("continuous_change_lane_min_time = %d", examParam.continuous_change_lane_min_time);
                }
                if (doc.HasMember("crash_dotted_line_cumulative_time")) {
                    const Value &a = doc["crash_dotted_line_cumulative_time"];
                    examParam.crash_dotted_line_cumulative_time = D_SEC(a.GetInt());
                    DEBUG("crash_dotted_line_cumulative_time = %d", examParam.crash_dotted_line_cumulative_time);
                }
                if (doc.HasMember("turn_signal_min_advance")) {
                    const Value &a = doc["turn_signal_min_advance"];
                    examParam.turn_signal_min_advance = D_SEC(a.GetInt());
                    DEBUG("turn_signal_min_advance = %d", examParam.turn_signal_min_advance);
                }
                if (doc.HasMember("start_car_max_rpm")) {
                    const Value &a = doc["start_car_max_rpm"];
                    examParam.start_car_max_rpm = a.GetInt();
                    DEBUG("start_car_max_rpm = %d", examParam.start_car_max_rpm);
                }
                if (doc.HasMember("start_car_limit_distance")) {
                    const Value &a = doc["start_car_limit_distance"];
                    examParam.start_car_limit_distance = a.GetInt();
                    DEBUG("start_car_limit_distance = %d", examParam.start_car_limit_distance);
                }
                if (doc.HasMember("open_door_drive_allow_distance")) {
                    const Value &a = doc["open_door_drive_allow_distance"];
                    examParam.open_door_drive_allow_distance = a.GetDouble();
                    DEBUG("open_door_drive_allow_distance = %f", examParam.open_door_drive_allow_distance);
                }
                if (doc.HasMember("change_lane_limit_distance")) {
                    const Value &a = doc["change_lane_limit_distance"];
                    examParam.change_lane_limit_distance = a.GetInt();
                    DEBUG("change_lane_limit_distance = %d", examParam.change_lane_limit_distance);
                }
                if (doc.HasMember("shift_limit_distance")) {
                    const Value &a = doc["shift_limit_distance"];
                    examParam.shift_limit_distance = a.GetInt();
                    DEBUG("shift_limit_distance = %d", examParam.shift_limit_distance);
                }
                if (doc.HasMember("shift_hold_time")) {
                    const Value &a = doc["shift_hold_time"];
                    examParam.shift_hold_time = D_SEC(a.GetInt());
                    DEBUG("shift_hold_time = %d", examParam.shift_hold_time);
                }
                int straight_limit_distance;
                if (doc.HasMember("straight_limit_distance")) {
                    const Value &a = doc["straight_limit_distance"];
                    examParam.straight_limit_distance = a.GetInt();
                    DEBUG("straight_limit_distance = %d", examParam.straight_limit_distance);
                }
                if (doc.HasMember("straight_max_offset")) {
                    const Value &a = doc["straight_max_offset"];
                    examParam.straight_max_offset = a.GetDouble();
                    DEBUG("straight_max_offset = %f", examParam.straight_max_offset);
                }
                if (doc.HasMember("overtake_limit_distance")) {
                    const Value &a = doc["overtake_limit_distance"];
                    examParam.overtake_limit_distance = a.GetInt();
                    DEBUG("overtake_limit_distance = %d", examParam.overtake_limit_distance);
                }
                if (doc.HasMember("stop_car_limit_distance")) {
                    const Value &a = doc["stop_car_limit_distance"];
                    examParam.stop_car_limit_distance = a.GetInt();
                    DEBUG("stop_car_limit_distance = %d", examParam.stop_car_limit_distance);
                }
                if (doc.HasMember("stop_car_open_door_allow_time")) {
                    const Value &a = doc["stop_car_open_door_allow_time"];
                    examParam.stop_car_open_door_allow_time = D_SEC(a.GetInt());
                    DEBUG("stop_car_open_door_allow_time = %d", examParam.stop_car_open_door_allow_time);
                }
                if (doc.HasMember("stop_car_edge_red_distance")) {
                    const Value &a = doc["stop_car_edge_red_distance"];
                    examParam.stop_car_edge_red_distance = a.GetDouble();
                    DEBUG("stop_car_edge_red_distance = %f", examParam.stop_car_edge_red_distance);
                }
                if (doc.HasMember("stop_car_edge_yellow_distance")) {
                    const Value &a = doc["stop_car_edge_yellow_distance"];
                    examParam.stop_car_edge_yellow_distance = a.GetDouble();
                    DEBUG("stop_car_edge_yellow_distance = %f", examParam.stop_car_edge_yellow_distance);
                }
                if (doc.HasMember("crossing_stop_valid_distance")) {
                    const Value &a = doc["crossing_stop_valid_distance"];
                    examParam.crossing_stop_valid_distance = a.GetDouble();
                    DEBUG("crossing_stop_valid_distance = %f", examParam.crossing_stop_valid_distance);
                }
                if (doc.HasMember("cross_school_max_speed")) {
                    const Value &a = doc["cross_school_max_speed"];
                    examParam.cross_school_max_speed = a.GetInt();
                    DEBUG("cross_school_max_speed = %d", examParam.cross_school_max_speed);
                }
                if (doc.HasMember("crossing_break_valid_distance")) {
                    const Value &a = doc["crossing_break_valid_distance"];
                    examParam.crossing_break_valid_distance = a.GetInt();
                    DEBUG("crossing_break_valid_distance = %d", examParam.crossing_break_valid_distance);
                }
            }
            break;
@@ -1975,3 +2025,16 @@
{
    SendMsgToMainProcIndep(ID_SM_LIGHT_EXAM_REQ, NULL);
}
void MA_SendBlueStatus(int status)
{
    StringBuffer sb;
    Writer<StringBuffer> writer(sb);
    writer.StartObject();
    writer.Key("bluetooth_status");
    writer.Int(status);
    writer.EndObject();
    SendMsgToMainProcIndep(ID_SM_BLUETOOTH_BRIEF, sb.GetString());
}
lib/src/main/cpp/master/comm_if.h
@@ -153,4 +153,6 @@
void MA_SendCrossingStatus(const struct crossingStatusBrief *brief);
void MA_SendCanStatus(const struct canBrief *brief);
void MA_SendBlueStatus(int status);
#endif //MYAPPLICATION2_COMM_IF_H
lib/src/main/cpp/mcu/mcu_if.cpp
@@ -12,6 +12,8 @@
#include "../jni_log.h"
#include "../common/serial_port.h"
#include "../rtk_platform/platform.h"
#include "../rtk_module/parse_gps.h"
#include "../native-lib.h"
#define DEBUG(fmt, args...)     LOGD("<mcu_if> <%s>: " fmt, __func__, ##args)
@@ -46,6 +48,8 @@
#define ID_CM_READ_RFCARD         0x0009
#define ID_MC_RFCARD_RSP        0x8009
#define ID_CM_SHUTDOWN          0x0020
#define ID_MC_GNSS_DATA         0x800A
#define ID_CM_SINAN_CMD_DATA    0x000B
static parse_status_t parse_status;
@@ -65,15 +69,27 @@
const int DFU_MAX_TRY = 3;
const int DFU_FILE_BLOCK_SIZE = 896;
static int (*WriteMcu)(int id, const void *buf, int len);
static int WriteBluetooth(int id, const void *buf, int len);
static void *UartThread1(void *p);
static void ParseMcuTimeout(union sigval sig);
static void McuCommandEntry(uint16_t id, const uint8_t *data, int lenth);
static void McuCommandEntry(uint16_t id, const uint8_t *data, int length);
static void SendDfuFile(int fileLen, int sentLen, int blockLen, const uint8_t *data);
static void GoNextDfuLater(union sigval sig);
static void GoNextDfu(void);
static void ReadCardTimeout(union sigval sig);
void McuCommModeSel(int mode)
{
    if (mode == 0) {
        WriteMcu = WriteSerialPort;
    } else {
        WriteMcu = WriteBluetooth;
    }
}
void ParseMcuInit(void)
{
@@ -83,8 +99,15 @@
    parse_status = SYNC_HEAD_ONE;
    AppTimer_delete(ParseMcuTimeout);
    SendMcuCommand(ID_CM_APP_BOOT, NULL, 0);
//    SendMcuCommand(ID_CM_APP_BOOT, NULL, 0);
}
static int WriteBluetooth(int id, const void *buf, int len)
{
    SendToBluetooth((uint8_t *)buf, len);
    return len;
}
#define PARSE_BUFF_SIZE         4096
@@ -251,13 +274,15 @@
    buffer[x++] = HI_UINT16(crc16);
    buffer[x++] = LO_UINT16(crc16);
    WriteSerialPort(MCU_UART, buffer, x);
    WriteMcu(MCU_UART, buffer, x);
}
void ConfigMCU(void)
{
    McuCommModeSel(1);
    // TODO
    static struct serial_config serialConfig;
  /*  static struct serial_config serialConfig;
    strcpy(serialConfig.name, "/dev/ttyHSL1");
    serialConfig.baud = 115200;
@@ -270,7 +295,7 @@
    pthread_attr_t attr;
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);//detached
    pthread_create(&pid, &attr, UartThread1, &serialConfig);
    pthread_create(&pid, &attr, UartThread1, &serialConfig);*/
}
void SendRtkToMcu(const uint8_t *data, int length)
@@ -296,20 +321,23 @@
    AppTimer_add(sendrtk, D_SEC(1));
}
static void McuCommandEntry(uint16_t id, const uint8_t *data, int lenth)
static uint8_t GnssBuf[PARSE_BUFF_SIZE];
static int GnssBufLen = 0;
static void McuCommandEntry(uint16_t id, const uint8_t *data, int length)
{
    static int ii = 0;
    switch (id) {
        case ID_MC_MCU_BOOT:
            DEBUG("MCU BOOT");
            if (lenth == 8) {
                PlatformStatusChanged(CAN_UPDATE_EVT, data, lenth);
            if (length == 8) {
                PlatformStatusChanged(CAN_UPDATE_EVT, data, length);
            }
            break;
        case ID_MC_DFU_RSP:
            DEBUG("ID_MC_DFU_RSP %d len %d", data[0], lenth);
            DEBUG("ID_MC_DFU_RSP %d len %d", data[0], length);
            if (data[0] == 0) {
                // 第一包传输成功
@@ -329,12 +357,12 @@
                int total = dfuFileLength / DFU_FILE_BLOCK_SIZE + ((dfuFileLength % DFU_FILE_BLOCK_SIZE)?1:0);
                int a = 0, b = 0;
                for (int i = 1; i < lenth; ++i) {
                for (int i = 1; i < length; ++i) {
                    for (int j = 0; j < 8; ++j) {
                        if ((data[i] & BV(j))) b++;
                        a++;
                        if (a == total) {
                            i = lenth;
                            i = length;
                            break;
                        }
                    }
@@ -343,7 +371,7 @@
                DEBUG("BITMAP total %d succ %d", total, b);
                //memset(dfuFileBitmap, 0, sizeof(dfuFileBitmap));
                memcpy(dfuFileBitmap, data + 1, lenth - 1);
                memcpy(dfuFileBitmap, data + 1, length - 1);
                if (total % 8) {
                    dfuFileBitmap[total/8] &= ~BV((total%8) - 1);
@@ -362,16 +390,16 @@
        case ID_MC_MCU_DFU_RSP:
            break;
        case ID_MC_CAR_INFO2:
//            DEBUG("ID_MC_CAR_INFO2 %d", lenth);
            if (lenth > 0) {
                PlatformStatusChanged(CAR_SENSOR_UPDATE_EVT, data, lenth);
//            DEBUG("ID_MC_CAR_INFO2 %d", length);
            if (length > 0) {
                PlatformStatusChanged(CAR_SENSOR_UPDATE_EVT, data, length);
            }
            break;
        case ID_MC_CAR_INFO: {
//            DEBUG("ID_MC_CAR_INFO %d", lenth);
//            DEBUG("ID_MC_CAR_INFO %d", length);
            if (lenth > 0)
                PlatformStatusChanged(MCU_UPDATE_EVT, data, lenth);
            if (length > 0)
                PlatformStatusChanged(MCU_UPDATE_EVT, data, length);
            break;
        }
        case ID_MC_RTK_DATA:
@@ -381,9 +409,26 @@
            DEBUG("ID_MC_RFCARD_RSP");
            AppTimer_delete(ReadCardTimeout);
            if (lenth > 0)
                PlatformStatusChanged(CARD_UPDATE_EVT, data, lenth);
            if (length > 0)
                PlatformStatusChanged(CARD_UPDATE_EVT, data, length);
            break;
        case ID_MC_GNSS_DATA: {
            length = (length > PARSE_BUFF_SIZE - GnssBufLen) ? (PARSE_BUFF_SIZE - GnssBufLen) : length;
            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");
                    GnssBufLen = 0;
                }
            }
            break;
        }
        default:
            break;
    }
lib/src/main/cpp/mcu/mcu_if.h
@@ -7,6 +7,7 @@
#include <cstdint>
void McuCommModeSel(int mode);
void ConfigMCU(void);
void SendRtkToMcu(const uint8_t *data, int length);
void ParseMcuInit(void);
lib/src/main/cpp/native-lib.cpp
@@ -286,6 +286,72 @@
        }
    }
}
void SendToBluetooth(const uint8_t *data, int length)
{
    JNIEnv *env;
    bool ready_in_java_env = false;
    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;
        }
    } else {
        ready_in_java_env = true;
    }
    jclass cls = env->GetObjectClass(sg_obj);
    jmethodID fun = env->GetMethodID(cls, "WriteBluetooth", "([B)V");
    jbyteArray array = env->NewByteArray(length);
    env->SetByteArrayRegion(array, 0, length, (jbyte *) data);
    env->CallVoidMethod(sg_obj, fun, array);
    env->DeleteLocalRef(array);
    env->DeleteLocalRef(cls);
    if (!ready_in_java_env) {
        //Detach主线程
        if (sg_jvm->DetachCurrentThread() != JNI_OK) {
            LOGE("%s: DetachCurrentThread() failed", __FUNCTION__);
        }
    }
}
void ConnectToBluetooth(const char *addr, const char *pin)
{
    JNIEnv *env;
    bool ready_in_java_env = false;
    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;
        }
    } else {
        ready_in_java_env = true;
    }
    jclass cls = env->GetObjectClass(sg_obj);
    jmethodID fun = env->GetMethodID(cls, "ConnectBluetooth", "(Ljava/lang/String;Ljava/lang/String;)V");
    env->CallVoidMethod(sg_obj, fun, env->NewStringUTF(addr), env->NewStringUTF(pin));
    env->DeleteLocalRef(cls);
    if (!ready_in_java_env) {
        //Detach主线程
        if (sg_jvm->DetachCurrentThread() != JNI_OK) {
            LOGE("%s: DetachCurrentThread() failed", __FUNCTION__);
        }
    }
}
extern "C"
JNIEXPORT void JNICALL
Java_com_anyun_exam_lib_RemoteService_startNative(JNIEnv *env, jobject thiz) {
@@ -405,3 +471,25 @@
        env->ReleaseByteArrayElements(rom, c_dat, NULL);
    }
}
extern "C"
JNIEXPORT void JNICALL
Java_com_anyun_exam_lib_RemoteService_BluetoothDataComeIn(JNIEnv *env, jobject thiz,
                                                          jbyteArray data, jint length) {
    // TODO: implement BluetoothDataComeIn()
    jbyte *c_dat = env->GetByteArrayElements(data, NULL);
    PlatformStatusChanged(BLUETOOTH_DATA_EVT, (uint8_t *)c_dat, length);
    env->ReleaseByteArrayElements(data, c_dat, NULL);
}
extern "C"
JNIEXPORT void JNICALL
Java_com_anyun_exam_lib_RemoteService_BluetoothStatusChange(JNIEnv *env, jobject thiz,
                                                            jint status) {
    // TODO: implement BluetoothStatusChange()
    uint8_t  sta = status;
    PlatformStatusChanged(BLUETOOTH_STATUS_EVT, &sta, 1);
}
lib/src/main/cpp/native-lib.h
@@ -28,5 +28,7 @@
int PlayTTS(const char *string, void (*callback)(int));
int PlayTTS(std::string &tts, void (*callback)(int));
void PlayRing(void);
void SendToBluetooth(const uint8_t *data, int length);
void ConnectToBluetooth(const char *addr, const char *pin);
#endif //RTKBASESTATION_NATIVE_LIB_H
lib/src/main/cpp/rtk_module/rtk.cpp
@@ -18,6 +18,8 @@
#include "../common/apptimer.h"
#include "../rtk_platform/platform.h"
#include "../native-lib.h"
#include "virtual_rtk.h"
#include "../mcu/mcu_if.h"
#define DEBUG(fmt, args...)     LOGD("<rtk> <%s>: " fmt, __func__, ##args)
@@ -37,12 +39,25 @@
static gpsStatus_t gpsStatus;
static int (*WriteRtk)(int id, const void *buf, int len);
static rtk_info CurrRTKInfo;
static bool needSetPjk = false;
static void CheckPjkParam(void);
static void CheckPjkParamTimeout(union sigval sig);
static int WriteBluetooth(int id, const void *buf, int len);
static void *UartThread(void *p);
void RtkCommModeSel(int mode)
{
    if (mode == 0) {
        WriteRtk = WriteSerialPort;
    } else {
        WriteRtk = WriteBluetooth;
    }
}
void ConfigRTKModule(void)
{
@@ -55,7 +70,9 @@
    memset(&gpsStatus, 0, sizeof(gpsStatus));
    gpsStatus.hh = -1;
    static struct serial_config serialConfig;
    RtkCommModeSel(1);
    /*static struct serial_config serialConfig;
    strcpy(serialConfig.name, "/dev/ttyHSL0");
    serialConfig.baud = 115200;
@@ -68,17 +85,23 @@
    pthread_attr_t attr;
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);//detached
    pthread_create(&pid, &attr, UartThread, &serialConfig);
    pthread_create(&pid, &attr, UartThread, &serialConfig);*/
}
void ConfigRTKModuleLater(void)
{
    AppTimer_delete(CheckPjkParamTimeout);
    AppTimer_add(CheckPjkParamTimeout, D_SEC(1));
}
void FactorySettings(void)
{
    WriteSerialPort(RTK_MODULE_UART, FACTORY, strlen(FACTORY));
    WriteRtk(RTK_MODULE_UART, FACTORY, strlen(FACTORY));
}
void RebootModule(void)
{
    WriteSerialPort(RTK_MODULE_UART, REBOOT, strlen(REBOOT));
    WriteRtk(RTK_MODULE_UART, REBOOT, strlen(REBOOT));
}
void handleRTKRebootComp(const struct nmea *s)
@@ -88,6 +111,7 @@
}
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;
@@ -140,8 +164,8 @@
void SetAYFactoryParam(int freq)
{
    WriteSerialPort(RTK_MODULE_UART, UNLOGALL, strlen(UNLOGALL));
    WriteSerialPort(RTK_MODULE_UART, IFCOM2, strlen(IFCOM2));
    WriteRtk(RTK_MODULE_UART, UNLOGALL, strlen(UNLOGALL));
    WriteRtk(RTK_MODULE_UART, IFCOM2, strlen(IFCOM2));
    if (freq == 0)
        freq = 5;
@@ -149,13 +173,13 @@
    for (int i = 0; i < sizeof(PJKITEMS)/ sizeof(PJKITEMS[0]); ++i) {
        char cmd[64];
        sprintf(cmd, "log com1 %s ontime %0.1f\r\n", PJKITEMS[i], 1.0/(double)freq);
        WriteSerialPort(RTK_MODULE_UART, cmd, strlen(cmd));
        WriteRtk(RTK_MODULE_UART, cmd, strlen(cmd));
    }
    for (int i = 0; i <  sizeof(GPSITEMS)/ sizeof(GPSITEMS[0]); ++i) {
        char cmd[64];
        sprintf(cmd, "log com1 %s ontime %0.1f\r\n", GPSITEMS[i], 1.0/(double)freq);
        WriteSerialPort(RTK_MODULE_UART, cmd, strlen(cmd));
        WriteRtk(RTK_MODULE_UART, cmd, strlen(cmd));
    }
//    WriteSerialPort(RTK_MODULE_UART, AY_PJKPARAM, strlen(AY_PJKPARAM));
@@ -168,7 +192,7 @@
    sprintf(buff, "set pjkpara 6378137 298.257223563 0 %d 0 500000\r\n", centLon);
    WriteSerialPort(RTK_MODULE_UART, buff, strlen(buff));
    WriteRtk(RTK_MODULE_UART, buff, strlen(buff));
    DEBUG("%s", buff);
}
@@ -215,6 +239,9 @@
        if (RxBufLen > 0) {
#if 1
            if (VirtualIsConnected()) {     //PC模拟用时
                RxBufLen = 0;
            } else {
            const uint8_t *ptr = parseGPS(RxBuf, RxBuf + RxBufLen);
            if(ptr != RxBuf) {
                memcpy(RxBuf, ptr, RxBufLen - (ptr - RxBuf));
@@ -222,6 +249,7 @@
            } else if(RxBufLen == PARSE_BUFF_SIZE) {        //填满了,且没有一个\r,都抛弃
                DEBUG("Parse GPS error");
                RxBufLen = 0;
                }
            }
#else
            RxBufLen = 0;           //PC模拟用时
@@ -233,7 +261,6 @@
    }
    pthread_exit(NULL);
}
void handleUnrecognisedNMEA(const uint8_t *data, uint16_t length) {
//    char buff[4096] = {0};
@@ -464,7 +491,7 @@
static void CheckPjkParam(void)
{
    int n = WriteSerialPort(RTK_MODULE_UART, INQ_PJK_PARAM, strlen(INQ_PJK_PARAM));
    int n = WriteRtk(RTK_MODULE_UART, INQ_PJK_PARAM, strlen(INQ_PJK_PARAM));
    DEBUG("CN = %d", n);
    AppTimer_delete(CheckPjkParamTimeout);
    AppTimer_add(CheckPjkParamTimeout, D_SEC(3));
@@ -479,3 +506,10 @@
    CheckPjkParam();
}
static int WriteBluetooth(int id, const void *buf, int len)
{
//    SendToBluetooth((uint8_t *)buf, len);
    SendMcuCommand(0x000B, (uint8_t *)buf, len);
    return len;
}
lib/src/main/cpp/rtk_module/rtk.h
@@ -39,7 +39,9 @@
    double y;
}rtk_info;
void RtkCommModeSel(int mode);
void ConfigRTKModule(void);
void ConfigRTKModuleLater(void);
void FactorySettings(void);
void RebootModule(void);
void SetAYFactoryParam(int freq);
lib/src/main/cpp/rtk_module/virtual_rtk.cpp
@@ -15,30 +15,55 @@
#define DEBUG(fmt, args...)     LOGD("<virtual_device> <%s>: " fmt, __func__, ##args)
#define PARSE_BUFF_SIZE         4096
struct vSocket {
    char domain_name[32];
    int port;
};
} VAddr;
static bool virtRtkIsValid = false;
static int connectCnt = 0;
static void ConnectLater(union sigval sig);
static void ConnectV(void);
static void *VDataListenThread(void *p);
void InitVirtualDevice(const char *domain_name, int port)
{
    DEBUG("InitVirtualDevice %s: %d", domain_name, port);
    struct vSocket *ptr = (struct vSocket *)malloc(sizeof(struct vSocket));
    strcpy(VAddr.domain_name, domain_name);
    VAddr.port = port;
    strcpy(ptr->domain_name, domain_name);
    ptr->port = port;
    ConnectV();
}
bool VirtualIsConnected(void)
{
    bool temp;
    do {
        temp = virtRtkIsValid;
    } while (temp != virtRtkIsValid);
    return temp;
}
static void ConnectLater(union sigval sig) {
    AppTimer_delete(ConnectLater);
    ConnectV();
}
static void ConnectV(void)
{
    pthread_t pid;
    pthread_attr_t attr;
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);//detached
    pthread_create(&pid, &attr, VDataListenThread, ptr);
    pthread_create(&pid, &attr, VDataListenThread, &VAddr);
}
#define PARSE_BUFF_SIZE         4096
static void *VDataListenThread(void *p) {
    struct vSocket *vs = (struct vSocket *)p;
@@ -53,10 +78,14 @@
    int fd = -1;
    int RxBufLen = 0;
    connectCnt++;
    fd = ConnectTCP(vs->domain_name, vs->port);
    if (fd > 0) {
        DEBUG("虚拟平台连接成功");
        virtRtkIsValid = true;
        connectCnt = 0;
//        PlayTTS("模拟器连接", NULL);
    } else {
        DEBUG("虚拟平台连接失败");
@@ -96,8 +125,11 @@
    if (fd > 0) {
        DisconnectTCP(fd);
    }
    virtRtkIsValid = false;
    free(vs);
    if (connectCnt < 5) {
        AppTimer_add(ConnectLater, D_SEC(3));
    }
//    PlayTTS("模拟器断开", NULL);
lib/src/main/cpp/rtk_module/virtual_rtk.h
@@ -6,5 +6,6 @@
#define MYAPPLICATION2_VIRTUAL_RTK_H
void InitVirtualDevice(const char *domain_name, int port);
bool VirtualIsConnected(void);
#endif //MYAPPLICATION2_VIRTUAL_RTK_H
lib/src/main/cpp/rtk_platform/platform.cpp
@@ -110,7 +110,7 @@
static void AddEvnet(uint32_t event, const uint8_t *data, int length)
{
    DEBUG("AddEvnet 0x%04X length %d", event, length);
//    DEBUG("AddEvnet 0x%04X length %d", event, length);
    struct event_queue_t *nw = (struct event_queue_t *)malloc(sizeof(struct event_queue_t));
    nw->next = NULL;
@@ -378,6 +378,9 @@
    }
    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;
@@ -400,6 +403,8 @@
        }
        UpdateRTKInfo(rtk);
//        DEBUG("driver_test 评判耗时 %ld", AppTimer_GetTickCount() - ost);
        DEBUG("RTK_UPDATE_EVT =================");
    }
@@ -569,6 +574,32 @@
            MA_MainProcMsgEntry(c.a, (char *) data + 4);
        }
    }
    if (events & BLUETOOTH_STATUS_EVT) {
        DEBUG("BLUETOOTH_STATUS_EVT %d", data[0]);
        if (data[0] == 3) {
            // Connected
            ParseMcuInit();
            ConfigRTKModuleLater();
            PlayTTS("蓝牙连接", NULL);
        } else if (data[0] == 2) {
            // Disconnect
            PlayTTS("蓝牙断开", NULL);
        } else if (data[0] == 1) {
            // Open
            ConnectToBluetooth("00:1B:35:16:20:4A", "3800");
//            ConnectToBluetooth("00:1D:43:9A:E0:79", "1900");
//            ConnectToBluetooth("DESKTOP-IE9V7U8", "0000");
            PlayTTS("蓝牙启动", NULL);
        } else {
            // Close
            PlayTTS("蓝牙关闭", NULL);
        }
    }
    if (events & BLUETOOTH_DATA_EVT) {
        ParseMcu(data, length);
    }
}
static void *PlatformDataListenThread(void *p) {
lib/src/main/cpp/rtk_platform/platform.h
@@ -19,6 +19,8 @@
#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
typedef struct {
    char domain_name[32];
lib/src/main/cpp/test_common/Geometry.cpp
@@ -358,6 +358,19 @@
    return deg;
}
double DeltaYaw(double yaw1, double yaw2)
{
    double deltaAng;
    if (fabs(yaw1 - yaw2) > 180.0) {
        deltaAng = 360.0 - fabs(yaw1 - yaw2);
    } else {
        deltaAng = fabs(yaw1 - yaw2);
    }
    return deltaAng;
}
/**********************************************************
 * base 和 dest的第二点重合时形成的夹角
 * @param base
lib/src/main/cpp/test_common/Geometry.h
@@ -52,6 +52,7 @@
double DistanceOf(PointF point1, PointF point2);
double DistanceOf(PointF point, Line line);
double YawOf(PointF p1, PointF p2);
double DeltaYaw(double yaw1, double yaw2);
double CalculateAngle(Line base, Line dest);
PointF rotatePoint(PointF oldPoint, PointF centre, double degree);
bool InsidePolygon(const Polygon *t1, const Polygon *t2);
lib/src/main/cpp/test_items/driving_curve.cpp
@@ -130,7 +130,7 @@
    } else if (moveDirect == 0) {
        uint32_t tp = TimeMakeComposite(rtkTime->hh, rtkTime->mm, rtkTime->ss, rtkTime->mss*10);
        if (tp - stopTimepoint >= examParam.curve_pause_criteria && !reportStopCarTimeout) {
        if (tp - stopTimepoint >= CorrectPauseCriteria(examParam.curve_pause_criteria) && !reportStopCarTimeout) {
            // 停车超2秒,不合格
            AddExamFault(28, rtkTime);
            DEBUG("中途停车");
lib/src/main/cpp/test_items/park_bottom.cpp
@@ -175,7 +175,7 @@
            if (moveDirect == storeMoveDirectBeforeStop) {
                // 同方向再启动,继续判断是否停车超时
                if (tp - stopTimepoint >= examParam.park_bottom_pause_criteria && reverseCar) {
                if (tp - stopTimepoint >= CorrectPauseCriteria(examParam.park_bottom_pause_criteria) && reverseCar) {
                    // 停车超2秒,每次扣5分
                    AddExamFault(11, rtkTime);
                    DEBUG("中途停车");
lib/src/main/cpp/test_items/park_edge.cpp
@@ -143,7 +143,7 @@
            if (moveStatus == storeMoveStatusBeforeStop) {
                // 同方向再启动,继续判断是否停车超时
                if (tp - stopTimepoint >= examParam.park_edge_pause_criteria && occurMoveBack) {
                if (tp - stopTimepoint >= CorrectPauseCriteria(examParam.park_edge_pause_criteria) && occurMoveBack) {
                    // 停车超2秒,每次扣5分
                    AddExamFault(26, rtkTime);
                    DEBUG("停车超时");
lib/src/main/cpp/test_items/turn_a90.cpp
@@ -99,7 +99,7 @@
    } else if (moveDirect == 0) {
        uint32_t tp = TimeMakeComposite(rtkTime->hh, rtkTime->mm, rtkTime->ss, rtkTime->mss*10);
        if (tp - stopTimepoint >= examParam.turn_a90_pause_criteria && !reportStopCarTimeout) {
        if (tp - stopTimepoint >= CorrectPauseCriteria(examParam.turn_a90_pause_criteria) && !reportStopCarTimeout) {
            // 停车超2秒,每次扣5分
            AddExamFault(31, rtkTime);
            DEBUG("中途停车");
lib/src/main/cpp/test_items2/road_exam.cpp
@@ -106,6 +106,12 @@
static map<int, int> CrossingHint;
static map<int, bool> ErrorLaneReport;
typedef struct {
    int road_id;
    double distance;
} trigger_detect_t;
static map<int, trigger_detect_t> TriggerDetect;           // 距离本路段各触发点的距离
#define ROAD_EXAM_READY_NEXT            0
#define ROAD_EXAM_FREE_RUN              1
#define ROAD_EXAM_ITEM_CAR_START            2
@@ -134,7 +140,7 @@
static int prevTurnWise;
static void ItemExam(road_exam_map &RoadMap, int roadIndex, const car_model *car, LIST_CAR_MODEL &CarModelList, double speed, int moveDirect, const struct RtkTime *rtkTime, double straight, double road_end);
static void ItemExam2(road_exam_map &RoadMap, int roadIndex, const car_model *car, LIST_CAR_MODEL &CarModelList);
static void ItemExam2(road_exam_map &RoadMap, int roadIndex, const car_model *car, LIST_CAR_MODEL &CarModelList, int forward, int moveDirect);
static int isTurn(int currYaw, int prevYaw, int thres);
static void ResetTurnDetect(const car_model *car);
static void DetectTurn(const car_model *car, int moveDirect, const struct RtkTime *rtkTime);
@@ -142,7 +148,7 @@
static int NearbyCrossingGuide(road_exam_map &RoadMap, int &stopLineIndex, int roadIndex, road_t &road, const car_model *car);
static int EntryItem(int index, road_exam_map &RoadMap, const car_model *car, LIST_CAR_MODEL &CarModelList);
static int EntryItem(int index, road_exam_map &RoadMap, const car_model *car, LIST_CAR_MODEL &CarModelList, int forward, int moveDirect);
static int CalcRoadIndex(int currRoadIndex, road_exam_map &RoadMap, const car_model *car);
@@ -187,6 +193,8 @@
    RoadExamItem[ROAD_EXAM_ITEM_CAR_STOP] = ROAD_EXAM_ITEM_NOT_EXEC;
    RoadExamStatus = ROAD_EXAM_READY_NEXT;
    TriggerDetect.clear();
    win = false;
}
@@ -1276,7 +1284,7 @@
void TestRoadGeneral(road_exam_map &RoadMap, const car_model *car, LIST_CAR_MODEL &CarModelList, double speed, int moveDirect, const struct RtkTime *rtkTime)
{
    double BigStraightRoadFree = 0, RoadCrossingFree = 0, TargetFree = 0;
    int forward = 0;                    // 车辆相对当前道路的
    UpdateCarSensor(rtkTime);
    UpdataOdo(speed, moveDirect, rtkTime);
@@ -1436,7 +1444,7 @@
            prevMoveDirect = moveDirect;
        } else if (moveDirect == 0) {
            // 持续停车
            if (TimeGetDiff(rtkTime, &stopTimepoint) >= examParam.road_pause_criteria && !StopCarOnRedArea &&
            if (TimeGetDiff(rtkTime, &stopTimepoint) >= CorrectPauseCriteria(examParam.road_pause_criteria) && !StopCarOnRedArea &&
                StopOnRedArea(RoadMap, car)) {
                // 停车超2秒,停在红区,不合格
                AddExamFault(16, rtkTime);
@@ -1491,6 +1499,34 @@
        car_sensor_value_t brk = ReadCarSensorValue(BREAK);
        // 检测通过路口、人行道等区域时,释放刹车或减速
        TargetFree = ApproachTarget(RoadMap, car, currExamMapIndex, (brk.value == BREAK_ACTIVE), speed, moveDirect, rtkTime);
        // 检查
        projection_t projection;
        uint32_t tm1 = AppTimer_GetTickCount();
        projection = CalcProjectionWithRoadEdgeEx(RoadMap.roads[currExamMapIndex].rightEdge, car->carXY[car->axial[AXIAL_FRONT]]);
        if (projection.edgeIndex < RoadMap.roads[currExamMapIndex].rightEdge.size()) {
            if (projection.pointIndex < RoadMap.roads[currExamMapIndex].rightEdge[projection.edgeIndex].points.size() - 1) {
                double roadYaw = YawOf(RoadMap.roads[currExamMapIndex].rightEdge[projection.edgeIndex].points[projection.pointIndex + 1],
                      RoadMap.roads[currExamMapIndex].rightEdge[projection.edgeIndex].points[projection.pointIndex]);
                int deltaAng;
                if (ABS((int)roadYaw - (int)car->yaw) > 180) {
                    deltaAng = 360 - ABS((int)roadYaw - (int)car->yaw);
                } else {
                    deltaAng = ABS((int)roadYaw - (int)car->yaw);
                }
                if (deltaAng < 90) {
                    forward = 1;
                } else {
                    forward = -1;
                }
//                DEBUG("路段方向 %f 车辆方向 %f 差值 %d 耗时 %ld", roadYaw, car->yaw, deltaAng, AppTimer_GetTickCount() - tm1);
            }
        }
    }
    ExitTarget(RoadMap, car, CarModelList, rtkTime);
@@ -1554,7 +1590,7 @@
        ItemExam(RoadMap, currExamMapIndex, car, CarModelList, speed, moveDirect, rtkTime,
                 BigStraightRoadFree,
                 TargetFree > RoadCrossingFree ? RoadCrossingFree : TargetFree);
        ItemExam2(RoadMap, currExamMapIndex, car, CarModelList);
        ItemExam2(RoadMap, currExamMapIndex, car, CarModelList, forward, moveDirect);
    }
}
@@ -1621,6 +1657,7 @@
        }
    } else if (RoadExamStatus == ROAD_EXAM_FREE_RUN) {
        if (ReadOdo() - freeRunDistance > freeRunExceptDistance) {
            DEBUG("寻找下一个子项目");
            RoadExamStatus = ROAD_EXAM_READY_NEXT;
        }
    } else {
@@ -1649,6 +1686,7 @@
        }
        if (!testing) {
            DEBUG("当前子项结束");
            RoadExamItem[RoadExamStatus] = ROAD_EXAM_ITEM_EXECED;
            if (RoadExamStatus == ROAD_EXAM_ITEM_CAR_START) {
                freeRunExceptDistance = 60.0;
@@ -1665,9 +1703,13 @@
    }
}
static void ItemExam2(road_exam_map &RoadMap, int roadIndex, const car_model *car, LIST_CAR_MODEL &CarModelList)
static void ItemExam2(road_exam_map &RoadMap, int roadIndex, const car_model *car, LIST_CAR_MODEL &CarModelList, int forward, int moveDirect)
{
    int item = EntryItem(roadIndex, RoadMap, car, CarModelList);
    int item = 0;
    if (RoadExamStatus == ROAD_EXAM_READY_NEXT) {
        item = EntryItem(roadIndex, RoadMap, car, CarModelList, forward, moveDirect);
    }
    if (RoadExamStatus == ROAD_EXAM_READY_NEXT && item == 3) {
        StartDriveStraightExam();
@@ -1919,13 +1961,35 @@
    return false;
}
static int EntryItem(int index, road_exam_map &RoadMap, const car_model *car, LIST_CAR_MODEL &CarModelList)
static int EntryItem(int index, road_exam_map &RoadMap, const car_model *car, LIST_CAR_MODEL &CarModelList, int forward, int moveDirect)
{
    if (index < 0 || index >= RoadMap.roads.size() || RoadMap.examScheme.size() == 0)
    if (index < 0 || index >= RoadMap.roads.size() || RoadMap.examScheme.size() == 0 || CarModelList.size() < 2)
        return -1;
    list<car_model *>::iterator iter = CarModelList.begin();
    Line trace;
    PointF p1, p2;
    p1 = ((car_model *)(*iter))->carXY[((car_model *)(*iter))->axial[AXIAL_FRONT]];
    ++iter;
    p2 = ((car_model *)(*iter))->carXY[((car_model *)(*iter))->axial[AXIAL_FRONT]];
    MakeLine(&trace, &p1, &p2);
    double trace_length = DistanceOf(p1, p2);
    if (TriggerDetect.size() > 0) {
        auto it = TriggerDetect.begin();
        if (it->second.road_id != RoadMap.roads[index].id) {
            TriggerDetect.clear();
        }
    }
    for (int j = 0; j < RoadMap.examScheme[0].triggerLines.size(); ++j) {
        if (RoadMap.examScheme[0].triggerLines[j].road == RoadMap.roads[index].id) {
            /*Line triggerLine;
            PointF p2 = CalcProjectionWithRoadEdge(RoadMap.roads[index].leftEdge, RoadMap.triggerLines[i].points[0]);
@@ -1937,7 +2001,7 @@
                return RoadMap.triggerLines[i].active;
            }*/
            vector<double> vec;
           /* vector<double> vec;
            PointF p1 = CalcProjectionWithRoadEdge(RoadMap.roads[index].rightEdge,
                                                   car->carXY[car->axial[AXIAL_FRONT]]);
@@ -1954,6 +2018,87 @@
            if (fabs(vec[0] + vec[1] - vec[2]) < 0.1) {
                DEBUG("触发项目 %d", RoadMap.examScheme[0].triggerLines[j].active);
                return RoadMap.examScheme[0].triggerLines[j].active;
            }*/
//            double angleOf = DeltaYaw(YawOf(RoadMap.examScheme[0].triggerLines[j].points[0], car->carXY[car->axial[AXIAL_FRONT]]), car->yaw);
//            auto it = TriggerDetect.find(j);
//
//            if (it != TriggerDetect.end()) {
//                if (fabs(angleOf - it->second.angleOf) > 2.0) {
//                    bool trigger = false;
//
//                    trigger_detect_t up;
//
//                    if (moveDirect == 1 && forward == 1 && it->second.angleOf <= 90 && angleOf > 90) {
//                        trigger = true;
//                    }
//                    DEBUG("观察子<%d> 更新 %f -> %f", j, it->second.angleOf, angleOf);
//
//                    up.angleOf = angleOf;
//                    up.road_id = RoadMap.roads[index].id;
//
//                    TriggerDetect[j] = up;
//
//
//
//                    if (trigger) {
//                        DEBUG("pos %d 触发项目 %d", j, RoadMap.examScheme[0].triggerLines[j].active);
//                        return RoadMap.examScheme[0].triggerLines[j].active;
//                    }
//                }
//            } else {
//                trigger_detect_t up;
//
//                up.road_id = RoadMap.roads[index].id;
//                up.angleOf = angleOf;
//
//                TriggerDetect.insert(pair<int, trigger_detect_t>(j, up));
//
//                DEBUG("观察子<%d> 加入 %f", j, angleOf);
//            }
//            double dist = DistanceOf(car->carXY[car->axial[AXIAL_FRONT]],
//                       RoadMap.examScheme[0].triggerLines[j].points[0]);
            auto it = TriggerDetect.find(j);
            if (it != TriggerDetect.end()) {
                PointF verticalPoint;
                if (moveDirect == 1 &&
                    forward == 1 &&
                    trace_length > 0.01 &&
                    VerticalPointOnLine(RoadMap.examScheme[0].triggerLines[j].points[0], trace, verticalPoint) &&
                    DistanceOf(verticalPoint, RoadMap.examScheme[0].triggerLines[j].points[0]) < it->second.distance) {
                    DEBUG("pos %d 触发项目 %d", j, RoadMap.examScheme[0].triggerLines[j].active);
                    DEBUG("(%f, %f) ON (%f, %f)-(%f, %f) IS (%f, %f) trace %f",
                          RoadMap.examScheme[0].triggerLines[j].points[0].X,
                          RoadMap.examScheme[0].triggerLines[j].points[0].Y,
                          trace.X1,
                          trace.Y1,
                          trace.X2,
                          trace.Y2,
                          verticalPoint.X,
                          verticalPoint.Y,
                          trace_length);
                    return RoadMap.examScheme[0].triggerLines[j].active;
                }
            } else {
                PointF p1 = CalcProjectionWithRoadEdge(RoadMap.roads[index].leftEdge, RoadMap.examScheme[0].triggerLines[j].points[0]);
                PointF p2 = CalcProjectionWithRoadEdge(RoadMap.roads[index].rightEdge, RoadMap.examScheme[0].triggerLines[j].points[0]);
                double dist1 = DistanceOf(p1, RoadMap.examScheme[0].triggerLines[j].points[0]);
                double dist2 = DistanceOf(p2, RoadMap.examScheme[0].triggerLines[j].points[0]);
                trigger_detect_t up;
                up.road_id = RoadMap.roads[index].id;
                up.distance = MAX(dist1, dist2);
                TriggerDetect.insert(pair<int, trigger_detect_t>(j, up));
                DEBUG("观察子<%d> 加入 %f", j, MAX(dist1, dist2));
            }
        }
    }
lib/src/main/cpp/test_items2/through_something.cpp
@@ -228,6 +228,10 @@
        Line line;
        int roadIndex = 0;
        if (RoadMap.specialAreas[x].type == SCHOOL_AREA) {          // 离开学校区域不按跨线判定
            continue;
        }
        for (; roadIndex < RoadMap.roads.size(); ++roadIndex) {
            if (RoadMap.roads[roadIndex].id == RoadMap.specialAreas[x].road)
                break;
lib/src/main/java/com/anyun/exam/lib/Ota.java
New file
@@ -0,0 +1,55 @@
package com.anyun.exam.lib;
import android.content.Context;
import android.os.Build;
import android.os.RecoverySystem;
import android.util.Log;
import java.io.File;
import java.io.IOException;
public class Ota {
    private final static String TAG = "OTA";
    static String dest = "/data/media/0/update.zip";
    public boolean excuteUpdateZip(Context context, String path) {
        boolean verifyPass = false;
        // TODO Auto-generated method stub
        try {
            File ota = new File(dest);
            Log.d(TAG, "path = " + ota.getCanonicalPath() + "  " + ota.exists());
            Log.d(TAG, "Product Model: " + Build.DISPLAY);
            try {
                RecoverySystem.verifyPackage(ota, recoveryVerifyListener, null);
                verifyPass = true;
                Log.d(TAG, "Verify OK");
            } catch (Exception e) {
                verifyPass = false;
                Log.d(TAG, "Zip Verify Fail!");
            }
            if (verifyPass) {
                RecoverySystem.installPackage(context, ota);
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            Log.e(TAG, "OTA 错误 " + e.getMessage());
        } finally {
            return verifyPass;
        }
    }
    RecoverySystem.ProgressListener recoveryVerifyListener = new RecoverySystem.ProgressListener() {
        public void onProgress(int progress) {
            Log.d(TAG, "verify progress" + progress);
//            final int progress1=progress;
//            showinfo("verify progress " + progress1+" %");
        }
    };
}
lib/src/main/java/com/anyun/exam/lib/RemoteService.java
@@ -1,22 +1,31 @@
package com.anyun.exam.lib;
import android.Manifest;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Process;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.util.Base64;
import android.util.Log;
import com.anyun.exam.lib.util.Bluetooth;
import com.anyun.exam.lib.util.BluetoothChatService;
import com.anyun.exam.lib.util.BluetoothChatServiceCallback;
import com.anyun.exam.lib.util.Constants;
import com.anyun.exam.lib.util.DESUtil;
import com.anyun.exam.lib.util.NetUtils;
import com.anyun.exam.lib.util.ProperUtil;
@@ -24,6 +33,8 @@
import com.anyun.exam.lib.util.SpeakerCallback;
import androidx.annotation.Nullable;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import java.io.IOException;
import java.io.InputStream;
@@ -32,6 +43,9 @@
import java.util.ArrayList;
import java.util.Properties;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.regex.Pattern;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
/**
 * MyApplication2
@@ -52,6 +66,13 @@
    private Uri ringUri = null;
    private Upgrade upgrade = null;
    private Bluetooth mBluetooth = null;
    private BluetoothChatService mChatService = null;
    private String mConnectedDeviceName = null;
    private String mTargetBluetooth = null;
    private String mTargetBluetoothAddr = null;
    private boolean mDiscoveryBluetooth = false;
    private IRemoteInterface.Stub iRemoteInterface = new IRemoteInterface.Stub(){
        @Override
@@ -75,7 +96,7 @@
            if (cmd == 0x8100) {
                try {
                    byte [] file = value.getBytes("ISO-8859-1");
                    Log.d(TAG, byte2hex(file));
//                    Log.d(TAG, byte2hex(file));
                    MainProcBinMsgEntry(cmd, file, file.length);
                } catch (UnsupportedEncodingException e) {
                    Log.d(TAG, "UnsupportedEncodingException");
@@ -102,7 +123,7 @@
        new Thread(new TestThread()).start();
        new Thread(new AutoUpdateMcuThread(this)).start();
//        new Thread(new AutoUpdateMcuThread(this)).start();
        upgrade = Upgrade.getInstance(getApplicationContext());
        upgrade.CheckUpgrade();
@@ -114,6 +135,11 @@
        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);
    }
    class AutoUpdateMcuThread implements Runnable {
@@ -232,7 +258,10 @@
        @Override
        public void run() {
            try {
                Thread.sleep(500);
                Thread.sleep(30000);
//                Ota ota = new Ota();
//                ota.excuteUpdateZip(getApplicationContext(), "");
            } catch (InterruptedException e) {
            }
@@ -250,6 +279,15 @@
    public void onDestroy() {
        super.onDestroy();
        Log.i(TAG,"onDestroy");
        if (mChatService != null) {
            mChatService.stop();
        }
        if (mBluetooth != null) {
            mBluetooth.CloseBluetooth();
            mBluetooth.unRegisterReceiver();
        }
        mIsServiceDestroyed.set(true);
        Log.d(TAG, "onDestory executed 进程 " + Process.myPid());
@@ -362,6 +400,125 @@
        }
    }
    public void ConnectBluetooth(String name, String pin) {
        if (mBluetooth != null && mChatService != null) {
            mBluetooth.SetPin(pin);
            mTargetBluetooth = name;
            if (isMac(name)) {
                mTargetBluetoothAddr = name;
                handlerConnectBluetooth.removeCallbacks(runnableConnectBluetooth);
                handlerConnectBluetooth.postDelayed(runnableConnectBluetooth, 500);
            } else {
                mDiscoveryBluetooth = true;
                mBluetooth.doDiscovery(name);
            }
        }
    }
    Handler handlerConnectBluetooth = new Handler();
    Runnable runnableConnectBluetooth = new Runnable() {
        @Override
        public void run() {
            if (mChatService != null && mTargetBluetoothAddr != null) {
                mChatService.connect(mTargetBluetoothAddr, true);
            }
        }
    };
    public boolean isMac(String addr) {
        String pattern = "^([0-9A-Fa-f]{2})(:[0-9A-Fa-f]{2}){5}$";
        return Pattern.matches(pattern, addr);
    }
    public void WriteBluetooth(byte []data) {
        if (mChatService != null && mChatService.getState() == BluetoothChatService.STATE_CONNECTED) {
            mChatService.write(data);
        }
    }
    private final Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case Constants.MESSAGE_BLUETOOTH_STATUS:
                    if (msg.arg1 == 1) {
                        Log.d(TAG, "蓝牙开启");
//                        mBluetooth.doDiscovery();
                        if (mChatService != null) {
//                            mChatService.connect("00:1D:43:9A:E0:79", true);
//                            mChatService.connect("00:1A:7D:DA:71:11", true);
                        }
                        BluetoothStatusChange(1);
                    } else {
                        Log.d(TAG, "蓝牙关闭");
                        BluetoothStatusChange(0);
                    }
                    break;
                case Constants.MESSAGE_BLUETOOTH_FOUND:
                    String btaddr = msg.getData().getString(Constants.DEVICE_ADDRESS);
                    Log.d(TAG, "发现设备 " + btaddr);
                    if (mDiscoveryBluetooth) {
                        mTargetBluetoothAddr = btaddr;
                    }
                    break;
                case Constants.MESSAGE_BLUETOOTH_DISCOVERY_FINISHED:
                    Log.d(TAG, "搜索结束");
                    if (mDiscoveryBluetooth) {
                        handlerConnectBluetooth.removeCallbacks(runnableConnectBluetooth);
                        handlerConnectBluetooth.postDelayed(runnableConnectBluetooth, 500);
                    }
                    mDiscoveryBluetooth = false;
                    break;
                case Constants.MESSAGE_STATE_CHANGE:
                    switch (msg.arg1) {
                        case BluetoothChatService.STATE_CONNECTED:
                            Log.d(TAG, "蓝牙已连接");
                            BluetoothStatusChange(3);
                            break;
                        case BluetoothChatService.STATE_CONNECTING:
                            Log.d(TAG, "蓝牙连接中...");
                            break;
                        case BluetoothChatService.STATE_LISTEN:
                            Log.d(TAG, "蓝牙监听");
                            BluetoothStatusChange(2);
                            break;
                        case BluetoothChatService.STATE_NONE:
                            Log.d(TAG, "蓝牙无效");
                            BluetoothStatusChange(2);
                            handlerConnectBluetooth.removeCallbacks(runnableConnectBluetooth);
                            handlerConnectBluetooth.postDelayed(runnableConnectBluetooth, 5000);
                            break;
                    }
                    break;
                case Constants.MESSAGE_WRITE:
                    break;
                case Constants.MESSAGE_READ:
//                    Log.d(TAG, String.format("蓝牙数据 length = %d 线程 %d", msg.arg1, Thread.currentThread().getId()));
                    BluetoothDataComeIn((byte[]) msg.obj, msg.arg1);
                    /*if (ndkUtils != null) {
                        byte[] readBuf = (byte[]) msg.obj;
                        ndkUtils.bluetoothMoreData(readBuf, msg.arg1);
                    }*/
                    break;
                case Constants.MESSAGE_DEVICE_NAME:
                    // save the connected device's name
                    mConnectedDeviceName = msg.getData().getString(Constants.DEVICE_NAME);
                    Log.d(TAG, "MESSAGE_DEVICE_NAME: " + mConnectedDeviceName);
                    break;
                case Constants.MESSAGE_TOAST:
                    break;
                    default:break;
            }
        }
    };
    class DataCallback implements BluetoothChatServiceCallback {
        @Override
        public void iDataComeIn(byte []data, int length) {
        }
    }
    // Used to load the 'native-lib' library on application startup.
    static {
        System.loadLibrary("native-lib");
@@ -372,4 +529,6 @@
    public native void MainProcBinMsgEntry(int cmd, byte []data, int length);
    public native void UpgradeMcu(String vercode, byte []rom);
    public native void TextSpeakEnd(int id);
    public native void BluetoothStatusChange(int status);
    public native void BluetoothDataComeIn(byte []data, int length);
}
lib/src/main/java/com/anyun/exam/lib/util/Bluetooth.java
New file
@@ -0,0 +1,152 @@
package com.anyun.exam.lib.util;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import java.lang.reflect.Method;
public class Bluetooth extends BroadcastReceiver {
    private static final String TAG = Bluetooth.class.getCanonicalName();
    public static final String DEFAULT_BT_PASSWORD = "0000";
    private static Bluetooth instance = null;
    private Context context;
    private BluetoothAdapter mBtAdapter = null;
    private Handler mHandler;
    private String pin = DEFAULT_BT_PASSWORD;
    private String mName = null;
    public static Bluetooth getInstance(Context context, Handler handler) {
        if (instance == null) {
            synchronized (Bluetooth.class) {
                if (instance == null) {
                    instance = new Bluetooth(context, handler);
                }
            }
        }
        return instance;
    }
    private Bluetooth(Context context, Handler handler) {
        this.context = context;
        this.mHandler = handler;
        mBtAdapter = BluetoothAdapter.getDefaultAdapter();
        IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
        filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
        filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
        filter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED);
        filter.addAction(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);
        filter.addAction("android.bluetooth.device.action.PAIRING_REQUEST");
        context.registerReceiver(this, filter);
    }
    public void OpenBluetooth() {
        if (!mBtAdapter.isEnabled()) {
            mHandler.obtainMessage(Constants.MESSAGE_BLUETOOTH_STATUS, 0, -1, null)
                    .sendToTarget();
            mBtAdapter.enable();
        } else {
//            Intent discoveryIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
//            discoveryIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION,300);
//            discoveryIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
//            context.startActivity(discoveryIntent);
            mHandler.obtainMessage(Constants.MESSAGE_BLUETOOTH_STATUS, 1, -1, null)
                    .sendToTarget();
        }
    }
    public void CloseBluetooth() {
        if (mBtAdapter.isEnabled()) {
            mBtAdapter.disable();
        }
    }
    public void unRegisterReceiver() {
        context.unregisterReceiver(this);
    }
    public void SetPin(String pin) {
        this.pin = pin;
    }
    /**
     * Start device discover with the BluetoothAdapter
     */
    public void doDiscovery(String name) {
        Log.d(TAG, "doDiscovery()");
        mName = name;
        // If we're already discovering, stop it
        if (mBtAdapter.isDiscovering()) {
            mBtAdapter.cancelDiscovery();
        }
        // Request discover from BluetoothAdapter
        mBtAdapter.startDiscovery();
    }
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if (BluetoothDevice.ACTION_FOUND.equals(action)) {
            // Get the BluetoothDevice object from the Intent
            BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
            if (device.getName() != null && mName != null && device.getName().equals(mName)) {
                Message msg = mHandler.obtainMessage(Constants.MESSAGE_BLUETOOTH_FOUND);
                Bundle bundle = new Bundle();
                bundle.putString(Constants.DEVICE_ADDRESS, device.getAddress());
                msg.setData(bundle);
                mHandler.sendMessage(msg);
                mBtAdapter.cancelDiscovery();
            }
        } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
            Message msg = mHandler.obtainMessage(Constants.MESSAGE_BLUETOOTH_DISCOVERY_FINISHED);
            mHandler.sendMessage(msg);
        } else if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) {
            int status = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.STATE_OFF);
            int status2 = intent.getIntExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, BluetoothAdapter.STATE_OFF);
            if (status == BluetoothAdapter.STATE_ON) {
                OpenBluetooth();
            } else if (status == BluetoothAdapter.STATE_OFF) {
                OpenBluetooth();
            }
        } else if (action.equals("android.bluetooth.device.action.PAIRING_REQUEST")) {
            Log.d(TAG, "匹配请求");
            // Get the BluetoothDevice object from the Intent
            BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
            /*if (device.getName().equals(BLUETOOTH_OBD_NAME) || device.getName().equals(BLUETOOTH_TARGET2_NAME)) */{
                try {
                    ClsUtils.setPairingConfirmation(device.getClass(), device, true);
                    Log.d(TAG, "isOrderedBroadcast:"+isOrderedBroadcast()+",isInitialStickyBroadcast:"+isInitialStickyBroadcast());
                    if (isOrderedBroadcast()) {
                        abortBroadcast();
                    }
                    ClsUtils.setPin(device.getClass(), device, pin);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        } else if (BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED.equals(action)) {
        } else if (BluetoothAdapter.ACTION_SCAN_MODE_CHANGED.equals(action)) {
            int status = intent.getIntExtra(BluetoothAdapter.EXTRA_SCAN_MODE, BluetoothAdapter.SCAN_MODE_NONE);
            Log.d(TAG, "扫描模式 " + status);
        }
    }
}
lib/src/main/java/com/anyun/exam/lib/util/BluetoothChatService.java
New file
@@ -0,0 +1,540 @@
/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.anyun.exam.lib.util;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.UUID;
/**
 * This class does all the work for setting up and managing Bluetooth
 * connections with other devices. It has a thread that listens for
 * incoming connections, a thread for connecting with a device, and a
 * thread for performing data transmissions when connected.
 */
public class BluetoothChatService {
    // Debugging
    private static final String TAG = "BluetoothChatService";
    // Name for the SDP record when creating server socket
    private static final String NAME_SECURE = "BluetoothChatSecure";
    private static final String NAME_INSECURE = "BluetoothChatInsecure";
    // Unique UUID for this application
    private static final UUID MY_UUID_SECURE =
            UUID.fromString(/*"fa87c0d0-afac-11de-8a39-0800200c9a66"*/"00001101-0000-1000-8000-00805F9B34FB");
    private static final UUID MY_UUID_INSECURE =
            UUID.fromString(/*"8ce255c0-200a-11e0-ac64-0800200c9a66"*/"00001101-0000-1000-8000-00805F9B34FB");
    // Member fields
    private final BluetoothAdapter mAdapter;
    private final Handler mHandler;
    private AcceptThread mSecureAcceptThread;
    private AcceptThread mInsecureAcceptThread;
    private ConnectThread mConnectThread;
    private ConnectedThread mConnectedThread;
    private int mState;
    private Context mGuestContext = null;
    private BluetoothChatServiceCallback mCallback = null;
    // Constants that indicate the current connection state
    public static final int STATE_NONE = 0;       // we're doing nothing
    public static final int STATE_LISTEN = 1;     // now listening for incoming connections
    public static final int STATE_CONNECTING = 2; // now initiating an outgoing connection
    public static final int STATE_CONNECTED = 3;  // now connected to a remote device
    /**
     * Constructor. Prepares a new BluetoothChat session.
     *
     * @param context The UI Activity Context
     * @param handler A Handler to send messages back to the UI Activity
     */
    public BluetoothChatService(Context context, Handler handler) {
        mAdapter = BluetoothAdapter.getDefaultAdapter();
        mState = STATE_NONE;
        mHandler = handler;
        mGuestContext = context;
    }
    public void RegisterDataCallback(BluetoothChatServiceCallback cb) {
        mCallback = cb;
    }
    /**
     * Set the current state of the chat connection
     *
     * @param state An integer defining the current connection state
     */
    private synchronized void setState(int state) {
        Log.d(TAG, "setState() " + mState + " -> " + state);
        mState = state;
        // Give the new state to the Handler so the UI Activity can update
        mHandler.obtainMessage(Constants.MESSAGE_STATE_CHANGE, state, -1).sendToTarget();
    }
    /**
     * Return the current connection state.
     */
    public synchronized int getState() {
        return mState;
    }
    /**
     * Start the chat service. Specifically start AcceptThread to begin a
     * session in listening (server) mode. Called by the Activity onResume()
     */
    public synchronized void start() {
        Log.d(TAG, "start");
        // Cancel any thread attempting to make a connection
        if (mConnectThread != null) {
            mConnectThread.cancel();
            mConnectThread = null;
        }
        // Cancel any thread currently running a connection
        if (mConnectedThread != null) {
            mConnectedThread.cancel();
            mConnectedThread = null;
        }
        setState(STATE_NONE);
        // Start the thread to listen on a BluetoothServerSocket
        /*if (mSecureAcceptThread == null) {
            mSecureAcceptThread = new AcceptThread(true);
            mSecureAcceptThread.start();
        }*/
        /*if (mInsecureAcceptThread == null) {
            mInsecureAcceptThread = new AcceptThread(false);
            mInsecureAcceptThread.start();
        }*/
    }
    /**
     * Start the ConnectThread to initiate a connection to a remote device.
     *
     * @param device The BluetoothDevice to connect
     * @param secure Socket Security type - Secure (true) , Insecure (false)
     */
    public synchronized void connect(BluetoothDevice device, boolean secure) {
        Log.d(TAG, "connect to: " + device);
        // Cancel any thread attempting to make a connection
        if (mState == STATE_CONNECTING) {
            if (mConnectThread != null) {
                mConnectThread.cancel();
                mConnectThread = null;
            }
        }
        // Cancel any thread currently running a connection
        if (mConnectedThread != null) {
            mConnectedThread.cancel();
            mConnectedThread = null;
        }
        // Start the thread to connect with the given device
        mConnectThread = new ConnectThread(device, secure);
        mConnectThread.start();
        setState(STATE_CONNECTING);
    }
    public void connect(String address, boolean secure) {
        if (address != null) {
            BluetoothDevice device = mAdapter.getRemoteDevice(address);
            connect(device, secure);
        }
    }
    /**
     * Start the ConnectedThread to begin managing a Bluetooth connection
     *
     * @param socket The BluetoothSocket on which the connection was made
     * @param device The BluetoothDevice that has been connected
     */
    public synchronized void connected(BluetoothSocket socket, BluetoothDevice
            device, final String socketType) {
        Log.d(TAG, "connected, Socket Type:" + socketType + " class: " + device.getBluetoothClass().toString() +  " name: " + device.getName() + " bdaddr: " + device.getAddress());
        // Cancel the thread that completed the connection
        if (mConnectThread != null) {
            mConnectThread.cancel();
            mConnectThread = null;
        }
        // Cancel any thread currently running a connection
        if (mConnectedThread != null) {
            mConnectedThread.cancel();
            mConnectedThread = null;
        }
        // Cancel the accept thread because we only want to connect to one device
        if (mSecureAcceptThread != null) {
            mSecureAcceptThread.cancel();
            mSecureAcceptThread = null;
        }
        if (mInsecureAcceptThread != null) {
            mInsecureAcceptThread.cancel();
            mInsecureAcceptThread = null;
        }
        // Send the name of the connected device back to the UI Activity
        Message msg = mHandler.obtainMessage(Constants.MESSAGE_DEVICE_NAME);
        Bundle bundle = new Bundle();
        bundle.putString(Constants.DEVICE_NAME, device.getName());
        msg.setData(bundle);
        mHandler.sendMessage(msg);
        setState(STATE_CONNECTED);
        // Start the thread to manage the connection and perform transmissions
        mConnectedThread = new ConnectedThread(socket, socketType);
        mConnectedThread.start();
    }
    /**
     * Stop all threads
     */
    public synchronized void stop() {
        Log.d(TAG, "stop");
        if (mConnectThread != null) {
            mConnectThread.cancel();
            mConnectThread = null;
        }
        if (mConnectedThread != null) {
            mConnectedThread.cancel();
            mConnectedThread = null;
        }
        if (mSecureAcceptThread != null) {
            mSecureAcceptThread.cancel();
            mSecureAcceptThread = null;
        }
        if (mInsecureAcceptThread != null) {
            mInsecureAcceptThread.cancel();
            mInsecureAcceptThread = null;
        }
        mGuestContext = null;
        mCallback = null;
        setState(STATE_NONE);
    }
    /**
     * Write to the ConnectedThread in an unsynchronized manner
     *
     * @param out The bytes to write
     * @see ConnectedThread#write(byte[])
     */
    public void write(byte[] out) {
        // Create temporary object
        ConnectedThread r;
        // Synchronize a copy of the ConnectedThread
        synchronized (this) {
            if (mState != STATE_CONNECTED) return;
            r = mConnectedThread;
        }
        // Perform the write unsynchronized
        r.write(out);
    }
    /**
     * Indicate that the connection attempt failed and notify the UI Activity.
     */
    private void connectionFailed() {
        // Send a failure message back to the Activity
        Message msg = mHandler.obtainMessage(Constants.MESSAGE_TOAST);
        Bundle bundle = new Bundle();
        bundle.putString(Constants.TOAST, "Unable to connect device");
        msg.setData(bundle);
        mHandler.sendMessage(msg);
        // Start the service over to restart listening mode
        BluetoothChatService.this.start();
    }
    /**
     * Indicate that the connection was lost and notify the UI Activity.
     */
    private void connectionLost() {
        // Send a failure message back to the Activity
        Message msg = mHandler.obtainMessage(Constants.MESSAGE_TOAST);
        Bundle bundle = new Bundle();
        bundle.putString(Constants.TOAST, "Device connection was lost");
        msg.setData(bundle);
        mHandler.sendMessage(msg);
        // Start the service over to restart listening mode
        BluetoothChatService.this.start();
    }
    /**
     * This thread runs while listening for incoming connections. It behaves
     * like a server-side client. It runs until a connection is accepted
     * (or until cancelled).
     */
    private class AcceptThread extends Thread {
        // The local server socket
        private final BluetoothServerSocket mmServerSocket;
        private String mSocketType;
        public AcceptThread(boolean secure) {
            BluetoothServerSocket tmp = null;
            mSocketType = secure ? "Secure" : "Insecure";
            // Create a new listening server socket
            try {
                if (secure) {
                    tmp = mAdapter.listenUsingRfcommWithServiceRecord(NAME_SECURE,
                            MY_UUID_SECURE);
                } else {
                    tmp = mAdapter.listenUsingInsecureRfcommWithServiceRecord(
                            NAME_INSECURE, MY_UUID_INSECURE);
                }
            } catch (IOException e) {
                Log.e(TAG, "Socket Type: " + mSocketType + " listen() failed", e);
            }
            mmServerSocket = tmp;
        }
        public void run() {
            Log.d(TAG, "Socket Type: " + mSocketType +
                    " BEGIN mAcceptThread " + this);
            BluetoothSocket socket = null;
            // Listen to the server socket if we're not connected
            while (mState != STATE_CONNECTED && mmServerSocket != null) {
                try {
                    // This is a blocking call and will only return on a
                    // successful connection or an exception
                    socket = mmServerSocket.accept();
                } catch (IOException e) {
                    Log.e(TAG, "Socket Type: " + mSocketType + "accept() failed", e);
                    break;
                }
                // If a connection was accepted
                if (socket != null) {
                    synchronized (BluetoothChatService.this) {
                        switch (mState) {
                            case STATE_LISTEN:
                            case STATE_CONNECTING:
                                // Situation normal. Start the connected thread.
                                connected(socket, socket.getRemoteDevice(),
                                        mSocketType);
                                break;
                            case STATE_NONE:
                            case STATE_CONNECTED:
                                // Either not ready or already connected. Terminate new socket.
                                try {
                                    socket.close();
                                } catch (IOException e) {
                                    Log.e(TAG, "Could not close unwanted socket", e);
                                }
                                break;
                        }
                    }
                }
            }
            Log.i(TAG, "END mAcceptThread, socket Type: " + mSocketType);
        }
        public void cancel() {
            Log.d(TAG, "Socket Type" + mSocketType + "cancel " + this);
            try {
                if (mmServerSocket != null)
                    mmServerSocket.close();
            } catch (IOException e) {
                Log.e(TAG, "Socket Type" + mSocketType + "close() of server failed", e);
            }
        }
    }
    /**
     * This thread runs while attempting to make an outgoing connection
     * with a device. It runs straight through; the connection either
     * succeeds or fails.
     */
    private class ConnectThread extends Thread {
        private final BluetoothSocket mmSocket;
        private final BluetoothDevice mmDevice;
        private String mSocketType;
        public ConnectThread(BluetoothDevice device, boolean secure) {
            mmDevice = device;
            BluetoothSocket tmp = null;
            mSocketType = secure ? "Secure" : "Insecure";
            // Get a BluetoothSocket for a connection with the
            // given BluetoothDevice
            try {
                if (secure) {
                    tmp = device.createRfcommSocketToServiceRecord(
                            MY_UUID_SECURE);
                } else {
                    tmp = device.createInsecureRfcommSocketToServiceRecord(
                            MY_UUID_INSECURE);
                }
            } catch (IOException e) {
                Log.e(TAG, "Socket Type: " + mSocketType + "create() failed", e);
            }
            mmSocket = tmp;
        }
        public void run() {
            Log.i(TAG, "BEGIN mConnectThread SocketType:" + mSocketType);
            // Always cancel discovery because it will slow down a connection
            mAdapter.cancelDiscovery();
            // Make a connection to the BluetoothSocket
            try {
                // This is a blocking call and will only return on a
                // successful connection or an exception
                mmSocket.connect();
            } catch (IOException e) {
                // Close the socket
                try {
                    mmSocket.close();
                } catch (IOException e2) {
                    Log.e(TAG, "unable to close() " + mSocketType +
                            " socket during connection failure", e2);
                }
                connectionFailed();
                return;
            }
            // Reset the ConnectThread because we're done
            synchronized (BluetoothChatService.this) {
                mConnectThread = null;
            }
            // Start the connected thread
            connected(mmSocket, mmDevice, mSocketType);
        }
        public void cancel() {
            try {
                mmSocket.close();
            } catch (IOException e) {
                Log.e(TAG, "close() of connect " + mSocketType + " socket failed", e);
            }
        }
    }
    /**
     * This thread runs during a connection with a remote device.
     * It handles all incoming and outgoing transmissions.
     */
    private class ConnectedThread extends Thread {
        private final BluetoothSocket mmSocket;
        private final InputStream mmInStream;
        private final OutputStream mmOutStream;
        public ConnectedThread(BluetoothSocket socket, String socketType) {
            Log.d(TAG, "create ConnectedThread: " + socketType);
            mmSocket = socket;
            InputStream tmpIn = null;
            OutputStream tmpOut = null;
            // Get the BluetoothSocket input and output streams
            try {
                tmpIn = socket.getInputStream();
                tmpOut = socket.getOutputStream();
            } catch (IOException e) {
                Log.e(TAG, "temp sockets not created", e);
            }
            mmInStream = tmpIn;
            mmOutStream = tmpOut;
        }
        public void run() {
            Log.i(TAG, "BEGIN mConnectedThread");
            // Keep listening to the InputStream while connected
            while (mState == STATE_CONNECTED) {
                try {
                    byte[] buffer = new byte[4096];
                    int bytes;
                    // Read from the InputStream
                    bytes = mmInStream.read(buffer);
                    if (mCallback != null) {
                        mCallback.iDataComeIn(buffer, bytes);
                    } else {
                        // Send the obtained bytes to the UI Activity
                    mHandler.obtainMessage(Constants.MESSAGE_READ, bytes, -1, buffer)
                            .sendToTarget();
                    }
                } catch (IOException e) {
                    Log.e(TAG, "disconnected", e);
                    connectionLost();
                    // Start the service over to restart listening mode
//                    BluetoothChatService.this.start();
                    break;
                }
            }
            Log.i(TAG, "END mConnectedThread");
        }
        /**
         * Write to the connected OutStream.
         *
         * @param buffer The bytes to write
         */
        public void write(byte[] buffer) {
            try {
                mmOutStream.write(buffer);
                // Share the sent message back to the UI Activity
//                mHandler.obtainMessage(Constants.MESSAGE_WRITE, -1, -1, buffer)
//                        .sendToTarget();
            } catch (IOException e) {
                Log.e(TAG, "Exception during write", e);
            }
        }
        public void cancel() {
            try {
                mmSocket.close();
            } catch (IOException e) {
                Log.e(TAG, "close() of connect socket failed", e);
            }
        }
    }
}
lib/src/main/java/com/anyun/exam/lib/util/BluetoothChatServiceCallback.java
New file
@@ -0,0 +1,5 @@
package com.anyun.exam.lib.util;
public interface BluetoothChatServiceCallback {
    void iDataComeIn(byte[] data, int length);
}
lib/src/main/java/com/anyun/exam/lib/util/ClsUtils.java
New file
@@ -0,0 +1,138 @@
package com.anyun.exam.lib.util;
/************************************ 蓝牙配对函数 * **************/
import android.bluetooth.BluetoothDevice;
import android.util.Log;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class ClsUtils
{
    /**
     * 与设备配对 参考源码:platform/packages/apps/Settings.git
     * /Settings/src/com/android/settings/bluetooth/CachedBluetoothDevice.java
     */
    static public boolean createBond(Class btClass, BluetoothDevice btDevice)
    throws Exception
    {
        Method createBondMethod = btClass.getMethod("createBond");
        Boolean returnValue = (Boolean) createBondMethod.invoke(btDevice);
        return returnValue.booleanValue();
    }
    /**
     * 与设备解除配对 参考源码:platform/packages/apps/Settings.git
     * /Settings/src/com/android/settings/bluetooth/CachedBluetoothDevice.java
     */
    static public boolean removeBond(Class<?> btClass, BluetoothDevice btDevice)
            throws Exception
    {
        Method removeBondMethod = btClass.getMethod("removeBond");
        Boolean returnValue = (Boolean) removeBondMethod.invoke(btDevice);
        return returnValue.booleanValue();
    }
    static public boolean setPin(Class<? extends BluetoothDevice> btClass, BluetoothDevice btDevice,
                                 String str) throws Exception
    {
        try
        {
            Method removeBondMethod = btClass.getDeclaredMethod("setPin",
                    new Class[]
                    {byte[].class});
            Boolean returnValue = (Boolean) removeBondMethod.invoke(btDevice,
                    new Object[]
                    {str.getBytes()});
            Log.e("returnValue", "" + returnValue);
        }
        catch (SecurityException e)
        {
            // throw new RuntimeException(e.getMessage());
            e.printStackTrace();
        }
        catch (IllegalArgumentException e)
        {
            // throw new RuntimeException(e.getMessage());
            e.printStackTrace();
        }
        catch (Exception e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return true;
    }
    // 取消用户输入
    static public boolean cancelPairingUserInput(Class<?> btClass,
                                                 BluetoothDevice device)  throws Exception
    {
        Method createBondMethod = btClass.getMethod("cancelPairingUserInput");
//        cancelBondProcess(btClass, device);
        Boolean returnValue = (Boolean) createBondMethod.invoke(device);
        return returnValue.booleanValue();
    }
    // 取消配对
    static public boolean cancelBondProcess(Class<?> btClass,
                                            BluetoothDevice device)
    throws Exception
    {
        Method createBondMethod = btClass.getMethod("cancelBondProcess");
        Boolean returnValue = (Boolean) createBondMethod.invoke(device);
        return returnValue.booleanValue();
    }
    //确认配对
    static public void setPairingConfirmation(Class<?> btClass, BluetoothDevice device, boolean isConfirm)throws Exception
    {
        Method setPairingConfirmation = btClass.getDeclaredMethod("setPairingConfirmation",boolean.class);
        setPairingConfirmation.invoke(device,isConfirm);
    }
    /**
     *
     * @param clsShow
     */
    static public void printAllInform(Class clsShow)
    {
        try
        {
            // 取得所有方法
            Method[] hideMethod = clsShow.getMethods();
            int i = 0;
            for (; i < hideMethod.length; i++)
            {
                Log.e("method name", hideMethod[i].getName() + ";and the i is:"
                        + i);
            }
            // 取得所有常量
            Field[] allFields = clsShow.getFields();
            for (i = 0; i < allFields.length; i++)
            {
                Log.e("Field name", allFields[i].getName());
            }
        }
        catch (SecurityException e)
        {
            // throw new RuntimeException(e.getMessage());
            e.printStackTrace();
        }
        catch (IllegalArgumentException e)
        {
            // throw new RuntimeException(e.getMessage());
            e.printStackTrace();
        }
        catch (Exception e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}
lib/src/main/java/com/anyun/exam/lib/util/Constants.java
New file
@@ -0,0 +1,40 @@
/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.anyun.exam.lib.util;
/**
 * Defines several constants used between {@link BluetoothChatService} and the UI.
 */
public interface Constants {
    // Message types sent from the BluetoothChatService Handler
    public static final int MESSAGE_STATE_CHANGE = 1;
    public static final int MESSAGE_READ = 2;
    public static final int MESSAGE_WRITE = 3;
    public static final int MESSAGE_DEVICE_NAME = 4;
    public static final int MESSAGE_TOAST = 5;
    public static final int MESSAGE_BLUETOOTH_STATUS = 6;
    public static final int MESSAGE_BLUETOOTH_FOUND = 7;
    public static final int MESSAGE_BLUETOOTH_DISCOVERY_FINISHED = 8;
    // Key names received from the BluetoothChatService Handler
    public static final String DEVICE_NAME = "device_name";
    public static final String DEVICE_ADDRESS = "device_address";
    public static final String TOAST = "toast";
}