From 95046e2198b34a0eabc4dfcbaba329c1a9da9f0c Mon Sep 17 00:00:00 2001 From: UnknownObject Date: Thu, 25 May 2023 19:49:13 +0800 Subject: [PATCH] commit all --- .idea/misc.xml | 4 + app/build.gradle | 5 +- app/release/output-metadata.json | 4 +- app/src/main/AndroidManifest.xml | 9 + app/src/main/cpp/main_car_aes.cpp | 199 ++-------- app/src/main/cpp/main_car_aes.h | 89 +---- app/src/main/cpp/ocr_text.h | 3 +- .../com/uns/maincar/constants/Commands.java | 6 + .../java/com/uns/maincar/constants/Flags.java | 1 + .../java/com/uns/maincar/gui/DebugPage.java | 41 ++ .../com/uns/maincar/gui/MainActivity.java | 224 ++++++----- .../java/com/uns/maincar/gui/RaceTasks.java | 61 +++ .../uns/maincar/gui/SingleFunctionTest.java | 39 ++ .../com/uns/maincar/tools/TextFilter.java | 11 + .../maincar/tools/camera/CameraOperator.java | 62 +++ .../maincar/tools/camera/CameraSearcher.java | 83 ++++ .../main/res/layout/activity_debug_page.xml | 77 ++++ app/src/main/res/layout/activity_main.xml | 374 +----------------- .../main/res/layout/activity_race_tasks.xml | 201 ++++++++++ .../layout/activity_single_function_test.xml | 188 +++++++++ .../6x33t2q6/meta/arm64-v8a/build_model.json | 6 +- .../arm64-v8a/metadata_generation_record.json | 6 +- .../metadata_generation_record.json | 6 +- .../x86/generate_cxx_metadata_292_timing.txt | 4 + .../x86/generate_cxx_metadata_31_timing.txt | 10 + .../meta/x86/metadata_generation_record.json | 6 +- .../x86_64/metadata_generation_record.json | 6 +- .../6x33t2q6/obj/x86/libopencv_jni_shared.a | Bin 700 -> 700 bytes .../generate_cxx_metadata_223_timing.txt | 5 + .../arm64-v8a/metadata_generation_record.json | 6 +- .../metadata_generation_record.json | 6 +- .../meta/x86/metadata_generation_record.json | 6 +- .../x86_64/metadata_generation_record.json | 6 +- .../cxx/abi_configuration_1842623l.log | 2 +- .../cxx/abi_configuration_311k5o12.log | 2 +- .../cxx/create_cxx_tasks_1343_timing.txt | 12 + .../cxx/create_cxx_tasks_292_timing.txt | 25 ++ .../cxx/create_cxx_tasks_31_timing.txt | 51 +++ .../cxx/ndk_locator_record_50t213g5.log | 12 +- 39 files changed, 1125 insertions(+), 733 deletions(-) create mode 100644 app/src/main/java/com/uns/maincar/gui/DebugPage.java create mode 100644 app/src/main/java/com/uns/maincar/gui/RaceTasks.java create mode 100644 app/src/main/java/com/uns/maincar/gui/SingleFunctionTest.java create mode 100644 app/src/main/java/com/uns/maincar/tools/camera/CameraOperator.java create mode 100644 app/src/main/java/com/uns/maincar/tools/camera/CameraSearcher.java create mode 100644 app/src/main/res/layout/activity_debug_page.xml create mode 100644 app/src/main/res/layout/activity_race_tasks.xml create mode 100644 app/src/main/res/layout/activity_single_function_test.xml diff --git a/.idea/misc.xml b/.idea/misc.xml index 32de682..9f2ea71 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -7,9 +7,13 @@ + + + + diff --git a/app/build.gradle b/app/build.gradle index 1f39919..2b41740 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -9,8 +9,8 @@ android { applicationId "com.uns.maincar" minSdk 26 targetSdk 32 - versionCode 25 - versionName '2.2.2' + versionCode 30 + versionName '3.0.0' testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" externalNativeBuild { @@ -18,7 +18,6 @@ android { cppFlags '' } } - versionNameSuffix '-beta' } buildTypes { diff --git a/app/release/output-metadata.json b/app/release/output-metadata.json index 796f0e6..ec71d0a 100644 --- a/app/release/output-metadata.json +++ b/app/release/output-metadata.json @@ -11,8 +11,8 @@ "type": "SINGLE", "filters": [], "attributes": [], - "versionCode": 25, - "versionName": "2.2.2-beta", + "versionCode": 30, + "versionName": "3.0.0", "outputFile": "app-release.apk" } ], diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index eb11ff0..bdc26cf 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -38,6 +38,15 @@ android:theme="@style/Theme.MainCar" android:usesCleartextTraffic="true" tools:targetApi="31"> + + + diff --git a/app/src/main/cpp/main_car_aes.cpp b/app/src/main/cpp/main_car_aes.cpp index edeaa4e..3824606 100644 --- a/app/src/main/cpp/main_car_aes.cpp +++ b/app/src/main/cpp/main_car_aes.cpp @@ -10,186 +10,52 @@ namespace uns { - BinaryByteArray uns::MC_AES::CreateTextArray(std::string str) + void MC_AES::KSA() { - if (str.size() > 16) - return nullptr; - BinaryByteArray arr = new ByteArray[4]; - for (int i = 0; i < 4; i++) - arr[i] = new byte[4]; - if (str.size() != 16) + int j = 0; + for (i = 0; i < 256; i++) { - int fix_bit = 16 - str.size(); - while (str.size() < 16) - str.push_back(fix_bit); + j = (j + S[i] + K[i]) % 256; + Swap(S[i], S[j]); } - for (int i = 0; i < str.size(); i += 4) - { - for (int j = i; j < i + 4; j++) - arr[j - i][i / 4] = str[j]; - } - return arr; - } - - word uns::MC_AES::Byte2Word(std::string str_4) - { - word result = 0; - result |= ((unsigned long long)str_4[0] << 24); - result |= ((unsigned long long)str_4[1] << 16); - result |= ((unsigned long long)str_4[2] << 8); - result |= str_4[3]; - return result; - } - - WordArray uns::MC_AES::CreateKeyArray(std::string key) - { - if (key.size() != 16) - return nullptr; - WordArray arr = new word[4]; - for (int i = 0; i < 16; i += 4) - arr[i / 4] = Byte2Word(key.substr(i, 4)); - return arr; - } - - word uns::MC_AES::CircleLeft(word rw) - { - word high = rw << 8; - word low = rw >> 24; - return high | low; - } - - ByteArray uns::MC_AES::MoveLeft(ByteArray bytes, int bits) - { - if (bits == 0) - return bytes; - else - { - bits = bits % 4; - while (bits--) - { - byte index = bytes[0]; - for (int i = 0; i < 3; i++) - bytes[i] = bytes[i + 1]; - bytes[3] = index; - } - return bytes; - } - } - - word uns::MC_AES::SubWord(word sw) - { - word temp; - for (int i = 0; i < 32; i += 8) - { - int row = sw[i + 7] * 8 + sw[i + 6] * 4 + sw[i + 5] * 2 + sw[i + 4]; - int col = sw[i + 3] * 8 + sw[i + 2] * 4 + sw[i + 1] * 2 + sw[i]; - byte val = S_Box[row][col]; - for (int j = 0; j < 8; ++j) - temp[i + j] = val[j]; - } - return temp; - } - - WordArray uns::MC_AES::KeyExpansion(WordArray fix_key) - { - WordArray keys = new word[44]; - for (int i = 0; i < 44; i++) - { - if (i < 4) - keys[i] = fix_key[i]; - else if ((i % 4) != 0) - keys[i] = keys[i - 4] ^ keys[i - 1]; - else - keys[i] = keys[i - 4] ^ SubWord(CircleLeft(keys[i - 1])) ^ Rcon[(i / 4) - 1]; - } - delete[] fix_key; - return keys; - } - - BinaryByteArray uns::MC_AES::BytesReplace(BinaryByteArray bytes) - { - for (int i = 0; i < 4; i++) - for (int j = 0; j < 4; j++) - { - int row = bytes[i][j][7] * 8 + bytes[i][j][6] * 4 + bytes[i][j][5] * 2 + bytes[i][j][4]; - int col = bytes[i][j][3] * 8 + bytes[i][j][2] * 4 + bytes[i][j][1] * 2 + bytes[i][j][0]; - bytes[i][j] = S_Box[row][col]; - } - return bytes; } - BinaryByteArray uns::MC_AES::ByteShift(BinaryByteArray bytes) + int MC_AES::PRGA() { - for (int i = 0; i < 4; i++) - bytes[i] = MoveLeft(bytes[i], i); - return bytes; + i = (i + 1) % 256; + j = (j + S[i]) % 256; + Swap(S[i], S[j]); + int t = (S[i] + S[j]) % 256; + return S[t]; } - BinaryByteArray uns::MC_AES::ColumnMix(BinaryByteArray bytes) + void MC_AES::Swap(int &a, int &b) { - for(int i = 0; i < 4; i++) - for (int j = 0; j < 4; j++) - bytes[i][j] = bytes[i][j].to_ullong() + Columns[i][j].to_ulong(); - return bytes; + int temp = a; + a = b; + b = temp; } - byte uns::MC_AES::SplitWord(word w, int index) + void MC_AES::InitBox(std::string data) { - if ((index < 0) || (index >= 4)) - return 0; - WordSpliter spliter; - spliter._word = w.to_ullong(); - return spliter._result[index]; - } - - WordArray uns::MC_AES::GetCurrentKeys(WordArray keys, int times) - { - if ((times < 0) || (times >= 10)) - return nullptr; - WordArray result = new word[4]; - for (int i = 4; i <= 7; i++) - result[i - 4] = keys[i + times]; - return result; - } - - BinaryByteArray uns::MC_AES::ColumnMix(BinaryByteArray bytes, WordArray keys) - { - for (int i = 0; i < 4; i++) + int data_index = 0; + for (int i = 0; i < 256; i++) { - for (int j = 0; j < 4; j++) - bytes[j][i] ^= SplitWord(keys[i], 3 - j).to_ullong(); + S.push_back(i); + K.push_back(data[data_index++]); + if (data_index == data.length()) + data_index = 0; } - delete[] keys; - return bytes; - } - - ByteArray uns::MC_AES::GetAlarmCode(BinaryByteArray bytes) - { - WordArray wcode = new word[4]; - ByteArray bcode = new byte[6]; - memset(wcode, 0, sizeof(wcode)); - memset(bcode, 0, sizeof(bcode)); - for (int i = 0; i < 4; i++) - for (int j = 0; j < 4; j++) - wcode[i] = wcode[i].to_ullong() + bytes[j][i].to_ullong(); - bcode[0] = S_Box[0x0][0x0]; - bcode[1] = S_Box[0xF][0xF]; - for (int i = 0; i < 4; i++) - bcode[i + 2] = SplitWord(wcode[i], 0); - delete[] wcode; - return bcode; } - ByteArray MC_AES::RunAES(std::string text, std::string key) + Box MC_AES::Run(std::string info, std::string data) { - BinaryByteArray arr = CreateTextArray(text); - WordArray warr = KeyExpansion(CreateKeyArray(key)); - for (int i = 0; i < 10; i++) - arr = ColumnMix(ColumnMix(ByteShift(BytesReplace(arr))), GetCurrentKeys(warr, i)); - ByteArray code = GetAlarmCode(arr); - delete[] arr; - delete[] warr; - return code; + InitBox(data); + KSA(); + Box password; + for (auto &chr: info) + password.push_back(PRGA() ^ chr); + return password; } }; @@ -206,11 +72,10 @@ jboolean JNICALL Java_com_uns_maincar_cpp_1interface_MainCarAES_RunAES(JNIEnv *e if(result == nullptr) return false; uns::MC_AES aes; - uns::ByteArray arr = aes.RunAES(env->GetStringUTFChars(text, 0)); - jbyte barr[6] = { 0 }; + uns::Box arr = aes.Run("chinaskills", env->GetStringUTFChars(text, 0)); + jbyte barr[6] = {0}; for(int i = 0; i < 6; i++) - barr[i] = (jbyte)arr[i].to_ulong(); + barr[i] = (jbyte) arr[i]; env->SetByteArrayRegion(result, 0, 6, barr); - delete[] arr; return true; } \ No newline at end of file diff --git a/app/src/main/cpp/main_car_aes.h b/app/src/main/cpp/main_car_aes.h index fc95887..ddbecf5 100644 --- a/app/src/main/cpp/main_car_aes.h +++ b/app/src/main/cpp/main_car_aes.h @@ -8,7 +8,7 @@ //数据处理算法 -#define MAIN_CAR_AES_VERSION "1.0.0" +#define MAIN_CAR_AES_VERSION "2.0.0" #include #include @@ -17,87 +17,24 @@ namespace uns { - using byte = std::bitset<8>; - using word = std::bitset<32>; - - using ByteArray = byte*; - using WordArray = word*; - using BinaryByteArray = byte**; - using BinaryWordArray = word**; - - union WordSpliter - { - unsigned long long _word; - char _result[4]; - }; + using Box = std::vector; class MC_AES { private: - byte S_Box[16][16] = - { - {0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, - 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76}, - {0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, - 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0}, - {0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, - 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15}, - {0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, - 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75}, - {0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, - 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84}, - {0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, - 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF}, - {0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, - 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8}, - {0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, - 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2}, - {0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, - 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73}, - {0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, - 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB}, - {0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, - 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79}, - {0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, - 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08}, - {0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, - 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A}, - {0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, - 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E}, - {0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, - 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF}, - {0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, - 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16} - }; - word Rcon[10] = - { - 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, - 0x20000000, 0x40000000, 0x80000000, 0x1b000000, 0x36000000 - }; - byte Columns[4][4] = - { - {0x0E, 0x09, 0x0D, 0x0B}, - {0x0B, 0x0E, 0x0D, 0x09}, - {0x0D, 0x09, 0x0B, 0x0E}, - {0x09, 0x0D, 0x0B, 0x0E} - }; + Box S, K; + int i = 0, j = 0; private: - BinaryByteArray CreateTextArray(std::string str); - word Byte2Word(std::string str_4); - WordArray CreateKeyArray(std::string key); - word CircleLeft(word rw); - ByteArray MoveLeft(ByteArray bytes, int bits); - word SubWord(word sw); - WordArray KeyExpansion(WordArray fix_key); - BinaryByteArray BytesReplace(BinaryByteArray bytes); - BinaryByteArray ByteShift(BinaryByteArray bytes); - BinaryByteArray ColumnMix(BinaryByteArray bytes); - byte SplitWord(word w, int index); - WordArray GetCurrentKeys(WordArray keys, int times); - BinaryByteArray ColumnMix(BinaryByteArray bytes, WordArray keys); - ByteArray GetAlarmCode(BinaryByteArray bytes); + void KSA(); + + int PRGA(); + + void Swap(int &a, int &b); + + void InitBox(std::string data); + public: - ByteArray RunAES(std::string text, std::string key = "abcdefghijklmnop"); + Box Run(std::string info, std::string data); }; }; diff --git a/app/src/main/cpp/ocr_text.h b/app/src/main/cpp/ocr_text.h index 6ce31b4..ba9ef99 100644 --- a/app/src/main/cpp/ocr_text.h +++ b/app/src/main/cpp/ocr_text.h @@ -19,11 +19,10 @@ namespace uns class OCRSupport { private: - const int limit = 90; + const int limit = 105; cv::Rect roi = cv::Rect(150, 60, 350, 300); private: bool PixelCheck(const cv::Vec3b &pixel); - public: cv::Mat CutImageSize(const cv::Mat &img); diff --git a/app/src/main/java/com/uns/maincar/constants/Commands.java b/app/src/main/java/com/uns/maincar/constants/Commands.java index ef4f21b..138cdef 100644 --- a/app/src/main/java/com/uns/maincar/constants/Commands.java +++ b/app/src/main/java/com/uns/maincar/constants/Commands.java @@ -73,6 +73,12 @@ public class Commands public static byte TASK_NUMBER_7 = 0x07; public static byte TASK_NUMBER_8 = 0x08; public static byte TASK_NUMBER_9 = 0x09; + public static byte TASK_NUMBER_10 = 0x10; + public static byte TASK_NUMBER_11 = 0x11; + public static byte TASK_NUMBER_12 = 0x12; + public static byte TASK_NUMBER_13 = 0x13; + public static byte TASK_NUMBER_14 = 0x14; + public static byte TASK_NUMBER_15 = 0x15; //全自动模式 public static final byte RECEIVE_FULL_AUTO = (byte) 0xA0; diff --git a/app/src/main/java/com/uns/maincar/constants/Flags.java b/app/src/main/java/com/uns/maincar/constants/Flags.java index df2165b..13f7c49 100644 --- a/app/src/main/java/com/uns/maincar/constants/Flags.java +++ b/app/src/main/java/com/uns/maincar/constants/Flags.java @@ -12,6 +12,7 @@ public class Flags //日志TAG public static final String CLIENT_TAG = "MAIN-CAR-CLIENT"; public static final String CLIENT_SEND_EX = "SEND-EX-RECEIVED"; + public static final String SUB_ACTIVITY_TAG = "SUB-ACTIVITY"; //摄像头控制指令 public static final int CAMERA_UP = 0; diff --git a/app/src/main/java/com/uns/maincar/gui/DebugPage.java b/app/src/main/java/com/uns/maincar/gui/DebugPage.java new file mode 100644 index 0000000..e34b1f9 --- /dev/null +++ b/app/src/main/java/com/uns/maincar/gui/DebugPage.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2023. UnknownNetworkService Group + * This file is created by UnknownObject at 2023 - 5 - 1 + */ + +package com.uns.maincar.gui; + +import android.annotation.SuppressLint; +import android.os.Bundle; +import android.util.Log; +import android.widget.Toast; + +import androidx.appcompat.app.AppCompatActivity; + +import com.uns.maincar.R; +import com.uns.maincar.constants.Flags; + +public class DebugPage extends AppCompatActivity +{ + + @SuppressLint("StaticFieldLeak") + protected static MainActivity Parent = null; //用于调用MainActivity内函数的静态成员变量 + + @Override + protected void onCreate(Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_debug_page); + + if (Parent == null) + { + Toast.makeText(this, "Context is null!", Toast.LENGTH_SHORT).show(); + Log.e(Flags.SUB_ACTIVITY_TAG, "Context IS NULL"); + finish(); + } + + findViewById(R.id.btn_debug_send).setOnClickListener(view -> Parent.DebugPageCallback_DebugSend()); + + findViewById(R.id.btn_send).setOnClickListener(view -> Parent.DebugPageCallback_SendByInput(this)); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/uns/maincar/gui/MainActivity.java b/app/src/main/java/com/uns/maincar/gui/MainActivity.java index ae70171..720fd27 100644 --- a/app/src/main/java/com/uns/maincar/gui/MainActivity.java +++ b/app/src/main/java/com/uns/maincar/gui/MainActivity.java @@ -6,6 +6,7 @@ package com.uns.maincar.gui; import android.annotation.SuppressLint; +import android.app.Activity; import android.content.Context; import android.content.Intent; import android.graphics.Bitmap; @@ -26,8 +27,6 @@ import android.widget.Toast; import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; -import com.bkrcl.control_car_video.camerautil.CameraCommandUtil; -import com.bkrcl.control_car_video.camerautil.SearchCameraUtil; import com.uns.maincar.R; import com.uns.maincar.communication.CommandDecoder; import com.uns.maincar.communication.CommandEncoder; @@ -49,6 +48,8 @@ import com.uns.maincar.cpp_interface.TrafficSign; import com.uns.maincar.tools.ImageReleaser; import com.uns.maincar.tools.OCRDataReleaser; import com.uns.maincar.tools.TextFilter; +import com.uns.maincar.tools.camera.CameraOperator; +import com.uns.maincar.tools.camera.CameraSearcher; import java.io.UnsupportedEncodingException; import java.util.ArrayList; @@ -74,10 +75,8 @@ public class MainActivity extends AppCompatActivity private ImageView pic_received; //控件——存储Toast的内容,由ToastLog()进行管理 private TextView text_toast; - //控制主车相机 - private CameraCommandUtil cameraCommandUtil; //寻找主车相机 - private SearchCameraUtil searchCameraUtil = null; + private CameraSearcher cameraSearcher = null; //程序状态,通过所有自检后会设置为true private boolean SystemStatus = false; //文件状态,获取到存储权限并释放完毕所有文件会设置为true @@ -224,7 +223,22 @@ public class MainActivity extends AppCompatActivity //处理二维码数据,使用从C++代码中导出的算法 private byte[] ProcessQRData(ArrayList qr_data) { - return MainCarAES.CalcAES(qr_data.get(0)); + String validate_result = ""; + CommandEncoder encoder = new CommandEncoder(); + TextFilter filter = new TextFilter(); + for (String data : qr_data) + { + String processed_data = filter.LetterAndNumber(data); + if (processed_data.length() > 0) + { + validate_result = processed_data; + break; + } + } + if (validate_result.equals("")) + return encoder.GenerateCommand(Commands.QR_FAILED, (byte) 0, (byte) 0, (byte) 0); + else + return MainCarAES.CalcAES(validate_result); } //获取程序自检指令,根据自检状态返回成功或失败 @@ -414,7 +428,7 @@ public class MainActivity extends AppCompatActivity private void OCRRecognizeText() { TextFilter filter = new TextFilter(); - String str = filter.NoUnderLine(filter.RemoveEmptyCharacter(OCR.DecodeImage(currImage))); + String str = filter.ChineseOnly(filter.RemoveEmptyCharacter(OCR.DecodeImage(currImage))); ToastLog("OCR Result: [" + str + "]", false, true); byte[] b_str; try @@ -455,8 +469,8 @@ public class MainActivity extends AppCompatActivity return msg_str.toString(); } - //向主车发送一条任务指令 - private void SendTaskCommand(byte task_cmd) + //向主车发送一条任务指令(改为protected允许类外调用) + protected void SendTaskCommand(byte task_cmd) { CommandEncoder encoder = new CommandEncoder(); Thread th_send = new Thread(() -> @@ -469,98 +483,101 @@ public class MainActivity extends AppCompatActivity th_send.start(); } - //初始化比赛任务按钮 - private void InitTaskButton() + /* + 以下protected函数用于在主界面外允许对主界面功能的调用,利用静态MainActivity对象绕过Android对不同Activity间函数调用的限制 + 此操(mo)作(fa)仅用于实现UI分离和操作逻辑优化,与实际功能代码无关。 + */ + //----------------------------------------由此处开始---------------------------------------- + //用于调试页面的发送调试信息函数 + protected void DebugPageCallback_DebugSend() { - findViewById(R.id.btn_task_0).setOnClickListener(view -> SendTaskCommand(Commands.TASK_NUMBER_0)); - findViewById(R.id.btn_task_1).setOnClickListener(view -> SendTaskCommand(Commands.TASK_NUMBER_1)); - findViewById(R.id.btn_task_2).setOnClickListener(view -> SendTaskCommand(Commands.TASK_NUMBER_2)); - findViewById(R.id.btn_task_3).setOnClickListener(view -> SendTaskCommand(Commands.TASK_NUMBER_3)); - findViewById(R.id.btn_task_4).setOnClickListener(view -> SendTaskCommand(Commands.TASK_NUMBER_4)); - findViewById(R.id.btn_task_5).setOnClickListener(view -> SendTaskCommand(Commands.TASK_NUMBER_5)); - findViewById(R.id.btn_task_6).setOnClickListener(view -> SendTaskCommand(Commands.TASK_NUMBER_6)); - findViewById(R.id.btn_task_7).setOnClickListener(view -> SendTaskCommand(Commands.TASK_NUMBER_7)); - findViewById(R.id.btn_task_8).setOnClickListener(view -> SendTaskCommand(Commands.TASK_NUMBER_8)); - findViewById(R.id.btn_task_9).setOnClickListener(view -> SendTaskCommand(Commands.TASK_NUMBER_9)); + byte[] data = new byte[]{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}; + dtc_client.ThreadSend(data); } - //初始化图形界面 - private void InitGUI() + //用于调试页面的发送调试信息函数 + protected void DebugPageCallback_SendByInput(Activity context) { - pic_received = findViewById(R.id.camera_image); - text_toast = findViewById(R.id.text_toast); - - text_toast.setMovementMethod(ScrollingMovementMethod.getInstance()); - - findViewById(R.id.btn_debug_send).setOnClickListener(view -> + try { - byte[] data = new byte[]{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}; - dtc_client.ThreadSend(data); - }); - - findViewById(R.id.btn_camera_up).setOnClickListener(view -> + byte cmd0 = (byte) Integer.parseInt(((EditText) context.findViewById(R.id.edit_cmd0)).getText().toString(), 16); + byte cmd1 = (byte) Integer.parseInt(((EditText) context.findViewById(R.id.edit_cmd1)).getText().toString(), 16); + byte cmd2 = (byte) Integer.parseInt(((EditText) context.findViewById(R.id.edit_cmd2)).getText().toString(), 16); + byte cmd3 = (byte) Integer.parseInt(((EditText) context.findViewById(R.id.edit_cmd3)).getText().toString(), 16); + CommandEncoder encoder = new CommandEncoder(); + byte[] cmd = encoder.GenerateCommand(cmd0, cmd1, cmd2, cmd3); + dtc_client.ThreadSend(cmd); + //print debug information + Message.obtain(recvHandler, Flags.PRINT_DATA_ARRAY, cmd).sendToTarget(); + } + catch (Exception e) { - Thread th_send = new Thread(() -> cameraCommandUtil.postHttp(IPCamera, Flags.CAMERA_UP, 5)); - th_send.start(); - }); - - findViewById(R.id.btn_camera_down).setOnClickListener(view -> + ToastLog("Input Data Invalidate", true, false); + } + } + + //提供给单元测试页面用于初始化按钮的回调函数 + protected void InitSingleFunctionTestUnit(Activity context) + { + context.findViewById(R.id.btn_camera_up).setOnClickListener(view -> { - Thread th_send = new Thread(() -> cameraCommandUtil.postHttp(IPCamera, Flags.CAMERA_DOWN, 5)); + Thread th_send = new Thread(() -> + { + if (!CameraOperator.SendCommand(IPCamera, Flags.CAMERA_UP, 5)) + ToastLog("Camera Command (UP) Failure.", false, true); + }); th_send.start(); }); - findViewById(R.id.btn_camera_left).setOnClickListener(view -> + context.findViewById(R.id.btn_camera_down).setOnClickListener(view -> { - Thread th_send = new Thread(() -> cameraCommandUtil.postHttp(IPCamera, Flags.CAMERA_LEFT, 5)); + Thread th_send = new Thread(() -> + { + if (!CameraOperator.SendCommand(IPCamera, Flags.CAMERA_DOWN, 5)) + ToastLog("Camera Command (DOWN) Failure.", false, true); + }); th_send.start(); }); - findViewById(R.id.btn_camera_right).setOnClickListener(view -> + context.findViewById(R.id.btn_camera_left).setOnClickListener(view -> { - Thread th_send = new Thread(() -> cameraCommandUtil.postHttp(IPCamera, Flags.CAMERA_RIGHT, 5)); + Thread th_send = new Thread(() -> + { + if (!CameraOperator.SendCommand(IPCamera, Flags.CAMERA_LEFT, 5)) + ToastLog("Camera Command (LEFT) Failure.", false, true); + }); th_send.start(); }); - findViewById(R.id.btn_send).setOnClickListener(view -> + context.findViewById(R.id.btn_camera_right).setOnClickListener(view -> { - try + Thread th_send = new Thread(() -> { - byte cmd0 = (byte) Integer.parseInt(((EditText) findViewById(R.id.edit_cmd0)).getText().toString(), 16); - byte cmd1 = (byte) Integer.parseInt(((EditText) findViewById(R.id.edit_cmd1)).getText().toString(), 16); - byte cmd2 = (byte) Integer.parseInt(((EditText) findViewById(R.id.edit_cmd2)).getText().toString(), 16); - byte cmd3 = (byte) Integer.parseInt(((EditText) findViewById(R.id.edit_cmd3)).getText().toString(), 16); - CommandEncoder encoder = new CommandEncoder(); - byte[] cmd = encoder.GenerateCommand(cmd0, cmd1, cmd2, cmd3); - dtc_client.ThreadSend(cmd); - //print debug information - Message.obtain(recvHandler, Flags.PRINT_DATA_ARRAY, cmd).sendToTarget(); - } - catch (Exception e) - { - ToastLog("Input Data Invalidate", true, false); - } + if (!CameraOperator.SendCommand(IPCamera, Flags.CAMERA_RIGHT, 5)) + ToastLog("Camera Command (RIGHT) Failure.", false, true); + }); + th_send.start(); }); - findViewById(R.id.btn_start_qr).setOnClickListener(view -> + context.findViewById(R.id.btn_start_qr).setOnClickListener(view -> { ToastLog("QR Code Started", false, false); ToastLog("QR Result: " + ByteArray2String(RecognizeQrCode()), false, false); }); - findViewById(R.id.btn_start_light).setOnClickListener(view -> + context.findViewById(R.id.btn_start_light).setOnClickListener(view -> { ToastLog("Traffic Light Started", false, false); ToastLog("TL Result: " + ByteArray2String(RecognizeTrafficLight()), false, false); }); - findViewById(R.id.btn_start_color_shape).setOnClickListener(view -> + context.findViewById(R.id.btn_start_color_shape).setOnClickListener(view -> { ToastLog("Color Shape Started", false, false); ToastLog("CS Result: " + ByteArray2String(RecognizeShapeColor()), false, false); }); - findViewById(R.id.btn_start_car_id).setOnClickListener(view -> + context.findViewById(R.id.btn_start_car_id).setOnClickListener(view -> { ToastLog("Car ID Started", false, false); Thread th_debug = new Thread(this::RecognizeCarID); @@ -568,38 +585,70 @@ public class MainActivity extends AppCompatActivity ToastLog("CID Finished", false, false); }); - findViewById(R.id.btn_start_sign).setOnClickListener(view -> + context.findViewById(R.id.btn_start_sign).setOnClickListener(view -> { ToastLog("Traffic Sign Started", false, false); ToastLog("TS Result: " + ByteArray2String(RecognizeTrafficSign()), false, false); }); - findViewById(R.id.btn_start_ocr).setOnClickListener(view -> + context.findViewById(R.id.btn_start_ocr).setOnClickListener(view -> { ToastLog("OCR Started", false, false); Thread th_debug = new Thread(this::OCRRecognizeText); th_debug.start(); }); - findViewById(R.id.btn_tft_page_down).setOnClickListener(view -> + context.findViewById(R.id.btn_tft_page_down).setOnClickListener(view -> { CommandEncoder encoder = new CommandEncoder(); dtc_client.ThreadSend(encoder.GenerateCommand(Commands.TFT_PAGE_DOWN, (byte) 0, (byte) 0, (byte) 0)); ToastLog("TFT Page Down Command Send.", false, true); }); - findViewById(R.id.btn_movement_control).setOnClickListener(view -> - { - startActivity(new Intent(this, MovementController.class)); - }); + context.findViewById(R.id.btn_movement_control).setOnClickListener(view -> startActivity(new Intent(this, MovementController.class))); - findViewById(R.id.btn_crash).setOnClickListener(view -> + context.findViewById(R.id.btn_crash).setOnClickListener(view -> { //崩溃按钮的作用:频繁调试时省去手动退出程序,清理后台的操作,节省时间。 dtc_client.DisableAutoReconnect(); dtc_client.CloseConnection(); //关闭通信 throw new NullPointerException(); //通过异常来崩溃。 }); + } + //----------------------------------------到此处终止---------------------------------------- + + //初始化图形界面 + private void InitGUI() + { + pic_received = findViewById(R.id.camera_image); + text_toast = findViewById(R.id.text_toast); + + text_toast.setMovementMethod(ScrollingMovementMethod.getInstance()); + + findViewById(R.id.btn_debug_page).setOnClickListener(view -> + { + DebugPage.Parent = this; + startActivity(new Intent(this, DebugPage.class)); + }); + + findViewById(R.id.btn_function_test).setOnClickListener(view -> + { + SingleFunctionTest.Parent = this; + startActivity(new Intent(this, SingleFunctionTest.class)); + }); + + findViewById(R.id.btn_race_tasks).setOnClickListener(view -> + { + RaceTasks.Parent = this; + startActivity(new Intent(this, RaceTasks.class)); + }); + + findViewById(R.id.btn_program_exit).setOnClickListener(view -> + { + dtc_client.DisableAutoReconnect(); + dtc_client.CloseConnection(); //关闭通信 + System.exit(0); + }); findViewById(R.id.text_toast).setOnLongClickListener(view -> { @@ -617,8 +666,6 @@ public class MainActivity extends AppCompatActivity ToastLog("Image Save Failure", true, false); return true; }); - - InitTaskButton(); } //打印日志 @@ -650,14 +697,14 @@ public class MainActivity extends AppCompatActivity } } - //启动寻找摄像头的线程 + //启动获取摄像头拍摄到的图片的线程 private void StartCameraImageUpdate(int duration) { Thread th_image = new Thread(() -> { while (true) { - currImage = cameraCommandUtil.httpForImage(IPCamera); + currImage = CameraOperator.GetImage(IPCamera); recvHandler.sendEmptyMessage(Flags.RECEIVED_IMAGE); Sleep(duration); } @@ -723,29 +770,20 @@ public class MainActivity extends AppCompatActivity Sleep(10); //Wait for Connection Thread dtc_client.EnableAutoReconnect(); //启动自动重连 - //初始化摄像头控制 - cameraCommandUtil = new CameraCommandUtil(); - ToastLog("CameraCommandUtil Ready.", false, false); - //寻找摄像头,获取其IP地址 Thread camera_thread = new Thread(() -> { - IPCamera = null; + boolean success; ToastLog("CameraSearchThread: Camera Thread Start", false, true); - while (IPCamera == null || IPCamera.equals("")) + cameraSearcher = new CameraSearcher(); + do { - searchCameraUtil = new SearchCameraUtil(); - try - { - IPCamera = searchCameraUtil.send(); - } - catch (NullPointerException e) - { - IPCamera = null; - } + success = cameraSearcher.SearchOnce(); } + while (!success); //避免”while循环具有空体“警告 + IPCamera = cameraSearcher.GetCameraIP(); ToastLog("CameraSearchThread: Camera Found. IP: " + IPCamera, false, true); - IPCamera = IPCamera + ":81"; + IPCamera += ":81"; ToastLog("Camera Address: " + IPCamera, false, true); StartCameraImageUpdate(50); //这里是程序初始化的最后一步,能到达此处标志着自检通过 @@ -786,7 +824,5 @@ public class MainActivity extends AppCompatActivity //Activity销毁时关闭通信 dtc_client.DisableAutoReconnect(); dtc_client.CloseConnection(); - - } } \ No newline at end of file diff --git a/app/src/main/java/com/uns/maincar/gui/RaceTasks.java b/app/src/main/java/com/uns/maincar/gui/RaceTasks.java new file mode 100644 index 0000000..0a43972 --- /dev/null +++ b/app/src/main/java/com/uns/maincar/gui/RaceTasks.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2023. UnknownNetworkService Group + * This file is created by UnknownObject at 2023 - 5 - 1 + */ + +package com.uns.maincar.gui; + +import android.annotation.SuppressLint; +import android.os.Bundle; +import android.util.Log; +import android.widget.Toast; + +import androidx.appcompat.app.AppCompatActivity; + +import com.uns.maincar.R; +import com.uns.maincar.constants.Commands; +import com.uns.maincar.constants.Flags; + +public class RaceTasks extends AppCompatActivity +{ + + @SuppressLint("StaticFieldLeak") + protected static MainActivity Parent = null; //用于调用MainActivity内函数的静态成员变量 + + //初始化比赛任务按钮 + private void InitTaskButton() + { + findViewById(R.id.btn_task_0).setOnClickListener(view -> Parent.SendTaskCommand(Commands.TASK_NUMBER_0)); + findViewById(R.id.btn_task_1).setOnClickListener(view -> Parent.SendTaskCommand(Commands.TASK_NUMBER_1)); + findViewById(R.id.btn_task_2).setOnClickListener(view -> Parent.SendTaskCommand(Commands.TASK_NUMBER_2)); + findViewById(R.id.btn_task_3).setOnClickListener(view -> Parent.SendTaskCommand(Commands.TASK_NUMBER_3)); + findViewById(R.id.btn_task_4).setOnClickListener(view -> Parent.SendTaskCommand(Commands.TASK_NUMBER_4)); + findViewById(R.id.btn_task_5).setOnClickListener(view -> Parent.SendTaskCommand(Commands.TASK_NUMBER_5)); + findViewById(R.id.btn_task_6).setOnClickListener(view -> Parent.SendTaskCommand(Commands.TASK_NUMBER_6)); + findViewById(R.id.btn_task_7).setOnClickListener(view -> Parent.SendTaskCommand(Commands.TASK_NUMBER_7)); + findViewById(R.id.btn_task_8).setOnClickListener(view -> Parent.SendTaskCommand(Commands.TASK_NUMBER_8)); + findViewById(R.id.btn_task_9).setOnClickListener(view -> Parent.SendTaskCommand(Commands.TASK_NUMBER_9)); + findViewById(R.id.btn_task_10).setOnClickListener(view -> Parent.SendTaskCommand(Commands.TASK_NUMBER_10)); + findViewById(R.id.btn_task_11).setOnClickListener(view -> Parent.SendTaskCommand(Commands.TASK_NUMBER_11)); + findViewById(R.id.btn_task_12).setOnClickListener(view -> Parent.SendTaskCommand(Commands.TASK_NUMBER_12)); + /*findViewById(R.id.btn_task_13).setOnClickListener(view -> Parent.SendTaskCommand(Commands.TASK_NUMBER_13)); + findViewById(R.id.btn_task_14).setOnClickListener(view -> Parent.SendTaskCommand(Commands.TASK_NUMBER_14)); + findViewById(R.id.btn_task_15).setOnClickListener(view -> Parent.SendTaskCommand(Commands.TASK_NUMBER_15));*/ + } + + @Override + protected void onCreate(Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_race_tasks); + + if (Parent == null) + { + Toast.makeText(this, "Context is null!", Toast.LENGTH_SHORT).show(); + Log.e(Flags.SUB_ACTIVITY_TAG, "Context IS NULL"); + finish(); + } + + InitTaskButton(); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/uns/maincar/gui/SingleFunctionTest.java b/app/src/main/java/com/uns/maincar/gui/SingleFunctionTest.java new file mode 100644 index 0000000..757fb41 --- /dev/null +++ b/app/src/main/java/com/uns/maincar/gui/SingleFunctionTest.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2023. UnknownNetworkService Group + * This file is created by UnknownObject at 2023 - 5 - 1 + */ + +package com.uns.maincar.gui; + +import android.annotation.SuppressLint; +import android.os.Bundle; +import android.util.Log; +import android.widget.Toast; + +import androidx.appcompat.app.AppCompatActivity; + +import com.uns.maincar.R; +import com.uns.maincar.constants.Flags; + +public class SingleFunctionTest extends AppCompatActivity +{ + + @SuppressLint("StaticFieldLeak") + protected static MainActivity Parent = null; //用于调用MainActivity内函数的静态成员变量 + + @Override + protected void onCreate(Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_single_function_test); + + if (Parent == null) + { + Toast.makeText(this, "Context is null!", Toast.LENGTH_SHORT).show(); + Log.e(Flags.SUB_ACTIVITY_TAG, "Context IS NULL"); + finish(); + } + + Parent.InitSingleFunctionTestUnit(this); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/uns/maincar/tools/TextFilter.java b/app/src/main/java/com/uns/maincar/tools/TextFilter.java index 08d4655..fc38182 100644 --- a/app/src/main/java/com/uns/maincar/tools/TextFilter.java +++ b/app/src/main/java/com/uns/maincar/tools/TextFilter.java @@ -53,4 +53,15 @@ public class TextFilter } return result.toString(); } + + public String ChineseOnly(String src) + { + StringBuilder result = new StringBuilder(); + for (int i = 0; i < src.length(); i++) + { + if (src.charAt(i) > 1500) + result.append(src.charAt(i)); + } + return result.toString(); + } } diff --git a/app/src/main/java/com/uns/maincar/tools/camera/CameraOperator.java b/app/src/main/java/com/uns/maincar/tools/camera/CameraOperator.java new file mode 100644 index 0000000..426ea95 --- /dev/null +++ b/app/src/main/java/com/uns/maincar/tools/camera/CameraOperator.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2023. UnknownNetworkService Group + * This file is created by UnknownObject at 2023 - 5 - 1 + */ + +package com.uns.maincar.tools.camera; + +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; + +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.URL; + +/* + 重写声明: + 此类由UnknownObject重写自BKRC官方库:CameraCommandUtil(camerautil.jar)。 + ”BKRC官方写的都是什么辣鸡代码啊“ + ————UnknownObject + */ + +public class CameraOperator +{ + public static Bitmap GetImage(String IP) + { + try + { + URL url = new URL("http://" + IP + "/snapshot.cgi?loginuse=admin&loginpas=888888&res=0"); + HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection(); + httpURLConnection.setDoInput(true); + httpURLConnection.connect(); + InputStream in = httpURLConnection.getInputStream(); + Bitmap bitmap = BitmapFactory.decodeStream(in); + in.close(); + httpURLConnection.disconnect(); + return bitmap; + } + catch (IOException e) + { + return null; + } + } + + public static boolean SendCommand(String IP, int command, int step) + { + if ((command < 0) || (step < 0)) + return false; + try + { + URL url = new URL("http://" + IP + "/decoder_control.cgi?loginuse=admin&loginpas=888888&" + "command=" + command + "&onestep=" + step); + HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection(); + urlConnection.connect(); + urlConnection.disconnect(); + return true; + } + catch (IOException e) + { + return false; + } + } +} diff --git a/app/src/main/java/com/uns/maincar/tools/camera/CameraSearcher.java b/app/src/main/java/com/uns/maincar/tools/camera/CameraSearcher.java new file mode 100644 index 0000000..4a2fe7a --- /dev/null +++ b/app/src/main/java/com/uns/maincar/tools/camera/CameraSearcher.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2023. UnknownNetworkService Group + * This file is created by UnknownObject at 2023 - 5 - 1 + */ + +package com.uns.maincar.tools.camera; + +import java.io.IOException; +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.InetAddress; +import java.nio.charset.StandardCharsets; + +/* + 重写声明: + 此类由UnknownObject重写自BKRC官方库:SearchCameraUtil(camerautil.jar)。 + ”BKRC官方写的都是什么辣鸡代码啊“ + ————UnknownObject + */ + +public class CameraSearcher +{ + private String IP = ""; + private final int PORT = 3565; + private final int SERVER_PORT = 8600; + private DatagramSocket socket = null; + private final byte[] recv = new byte[1024]; + private final byte[] pkt_msg = new byte[]{68, 72, 1, 1}; + + public CameraSearcher() + { + } + + private void DecodeIP(String text) + { + StringBuilder sb = new StringBuilder(""); + byte[] ip_byte = text.getBytes(StandardCharsets.UTF_8); + for (int i = 4; (i < 22) && (ip_byte[i] != 0); ++i) + { + if (ip_byte[i] == 46) + sb.append('.'); + else + sb.append((ip_byte[i] - 48)); + } + IP = sb.toString(); + } + + public boolean SearchOnce() + { + try + { + InetAddress local = InetAddress.getByName("255.255.255.255"); + if (socket != null) + { + socket.close(); + socket = null; + } + socket = new DatagramSocket(PORT); + DatagramPacket sendPacket = new DatagramPacket(pkt_msg, 4, local, SERVER_PORT); + DatagramPacket recvPacket = new DatagramPacket(recv, recv.length); + socket.send(sendPacket); + socket.receive(recvPacket); + String text = new String(recv, 0, recvPacket.getLength()); + socket.close(); + if (text.startsWith("DH")) + { + DecodeIP(text); + return true; + } + else + return false; + } + catch (IOException e) + { + return false; + } + } + + public String GetCameraIP() + { + return IP; + } +} diff --git a/app/src/main/res/layout/activity_debug_page.xml b/app/src/main/res/layout/activity_debug_page.xml new file mode 100644 index 0000000..e569b11 --- /dev/null +++ b/app/src/main/res/layout/activity_debug_page.xml @@ -0,0 +1,77 @@ + + + + +