Browse Source

最新包含有线通讯的app12.22

master
LIN\54376 3 weeks ago
parent
commit
0ad8de776d
  1. 15
      .gitignore
  2. 2
      .gradle/config.properties
  3. 1
      .idea/.name
  4. 6
      .idea/compiler.xml
  5. 10
      .idea/deploymentTargetDropDown.xml
  6. 18
      .idea/deploymentTargetSelector.xml
  7. 2
      .idea/gradle.xml
  8. 4
      .idea/misc.xml
  9. 1
      README.md
  10. 1
      app/.gitignore
  11. 3
      app/.idea/.gitignore
  12. 12
      app/.idea/gradle.xml
  13. 10
      app/.idea/migrations.xml
  14. 10
      app/.idea/misc.xml
  15. 73
      app/build.gradle
  16. 21
      app/proguard-rules.pro
  17. 29
      app/src/androidTest/java/com/example/fivewheel/AppDatabase.java
  18. 26
      app/src/androidTest/java/com/example/fivewheel/ExampleInstrumentedTest.java
  19. 20
      app/src/androidTest/java/com/example/fivewheel/RobotLog.java
  20. 17
      app/src/androidTest/java/com/example/fivewheel/RobotLogDao.java
  21. 43
      app/src/main/AndroidManifest.xml
  22. 539
      app/src/main/assets/iconfront/demo.css
  23. 4236
      app/src/main/assets/iconfront/demo_index.html
  24. 719
      app/src/main/assets/iconfront/iconfont.css
  25. 1
      app/src/main/assets/iconfront/iconfont.js
  26. 1241
      app/src/main/assets/iconfront/iconfont.json
  27. BIN
      app/src/main/assets/iconfront/iconfont.ttf
  28. BIN
      app/src/main/assets/iconfront/iconfont.woff
  29. BIN
      app/src/main/assets/iconfront/iconfont.woff2
  30. 42
      app/src/main/java/bsp_Error.proto
  31. 28
      app/src/main/java/bsp_IV.proto
  32. 15
      app/src/main/java/bsp_PV.proto
  33. 57
      app/src/main/java/com/example/fivewheel/AppDatabase.java
  34. 942
      app/src/main/java/com/example/fivewheel/MainActivity.java
  35. 20
      app/src/main/java/com/example/fivewheel/RobotLog.java
  36. 22
      app/src/main/java/com/example/fivewheel/RobotLogDao.java
  37. 1725
      app/src/main/java/com/example/fivewheel/models/BspError.java
  38. 1828
      app/src/main/java/com/example/fivewheel/models/BspIV.java
  39. 1048
      app/src/main/java/com/example/fivewheel/models/BspPV.java
  40. 792
      app/src/main/java/com/example/fivewheel/models/RobotData.java
  41. 615
      app/src/main/java/com/example/fivewheel/models/RobotRMACM.java
  42. 6
      app/src/main/java/com/example/fivewheel/services/CommunicationMethond.java
  43. 23
      app/src/main/java/com/example/fivewheel/services/CustomProber.java
  44. 154
      app/src/main/java/com/example/fivewheel/services/DataExchangeHelper.java
  45. 17
      app/src/main/java/com/example/fivewheel/services/DisplayUtils.java
  46. 66
      app/src/main/java/com/example/fivewheel/services/ErrorDeocdeHelper.java
  47. 72
      app/src/main/java/com/example/fivewheel/services/ModbusCRC.java
  48. 517
      app/src/main/java/com/example/fivewheel/services/ModbusRtuSlaveService.java
  49. 200
      app/src/main/java/com/example/fivewheel/services/ReceiivedIVHandler.java
  50. 54
      app/src/main/java/com/example/fivewheel/services/RobotDataHanlder.java
  51. 140
      app/src/main/java/com/example/fivewheel/services/RtspRecorder.java
  52. 324
      app/src/main/java/com/example/fivewheel/services/USBSerialPortHelper.java
  53. 27
      app/src/main/java/com/example/fivewheel/services/VideoPlayerHelper.java
  54. 124
      app/src/main/java/com/example/fivewheel/services/ttySerialPortHelper.java
  55. 67
      app/src/main/java/com/example/fivewheel/viewmodels/MainViewModel.java
  56. 7
      app/src/main/java/generate_java.bat
  57. BIN
      app/src/main/java/protoc.7z
  58. BIN
      app/src/main/java/protoc.exe
  59. 25
      app/src/main/res/drawable/background.xml
  60. 25
      app/src/main/res/drawable/blue_rounded_rectangle.xml
  61. 10
      app/src/main/res/drawable/border.xml
  62. 24
      app/src/main/res/drawable/borderblue.xml
  63. 14
      app/src/main/res/drawable/dash_line.xml
  64. 170
      app/src/main/res/drawable/ic_launcher_background.xml
  65. 30
      app/src/main/res/drawable/ic_launcher_foreground.xml
  66. 24
      app/src/main/res/drawable/message_rounded_rectangle.xml
  67. BIN
      app/src/main/res/drawable/squrelogo.png
  68. 760
      app/src/main/res/layout/activity_main.xml
  69. 15
      app/src/main/res/layout/dialog_logs.xml
  70. 6
      app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
  71. 6
      app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
  72. BIN
      app/src/main/res/mipmap-hdpi/ic_launcher.webp
  73. BIN
      app/src/main/res/mipmap-hdpi/ic_launcher_round.webp
  74. BIN
      app/src/main/res/mipmap-mdpi/ic_launcher.webp
  75. BIN
      app/src/main/res/mipmap-mdpi/ic_launcher_round.webp
  76. BIN
      app/src/main/res/mipmap-xhdpi/ic_launcher.webp
  77. BIN
      app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
  78. BIN
      app/src/main/res/mipmap-xxhdpi/ic_launcher.webp
  79. BIN
      app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
  80. BIN
      app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
  81. BIN
      app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
  82. 16
      app/src/main/res/values-night/themes.xml
  83. 157
      app/src/main/res/values/colors.xml
  84. 7
      app/src/main/res/values/strings.xml
  85. 25
      app/src/main/res/values/themes.xml
  86. 13
      app/src/main/res/xml/backup_rules.xml
  87. 19
      app/src/main/res/xml/data_extraction_rules.xml
  88. 38
      app/src/main/res/xml/device_filter.xml
  89. 17
      app/src/test/java/com/example/fivewheel/ExampleUnitTest.java
  90. 5
      build.gradle
  91. 21
      gradle.properties
  92. BIN
      gradle/wrapper/gradle-wrapper.jar
  93. 6
      gradle/wrapper/gradle-wrapper.properties
  94. 185
      gradlew
  95. 89
      gradlew.bat
  96. 363
      proto/RobotData.cs
  97. 792
      proto/com/example/removemarineanimals/models/RobotData.java
  98. 615
      proto/com/example/removemarineanimals/models/RobotRMACM.java
  99. 1
      proto/generate_c.bat
  100. 1
      proto/generate_c.txt

15
.gitignore

@ -0,0 +1,15 @@
*.iml
.gradle
/local.properties
/.idea/caches
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
.DS_Store
/build
/captures
.externalNativeBuild
.cxx
local.properties

2
.gradle/config.properties

@ -1,2 +1,2 @@
#Mon Dec 22 02:40:22 CST 2025
#Mon Dec 22 02:41:36 CST 2025
java.home=F\:\\Program Files\\Android\\Android Studio\\jbr

1
.idea/.name

@ -0,0 +1 @@
fivewheel

6
.idea/compiler.xml

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<bytecodeTargetLevel target="21" />
</component>
</project>

10
.idea/deploymentTargetDropDown.xml

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="deploymentTargetDropDown">
<value>
<entry key="app">
<State />
</entry>
</value>
</component>
</project>

18
.idea/deploymentTargetSelector.xml

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="deploymentTargetSelector">
<selectionStates>
<SelectionState runConfigName="app">
<option name="selectionMode" value="DROPDOWN" />
<DropdownSelection timestamp="2025-12-19T02:11:32.151250600Z">
<Target type="DEFAULT_BOOT">
<handle>
<DeviceId pluginId="LocalEmulator" identifier="path=C:\Users\asus\.android\avd\Medium_Phone.avd" />
</handle>
</Target>
</DropdownSelection>
<DialogSelection />
</SelectionState>
</selectionStates>
</component>
</project>

2
.idea/gradle.xml

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleMigrationSettings" migrationVersion="1" />
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
@ -12,6 +13,7 @@
<option value="$PROJECT_DIR$/app" />
</set>
</option>
<option name="resolveExternalAnnotations" value="false" />
</GradleProjectSettings>
</option>
</component>

4
.idea/misc.xml

@ -1,6 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="jbr-21" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
<option name="id" value="Android" />
</component>

1
README.md

@ -0,0 +1 @@
项目初始化

1
app/.gitignore

@ -0,0 +1 @@
/build

3
app/.idea/.gitignore

@ -0,0 +1,3 @@
# Default ignored files
/shelf/
/workspace.xml

12
app/.idea/gradle.xml

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleJvm" value="#GRADLE_LOCAL_JAVA_HOME" />
<option name="resolveExternalAnnotations" value="false" />
</GradleProjectSettings>
</option>
</component>
</project>

10
app/.idea/migrations.xml

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectMigrations">
<option name="MigrateToGradleLocalJavaHome">
<set>
<option value="$PROJECT_DIR$" />
</set>
</option>
</component>
</project>

10
app/.idea/misc.xml

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="ProjectRootManager">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
<option name="id" value="Android" />
</component>
</project>

73
app/build.gradle

@ -0,0 +1,73 @@
plugins {
id 'com.android.application'
}
android {
namespace 'com.example.fivewheel'
compileSdk 34
viewBinding
{
enabled true
}
// //add this feature
dataBinding
{
enabled true
}
defaultConfig {
applicationId "com.example.fivewheel"
minSdk 24
targetSdk 34
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
// binding
buildFeatures {
viewBinding true
dataBinding true
buildConfig true
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
// AndroidX
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.google.android.material:material:1.9.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
//implementation project(':app')
//
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
//
implementation 'com.github.mik3y:usb-serial-for-android:3.7.0'
implementation 'com.google.protobuf:protobuf-java:4.27.2'
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.20")
implementation 'com.github.nodemedia:nodemediaclient-android:2.9.20'
implementation 'io.github.xmaihh:serialport:2.1.1'
// implementation 'com.arthenica:ffmpeg-kit-full:6.0-2'
// Room
def room_version = "2.6.1"
implementation "androidx.room:room-runtime:$room_version"
annotationProcessor "androidx.room:room-compiler:$room_version"
implementation "androidx.room:room-ktx:$room_version" // /LiveData
}

21
app/proguard-rules.pro

@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

29
app/src/androidTest/java/com/example/fivewheel/AppDatabase.java

@ -0,0 +1,29 @@
package com.example.fivewheel;
import android.content.Context;
import androidx.room.Database;
import androidx.room.Room;
import androidx.room.RoomDatabase;
@Database(entities = {RobotLog.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {
public abstract RobotLogDao robotLogDao();
private static volatile AppDatabase INSTANCE;
public static AppDatabase getInstance(Context context) {
if (INSTANCE == null) {
synchronized (AppDatabase.class) {
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
AppDatabase.class, "robot_logs.db")
.fallbackToDestructiveMigration() // 数据库升级时清空数据,可根据需求改
.build();
}
}
}
return INSTANCE;
}
}

26
app/src/androidTest/java/com/example/fivewheel/ExampleInstrumentedTest.java

@ -0,0 +1,26 @@
package com.example.fivewheel;
import android.content.Context;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
/**
* Instrumented test, which will execute on an Android device.
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
assertEquals("com.example.removemarineanimals", appContext.getPackageName());
}
}

20
app/src/androidTest/java/com/example/fivewheel/RobotLog.java

@ -0,0 +1,20 @@
package com.example.fivewheel;
import androidx.room.ColumnInfo;
import androidx.room.Entity;
import androidx.room.PrimaryKey;
@Entity(tableName = "robot_logs")
public class RobotLog {
@PrimaryKey(autoGenerate = true)
public int id;
@ColumnInfo(name = "type") // "error" 或 "param_change"
public String type;
@ColumnInfo(name = "message") // 具体信息:报错内容或修改了哪个参数
public String message;
@ColumnInfo(name = "time") // 时间戳
public long time;
}

17
app/src/androidTest/java/com/example/fivewheel/RobotLogDao.java

@ -0,0 +1,17 @@
package com.example.fivewheel;
import androidx.room.Dao;
import androidx.room.Insert;
import androidx.room.Query;
import java.util.List;
@Dao
public interface RobotLogDao {
@Insert
void insert(RobotLog log);
@Query("SELECT * FROM robot_logs ORDER BY time DESC")
List<RobotLog> getAllLogs();
}

43
app/src/main/AndroidManifest.xml

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-feature android:name="android.hardware.camera"/>
<uses-feature android:name="android.hardware.camera.autofocus"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.FLASHLIGHT"/>
<uses-permission android:name="android.permission.USB_PERMISSION" />
<uses-feature android:name="android.hardware.usb.accessory" android:required="false" />
<uses-feature android:name="android.hardware.usb.host" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.VIBRATE"/>
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@drawable/squrelogo"
android:label="@string/app_name"
android:roundIcon= "@drawable/squrelogo"
android:supportsRtl="true"
android:theme="@style/Theme.RemoveMarineAnimals"
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
</intent-filter>
<meta-data
android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
android:resource="@xml/device_filter" />
</activity>
</application>
</manifest>

539
app/src/main/assets/iconfront/demo.css

@ -0,0 +1,539 @@
/* Logo 字体 */
@font-face {
font-family: "iconfont logo";
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834');
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834#iefix') format('embedded-opentype'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.woff?t=1545807318834') format('woff'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.ttf?t=1545807318834') format('truetype'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.svg?t=1545807318834#iconfont') format('svg');
}
.logo {
font-family: "iconfont logo";
font-size: 160px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
/* tabs */
.nav-tabs {
position: relative;
}
.nav-tabs .nav-more {
position: absolute;
right: 0;
bottom: 0;
height: 42px;
line-height: 42px;
color: #666;
}
#tabs {
border-bottom: 1px solid #eee;
}
#tabs li {
cursor: pointer;
width: 100px;
height: 40px;
line-height: 40px;
text-align: center;
font-size: 16px;
border-bottom: 2px solid transparent;
position: relative;
z-index: 1;
margin-bottom: -1px;
color: #666;
}
#tabs .active {
border-bottom-color: #f00;
color: #222;
}
.tab-container .content {
display: none;
}
/* 页面布局 */
.main {
padding: 30px 100px;
width: 960px;
margin: 0 auto;
}
.main .logo {
color: #333;
text-align: left;
margin-bottom: 30px;
line-height: 1;
height: 110px;
margin-top: -50px;
overflow: hidden;
*zoom: 1;
}
.main .logo a {
font-size: 160px;
color: #333;
}
.helps {
margin-top: 40px;
}
.helps pre {
padding: 20px;
margin: 10px 0;
border: solid 1px #e7e1cd;
background-color: #fffdef;
overflow: auto;
}
.icon_lists {
width: 100% !important;
overflow: hidden;
*zoom: 1;
}
.icon_lists li {
width: 100px;
margin-bottom: 10px;
margin-right: 20px;
text-align: center;
list-style: none !important;
cursor: default;
}
.icon_lists li .code-name {
line-height: 1.2;
}
.icon_lists .icon {
display: block;
height: 100px;
line-height: 100px;
font-size: 42px;
margin: 10px auto;
color: #333;
-webkit-transition: font-size 0.25s linear, width 0.25s linear;
-moz-transition: font-size 0.25s linear, width 0.25s linear;
transition: font-size 0.25s linear, width 0.25s linear;
}
.icon_lists .icon:hover {
font-size: 100px;
}
.icon_lists .svg-icon {
/* 通过设置 font-size 来改变图标大小 */
width: 1em;
/* 图标和文字相邻时,垂直对齐 */
vertical-align: -0.15em;
/* 通过设置 color 来改变 SVG 的颜色/fill */
fill: currentColor;
/* path stroke 溢出 viewBox 部分在 IE 下会显示
normalize.css 中也包含这行 */
overflow: hidden;
}
.icon_lists li .name,
.icon_lists li .code-name {
color: #666;
}
/* markdown 样式 */
.markdown {
color: #666;
font-size: 14px;
line-height: 1.8;
}
.highlight {
line-height: 1.5;
}
.markdown img {
vertical-align: middle;
max-width: 100%;
}
.markdown h1 {
color: #404040;
font-weight: 500;
line-height: 40px;
margin-bottom: 24px;
}
.markdown h2,
.markdown h3,
.markdown h4,
.markdown h5,
.markdown h6 {
color: #404040;
margin: 1.6em 0 0.6em 0;
font-weight: 500;
clear: both;
}
.markdown h1 {
font-size: 28px;
}
.markdown h2 {
font-size: 22px;
}
.markdown h3 {
font-size: 16px;
}
.markdown h4 {
font-size: 14px;
}
.markdown h5 {
font-size: 12px;
}
.markdown h6 {
font-size: 12px;
}
.markdown hr {
height: 1px;
border: 0;
background: #e9e9e9;
margin: 16px 0;
clear: both;
}
.markdown p {
margin: 1em 0;
}
.markdown>p,
.markdown>blockquote,
.markdown>.highlight,
.markdown>ol,
.markdown>ul {
width: 80%;
}
.markdown ul>li {
list-style: circle;
}
.markdown>ul li,
.markdown blockquote ul>li {
margin-left: 20px;
padding-left: 4px;
}
.markdown>ul li p,
.markdown>ol li p {
margin: 0.6em 0;
}
.markdown ol>li {
list-style: decimal;
}
.markdown>ol li,
.markdown blockquote ol>li {
margin-left: 20px;
padding-left: 4px;
}
.markdown code {
margin: 0 3px;
padding: 0 5px;
background: #eee;
border-radius: 3px;
}
.markdown strong,
.markdown b {
font-weight: 600;
}
.markdown>table {
border-collapse: collapse;
border-spacing: 0px;
empty-cells: show;
border: 1px solid #e9e9e9;
width: 95%;
margin-bottom: 24px;
}
.markdown>table th {
white-space: nowrap;
color: #333;
font-weight: 600;
}
.markdown>table th,
.markdown>table td {
border: 1px solid #e9e9e9;
padding: 8px 16px;
text-align: left;
}
.markdown>table th {
background: #F7F7F7;
}
.markdown blockquote {
font-size: 90%;
color: #999;
border-left: 4px solid #e9e9e9;
padding-left: 0.8em;
margin: 1em 0;
}
.markdown blockquote p {
margin: 0;
}
.markdown .anchor {
opacity: 0;
transition: opacity 0.3s ease;
margin-left: 8px;
}
.markdown .waiting {
color: #ccc;
}
.markdown h1:hover .anchor,
.markdown h2:hover .anchor,
.markdown h3:hover .anchor,
.markdown h4:hover .anchor,
.markdown h5:hover .anchor,
.markdown h6:hover .anchor {
opacity: 1;
display: inline-block;
}
.markdown>br,
.markdown>p>br {
clear: both;
}
.hljs {
display: block;
background: white;
padding: 0.5em;
color: #333333;
overflow-x: auto;
}
.hljs-comment,
.hljs-meta {
color: #969896;
}
.hljs-string,
.hljs-variable,
.hljs-template-variable,
.hljs-strong,
.hljs-emphasis,
.hljs-quote {
color: #df5000;
}
.hljs-keyword,
.hljs-selector-tag,
.hljs-type {
color: #a71d5d;
}
.hljs-literal,
.hljs-symbol,
.hljs-bullet,
.hljs-attribute {
color: #0086b3;
}
.hljs-section,
.hljs-name {
color: #63a35c;
}
.hljs-tag {
color: #333333;
}
.hljs-title,
.hljs-attr,
.hljs-selector-id,
.hljs-selector-class,
.hljs-selector-attr,
.hljs-selector-pseudo {
color: #795da3;
}
.hljs-addition {
color: #55a532;
background-color: #eaffea;
}
.hljs-deletion {
color: #bd2c00;
background-color: #ffecec;
}
.hljs-link {
text-decoration: underline;
}
/* 代码高亮 */
/* PrismJS 1.15.0
https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript */
/**
* prism.js default theme for JavaScript, CSS and HTML
* Based on dabblet (http://dabblet.com)
* @author Lea Verou
*/
code[class*="language-"],
pre[class*="language-"] {
color: black;
background: none;
text-shadow: 0 1px white;
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
text-align: left;
white-space: pre;
word-spacing: normal;
word-break: normal;
word-wrap: normal;
line-height: 1.5;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
}
pre[class*="language-"]::-moz-selection,
pre[class*="language-"] ::-moz-selection,
code[class*="language-"]::-moz-selection,
code[class*="language-"] ::-moz-selection {
text-shadow: none;
background: #b3d4fc;
}
pre[class*="language-"]::selection,
pre[class*="language-"] ::selection,
code[class*="language-"]::selection,
code[class*="language-"] ::selection {
text-shadow: none;
background: #b3d4fc;
}
@media print {
code[class*="language-"],
pre[class*="language-"] {
text-shadow: none;
}
}
/* Code blocks */
pre[class*="language-"] {
padding: 1em;
margin: .5em 0;
overflow: auto;
}
:not(pre)>code[class*="language-"],
pre[class*="language-"] {
background: #f5f2f0;
}
/* Inline code */
:not(pre)>code[class*="language-"] {
padding: .1em;
border-radius: .3em;
white-space: normal;
}
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: slategray;
}
.token.punctuation {
color: #999;
}
.namespace {
opacity: .7;
}
.token.property,
.token.tag,
.token.boolean,
.token.number,
.token.constant,
.token.symbol,
.token.deleted {
color: #905;
}
.token.selector,
.token.attr-name,
.token.string,
.token.char,
.token.builtin,
.token.inserted {
color: #690;
}
.token.operator,
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string {
color: #9a6e3a;
background: hsla(0, 0%, 100%, .5);
}
.token.atrule,
.token.attr-value,
.token.keyword {
color: #07a;
}
.token.function,
.token.class-name {
color: #DD4A68;
}
.token.regex,
.token.important,
.token.variable {
color: #e90;
}
.token.important,
.token.bold {
font-weight: bold;
}
.token.italic {
font-style: italic;
}
.token.entity {
cursor: help;
}

4236
app/src/main/assets/iconfront/demo_index.html

File diff suppressed because it is too large

719
app/src/main/assets/iconfront/iconfont.css

@ -0,0 +1,719 @@
@font-face {
font-family: "iconfont"; /* Project id 3005536 */
src: url('iconfont.woff2?t=1719904676087') format('woff2'),
url('iconfont.woff?t=1719904676087') format('woff'),
url('iconfont.ttf?t=1719904676087') format('truetype');
}
.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-answer:before {
content: "\e64a";
}
.icon-app:before {
content: "\e658";
}
.icon-browser:before {
content: "\e659";
}
.icon-camera:before {
content: "\e65a";
}
.icon-cart:before {
content: "\e65c";
}
.icon-check:before {
content: "\e65d";
}
.icon-code:before {
content: "\e65e";
}
.icon-computer:before {
content: "\e65f";
}
.icon-delete:before {
content: "\e661";
}
.icon-deliver:before {
content: "\e662";
}
.icon-display:before {
content: "\e663";
}
.icon-down:before {
content: "\e664";
}
.icon-download:before {
content: "\e669";
}
.icon-edit:before {
content: "\e66a";
}
.icon-favor:before {
content: "\e66b";
}
.icon-file:before {
content: "\e66c";
}
.icon-fill:before {
content: "\e66e";
}
.icon-fold:before {
content: "\e66f";
}
.icon-folder:before {
content: "\e670";
}
.icon-hide:before {
content: "\e671";
}
.icon-home:before {
content: "\e672";
}
.icon-information:before {
content: "\e673";
}
.icon-link:before {
content: "\e674";
}
.icon-baojing:before {
content: "\e675";
}
.icon-renwu:before {
content: "\e676";
}
.icon-yonghu2:before {
content: "\e678";
}
.icon-xiangqing:before {
content: "\e679";
}
.icon-zhuzhuangtu:before {
content: "\e67f";
}
.icon-shouxinguanli:before {
content: "\e680";
}
.icon-fuwuqi:before {
content: "\e681";
}
.icon-renwu1:before {
content: "\e682";
}
.icon-wupinxiang:before {
content: "\e683";
}
.icon-xiangqing1:before {
content: "\e684";
}
.icon-zhexiantu:before {
content: "\e685";
}
.icon-jiegou:before {
content: "\e686";
}
.icon-gongzuotai:before {
content: "\e687";
}
.icon-shezhi1:before {
content: "\e688";
}
.icon-chanpin:before {
content: "\e689";
}
.icon-liucheng:before {
content: "\e68a";
}
.icon-yonghu3:before {
content: "\e68b";
}
.icon-jiekuanshenqing:before {
content: "\e68c";
}
.icon-zuidahua:before {
content: "\e65b";
}
.icon-mima:before {
content: "\e634";
}
.icon-mima1:before {
content: "\e635";
}
.icon-zuidahua1:before {
content: "\e637";
}
.icon-mima2:before {
content: "\e665";
}
.icon-guanbi:before {
content: "\e63b";
}
.icon-mima3:before {
content: "\e660";
}
.icon-zuixiaohua:before {
content: "\e67e";
}
.icon-cuowuguanbiquxiao:before {
content: "\e8e7";
}
.icon-guanbi1:before {
content: "\e63d";
}
.icon-guanbi2:before {
content: "\e63f";
}
.icon-guanbi3:before {
content: "\eaf2";
}
.icon-mima4:before {
content: "\e642";
}
.icon-guanbi4:before {
content: "\e645";
}
.icon-guanbi5:before {
content: "\e6a5";
}
.icon-mima5:before {
content: "\e8b2";
}
.icon-zuixiaohua1:before {
content: "\e656";
}
.icon-guanbi6:before {
content: "\e646";
}
.icon-tuichu:before {
content: "\e655";
}
.icon-tuichu1:before {
content: "\e638";
}
.icon-tuichu2:before {
content: "\e7c8";
}
.icon-configuration-management:before {
content: "\e616";
}
.icon-ziyuan120:before {
content: "\e789";
}
.icon-renwuguanli3:before {
content: "\e781";
}
.icon-zhinengkeji-icon-8:before {
content: "\e617";
}
.icon-agora_mianxiangyonglidejiejuefangan:before {
content: "\e67c";
}
.icon-peizhi-yunweipeizhi:before {
content: "\e618";
}
.icon-renwuguanli4:before {
content: "\ec4c";
}
.icon-bianji5:before {
content: "\e816";
}
.icon-chexing:before {
content: "\e61b";
}
.icon-renwuguanli5:before {
content: "\e6e2";
}
.icon-chanpinyaliceshi:before {
content: "\e61f";
}
.icon-2-1peizhiguanli:before {
content: "\e632";
}
.icon-xiaopangchechachexing:before {
content: "\e621";
}
.icon-zidonghua:before {
content: "\e633";
}
.icon-gongyingshangguanli2:before {
content: "\e622";
}
.icon-renwuguanli6:before {
content: "\e625";
}
.icon-gongyingshangguanli3:before {
content: "\e67b";
}
.icon-gongyingshangguanli4:before {
content: "\e626";
}
.icon-renwuguanli7:before {
content: "\e627";
}
.icon-jiedianshijianceshi:before {
content: "\e63a";
}
.icon-rizhiguanli2:before {
content: "\e6a7";
}
.icon-xitongrizhi1:before {
content: "\e6a9";
}
.icon-wangluo1:before {
content: "\e628";
}
.icon-wangluozidonghuaguanli:before {
content: "\e6ab";
}
.icon-renwuguanli8:before {
content: "\e653";
}
.icon-chexing-xianxing3-0:before {
content: "\e694";
}
.icon-renwuguanli9:before {
content: "\e64f";
}
.icon-gongyezidonghua:before {
content: "\e654";
}
.icon-iServershujujieruceshi:before {
content: "\e629";
}
.icon-qingxierukuceshi:before {
content: "\e62a";
}
.icon-renwuguanli10:before {
content: "\e62b";
}
.icon-gongyingshangguanli5:before {
content: "\e62c";
}
.icon-peizhiguanli:before {
content: "\e67d";
}
.icon-chexingguanli:before {
content: "\e66d";
}
.icon-a-ziyuan114:before {
content: "\e62d";
}
.icon-bumenguanli2:before {
content: "\e636";
}
.icon-peizhiguanli1:before {
content: "\e641";
}
.icon-peizhiguanli2:before {
content: "\e643";
}
.icon-a-lianhe79:before {
content: "\e677";
}
.icon-a-wenjianjiawenjian:before {
content: "\e644";
}
.icon-wenben:before {
content: "\e600";
}
.icon-wenbenbianjitianchong:before {
content: "\e6d4";
}
.icon-rizhiguanli:before {
content: "\e639";
}
.icon-bianji:before {
content: "\e612";
}
.icon-ceshifuzhu:before {
content: "\e601";
}
.icon-huiguiceshi:before {
content: "\e608";
}
.icon-yonghu:before {
content: "\e788";
}
.icon-ceshi:before {
content: "\e6e1";
}
.icon-icon-supplier:before {
content: "\e63c";
}
.icon-suyaniconchanpinleibufenzuodaohangbufen87:before {
content: "\e730";
}
.icon-tijiaorizhi:before {
content: "\e650";
}
.icon-bianji1:before {
content: "\e62e";
}
.icon-bianji2:before {
content: "\e619";
}
.icon-wangluo:before {
content: "\e609";
}
.icon-peizhi:before {
content: "\e667";
}
.icon-gongyingshangguanli:before {
content: "\e611";
}
.icon-wenjian:before {
content: "\e67a";
}
.icon-renwuguanli:before {
content: "\e657";
}
.icon-sucai:before {
content: "\e602";
}
.icon-rizhiguanli1:before {
content: "\e62f";
}
.icon-test-case-group:before {
content: "\e606";
}
.icon-test-case-secondary:before {
content: "\e607";
}
.icon-test-case-group2:before {
content: "\e60a";
}
.icon-wenjian1:before {
content: "\e604";
}
.icon-xiaoshouzidonghua:before {
content: "\e6a0";
}
.icon-kujialeqiyezhan_shengchanzidonghua:before {
content: "\e64b";
}
.icon-bumenguanli:before {
content: "\e624";
}
.icon-noun__cc:before {
content: "\e610";
}
.icon-wenjian2:before {
content: "\e630";
}
.icon-bumen:before {
content: "\e758";
}
.icon-wenjianjia:before {
content: "\ec17";
}
.icon-oper-auto-1:before {
content: "\e7ca";
}
.icon-oper-auto:before {
content: "\e7cb";
}
.icon-pinzhijiance:before {
content: "\e620";
}
.icon-bumen1:before {
content: "\e64d";
}
.icon-gongyingshangguanli1:before {
content: "\e623";
}
.icon-bianji3:before {
content: "\e603";
}
.icon-bianji4:before {
content: "\e61c";
}
.icon-bumenguanli1:before {
content: "\e61d";
}
.icon-icon-:before {
content: "\e605";
}
.icon-wj-wjj:before {
content: "\e7b8";
}
.icon-bumen2:before {
content: "\e631";
}
.icon-rizhi:before {
content: "\e614";
}
.icon-peizhi1:before {
content: "\e60f";
}
.icon-caozuorizhi:before {
content: "\e60b";
}
.icon-ceshigongju:before {
content: "\e71a";
}
.icon-24gl-portraitMalePlus4:before {
content: "\eb25";
}
.icon-24gl-portraitMalePlus6:before {
content: "\eb27";
}
.icon-shezhi:before {
content: "\e61a";
}
.icon-peizhishezhi:before {
content: "\e64c";
}
.icon-peizhi2:before {
content: "\e6db";
}
.icon-yonghu1:before {
content: "\e668";
}
.icon-caiwuzidonghuapeizhi:before {
content: "\e60c";
}
.icon-wenjian3:before {
content: "\e64e";
}
.icon-xitongrizhi:before {
content: "\e60d";
}
.icon-wenjian4:before {
content: "\e695";
}
.icon-jurassic_user:before {
content: "\e6a4";
}
.icon-gongyingshangguanli_icox:before {
content: "\e6ce";
}
.icon-automated-processing_line:before {
content: "\e72f";
}
.icon-automated-processing_fill:before {
content: "\e731";
}
.icon-peizhixinxi:before {
content: "\e60e";
}
.icon-yingxiaozidonghua:before {
content: "\e666";
}
.icon-peizhi3:before {
content: "\e61e";
}
.icon-dianqizidonghua:before {
content: "\e613";
}
.icon-renwuguanli1:before {
content: "\e6de";
}
.icon-caiwuzidonghuapeizhi1:before {
content: "\e651";
}
.icon-xinicon_huabanfuben:before {
content: "\e647";
}
.icon-xinicon_huabanfuben1:before {
content: "\e648";
}
.icon-xinicon_huabanfuben2:before {
content: "\e649";
}
.icon-lishibanben:before {
content: "\e652";
}
.icon-jiedianpeizhi:before {
content: "\e63e";
}
.icon-louyuzidonghua:before {
content: "\e793";
}
.icon-renwuguanli2:before {
content: "\e615";
}
.icon-ceshi1:before {
content: "\e640";
}

1
app/src/main/assets/iconfront/iconfont.js

File diff suppressed because one or more lines are too long

1241
app/src/main/assets/iconfront/iconfont.json

File diff suppressed because it is too large

BIN
app/src/main/assets/iconfront/iconfont.ttf

Binary file not shown.

BIN
app/src/main/assets/iconfront/iconfont.woff

Binary file not shown.

BIN
app/src/main/assets/iconfront/iconfont.woff2

Binary file not shown.

42
app/src/main/java/bsp_Error.proto

@ -0,0 +1,42 @@
syntax = "proto3";
option java_multiple_files = false;
option java_package = "com.example.fivewheel.models";
message ErrorDataInfo
{
int32 Error_Value = 1;
bytes Error_Name=4;
}
message ErrorData
{
int32 ErrorCode=1;
int32 Motor_1_Error=21;
int32 Motor_2_Error=22;
int32 Motor_3_Error=23;
int32 Motor_4_Error=24;
int32 Motor_5_Error=25;
int32 Motor_6_Error=26;
int32 Motor_7_Error=27;
}
enum ComError // Error Bit Define
{
U7_SBus = 0;
Force_sensor = 1;
Ti5_LeftMotor = 2;
Ti5_RightMotor = 3;
Cmcu_Sensor =4;
Remote_Button_Reset_State = 5;
CMCU06_Force_sensor = 6;
Dynamometer_sensor= 7;
TL720D = 8;
Ultrasonic_sensor = 9;
Android_485 = 15;
}
//protoc --nanopb_out=. *.proto

28
app/src/main/java/bsp_IV.proto

@ -0,0 +1,28 @@
syntax = "proto3";
option java_multiple_files = false;
option java_package = "com.example.fivewheel.models";
message IV_struct_define{
//
//
int32 Robot_Move_AutoSpeed= 1;
int32 Robot_Move_ManualSpeed= 2;
int32 Robot_CurrentPosition= 3;
int32 Robot_AngleRoll= 4;
int32 Robot_Error= 5;
int32 Robot_DynamometerValue= 6;
int32 Robot_ForceValue= 7;
int32 Robot_CurrentState= 8;
int32 Robot_Current_Left= 9;
int32 Robot_Current_Right= 10;
int32 Robot_Error_Left= 11;
int32 Robot_Error_Right= 12;
int32 Robot_Compensation_Left= 13;
int32 Robot_Compensation_Right= 14;
int32 Robot_RESET = 15;
int64 TimeStamp=16;
int32 RobotRestart=17;
int32 RobotAngle=18;
int32 SystemError=19;
};

15
app/src/main/java/bsp_PV.proto

@ -0,0 +1,15 @@
syntax = "proto3";
option java_multiple_files = false;
option java_package = "com.example.fivewheel.models";
message PV_struct_define{
int32 Robot_ChgLength= 1;
double Robot_AutoSpeedBase=2;
double Robot_ManualSpeedBase=3;
int32 Robot_LaneChange_Direction = 4;
int32 Robot_Force = 5;
int64 TimeStamp=6;//
int32 RobotRestartAccepted=7;//Restart信号
int32 Robot_AutoWork = 8;
};

57
app/src/main/java/com/example/fivewheel/AppDatabase.java

@ -0,0 +1,57 @@
package com.example.fivewheel;
import static com.example.fivewheel.viewmodels.MainViewModel.mainBinding;
import android.content.Context;
import androidx.room.Database;
import androidx.room.Room;
import androidx.room.RoomDatabase;
@Database(entities = {RobotLog.class}, version = 1, exportSchema = false)
public abstract class AppDatabase extends RoomDatabase {
public abstract RobotLogDao robotLogDao();
private static volatile AppDatabase INSTANCE;
public static AppDatabase getInstance(Context context) {
if (INSTANCE == null) {
synchronized (AppDatabase.class) {
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
AppDatabase.class, "robot_logs.db")
.fallbackToDestructiveMigration() // 数据库升级时清空数据,可根据需求改
.build();
}
}
}
return INSTANCE;
}
// 在 MainActivity 中添加两个成员变量缓存电机状态
private String lastLeftError = "正常";
private String lastRightError = "正常";
// 在 TimerTask 或接收串口数据后调用的方法
private void checkMotorErrors() {
String currentLeftError = mainBinding.tvLeftError.getText().toString().trim();
String currentRightError = mainBinding.tvRightError.getText().toString().trim();
// 左电机状态变化且不正常时保存日志
if (!currentLeftError.equals("正常") && !currentLeftError.equals(lastLeftError)) {
saveMotorError("左电机", currentLeftError);
}
lastLeftError = currentLeftError;
// 右电机状态变化且不正常时保存日志
if (!currentRightError.equals("正常") && !currentRightError.equals(lastRightError)) {
saveMotorError("右电机", currentRightError);
}
lastRightError = currentRightError;
}
private void saveMotorError(String 左电机, String currentLeftError) {
}
}

942
app/src/main/java/com/example/fivewheel/MainActivity.java

@ -0,0 +1,942 @@
package com.example.fivewheel;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
import androidx.databinding.DataBindingUtil;
import androidx.lifecycle.ViewModelProvider;
import androidx.lifecycle.ViewModelStoreOwner;
import com.example.fivewheel.models.BspPV;
import com.example.fivewheel.models.RobotRMACM;
import com.example.fivewheel.services.CommunicationMethond;
import com.example.fivewheel.services.DataExchangeHelper;
import com.example.fivewheel.services.ModbusCRC;
import com.example.fivewheel.services.ModbusRtuSlaveService;
import com.example.fivewheel.services.USBSerialPortHelper;
import com.example.fivewheel.services.ttySerialPortHelper;
import com.example.fivewheel.viewmodels.MainViewModel;
import com.example.fivewheel.databinding.ActivityMainBinding;
import java.util.List;
import java.util.Locale;
import java.util.Timer;
import java.util.TimerTask;
import cn.nodemedia.NodePlayer;
public class MainActivity extends AppCompatActivity {
public ActivityMainBinding mainBinding;//通过Binding可以获取界面数据
public static CommunicationMethond AndroidMCUCommunicationMethod = CommunicationMethond.Wired;//0 默认无线, 1 有线
public RobotRMACM.RMACM robotRMACM;
public BspPV.PV_struct_define _toSendPV = BspPV.PV_struct_define.newBuilder().build();
public USBSerialPortHelper serialPortHelper;
// 整数输入框
private void setupIntegerEditText(EditText editText) {
editText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable editable) {
String text = editable.toString();
// 防止输入小数点
if (text.contains(".")) {
text = text.replace(".", "");
editText.setText(text);
editText.setSelection(editText.getText().length());
}
}
});
editText.setOnFocusChangeListener((v, hasFocus) -> {
if (!hasFocus) {
String text = editText.getText().toString().trim();
if (text.isEmpty()) {
editText.setText("0");
}
} else {
// 获得焦点时再显示光标
editText.setCursorVisible(true);
}
});
// 🔑 新增:编辑完成时自动隐藏光标
editText.setOnEditorActionListener((v, actionId, event) -> {
editText.setCursorVisible(false);
editText.clearFocus();
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
if (imm != null) {
imm.hideSoftInputFromWindow(editText.getWindowToken(), 0);
}
return false;
});
}
// 换道标志位,默认左换道
private int laneChangeDirection = 0;
// 按钮高亮状态
private boolean isLeftLaneChangeActive = true;
private boolean isRightLaneChangeActive = false;
// 自动工作标志位(0=未启动,1=已启动)
private int Robot_AutoWork = 0;
// 当前发送的参数值(存储编辑完成后的值)
private int currentChgLength = 100;
private double currentManualSpeed = 8;
private double currentAutoSpeed = 20;
private int currentForce = 300;
// 编辑框是否正在编辑的标志
private boolean isEditingChgLength = false;
private boolean isEditingManualSpeed = false;
private boolean isEditingAutoSpeed = false;
private boolean isEditingForce = false;
private void setupDecimalEditText(EditText editText, String paramName) {
editText.addTextChangedListener(new TextWatcher() {
@Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
@Override public void onTextChanged(CharSequence s, int start, int before, int count) {}
@Override
public void afterTextChanged(Editable editable) {
String text = editable.toString();
if (text.equals(".")) {
editText.setText("0.");
editText.setSelection(editText.getText().length());
}
}
});
editText.setOnFocusChangeListener((v, hasFocus) -> {
if (!hasFocus) {
// 编辑完成,更新对应的参数值
String text = editText.getText().toString().trim();
String originalText = text;
if (text.isEmpty()) {
text = getDefaultValue(paramName);
editText.setText(text);
} else {
// 验证并限制参数值
text = validateAndLimitValue(paramName, text);
// 如果值被调整,更新编辑框并显示提示
if (!text.equals(originalText)) {
editText.setText(text);
showRangeLimitDialog(paramName, originalText, text);
}
}
// 更新对应的参数值
updateParameterValue(paramName, text);
// 标记编辑完成
setEditingStatus(paramName, false);
// 保存参数修改日志
saveParamChange(paramName, text);
editText.setCursorVisible(false);
} else {
// 开始编辑,标记为编辑中
setEditingStatus(paramName, true);
editText.setCursorVisible(true);
// 延迟一小段时间后全选文本,确保焦点稳定
editText.postDelayed(() -> {
if (editText.hasFocus()) {
editText.selectAll();
}
}, 100);
}
});
// 编辑完成时自动隐藏光标
editText.setOnEditorActionListener((v, actionId, event) -> {
editText.setCursorVisible(false);
editText.clearFocus();
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
if (imm != null) {
imm.hideSoftInputFromWindow(editText.getWindowToken(), 0);
}
return false;
});
// 点击编辑框时也全选文本
editText.setOnClickListener(v -> {
if (editText.hasFocus()) {
editText.postDelayed(() -> {
if (editText.hasFocus()) {
editText.selectAll();
}
}, 100);
}
});
}
/**
* 更新参数值只在编辑完成后调用
*/
private void updateParameterValue(String paramName, String value) {
try {
switch (paramName) {
case "RobotChgLength":
currentChgLength = Integer.parseInt(value);
break;
case "RobotManualSpeed":
currentManualSpeed = Double.parseDouble(value);
break;
case "RobotAutoSpeed":
currentAutoSpeed = Double.parseDouble(value);
break;
case "RobotForce":
currentForce = Integer.parseInt(value);
break;
}
} catch (NumberFormatException e) {
// 如果解析失败,使用默认值
String defaultValue = getDefaultValue(paramName);
updateParameterValue(paramName, defaultValue);
}
}
/**
* 设置编辑状态
*/
private void setEditingStatus(String paramName, boolean isEditing) {
switch (paramName) {
case "RobotChgLength":
isEditingChgLength = isEditing;
break;
case "RobotManualSpeed":
isEditingManualSpeed = isEditing;
break;
case "RobotAutoSpeed":
isEditingAutoSpeed = isEditing;
break;
case "RobotForce":
isEditingForce = isEditing;
break;
}
}
/**
* 获取安全的发送值如果正在编辑返回旧值否则返回当前值
*/
private int getSafeChgLengthForSending() {
if (isEditingChgLength) {
// 正在编辑,返回旧值
return currentChgLength;
} else {
// 编辑完成,返回当前值
try {
String text = mainBinding.tvRobotChgLength.getText().toString().trim();
if (text.isEmpty()) return currentChgLength;
return Integer.parseInt(text);
} catch (NumberFormatException e) {
return currentChgLength;
}
}
}
private double getSafeManualSpeedForSending() {
if (isEditingManualSpeed) {
return currentManualSpeed;
} else {
try {
String text = mainBinding.tvRobotManualSpeed.getText().toString().trim();
if (text.isEmpty()) return currentManualSpeed;
return Double.parseDouble(text);
} catch (NumberFormatException e) {
return currentManualSpeed;
}
}
}
private double getSafeAutoSpeedForSending() {
if (isEditingAutoSpeed) {
return currentAutoSpeed;
} else {
try {
String text = mainBinding.tvRobotAutoSpeed.getText().toString().trim();
if (text.isEmpty()) return currentAutoSpeed;
return Double.parseDouble(text);
} catch (NumberFormatException e) {
return currentAutoSpeed;
}
}
}
private int getSafeForceForSending() {
if (isEditingForce) {
return currentForce;
} else {
try {
String text = mainBinding.tvRobotForce.getText().toString().trim();
if (text.isEmpty()) return currentForce;
return Integer.parseInt(text);
} catch (NumberFormatException e) {
return currentForce;
}
}
}
/**
* 验证并限制参数值范围
*/
private String validateAndLimitValue(String paramName, String value) {
try {
double numValue = Double.parseDouble(value);
switch (paramName) {
case "RobotChgLength":
int length = Math.max(0, Math.min(1000, (int) Math.round(numValue)));
return String.valueOf(length);
case "RobotManualSpeed":
case "RobotAutoSpeed":
double speed = Math.max(0, Math.min(30, numValue));
return (speed == (int)speed) ? String.valueOf((int)speed) : String.format(Locale.getDefault(),"%.1f", speed);
case "RobotForce":
int force = Math.max(300, Math.min(3000, (int) Math.round(numValue)));
return String.valueOf(force);
default:
return value;
}
} catch (NumberFormatException e) {
return getDefaultValue(paramName);
}
}
/**
* 获取参数的默认值
*/
private String getDefaultValue(String paramName) {
switch (paramName) {
case "RobotChgLength": return "100";
case "RobotManualSpeed": return "8";
case "RobotAutoSpeed": return "20";
case "RobotForce": return "300";
default: return "0";
}
}
/**
* 显示范围限制提示对话框
*/
private void showRangeLimitDialog(String paramName, String originalValue, String adjustedValue) {
runOnUiThread(() -> {
String paramDisplayName = getParamDisplayName(paramName);
String rangeInfo = getRangeInfo(paramName);
String message = String.format("输入值 %s 已调整为 %s\n%s",
originalValue, adjustedValue, rangeInfo);
new AlertDialog.Builder(this)
.setTitle(paramDisplayName + " 调整提示")
.setMessage(message)
.setPositiveButton("确定", null)
.show();
});
}
/**
* 获取参数显示名称
*/
private String getParamDisplayName(String paramName) {
switch (paramName) {
case "RobotChgLength": return "换道长度";
case "RobotManualSpeed": return "手动速度";
case "RobotAutoSpeed": return "自动速度";
case "RobotForce": return "压力值";
default: return paramName;
}
}
/**
* 获取参数范围信息
*/
private String getRangeInfo(String paramName) {
switch (paramName) {
case "RobotChgLength": return "有效范围:0 — 1000";
case "RobotManualSpeed":
case "RobotAutoSpeed": return "有效范围:0 - 30";
case "RobotForce": return "有效范围:300 - 3000";
default: return "";
}
}
// 安全取值,防止 Timer 崩溃
private int getSafeInt(@NonNull EditText editText, int defaultValue) {
String text = editText.getText().toString().trim();
if (text.isEmpty()) return defaultValue;
try {
return Integer.parseInt(text);
} catch (NumberFormatException e) {
return defaultValue;
}
}
private double getSafeDouble(@NonNull EditText editText, double defaultValue) {
String text = editText.getText().toString().trim();
if (text.isEmpty()) return defaultValue;
try {
return Double.parseDouble(text);
} catch (NumberFormatException e) {
return defaultValue;
}
}
Timer timer = new Timer();
public MainActivity() {
robotRMACM = RobotRMACM.RMACM.newBuilder().setRobotSpeed(0).setLightBrightness(0).build();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//MainViewModel binding region
mainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
MainViewModel vm = new ViewModelProvider((ViewModelStoreOwner) this).get(MainViewModel.class);
MainViewModel.mainBinding = mainBinding;
mainBinding.btnShowLogs.setOnClickListener(v -> showLogsDialog());
mainBinding.setVm(vm);
// 设置左右换道按钮的点击监听器
mainBinding.btnLeftLaneChange.setOnClickListener(v -> {
setLaneChangeDirection(0); // 左换道
updateButtonStyles();
saveOperationLog("切换至左换道");
});
mainBinding.btnRightLaneChange.setOnClickListener(v -> {
setLaneChangeDirection(1); // 右换道
updateButtonStyles();
saveOperationLog("切换至右换道");
});
//设置自动工作按钮的点击监听器
mainBinding.btnBindAutoWork.setOnClickListener(v -> {
Robot_AutoWork = 1; // 标志位置 1
updateAutoWorkButtonStyle(); // 变色
saveOperationLog("开启自动工作模式");
});
// 初始化按钮样式
updateButtonStyles();
updateAutoWorkButtonStyle();
setupDecimalEditText(mainBinding.tvRobotChgLength, "RobotChgLength");
setupDecimalEditText(mainBinding.tvRobotManualSpeed, "RobotManualSpeed");
setupDecimalEditText(mainBinding.tvRobotAutoSpeed, "RobotAutoSpeed");
setupDecimalEditText(mainBinding.tvRobotForce, "RobotForce");
// 保存参数
SharedPreferences sharedPreferences = getSharedPreferences("MyData", Context.MODE_PRIVATE);
String Str_RobotChgLength = sharedPreferences.getString("RobotChgLength", "100");
String Str_RobotLeftCompensation = sharedPreferences.getString("RobotLeftCompensation", "0");
String Str_RobotRightCompensation = sharedPreferences.getString("RobotRightCompensation", "0");
String Str_RobotManualSpeed = sharedPreferences.getString("RobotManualSpeed", "8");
String Str_RobotAutoSpeed = sharedPreferences.getString("RobotAutoSpeed", "20");
String Str_RobotForce = sharedPreferences.getString("RobotForce", "300");
// 初始化当前参数值
currentChgLength = Integer.parseInt(Str_RobotChgLength);
currentManualSpeed = Double.parseDouble(Str_RobotManualSpeed);
currentAutoSpeed = Double.parseDouble(Str_RobotAutoSpeed);
currentForce = Integer.parseInt(Str_RobotForce);
mainBinding.rFAngleRoll.setText(String.valueOf(0));
mainBinding.tvRobotError.setText(String.valueOf(0));
mainBinding.tvRobotChgLength.setText(Str_RobotChgLength);
mainBinding.tvRobotLeftCompensation.setText(Str_RobotLeftCompensation);
mainBinding.tvRobotRightCompensation.setText(Str_RobotRightCompensation);
mainBinding.tvForce.setText(String.valueOf(0));
mainBinding.tvRobotManualSpeed.setText(Str_RobotManualSpeed);
mainBinding.tvRobotAutoSpeed.setText(Str_RobotAutoSpeed);
mainBinding.tvRobotCurrent.setText(String.valueOf(0));
mainBinding.tvDynamometer.setText(String.valueOf(0));
mainBinding.tvRobotForce.setText(Str_RobotForce);
/* 删除15天前旧日志*/
deleteOldLogs();
/* NodePlayer 播放视频区域*/
NodePlayer nodePlayer0 = new NodePlayer(this);
// NodePlayer nodePlayer1=new NodePlayer(this);
//String address0 = "rtsp://192.168.1.168:8554/0";
// String address1 = "rtsp://192.168.1.169:8554/0";
//String addressTest = "rtsp://rtspstream:yEhp9qzAqveM9kHIE7GcL@zephyr.rtsp.stream/movie";
String address0 = "rtsp://192.168.144.25:8554/main.264";
/**/
//VideoPlayerHelper.startVedio(+mainBinding.nodePlayerView0,nodePlayer0,address0);
// VideoPlayerHelper.startVedio(mainBinding.nodePlayerView1,nodePlayer1,address1);
//VideoPlayerHelper.startVedio(mainBinding.nodePlayerView1,nodePlayer1,addressTest);
/* USB串口 控制区域*/
serialPortHelper = new USBSerialPortHelper(this, 38400);
serialPortHelper.intialize();
serialPortHelper.connect();
ttySerialPortHelper.MainActivity = this;
ttySerialPortHelper.Open();
ModbusRtuSlaveService.ModbusRtuSlaveServiceIntialize(serialPortHelper);
}
int UARTSendCount = 0;
public int USBSerialPortReceivedTimeCounter = 0;
@Override
protected void onStart() {
super.onStart();
serialPortHelper.onStart();
UARTSendCount = 0;
timer.schedule(new TimerTask() {
@Override
public void run() {
// 使用 Handler 或 runOnUiThread 更新 UI
runOnUiThread(new Runnable() {
@Override
public void run() {
ttySerialPortHelper.ReceivedCounter++;
if(ttySerialPortHelper.ReceivedCounter>=8)//250*4*2
{
ModbusRtuSlaveService.holdingRegisters[18]= 0;//不在线 sdk坏了
}else
{
ModbusRtuSlaveService.holdingRegisters[18]= 1;//在线
}
// 使用安全的发送值获取方法(只在编辑完成后发送新值)
_toSendPV = _toSendPV.toBuilder()
.setRobotChgLength(getSafeInt(mainBinding.tvRobotChgLength, 0))
.setRobotAutoSpeedBase(getSafeDouble(mainBinding.tvRobotAutoSpeed, 0.0))
.setRobotManualSpeedBase(getSafeDouble(mainBinding.tvRobotManualSpeed, 0.0))
.setRobotForce(getSafeInt(mainBinding.tvRobotForce, 0))
.setTimeStamp(System.currentTimeMillis())
.build();
USBSerialPortReceivedTimeCounter++;
if(USBSerialPortReceivedTimeCounter>=10)
{
USBSerialPortReceivedTimeCounter=10;
AndroidMCUCommunicationMethod = CommunicationMethond.Wireless;
}else
{
AndroidMCUCommunicationMethod = CommunicationMethond.Wired;
}
if (AndroidMCUCommunicationMethod == CommunicationMethond.Wireless) {
//若sdk有数据返回,则停止发送
if (ttySerialPortHelper.IsAllButtonSendBack == true) {
UARTSendCount = 0;
}
if (UARTSendCount <= 8) {
UARTSendCount++;
ttySerialPortHelper.SendData(ttySerialPortHelper.stopgetAllChData);
ttySerialPortHelper.IsAllButtonSendBack = false;
return;
}
ttySerialPortHelper.SendData(DataExchangeHelper.getSendPVBytes(_toSendPV));
return;
}
//有线
if (AndroidMCUCommunicationMethod == CommunicationMethond.Wired) {
if (ttySerialPortHelper.IsAllButtonSendBack == false) {
ttySerialPortHelper.SendData(ttySerialPortHelper.getAllChData_50Hz);
}
}
// ttySerialPortHelper.SendData(DataExchangeHelper.getSendPVBytes(_toSendPV));
}
});
}
}, 0, 250); // 延迟 0 毫秒,每隔 1000 毫秒执行一次
}
@Override
public void onStop() {
SharedPreferences sharedPreferences = getSharedPreferences("MyData", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString("RobotChgLength", String.valueOf(mainBinding.tvRobotChgLength.getText()));
editor.putString("RobotLeftCompensation", String.valueOf(mainBinding.tvRobotLeftCompensation.getText()));
editor.putString("RobotRightCompensation", String.valueOf(mainBinding.tvRobotRightCompensation.getText()));
editor.putString("RobotManualSpeed", String.valueOf(mainBinding.tvRobotManualSpeed.getText()));
editor.putString("RobotAutoSpeed", String.valueOf(mainBinding.tvRobotAutoSpeed.getText()));
editor.apply();
// 保存数据
serialPortHelper.onStop();
super.onStop();
}
@Override
public void onResume() {
super.onResume();
serialPortHelper.onResume();
}
@Override
public void onPause() {
super.onPause();
serialPortHelper.onPause();
stopSending();
SharedPreferences sharedPreferences = getSharedPreferences("MyData", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
// 添加空值检查
String chgLength = String.valueOf(mainBinding.tvRobotChgLength.getText());
if (chgLength.isEmpty()) chgLength = "100";
String leftComp = String.valueOf(mainBinding.tvRobotLeftCompensation.getText());
if (leftComp.isEmpty()) leftComp = "0";
String rightComp = String.valueOf(mainBinding.tvRobotRightCompensation.getText());
if (rightComp.isEmpty()) rightComp = "0";
String manualSpeed = String.valueOf(mainBinding.tvRobotManualSpeed.getText());
if (manualSpeed.isEmpty()) manualSpeed = "8";
String autoSpeed = String.valueOf(mainBinding.tvRobotAutoSpeed.getText());
if (autoSpeed.isEmpty()) autoSpeed = "20";
String force = String.valueOf(mainBinding.tvRobotForce.getText());
if (force.isEmpty()) force = "300";
editor.putString("RobotChgLength", chgLength);
editor.putString("RobotLeftCompensation", leftComp);
editor.putString("RobotRightCompensation", rightComp);
editor.putString("RobotManualSpeed", manualSpeed);
editor.putString("RobotAutoSpeed", autoSpeed);
editor.putString("RobotForce", force);
editor.apply();
}
@Override
protected void onDestroy() {
super.onDestroy();
if (timer != null) {
timer.cancel();
}
ttySerialPortHelper.onDestroy();
}
private TimerTask sendTask;
private void startSending() {
stopSending();
if (timer == null) {
timer = new Timer();
sendTask = new TimerTask() {
@Override
public void run() {
try {
// 使用安全的发送值获取方法(只在编辑完成后发送新值)
int chgLength = getSafeChgLengthForSending();
double manualSpeed = getSafeManualSpeedForSending();
double autoSpeed = getSafeAutoSpeedForSending();
int force = getSafeForceForSending();
// 在发送前进行范围限制(二次保障)
chgLength = Math.max(0, Math.min(1000, chgLength));
manualSpeed = Math.max(0, Math.min(30, manualSpeed));
autoSpeed = Math.max(0, Math.min(30, autoSpeed));
force = Math.max(300, Math.min(3000, force));
_toSendPV = _toSendPV.toBuilder()
.setRobotChgLength(chgLength)
.setRobotAutoSpeedBase(autoSpeed)
.setRobotManualSpeedBase(manualSpeed)
.setRobotLaneChangeDirection(laneChangeDirection)
.setRobotForce(force)
.setRobotAutoWork(Robot_AutoWork)
.setTimeStamp(System.currentTimeMillis())
.build();
byte[] byteArray = _toSendPV.toByteArray();
byte[] sendByteArray = new byte[byteArray.length + 4];
byte[] sendByteArray3 = new byte[byteArray.length + 6];
if (byteArray.length != 0) {
System.arraycopy(byteArray, 0, sendByteArray, 4, byteArray.length);
}
sendByteArray[0] = (byte) 0x55;
sendByteArray[1] = (byte) 0x55;
sendByteArray[2] = (byte) 0x01;
sendByteArray[3] = (byte) 0x01;
byte[] byteArray2 = ModbusCRC.calculateCRC(sendByteArray);
System.arraycopy(sendByteArray, 0, sendByteArray3, 0, sendByteArray.length);
System.arraycopy(byteArray2, 0, sendByteArray3, sendByteArray3.length - 2, 2);
ttySerialPortHelper.SendData(sendByteArray3);
runOnUiThread(() -> checkMotorErrors());
} catch (Exception e) {
android.util.Log.e("MainActivity", "Error in startSending timer task", e);
}
}
};
timer.schedule(sendTask, 0, 1000);
}
}
private void stopSending() {
try {
if (sendTask != null) {
sendTask.cancel();
sendTask = null;
}
if (timer != null) {
timer.cancel();
timer.purge();
timer = null;
}
} catch (Exception ignored) {}
}
// 设置换道方向
private void setLaneChangeDirection(int direction) {
laneChangeDirection = direction;
isLeftLaneChangeActive = (direction == 0);
isRightLaneChangeActive = (direction == 1);
}
// 更新按钮样式
private void updateButtonStyles() {
// 左换道按钮样式
if (isLeftLaneChangeActive) {
mainBinding.btnLeftLaneChange.setTextColor(ContextCompat.getColor(this, R.color.mediumvioletred));
mainBinding.btnLeftLaneChange.setBackgroundResource(R.drawable.blue_rounded_rectangle);
} else {
mainBinding.btnLeftLaneChange.setTextColor(ContextCompat.getColor(this, R.color.deepskyblue));
mainBinding.btnLeftLaneChange.setBackgroundResource(R.drawable.blue_rounded_rectangle);
}
// 右换道按钮样式
if (isRightLaneChangeActive) {
mainBinding.btnRightLaneChange.setTextColor(ContextCompat.getColor(this, R.color.mediumvioletred));
mainBinding.btnRightLaneChange.setBackgroundResource(R.drawable.blue_rounded_rectangle);
} else {
mainBinding.btnRightLaneChange.setTextColor(ContextCompat.getColor(this, R.color.deepskyblue));
mainBinding.btnRightLaneChange.setBackgroundResource(R.drawable.blue_rounded_rectangle);
}
}
//
private void updateAutoWorkButtonStyle() {
if (Robot_AutoWork == 1) {
mainBinding.btnBindAutoWork.setTextColor(
ContextCompat.getColor(this, R.color.mediumvioletred));
mainBinding.btnBindAutoWork.setBackgroundResource(R.drawable.blue_rounded_rectangle);
} else {
mainBinding.btnBindAutoWork.setTextColor(
ContextCompat.getColor(this, R.color.deepskyblue));
mainBinding.btnBindAutoWork.setBackgroundResource(R.drawable.blue_rounded_rectangle);
}
}
private void saveMotorError(String motorSide, String errorMsg) {
new Thread(() -> {
AppDatabase db = AppDatabase.getInstance(this);
RobotLog log = new RobotLog();
log.type = "error";
log.message = motorSide + " 电机报错: " + errorMsg;
log.time = System.currentTimeMillis();
db.robotLogDao().insert(log);
}).start();
}
private String lastLeftError = "xxx";
private String lastRightError = "xxx";
private void checkMotorErrors() {
String currentLeftError = mainBinding.tvLeftError.getText().toString().trim();
String currentRightError = mainBinding.tvRightError.getText().toString().trim();
if (!currentLeftError.equals("正常") && !currentLeftError.equals(lastLeftError)) {
saveMotorError("左电机", currentLeftError);
}
lastLeftError = currentLeftError;
if (!currentRightError.equals("正常") && !currentRightError.equals(lastRightError)) {
saveMotorError("右电机", currentRightError);
}
lastRightError = currentRightError;
}
// 禁用所有输入和点击
public void disableParameterArea() {
runOnUiThread(() -> disableViewRecursive(mainBinding.setLayout));
}
// 启用所有输入和点击
public void enableParameterArea() {
runOnUiThread(() -> enableViewRecursive(mainBinding.setLayout));
}
// 递归禁用
private void disableViewRecursive(View view) {
view.setEnabled(false);
view.setClickable(false);
view.setAlpha(0.8f);
if (view instanceof EditText) {
EditText editText = (EditText) view;
editText.setFocusable(false);
editText.setFocusableInTouchMode(false);
editText.setKeyListener(null);
editText.clearFocus();
editText.setCursorVisible(false);
}
if (view instanceof ViewGroup) {
ViewGroup group = (ViewGroup) view;
for (int i = 0; i < group.getChildCount(); i++) {
disableViewRecursive(group.getChildAt(i));
}
}
}
// 递归启用
private void enableViewRecursive(View view) {
view.setEnabled(true);
view.setClickable(true);
view.setAlpha(1.0f);
if (view instanceof EditText) {
EditText editText = (EditText) view;
editText.setFocusable(true);
editText.setFocusableInTouchMode(true);
editText.setCursorVisible(true);
// 重新设置 KeyListener 以恢复输入功能
editText.setKeyListener(new EditText(this).getKeyListener());
}
if (view instanceof ViewGroup) {
ViewGroup group = (ViewGroup) view;
for (int i = 0; i < group.getChildCount(); i++) {
enableViewRecursive(group.getChildAt(i));
}
}
}
private void saveParamChange(String paramName, String newValue) {
new Thread(() -> {
AppDatabase db = AppDatabase.getInstance(this);
RobotLog log = new RobotLog();
log.type = "param_change";
log.message = paramName + " 修改为 " + newValue;
log.time = System.currentTimeMillis();
db.robotLogDao().insert(log);
}).start();
}
private void saveOperationLog(String operation) {
new Thread(() -> {
AppDatabase db = AppDatabase.getInstance(this);
RobotLog log = new RobotLog();
log.type = "operation";
log.message = operation;
log.time = System.currentTimeMillis();
db.robotLogDao().insert(log);
}).start();
}
private void showLogsDialog() {
new Thread(() -> {
AppDatabase db = AppDatabase.getInstance(this);
List<RobotLog> logs = db.robotLogDao().getAllLogs();
StringBuilder sb = new StringBuilder();
for (RobotLog log : logs) {
sb.append("[").append(android.text.format.DateFormat.format("yyyy-MM-dd HH:mm:ss", log.time)).append("] ");
sb.append(log.type).append(": ").append(log.message).append("\n");
}
String logContent = sb.toString();
runOnUiThread(() -> {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("日志信息");
View dialogView = getLayoutInflater().inflate(R.layout.dialog_logs, null);
TextView tvLogs = dialogView.findViewById(R.id.tv_logs_content);
tvLogs.setText(logContent.isEmpty() ? "暂无日志" : logContent);
builder.setView(dialogView)
.setPositiveButton("关闭", null)
.show();
});
}).start();
}
private void deleteOldLogs() {
new Thread(() -> {
AppDatabase db = AppDatabase.getInstance(this);
long fifteenDaysAgo = System.currentTimeMillis() - 15L * 24 * 60 * 60 * 1000;
db.robotLogDao().deleteLogsBefore(fifteenDaysAgo);
}).start();
}
}

20
app/src/main/java/com/example/fivewheel/RobotLog.java

@ -0,0 +1,20 @@
package com.example.fivewheel;
import androidx.room.ColumnInfo;
import androidx.room.Entity;
import androidx.room.PrimaryKey;
@Entity(tableName = "robot_logs")
public class RobotLog {
@PrimaryKey(autoGenerate = true)
public int id;
@ColumnInfo(name = "type") // "error" 或 "param_change"
public String type;
@ColumnInfo(name = "message") // 具体信息:报错内容或修改了哪个参数
public String message;
@ColumnInfo(name = "time") // 时间戳
public long time;
}

22
app/src/main/java/com/example/fivewheel/RobotLogDao.java

@ -0,0 +1,22 @@
package com.example.fivewheel;
import androidx.room.Dao;
import androidx.room.Insert;
import androidx.room.Query;
import java.util.List;
@Dao
public interface RobotLogDao {
@Insert
void insert(RobotLog log);
@Query("SELECT * FROM robot_logs ORDER BY time DESC")
List<RobotLog> getAllLogs();
@Query("DELETE FROM robot_logs WHERE time < :timeLimit")
void deleteLogsBefore(long timeLimit);
}

1725
app/src/main/java/com/example/fivewheel/models/BspError.java

File diff suppressed because it is too large

1828
app/src/main/java/com/example/fivewheel/models/BspIV.java

File diff suppressed because it is too large

1048
app/src/main/java/com/example/fivewheel/models/BspPV.java

File diff suppressed because it is too large

792
app/src/main/java/com/example/fivewheel/models/RobotData.java

@ -0,0 +1,792 @@
// Generated by the protocol buffer compiler. DO NOT EDIT!
// NO CHECKED-IN PROTOBUF GENCODE
// source: robot_data.proto
// Protobuf Java Version: 4.27.2
package com.example.fivewheel.models;
public final class RobotData {
private RobotData() {}
static {
com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion(
com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC,
/* major= */ 4,
/* minor= */ 27,
/* patch= */ 2,
/* suffix= */ "",
RobotData.class.getName());
}
public static void registerAllExtensions(
com.google.protobuf.ExtensionRegistryLite registry) {
}
public static void registerAllExtensions(
com.google.protobuf.ExtensionRegistry registry) {
registerAllExtensions(
(com.google.protobuf.ExtensionRegistryLite) registry);
}
public interface DataTransOrBuilder extends
// @@protoc_insertion_point(interface_extends:DataTrans)
com.google.protobuf.MessageOrBuilder {
/**
* <pre>
* 横滚角
* </pre>
*
* <code>int32 RF_Angle_Roll = 1;</code>
* @return The rFAngleRoll.
*/
int getRFAngleRoll();
/**
* <pre>
* 俯仰角
* </pre>
*
* <code>int32 RF_Angle_Pitch = 2;</code>
* @return The rFAnglePitch.
*/
int getRFAnglePitch();
/**
* <pre>
* 航向角
* </pre>
*
* <code>int32 RF_Angle_Yaw = 3;</code>
* @return The rFAngleYaw.
*/
int getRFAngleYaw();
/**
* <pre>
* 海洋深度
* </pre>
*
* <code>int32 RF_Depth = 4;</code>
* @return The rFDepth.
*/
int getRFDepth();
}
/**
* Protobuf type {@code DataTrans}
*/
public static final class DataTrans extends
com.google.protobuf.GeneratedMessage implements
// @@protoc_insertion_point(message_implements:DataTrans)
DataTransOrBuilder {
private static final long serialVersionUID = 0L;
static {
com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion(
com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC,
/* major= */ 4,
/* minor= */ 27,
/* patch= */ 2,
/* suffix= */ "",
DataTrans.class.getName());
}
// Use DataTrans.newBuilder() to construct.
private DataTrans(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
super(builder);
}
private DataTrans() {
}
public static final com.google.protobuf.Descriptors.Descriptor
getDescriptor() {
return RobotData.internal_static_DataTrans_descriptor;
}
@Override
protected FieldAccessorTable
internalGetFieldAccessorTable() {
return RobotData.internal_static_DataTrans_fieldAccessorTable
.ensureFieldAccessorsInitialized(
DataTrans.class, Builder.class);
}
public static final int RF_ANGLE_ROLL_FIELD_NUMBER = 1;
private int rFAngleRoll_ = 0;
/**
* <pre>
* 横滚角
* </pre>
*
* <code>int32 RF_Angle_Roll = 1;</code>
* @return The rFAngleRoll.
*/
@Override
public int getRFAngleRoll() {
return rFAngleRoll_;
}
public static final int RF_ANGLE_PITCH_FIELD_NUMBER = 2;
private int rFAnglePitch_ = 0;
/**
* <pre>
* 俯仰角
* </pre>
*
* <code>int32 RF_Angle_Pitch = 2;</code>
* @return The rFAnglePitch.
*/
@Override
public int getRFAnglePitch() {
return rFAnglePitch_;
}
public static final int RF_ANGLE_YAW_FIELD_NUMBER = 3;
private int rFAngleYaw_ = 0;
/**
* <pre>
* 航向角
* </pre>
*
* <code>int32 RF_Angle_Yaw = 3;</code>
* @return The rFAngleYaw.
*/
@Override
public int getRFAngleYaw() {
return rFAngleYaw_;
}
public static final int RF_DEPTH_FIELD_NUMBER = 4;
private int rFDepth_ = 0;
/**
* <pre>
* 海洋深度
* </pre>
*
* <code>int32 RF_Depth = 4;</code>
* @return The rFDepth.
*/
@Override
public int getRFDepth() {
return rFDepth_;
}
private byte memoizedIsInitialized = -1;
@Override
public final boolean isInitialized() {
byte isInitialized = memoizedIsInitialized;
if (isInitialized == 1) return true;
if (isInitialized == 0) return false;
memoizedIsInitialized = 1;
return true;
}
@Override
public void writeTo(com.google.protobuf.CodedOutputStream output)
throws java.io.IOException {
if (rFAngleRoll_ != 0) {
output.writeInt32(1, rFAngleRoll_);
}
if (rFAnglePitch_ != 0) {
output.writeInt32(2, rFAnglePitch_);
}
if (rFAngleYaw_ != 0) {
output.writeInt32(3, rFAngleYaw_);
}
if (rFDepth_ != 0) {
output.writeInt32(4, rFDepth_);
}
getUnknownFields().writeTo(output);
}
@Override
public int getSerializedSize() {
int size = memoizedSize;
if (size != -1) return size;
size = 0;
if (rFAngleRoll_ != 0) {
size += com.google.protobuf.CodedOutputStream
.computeInt32Size(1, rFAngleRoll_);
}
if (rFAnglePitch_ != 0) {
size += com.google.protobuf.CodedOutputStream
.computeInt32Size(2, rFAnglePitch_);
}
if (rFAngleYaw_ != 0) {
size += com.google.protobuf.CodedOutputStream
.computeInt32Size(3, rFAngleYaw_);
}
if (rFDepth_ != 0) {
size += com.google.protobuf.CodedOutputStream
.computeInt32Size(4, rFDepth_);
}
size += getUnknownFields().getSerializedSize();
memoizedSize = size;
return size;
}
@Override
public boolean equals(final Object obj) {
if (obj == this) {
return true;
}
if (!(obj instanceof DataTrans)) {
return super.equals(obj);
}
DataTrans other = (DataTrans) obj;
if (getRFAngleRoll()
!= other.getRFAngleRoll()) return false;
if (getRFAnglePitch()
!= other.getRFAnglePitch()) return false;
if (getRFAngleYaw()
!= other.getRFAngleYaw()) return false;
if (getRFDepth()
!= other.getRFDepth()) return false;
if (!getUnknownFields().equals(other.getUnknownFields())) return false;
return true;
}
@Override
public int hashCode() {
if (memoizedHashCode != 0) {
return memoizedHashCode;
}
int hash = 41;
hash = (19 * hash) + getDescriptor().hashCode();
hash = (37 * hash) + RF_ANGLE_ROLL_FIELD_NUMBER;
hash = (53 * hash) + getRFAngleRoll();
hash = (37 * hash) + RF_ANGLE_PITCH_FIELD_NUMBER;
hash = (53 * hash) + getRFAnglePitch();
hash = (37 * hash) + RF_ANGLE_YAW_FIELD_NUMBER;
hash = (53 * hash) + getRFAngleYaw();
hash = (37 * hash) + RF_DEPTH_FIELD_NUMBER;
hash = (53 * hash) + getRFDepth();
hash = (29 * hash) + getUnknownFields().hashCode();
memoizedHashCode = hash;
return hash;
}
public static DataTrans parseFrom(
java.nio.ByteBuffer data)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data);
}
public static DataTrans parseFrom(
java.nio.ByteBuffer data,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data, extensionRegistry);
}
public static DataTrans parseFrom(
com.google.protobuf.ByteString data)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data);
}
public static DataTrans parseFrom(
com.google.protobuf.ByteString data,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data, extensionRegistry);
}
public static DataTrans parseFrom(byte[] data)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data);
}
public static DataTrans parseFrom(
byte[] data,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data, extensionRegistry);
}
public static DataTrans parseFrom(java.io.InputStream input)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessage
.parseWithIOException(PARSER, input);
}
public static DataTrans parseFrom(
java.io.InputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessage
.parseWithIOException(PARSER, input, extensionRegistry);
}
public static DataTrans parseDelimitedFrom(java.io.InputStream input)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessage
.parseDelimitedWithIOException(PARSER, input);
}
public static DataTrans parseDelimitedFrom(
java.io.InputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessage
.parseDelimitedWithIOException(PARSER, input, extensionRegistry);
}
public static DataTrans parseFrom(
com.google.protobuf.CodedInputStream input)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessage
.parseWithIOException(PARSER, input);
}
public static DataTrans parseFrom(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessage
.parseWithIOException(PARSER, input, extensionRegistry);
}
@Override
public Builder newBuilderForType() { return newBuilder(); }
public static Builder newBuilder() {
return DEFAULT_INSTANCE.toBuilder();
}
public static Builder newBuilder(DataTrans prototype) {
return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
}
@Override
public Builder toBuilder() {
return this == DEFAULT_INSTANCE
? new Builder() : new Builder().mergeFrom(this);
}
@Override
protected Builder newBuilderForType(
BuilderParent parent) {
Builder builder = new Builder(parent);
return builder;
}
/**
* Protobuf type {@code DataTrans}
*/
public static final class Builder extends
com.google.protobuf.GeneratedMessage.Builder<Builder> implements
// @@protoc_insertion_point(builder_implements:DataTrans)
DataTransOrBuilder {
public static final com.google.protobuf.Descriptors.Descriptor
getDescriptor() {
return RobotData.internal_static_DataTrans_descriptor;
}
@Override
protected FieldAccessorTable
internalGetFieldAccessorTable() {
return RobotData.internal_static_DataTrans_fieldAccessorTable
.ensureFieldAccessorsInitialized(
DataTrans.class, Builder.class);
}
// Construct using com.example.removemarineanimals.models.RobotData.DataTrans.newBuilder()
private Builder() {
}
private Builder(
BuilderParent parent) {
super(parent);
}
@Override
public Builder clear() {
super.clear();
bitField0_ = 0;
rFAngleRoll_ = 0;
rFAnglePitch_ = 0;
rFAngleYaw_ = 0;
rFDepth_ = 0;
return this;
}
@Override
public com.google.protobuf.Descriptors.Descriptor
getDescriptorForType() {
return RobotData.internal_static_DataTrans_descriptor;
}
@Override
public DataTrans getDefaultInstanceForType() {
return DataTrans.getDefaultInstance();
}
@Override
public DataTrans build() {
DataTrans result = buildPartial();
if (!result.isInitialized()) {
throw newUninitializedMessageException(result);
}
return result;
}
@Override
public DataTrans buildPartial() {
DataTrans result = new DataTrans(this);
if (bitField0_ != 0) { buildPartial0(result); }
onBuilt();
return result;
}
private void buildPartial0(DataTrans result) {
int from_bitField0_ = bitField0_;
if (((from_bitField0_ & 0x00000001) != 0)) {
result.rFAngleRoll_ = rFAngleRoll_;
}
if (((from_bitField0_ & 0x00000002) != 0)) {
result.rFAnglePitch_ = rFAnglePitch_;
}
if (((from_bitField0_ & 0x00000004) != 0)) {
result.rFAngleYaw_ = rFAngleYaw_;
}
if (((from_bitField0_ & 0x00000008) != 0)) {
result.rFDepth_ = rFDepth_;
}
}
@Override
public Builder mergeFrom(com.google.protobuf.Message other) {
if (other instanceof DataTrans) {
return mergeFrom((DataTrans)other);
} else {
super.mergeFrom(other);
return this;
}
}
public Builder mergeFrom(DataTrans other) {
if (other == DataTrans.getDefaultInstance()) return this;
if (other.getRFAngleRoll() != 0) {
setRFAngleRoll(other.getRFAngleRoll());
}
if (other.getRFAnglePitch() != 0) {
setRFAnglePitch(other.getRFAnglePitch());
}
if (other.getRFAngleYaw() != 0) {
setRFAngleYaw(other.getRFAngleYaw());
}
if (other.getRFDepth() != 0) {
setRFDepth(other.getRFDepth());
}
this.mergeUnknownFields(other.getUnknownFields());
onChanged();
return this;
}
@Override
public final boolean isInitialized() {
return true;
}
@Override
public Builder mergeFrom(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
if (extensionRegistry == null) {
throw new NullPointerException();
}
try {
boolean done = false;
while (!done) {
int tag = input.readTag();
switch (tag) {
case 0:
done = true;
break;
case 8: {
rFAngleRoll_ = input.readInt32();
bitField0_ |= 0x00000001;
break;
} // case 8
case 16: {
rFAnglePitch_ = input.readInt32();
bitField0_ |= 0x00000002;
break;
} // case 16
case 24: {
rFAngleYaw_ = input.readInt32();
bitField0_ |= 0x00000004;
break;
} // case 24
case 32: {
rFDepth_ = input.readInt32();
bitField0_ |= 0x00000008;
break;
} // case 32
default: {
if (!super.parseUnknownField(input, extensionRegistry, tag)) {
done = true; // was an endgroup tag
}
break;
} // default:
} // switch (tag)
} // while (!done)
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
throw e.unwrapIOException();
} finally {
onChanged();
} // finally
return this;
}
private int bitField0_;
private int rFAngleRoll_ ;
/**
* <pre>
* 横滚角
* </pre>
*
* <code>int32 RF_Angle_Roll = 1;</code>
* @return The rFAngleRoll.
*/
@Override
public int getRFAngleRoll() {
return rFAngleRoll_;
}
/**
* <pre>
* 横滚角
* </pre>
*
* <code>int32 RF_Angle_Roll = 1;</code>
* @param value The rFAngleRoll to set.
* @return This builder for chaining.
*/
public Builder setRFAngleRoll(int value) {
rFAngleRoll_ = value;
bitField0_ |= 0x00000001;
onChanged();
return this;
}
/**
* <pre>
* 横滚角
* </pre>
*
* <code>int32 RF_Angle_Roll = 1;</code>
* @return This builder for chaining.
*/
public Builder clearRFAngleRoll() {
bitField0_ = (bitField0_ & ~0x00000001);
rFAngleRoll_ = 0;
onChanged();
return this;
}
private int rFAnglePitch_ ;
/**
* <pre>
* 俯仰角
* </pre>
*
* <code>int32 RF_Angle_Pitch = 2;</code>
* @return The rFAnglePitch.
*/
@Override
public int getRFAnglePitch() {
return rFAnglePitch_;
}
/**
* <pre>
* 俯仰角
* </pre>
*
* <code>int32 RF_Angle_Pitch = 2;</code>
* @param value The rFAnglePitch to set.
* @return This builder for chaining.
*/
public Builder setRFAnglePitch(int value) {
rFAnglePitch_ = value;
bitField0_ |= 0x00000002;
onChanged();
return this;
}
/**
* <pre>
* 俯仰角
* </pre>
*
* <code>int32 RF_Angle_Pitch = 2;</code>
* @return This builder for chaining.
*/
public Builder clearRFAnglePitch() {
bitField0_ = (bitField0_ & ~0x00000002);
rFAnglePitch_ = 0;
onChanged();
return this;
}
private int rFAngleYaw_ ;
/**
* <pre>
* 航向角
* </pre>
*
* <code>int32 RF_Angle_Yaw = 3;</code>
* @return The rFAngleYaw.
*/
@Override
public int getRFAngleYaw() {
return rFAngleYaw_;
}
/**
* <pre>
* 航向角
* </pre>
*
* <code>int32 RF_Angle_Yaw = 3;</code>
* @param value The rFAngleYaw to set.
* @return This builder for chaining.
*/
public Builder setRFAngleYaw(int value) {
rFAngleYaw_ = value;
bitField0_ |= 0x00000004;
onChanged();
return this;
}
/**
* <pre>
* 航向角
* </pre>
*
* <code>int32 RF_Angle_Yaw = 3;</code>
* @return This builder for chaining.
*/
public Builder clearRFAngleYaw() {
bitField0_ = (bitField0_ & ~0x00000004);
rFAngleYaw_ = 0;
onChanged();
return this;
}
private int rFDepth_ ;
/**
* <pre>
* 海洋深度
* </pre>
*
* <code>int32 RF_Depth = 4;</code>
* @return The rFDepth.
*/
@Override
public int getRFDepth() {
return rFDepth_;
}
/**
* <pre>
* 海洋深度
* </pre>
*
* <code>int32 RF_Depth = 4;</code>
* @param value The rFDepth to set.
* @return This builder for chaining.
*/
public Builder setRFDepth(int value) {
rFDepth_ = value;
bitField0_ |= 0x00000008;
onChanged();
return this;
}
/**
* <pre>
* 海洋深度
* </pre>
*
* <code>int32 RF_Depth = 4;</code>
* @return This builder for chaining.
*/
public Builder clearRFDepth() {
bitField0_ = (bitField0_ & ~0x00000008);
rFDepth_ = 0;
onChanged();
return this;
}
// @@protoc_insertion_point(builder_scope:DataTrans)
}
// @@protoc_insertion_point(class_scope:DataTrans)
private static final DataTrans DEFAULT_INSTANCE;
static {
DEFAULT_INSTANCE = new DataTrans();
}
public static DataTrans getDefaultInstance() {
return DEFAULT_INSTANCE;
}
private static final com.google.protobuf.Parser<DataTrans>
PARSER = new com.google.protobuf.AbstractParser<DataTrans>() {
@Override
public DataTrans parsePartialFrom(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
Builder builder = newBuilder();
try {
builder.mergeFrom(input, extensionRegistry);
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
throw e.setUnfinishedMessage(builder.buildPartial());
} catch (com.google.protobuf.UninitializedMessageException e) {
throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial());
} catch (java.io.IOException e) {
throw new com.google.protobuf.InvalidProtocolBufferException(e)
.setUnfinishedMessage(builder.buildPartial());
}
return builder.buildPartial();
}
};
public static com.google.protobuf.Parser<DataTrans> parser() {
return PARSER;
}
@Override
public com.google.protobuf.Parser<DataTrans> getParserForType() {
return PARSER;
}
@Override
public DataTrans getDefaultInstanceForType() {
return DEFAULT_INSTANCE;
}
}
private static final com.google.protobuf.Descriptors.Descriptor
internal_static_DataTrans_descriptor;
private static final
com.google.protobuf.GeneratedMessage.FieldAccessorTable
internal_static_DataTrans_fieldAccessorTable;
public static com.google.protobuf.Descriptors.FileDescriptor
getDescriptor() {
return descriptor;
}
private static com.google.protobuf.Descriptors.FileDescriptor
descriptor;
static {
String[] descriptorData = {
"\n\020robot_data.proto\"b\n\tDataTrans\022\025\n\rRF_An" +
"gle_Roll\030\001 \001(\005\022\026\n\016RF_Angle_Pitch\030\002 \001(\005\022\024" +
"\n\014RF_Angle_Yaw\030\003 \001(\005\022\020\n\010RF_Depth\030\004 \001(\005B*" +
"\n&com.example.removemarineanimals.models" +
"P\000b\006proto3"
};
descriptor = com.google.protobuf.Descriptors.FileDescriptor
.internalBuildGeneratedFileFrom(descriptorData,
new com.google.protobuf.Descriptors.FileDescriptor[] {
});
internal_static_DataTrans_descriptor =
getDescriptor().getMessageTypes().get(0);
internal_static_DataTrans_fieldAccessorTable = new
com.google.protobuf.GeneratedMessage.FieldAccessorTable(
internal_static_DataTrans_descriptor,
new String[] { "RFAngleRoll", "RFAnglePitch", "RFAngleYaw", "RFDepth", });
descriptor.resolveAllFeaturesImmutable();
}
// @@protoc_insertion_point(outer_class_scope)
}

615
app/src/main/java/com/example/fivewheel/models/RobotRMACM.java

@ -0,0 +1,615 @@
// Generated by the protocol buffer compiler. DO NOT EDIT!
// NO CHECKED-IN PROTOBUF GENCODE
// source: robot_RMACM.proto
// Protobuf Java Version: 4.27.2
package com.example.fivewheel.models;
public final class RobotRMACM {
private RobotRMACM() {}
static {
com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion(
com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC,
/* major= */ 4,
/* minor= */ 27,
/* patch= */ 2,
/* suffix= */ "",
RobotRMACM.class.getName());
}
public static void registerAllExtensions(
com.google.protobuf.ExtensionRegistryLite registry) {
}
public static void registerAllExtensions(
com.google.protobuf.ExtensionRegistry registry) {
registerAllExtensions(
(com.google.protobuf.ExtensionRegistryLite) registry);
}
public interface RMACMOrBuilder extends
// @@protoc_insertion_point(interface_extends:RMACM)
com.google.protobuf.MessageOrBuilder {
/**
* <pre>
* 灯光亮度
* </pre>
*
* <code>int32 LightBrightness = 1;</code>
* @return The lightBrightness.
*/
int getLightBrightness();
/**
* <pre>
* 机器人速度
* </pre>
*
* <code>int32 Robot_Speed = 2;</code>
* @return The robotSpeed.
*/
int getRobotSpeed();
}
/**
* <pre>
* Remove Marine Animal Command
* </pre>
*
* Protobuf type {@code RMACM}
*/
public static final class RMACM extends
com.google.protobuf.GeneratedMessage implements
// @@protoc_insertion_point(message_implements:RMACM)
RMACMOrBuilder {
private static final long serialVersionUID = 0L;
static {
com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion(
com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC,
/* major= */ 4,
/* minor= */ 27,
/* patch= */ 2,
/* suffix= */ "",
RMACM.class.getName());
}
// Use RMACM.newBuilder() to construct.
private RMACM(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
super(builder);
}
private RMACM() {
}
public static final com.google.protobuf.Descriptors.Descriptor
getDescriptor() {
return RobotRMACM.internal_static_RMACM_descriptor;
}
@Override
protected FieldAccessorTable
internalGetFieldAccessorTable() {
return RobotRMACM.internal_static_RMACM_fieldAccessorTable
.ensureFieldAccessorsInitialized(
RMACM.class, Builder.class);
}
public static final int LIGHTBRIGHTNESS_FIELD_NUMBER = 1;
private int lightBrightness_ = 0;
/**
* <pre>
* 灯光亮度
* </pre>
*
* <code>int32 LightBrightness = 1;</code>
* @return The lightBrightness.
*/
@Override
public int getLightBrightness() {
return lightBrightness_;
}
public static final int ROBOT_SPEED_FIELD_NUMBER = 2;
private int robotSpeed_ = 0;
/**
* <pre>
* 机器人速度
* </pre>
*
* <code>int32 Robot_Speed = 2;</code>
* @return The robotSpeed.
*/
@Override
public int getRobotSpeed() {
return robotSpeed_;
}
private byte memoizedIsInitialized = -1;
@Override
public final boolean isInitialized() {
byte isInitialized = memoizedIsInitialized;
if (isInitialized == 1) return true;
if (isInitialized == 0) return false;
memoizedIsInitialized = 1;
return true;
}
@Override
public void writeTo(com.google.protobuf.CodedOutputStream output)
throws java.io.IOException {
if (lightBrightness_ != 0) {
output.writeInt32(1, lightBrightness_);
}
if (robotSpeed_ != 0) {
output.writeInt32(2, robotSpeed_);
}
getUnknownFields().writeTo(output);
}
@Override
public int getSerializedSize() {
int size = memoizedSize;
if (size != -1) return size;
size = 0;
if (lightBrightness_ != 0) {
size += com.google.protobuf.CodedOutputStream
.computeInt32Size(1, lightBrightness_);
}
if (robotSpeed_ != 0) {
size += com.google.protobuf.CodedOutputStream
.computeInt32Size(2, robotSpeed_);
}
size += getUnknownFields().getSerializedSize();
memoizedSize = size;
return size;
}
@Override
public boolean equals(final Object obj) {
if (obj == this) {
return true;
}
if (!(obj instanceof RMACM)) {
return super.equals(obj);
}
RMACM other = (RMACM) obj;
if (getLightBrightness()
!= other.getLightBrightness()) return false;
if (getRobotSpeed()
!= other.getRobotSpeed()) return false;
if (!getUnknownFields().equals(other.getUnknownFields())) return false;
return true;
}
@Override
public int hashCode() {
if (memoizedHashCode != 0) {
return memoizedHashCode;
}
int hash = 41;
hash = (19 * hash) + getDescriptor().hashCode();
hash = (37 * hash) + LIGHTBRIGHTNESS_FIELD_NUMBER;
hash = (53 * hash) + getLightBrightness();
hash = (37 * hash) + ROBOT_SPEED_FIELD_NUMBER;
hash = (53 * hash) + getRobotSpeed();
hash = (29 * hash) + getUnknownFields().hashCode();
memoizedHashCode = hash;
return hash;
}
public static RMACM parseFrom(
java.nio.ByteBuffer data)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data);
}
public static RMACM parseFrom(
java.nio.ByteBuffer data,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data, extensionRegistry);
}
public static RMACM parseFrom(
com.google.protobuf.ByteString data)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data);
}
public static RMACM parseFrom(
com.google.protobuf.ByteString data,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data, extensionRegistry);
}
public static RMACM parseFrom(byte[] data)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data);
}
public static RMACM parseFrom(
byte[] data,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data, extensionRegistry);
}
public static RMACM parseFrom(java.io.InputStream input)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessage
.parseWithIOException(PARSER, input);
}
public static RMACM parseFrom(
java.io.InputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessage
.parseWithIOException(PARSER, input, extensionRegistry);
}
public static RMACM parseDelimitedFrom(java.io.InputStream input)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessage
.parseDelimitedWithIOException(PARSER, input);
}
public static RMACM parseDelimitedFrom(
java.io.InputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessage
.parseDelimitedWithIOException(PARSER, input, extensionRegistry);
}
public static RMACM parseFrom(
com.google.protobuf.CodedInputStream input)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessage
.parseWithIOException(PARSER, input);
}
public static RMACM parseFrom(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessage
.parseWithIOException(PARSER, input, extensionRegistry);
}
@Override
public Builder newBuilderForType() { return newBuilder(); }
public static Builder newBuilder() {
return DEFAULT_INSTANCE.toBuilder();
}
public static Builder newBuilder(RMACM prototype) {
return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
}
@Override
public Builder toBuilder() {
return this == DEFAULT_INSTANCE
? new Builder() : new Builder().mergeFrom(this);
}
@Override
protected Builder newBuilderForType(
BuilderParent parent) {
Builder builder = new Builder(parent);
return builder;
}
/**
* <pre>
* Remove Marine Animal Command
* </pre>
*
* Protobuf type {@code RMACM}
*/
public static final class Builder extends
com.google.protobuf.GeneratedMessage.Builder<Builder> implements
// @@protoc_insertion_point(builder_implements:RMACM)
RMACMOrBuilder {
public static final com.google.protobuf.Descriptors.Descriptor
getDescriptor() {
return RobotRMACM.internal_static_RMACM_descriptor;
}
@Override
protected FieldAccessorTable
internalGetFieldAccessorTable() {
return RobotRMACM.internal_static_RMACM_fieldAccessorTable
.ensureFieldAccessorsInitialized(
RMACM.class, Builder.class);
}
// Construct using com.example.removemarineanimals.models.RobotRMACM.RMACM.newBuilder()
private Builder() {
}
private Builder(
BuilderParent parent) {
super(parent);
}
@Override
public Builder clear() {
super.clear();
bitField0_ = 0;
lightBrightness_ = 0;
robotSpeed_ = 0;
return this;
}
@Override
public com.google.protobuf.Descriptors.Descriptor
getDescriptorForType() {
return RobotRMACM.internal_static_RMACM_descriptor;
}
@Override
public RMACM getDefaultInstanceForType() {
return RMACM.getDefaultInstance();
}
@Override
public RMACM build() {
RMACM result = buildPartial();
if (!result.isInitialized()) {
throw newUninitializedMessageException(result);
}
return result;
}
@Override
public RMACM buildPartial() {
RMACM result = new RMACM(this);
if (bitField0_ != 0) { buildPartial0(result); }
onBuilt();
return result;
}
private void buildPartial0(RMACM result) {
int from_bitField0_ = bitField0_;
if (((from_bitField0_ & 0x00000001) != 0)) {
result.lightBrightness_ = lightBrightness_;
}
if (((from_bitField0_ & 0x00000002) != 0)) {
result.robotSpeed_ = robotSpeed_;
}
}
@Override
public Builder mergeFrom(com.google.protobuf.Message other) {
if (other instanceof RMACM) {
return mergeFrom((RMACM)other);
} else {
super.mergeFrom(other);
return this;
}
}
public Builder mergeFrom(RMACM other) {
if (other == RMACM.getDefaultInstance()) return this;
if (other.getLightBrightness() != 0) {
setLightBrightness(other.getLightBrightness());
}
if (other.getRobotSpeed() != 0) {
setRobotSpeed(other.getRobotSpeed());
}
this.mergeUnknownFields(other.getUnknownFields());
onChanged();
return this;
}
@Override
public final boolean isInitialized() {
return true;
}
@Override
public Builder mergeFrom(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
if (extensionRegistry == null) {
throw new NullPointerException();
}
try {
boolean done = false;
while (!done) {
int tag = input.readTag();
switch (tag) {
case 0:
done = true;
break;
case 8: {
lightBrightness_ = input.readInt32();
bitField0_ |= 0x00000001;
break;
} // case 8
case 16: {
robotSpeed_ = input.readInt32();
bitField0_ |= 0x00000002;
break;
} // case 16
default: {
if (!super.parseUnknownField(input, extensionRegistry, tag)) {
done = true; // was an endgroup tag
}
break;
} // default:
} // switch (tag)
} // while (!done)
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
throw e.unwrapIOException();
} finally {
onChanged();
} // finally
return this;
}
private int bitField0_;
private int lightBrightness_ ;
/**
* <pre>
* 灯光亮度
* </pre>
*
* <code>int32 LightBrightness = 1;</code>
* @return The lightBrightness.
*/
@Override
public int getLightBrightness() {
return lightBrightness_;
}
/**
* <pre>
* 灯光亮度
* </pre>
*
* <code>int32 LightBrightness = 1;</code>
* @param value The lightBrightness to set.
* @return This builder for chaining.
*/
public Builder setLightBrightness(int value) {
lightBrightness_ = value;
bitField0_ |= 0x00000001;
onChanged();
return this;
}
/**
* <pre>
* 灯光亮度
* </pre>
*
* <code>int32 LightBrightness = 1;</code>
* @return This builder for chaining.
*/
public Builder clearLightBrightness() {
bitField0_ = (bitField0_ & ~0x00000001);
lightBrightness_ = 0;
onChanged();
return this;
}
private int robotSpeed_ ;
/**
* <pre>
* 机器人速度
* </pre>
*
* <code>int32 Robot_Speed = 2;</code>
* @return The robotSpeed.
*/
@Override
public int getRobotSpeed() {
return robotSpeed_;
}
/**
* <pre>
* 机器人速度
* </pre>
*
* <code>int32 Robot_Speed = 2;</code>
* @param value The robotSpeed to set.
* @return This builder for chaining.
*/
public Builder setRobotSpeed(int value) {
robotSpeed_ = value;
bitField0_ |= 0x00000002;
onChanged();
return this;
}
/**
* <pre>
* 机器人速度
* </pre>
*
* <code>int32 Robot_Speed = 2;</code>
* @return This builder for chaining.
*/
public Builder clearRobotSpeed() {
bitField0_ = (bitField0_ & ~0x00000002);
robotSpeed_ = 0;
onChanged();
return this;
}
// @@protoc_insertion_point(builder_scope:RMACM)
}
// @@protoc_insertion_point(class_scope:RMACM)
private static final RMACM DEFAULT_INSTANCE;
static {
DEFAULT_INSTANCE = new RMACM();
}
public static RMACM getDefaultInstance() {
return DEFAULT_INSTANCE;
}
private static final com.google.protobuf.Parser<RMACM>
PARSER = new com.google.protobuf.AbstractParser<RMACM>() {
@Override
public RMACM parsePartialFrom(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
Builder builder = newBuilder();
try {
builder.mergeFrom(input, extensionRegistry);
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
throw e.setUnfinishedMessage(builder.buildPartial());
} catch (com.google.protobuf.UninitializedMessageException e) {
throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial());
} catch (java.io.IOException e) {
throw new com.google.protobuf.InvalidProtocolBufferException(e)
.setUnfinishedMessage(builder.buildPartial());
}
return builder.buildPartial();
}
};
public static com.google.protobuf.Parser<RMACM> parser() {
return PARSER;
}
@Override
public com.google.protobuf.Parser<RMACM> getParserForType() {
return PARSER;
}
@Override
public RMACM getDefaultInstanceForType() {
return DEFAULT_INSTANCE;
}
}
private static final com.google.protobuf.Descriptors.Descriptor
internal_static_RMACM_descriptor;
private static final
com.google.protobuf.GeneratedMessage.FieldAccessorTable
internal_static_RMACM_fieldAccessorTable;
public static com.google.protobuf.Descriptors.FileDescriptor
getDescriptor() {
return descriptor;
}
private static com.google.protobuf.Descriptors.FileDescriptor
descriptor;
static {
String[] descriptorData = {
"\n\021robot_RMACM.proto\"5\n\005RMACM\022\027\n\017LightBri" +
"ghtness\030\001 \001(\005\022\023\n\013Robot_Speed\030\002 \001(\005B*\n&co" +
"m.example.removemarineanimals.modelsP\000b\006" +
"proto3"
};
descriptor = com.google.protobuf.Descriptors.FileDescriptor
.internalBuildGeneratedFileFrom(descriptorData,
new com.google.protobuf.Descriptors.FileDescriptor[] {
});
internal_static_RMACM_descriptor =
getDescriptor().getMessageTypes().get(0);
internal_static_RMACM_fieldAccessorTable = new
com.google.protobuf.GeneratedMessage.FieldAccessorTable(
internal_static_RMACM_descriptor,
new String[] { "LightBrightness", "RobotSpeed", });
descriptor.resolveAllFeaturesImmutable();
}
// @@protoc_insertion_point(outer_class_scope)
}

6
app/src/main/java/com/example/fivewheel/services/CommunicationMethond.java

@ -0,0 +1,6 @@
package com.example.fivewheel.services;
public enum CommunicationMethond {
Wireless, Wired
}

23
app/src/main/java/com/example/fivewheel/services/CustomProber.java

@ -0,0 +1,23 @@
package com.example.fivewheel.services;
import com.hoho.android.usbserial.driver.FtdiSerialDriver;
import com.hoho.android.usbserial.driver.ProbeTable;
import com.hoho.android.usbserial.driver.UsbSerialProber;
/**
* add devices here, that are not known to DefaultProber
*
* if the App should auto start for these devices, also
* add IDs to app/src/main/res/xml/device_filter.xml
*/
public class CustomProber {
public static UsbSerialProber getCustomProber() {
ProbeTable customTable = new ProbeTable();
customTable.addProduct(0x1234, 0x0001, FtdiSerialDriver.class); // e.g. device with custom VID+PID
customTable.addProduct(0x1234, 0x0002, FtdiSerialDriver.class); // e.g. device with custom VID+PID
return new UsbSerialProber(customTable);
}
}

154
app/src/main/java/com/example/fivewheel/services/DataExchangeHelper.java

@ -0,0 +1,154 @@
package com.example.fivewheel.services;
import com.example.fivewheel.models.BspPV;
import com.example.fivewheel.models.BspIV;
import com.google.protobuf.InvalidProtocolBufferException;
public class DataExchangeHelper {
public static int[] decodedCH = new int[17];
static double slope = 1000.0 / (1950 - 1500);
public static int[] getdecodedCH(byte[] receivedData) {
for (int i = 0; i < 16; i++) {
decodedCH[i] = ((receivedData[8 + i * 2] & 0xFF) | (receivedData[9 + i * 2] & 0xFF) << 8);
}
for (int i = 0; i < 16; i++) {
decodedCH[i] = (int) Math.round(slope * (decodedCH[i] - 1500));
}
return decodedCH;
}
public static byte[] getSendPVBytes(BspPV.PV_struct_define _toSendPV) {
byte[] byteArray = _toSendPV.toByteArray();
byte[] sendbyteArray = new byte[byteArray.length + 4];
byte[] sendbyteArray3 = new byte[byteArray.length + 6];
if (byteArray.length != 0) {
System.arraycopy(byteArray, 0, sendbyteArray, 4, byteArray.length);
}
sendbyteArray[0] = (byte) 0x55;
sendbyteArray[1] = (byte) 0x55;
sendbyteArray[2] = (byte) 0x01;
sendbyteArray[3] = (byte) 0x01;
byte[] byteArray2 = ModbusCRC.calculateCRC(sendbyteArray);
System.arraycopy(sendbyteArray, 0, sendbyteArray3, 0, sendbyteArray.length);
System.arraycopy(byteArray2, 0, sendbyteArray3, sendbyteArray3.length - 2, 2);
return sendbyteArray3;
}
public static BspIV.IV_struct_define getIVByBytes(byte[] data) {
byte[] crcbytes = new byte[data.length - 2];
System.arraycopy(data, 0, crcbytes, 0, data.length - 2);
byte[] crc = ModbusCRC.calculateCRC(crcbytes);
// status(bytesToHex(data));
if (data[data.length - 2] == (byte) (crc[1] & 0xff) && data[data.length - 1] == (byte) (crc[0] & 0xff)) {
if ((data[0] == 0x55) && (data[1] == 0x55)) {
byte[] bytes = new byte[data.length - 4];
System.arraycopy(data, 2, bytes, 0, data.length - 4);
try {
BspIV.IV_struct_define _toReceiveIV = BspIV.IV_struct_define.parseFrom(bytes);
return _toReceiveIV;
} catch (InvalidProtocolBufferException ex) {
return null;
}
}
return null;
}
return null;
}
public static BspIV.IV_struct_define getIVByModbus() {
try {
//定义100 是IV的数据开头数组个数 建立多少个字节数组
byte[] bytes = new byte[ModbusRtuSlaveService.holdingRegisters[100]];
int modifyHoldingRegisterNum = (bytes.length + 1) / 2;
for (int i = 0; i < modifyHoldingRegisterNum; i++) {
bytes[2 * i] = (byte) (ModbusRtuSlaveService.holdingRegisters[101 + i] >> 8);
if (2 * i + 1 > bytes.length - 1) {
break;
}
bytes[2 * i + 1] = (byte) (ModbusRtuSlaveService.holdingRegisters[101 + i] & 0xff);
}
BspIV.IV_struct_define _toReceiveIV = BspIV.IV_struct_define.parseFrom(bytes);
return _toReceiveIV;
} catch (InvalidProtocolBufferException ex) {
return null;
}
}
//_toSendPV 换算成bytes
public static void setModbusPVValues(BspPV.PV_struct_define _toSendPV) {
byte[] byteArray = _toSendPV.toByteArray();
byte[] bytesToSend;
int modifyHoldingRegisterNum = (byteArray.length + 1) / 2;
if (byteArray.length != 0) {
if (byteArray.length % 2 != 0) {
bytesToSend = new byte[byteArray.length + 1];
bytesToSend[bytesToSend.length - 1] = 0;
} else {
bytesToSend = new byte[byteArray.length];
}
System.arraycopy(byteArray, 0, bytesToSend, 0, byteArray.length);
ModbusRtuSlaveService.holdingRegisters[19] = (short) byteArray.length;
//将数据转为小端发送
for (int i = 0; i < modifyHoldingRegisterNum; i++) {
ModbusRtuSlaveService.holdingRegisters[20 + i] = (short) (
((bytesToSend[2 * i + 1] & 0xFF) << 8) | // 高位字节
bytesToSend[2 * i] & 0xFF); // 低位字节
// (short) ((bytesToSend[2 * i + 1]) << 8 | ((short)bytesToSend[2 * i]));
}
}
}
/**
* 判断字符串是否是数字
*/
public static boolean isNumber(String value) {
return isInteger(value) || isDouble(value);
}
/**
* 判断字符串是否是整数
*/
public static boolean isInteger(String value) {
try {
Integer.parseInt(value);
return true;
} catch (NumberFormatException e) {
return false;
}
}
/**
* 判断字符串是否是浮点数
*/
public static boolean isDouble(String value) {
try {
Double.parseDouble(value);
if (value.contains("."))
return true;
return false;
} catch (NumberFormatException e) {
return false;
}
}
}

17
app/src/main/java/com/example/fivewheel/services/DisplayUtils.java

@ -0,0 +1,17 @@
package com.example.fivewheel.services;
import android.content.Context;
import android.content.res.Resources;
import android.util.TypedValue;
public class DisplayUtils {
// 静态方法,无需实例化即可调用
public static int dpToPx(Context context, int dp) {
Resources r = context.getResources();
return (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
dp,
r.getDisplayMetrics()
);
}
}

66
app/src/main/java/com/example/fivewheel/services/ErrorDeocdeHelper.java

@ -0,0 +1,66 @@
package com.example.fivewheel.services;
import com.example.fivewheel.models.BspError;
public class ErrorDeocdeHelper {
//private static Map<String, Integer> flagMap = new HashMap<>();
// public static void AddMap(String errorName, Integer bitPosition)
// {
// flagMap.put(errorName,bitPosition);
// }
private static String ErrorResult;
private static String addErrorResult;
public static String ErrorDeocde(int data)
{
ErrorResult="";
// 循环遍历 Map
// for (Map.Entry<String, Integer> entry : flagMap.entrySet()) {
// String key = entry.getKey();
// int bitPosiiton = entry.getValue();
//
// // 使用左移操作生成要检查的标志位
// int bitToCheck = 1 << bitPosiiton;
//
// // 判断该位置是否有对应的标志位
// if ((data & bitToCheck) != 0)
// {
// ErrorResult+=key+":\t 错误! ";
// } else
// {
//
// }
// }
for (BspError.ComError err : BspError.ComError.values()) {
int bitPosiiton = err.ordinal();
if (err.toString().equals("UNRECOGNIZED")) continue;
if (err.toString().equals("TL720D"))
addErrorResult = " 作业模式已切换至手动";
else
addErrorResult = " ";
// 使用左移操作生成要检查的标志位
int bitToCheck = 1 << bitPosiiton;
// 判断该位置是否有对应的标志位
if ((data & bitToCheck) != 0)
{
ErrorResult+=err.toString()+addErrorResult+"\t";
} else
{
}
}
return ErrorResult;
}
}

72
app/src/main/java/com/example/fivewheel/services/ModbusCRC.java

@ -0,0 +1,72 @@
package com.example.fivewheel.services;
public class ModbusCRC {
// /**
// * 一个字节包含位的数量 8
// */
// private static final int BITS_OF_BYTE = 8;
// /**
// * 多项式
// */
// private static final int POLYNOMIAL = 0xA001;
// /**
// * 初始值
// */
// private static final int INITIAL_VALUE = 0xFFFF;
//
// /**
// * CRC16 编码
// *
// * @param bytes 编码内容
// * @return 编码结果
// */
// public static int crc16(byte[] bytes) {
// int res = INITIAL_VALUE;
// for (int data : bytes) {
// res = res ^ data;
// for (int i = 0; i < BITS_OF_BYTE; i++) {
// res = (res & 0x0001) == 1 ? (res >> 1) ^ POLYNOMIAL : res >> 1;
// }
// }
// return revert(res);
// }
//
// /**
// * 翻转16位的高八位和低八位字节
// *
// * @param src 翻转数字
// * @return 翻转结果
// */
// private static int revert(int src) {
// int lowByte = (src & 0xFF00) >> 8;
// int highByte = (src & 0x00FF) << 8;
// return lowByte | highByte;
// }
/**
* 计算 Modbus CRC 校验值
* @param data 要计算校验值的字节数组
* @return CRC 校验值 2 字节的数组形式返回
*/
public static byte[] calculateCRC(byte[] data) {
int crc = 0xFFFF;
for (byte b : data) {
crc ^= (b & 0xFF);
for (int i = 0; i < 8; i++) {
if ((crc & 0x0001) != 0) {
crc >>= 1;
crc ^= 0xA001;
} else {
crc >>= 1;
}
}
}
// 将 CRC 结果拆分为两个字节
byte[] crcBytes = new byte[2];
crcBytes[0] = (byte) (crc & 0xFF);
crcBytes[1] = (byte) ((crc >> 8) & 0xFF);
return crcBytes;
}
}

517
app/src/main/java/com/example/fivewheel/services/ModbusRtuSlaveService.java

@ -0,0 +1,517 @@
package com.example.fivewheel.services;
import android.util.Log;
import java.util.Arrays;
import java.util.concurrent.atomic.AtomicBoolean;
public class ModbusRtuSlaveService {
public static void ModbusRtuSlaveServiceIntialize(USBSerialPortHelper serialPortHelper) {
_serialPortHelper = serialPortHelper;
initializeData();
}
public static final String TAG = "ModbusRtuSlave";
public static final int slaveId = 0x40;
public static Thread readThread;
public final AtomicBoolean shouldRead = new AtomicBoolean(false);
public static USBSerialPortHelper _serialPortHelper;
// Modbus 数据存储
public static final boolean[] coils = new boolean[65536];
public static final boolean[] discreteInputs = new boolean[65536];
public static final short[] holdingRegisters = new short[65536];
public static final short[] inputRegisters = new short[65536];
// 数据更新监听器
public DataUpdateListener dataUpdateListener;
public interface DataUpdateListener {
void onCoilUpdated(int address, boolean value);
void onRegisterUpdated(int address, short value);
void onError(String errorMessage);
}
public static void initializeData() {
// 初始化示例数据
Arrays.fill(holdingRegisters, (short) 0);
Arrays.fill(inputRegisters, (short) 0);
Arrays.fill(coils, false);
Arrays.fill(discreteInputs, false);
// 设置一些默认值 可以处理一些默认值 后面
// 温度
holdingRegisters[1] = 60; // 湿度
holdingRegisters[2] = 1000; // 压力
coils[0] = true; // 运行状态
coils[1] = false; // 报警状态
for (short i = 0; i < 200; i++) {
holdingRegisters[i] = i;
}
}
public final byte[] buffer = new byte[256];
//处理Modbus数据,这个可以在数据接收后调用 返回调用的功能码
public static int processModbusRequest(byte[] request, int length) {
if (length < 4) {
Log.w(TAG, "Request too short: " + length + " bytes");
return 0;
}
// 提取从站地址
byte receivedSlaveId = request[0];
if (receivedSlaveId != slaveId && receivedSlaveId != 0) {
Log.d(TAG, "Request not for this slave. Target: " + receivedSlaveId + ", Our ID: " + slaveId);
return 0;
}
Log.d(TAG, "Processing request for slave: " + receivedSlaveId);
// 验证CRC
if (!validateCrc(request, length)) {
Log.w(TAG, "CRC validation failed");
return 0;
}
// 处理Modbus请求
byte[] response = handleModbusFrame(request, length);
if (response != null && response.length > 0) {
try {
sendResponse(response);
return request[1];//返回功能码
} catch (Exception e) {
return 0;
}
}
return 0;
}
public static byte[] handleModbusFrame(byte[] frame, int length) {
if (length < 4) return null;
byte functionCode = frame[1];
byte[] response;// null;
Log.d(TAG, "Handling function code: 0x" + String.format("%02X", functionCode));
try {
switch (functionCode) {
case 0x01: // Read Coils
response = handleReadCoils(frame, length);
break;
case 0x02: // Read Discrete Inputs
response = handleReadDiscreteInputs(frame, length);
break;
case 0x03: // Read Holding Registers
response = handleReadHoldingRegisters(frame, length);
break;
case 0x04: // Read Input Registers
response = handleReadInputRegisters(frame, length);
break;
case 0x05: // Write Single Coil
response = handleWriteSingleCoil(frame, length);
break;
case 0x06: // Write Single Register
response = handleWriteSingleRegister(frame, length);
break;
case 0x0F: // Write Multiple Coils
response = handleWriteMultipleCoils(frame, length);
break;
case 0x10: // Write Multiple Registers
response = handleWriteMultipleRegisters(frame, length);
break;
default:
Log.w(TAG, "Unsupported function code: 0x" + String.format("%02X", functionCode));
response = createExceptionResponse(functionCode, (byte) 0x01); // Illegal function
break;
}
} catch (Exception e) {
Log.e(TAG, "Error handling Modbus request: " + e.getMessage());
response = createExceptionResponse(functionCode, (byte) 0x04); // Slave device failure
}
return response;
}
public static byte[] handleWriteMultipleRegisters(byte[] request, int length) {
int startAddress = ((request[2] & 0xFF) << 8) | (request[3] & 0xFF);
int quantity = ((request[4] & 0xFF) << 8) | (request[5] & 0xFF);
int byteCount = request[6] & 0xFF;
Log.d(TAG, "Write Multiple Registers - Start: " + startAddress + ", Quantity: " + quantity);
if (quantity < 1 || quantity > 123) {
return createExceptionResponse(request[1], (byte) 0x03);
}
if (startAddress + quantity > holdingRegisters.length) {
return createExceptionResponse(request[1], (byte) 0x02);
}
if (byteCount != quantity * 2) {
return createExceptionResponse(request[1], (byte) 0x03);
}
// 解析并写入寄存器数据
for (int i = 0; i < quantity; i++) {
int dataIndex = 7 + i * 2;
short value = (short) (((request[dataIndex] & 0xFF) << 8) | (request[dataIndex + 1] & 0xFF));
int registerAddress = startAddress + i;
holdingRegisters[registerAddress] = value;
}
byte[] response = createWriteMultipleResponse(request[1], startAddress, quantity);
Log.d(TAG, "Wrote " + quantity + " registers from address " + startAddress);
return response;
}
public static byte[] handleWriteMultipleCoils(byte[] request, int length) {
int startAddress = ((request[2] & 0xFF) << 8) | (request[3] & 0xFF);
int quantity = ((request[4] & 0xFF) << 8) | (request[5] & 0xFF);
int byteCount = request[6] & 0xFF;
Log.d(TAG, "Write Multiple Coils - Start: " + startAddress + ", Quantity: " + quantity);
if (quantity < 1 || quantity > 1968) {
return createExceptionResponse(request[1], (byte) 0x03);
}
if (startAddress + quantity > coils.length) {
return createExceptionResponse(request[1], (byte) 0x02);
}
int expectedByteCount = (quantity + 7) / 8;
if (byteCount != expectedByteCount) {
return createExceptionResponse(request[1], (byte) 0x03);
}
// 解析并写入线圈数据
for (int i = 0; i < quantity; i++) {
int byteIndex = 7 + (i / 8);
int bitIndex = i % 8;
boolean value = ((request[byteIndex] >> bitIndex) & 0x01) == 0x01;
int coilAddress = startAddress + i;
coils[coilAddress] = value;
}
byte[] response = createWriteMultipleResponse(request[1], startAddress, quantity);
Log.d(TAG, "Wrote " + quantity + " coils from address " + startAddress);
return response;
}
public static byte[] createWriteMultipleResponse(byte functionCode, int startAddress, int quantity) {
byte[] response = new byte[8];
response[0] = (byte) slaveId;
response[1] = functionCode;
response[2] = (byte) (startAddress >> 8);
response[3] = (byte) (startAddress & 0xFF);
response[4] = (byte) (quantity >> 8);
response[5] = (byte) (quantity & 0xFF);
addCrc(response);
return response;
}
public static byte[] createExceptionResponse(byte functionCode, byte exceptionCode) {
byte[] response = new byte[5];
response[0] = (byte) slaveId;
response[1] = (byte) (functionCode | 0x80);
response[2] = exceptionCode;
addCrc(response);
Log.w(TAG, "Exception response - Function: 0x" + String.format("%02X", functionCode) +
", Code: " + exceptionCode);
return response;
}
public static byte[] handleReadDiscreteInputs(byte[] request, int length) {
int startAddress = ((request[2] & 0xFF) << 8) | (request[3] & 0xFF);
int quantity = ((request[4] & 0xFF) << 8) | (request[5] & 0xFF);
Log.d(TAG, "Read Discrete Inputs - Start: " + startAddress + ", Quantity: " + quantity);
if (quantity < 1 || quantity > 2000) {
return createExceptionResponse(request[1], (byte) 0x03);
}
if (startAddress + quantity > discreteInputs.length) {
return createExceptionResponse(request[1], (byte) 0x02);
}
// 读离散输入响应结构:
// [slaveId] + [function] + [byteCount] + [data] + [CRC]
// 1字节 + 1字节 + 1字节 + N字节 + 2字节
int byteCount = (quantity + 7) / 8;
byte[] response = new byte[3 + byteCount + 2];
response[0] = (byte) slaveId;
response[1] = request[1];
response[2] = (byte) byteCount;
for (int i = 0; i < quantity; i++) {
if (discreteInputs[startAddress + i]) {
response[3 + i / 8] |= (1 << (i % 8));
}
}
addCrc(response);
Log.d(TAG, "Read " + quantity + " discrete inputs from address " + startAddress);
return response;
}
public static byte[] handleReadInputRegisters(byte[] request, int length) {
int startAddress = ((request[2] & 0xFF) << 8) | (request[3] & 0xFF);
int quantity = ((request[4] & 0xFF) << 8) | (request[5] & 0xFF);
Log.d(TAG, "Read Input Registers - Start: " + startAddress + ", Quantity: " + quantity);
if (quantity < 1 || quantity > 125) {
return createExceptionResponse(request[1], (byte) 0x03);
}
if (startAddress + quantity > inputRegisters.length) {
return createExceptionResponse(request[1], (byte) 0x02);
}
// 读输入寄存器响应结构:
// [slaveId] + [function] + [byteCount] + [data] + [CRC]
// 1字节 + 1字节 + 1字节 + (quantity × 2) + 2字节
byte[] response = new byte[3 + quantity * 2 + 2];
response[0] = (byte) slaveId;
response[1] = request[1];
response[2] = (byte) (quantity * 2);
for (int i = 0; i < quantity; i++) {
short value = inputRegisters[startAddress + i];
response[3 + i * 2] = (byte) (value >> 8);
response[3 + i * 2 + 1] = (byte) value;
}
addCrc(response);
Log.d(TAG, "Read " + quantity + " input registers from address " + startAddress);
return response;
}
public static byte[] handleReadHoldingRegisters(byte[] request, int length) {
int startAddress = ((request[2] & 0xFF) << 8) | (request[3] & 0xFF);
int quantity = ((request[4] & 0xFF) << 8) | (request[5] & 0xFF);
Log.d(TAG, "Read Holding Registers - Start: " + startAddress + ", Quantity: " + quantity);
// 验证参数
if (quantity < 1 || quantity > 125) {
Log.w(TAG, "Invalid quantity: " + quantity);
return createExceptionResponse(request[1], (byte) 0x03); // Illegal data value
}
if (startAddress + quantity > holdingRegisters.length) {
Log.w(TAG, "Address out of range: " + startAddress);
return createExceptionResponse(request[1], (byte) 0x02); // Illegal data address
}
// 读保持寄存器响应数据结构:
// [slaveId] + [function] + [byteCount] + [data] + [CRC]
// 1字节 + 1字节 + 1字节 + (quantity × 2) + 2字节
byte[] response = new byte[1 + 1 + 1 + quantity * 2 + 2]; // slaveId + function + byteCount + data + CRC
response[0] = (byte) slaveId;
response[1] = request[1]; // Function code
response[2] = (byte) (quantity * 2); // Byte count
// 填充寄存器数据
for (int i = 0; i < quantity; i++) {
short value = holdingRegisters[startAddress + i];
response[3 + i * 2] = (byte) (value >> 8);
response[3 + i * 2 + 1] = (byte) value;
}
// 添加CRC
addCrc(response);
Log.d(TAG, "Read " + quantity + " holding registers from address " + startAddress);
return response;
}
public static byte[] handleWriteSingleRegister(byte[] request, int length) {
int address = ((request[2] & 0xFF) << 8) | (request[3] & 0xFF);
short value = (short) (((request[4] & 0xFF) << 8) | (request[5] & 0xFF));
Log.d(TAG, "Write Single Register - Address: " + address + ", Value: " + value);
if (address >= holdingRegisters.length) {
Log.w(TAG, "Register address out of range: " + address);
return createExceptionResponse(request[1], (byte) 0x02); // Illegal data address
}
// 更新寄存器值
holdingRegisters[address] = value;
// 写单个寄存器响应结构:
// [slaveId] + [function] + [address] + [value] + [CRC]
// 1字节 + 1字节 + 2字节 + 2字节 + 2字节
byte[] response = new byte[8];
System.arraycopy(request, 0, response, 0, 6);
response[0] = (byte) slaveId;
addCrc(response);
Log.d(TAG, "Register " + address + " updated to: " + value);
return response;
}
public static byte[] handleReadCoils(byte[] request, int length) {
int startAddress = ((request[2] & 0xFF) << 8) | (request[3] & 0xFF);
int quantity = ((request[4] & 0xFF) << 8) | (request[5] & 0xFF);
Log.d(TAG, "Read Coils - Start: " + startAddress + ", Quantity: " + quantity);
if (quantity < 1 || quantity > 2000) {
return createExceptionResponse(request[1], (byte) 0x03);
}
if (startAddress + quantity > coils.length) {
return createExceptionResponse(request[1], (byte) 0x02);
}
// 读线圈响应结构:
// [slaveId] + [function] + [byteCount] + [data] + [CRC]
// 1字节 + 1字节 + 1字节 + N字节 + 2字节
// 数据字节数计算:N = ceil(quantity / 8)
// int byteCount = (quantity + 7) / 8; // 向上取整
// int totalBytes = 1 + 1 + 1 + byteCount + 2; // 5 + byteCount
int byteCount = (quantity + 7) / 8;
byte[] response = new byte[3 + byteCount + 2]; // slaveId + function + byteCount + data + CRC
response[0] = (byte) slaveId;
response[1] = request[1];
response[2] = (byte) byteCount;
// 打包线圈状态到字节
for (int i = 0; i < quantity; i++) {
if (coils[startAddress + i]) {
response[3 + i / 8] |= (1 << (i % 8));
}
}
addCrc(response);
return response;
}
public static byte[] handleWriteSingleCoil(byte[] request, int length) {
int address = ((request[2] & 0xFF) << 8) | (request[3] & 0xFF);
boolean value = (request[4] & 0xFF) == 0xFF;
Log.d(TAG, "Write Single Coil - Address: " + address + ", Value: " + value);
if (address >= coils.length) {
return createExceptionResponse(request[1], (byte) 0x02);
}
coils[address] = value;
// 写单个线圈响应结构:
// [slaveId] + [function] + [address] + [value] + [CRC]
// 1字节 + 1字节 + 2字节 + 2字节 + 2字节 固定 8 字节 byte[] response = new byte[1 + 1 + 2 + 2 + 2]; //
byte[] response = new byte[8];
System.arraycopy(request, 0, response, 0, 6);
response[0] = (byte) slaveId;
addCrc(response);
Log.d(TAG, "Coil " + address + " updated to: " + value);
return response;
}
public static boolean validateCrc(byte[] data, int length) {
if (length < 2) return false;
int calculatedCrc = calculateCrc(data, 0, length - 2);
int receivedCrc = (data[length - 1] & 0xFF) << 8 | (data[length - 2] & 0xFF);
boolean valid = calculatedCrc == receivedCrc;
if (!valid) {
Log.w(TAG, "CRC mismatch - Calculated: " + calculatedCrc + ", Received: " + receivedCrc);
}
return valid;
}
public static void addCrc(byte[] data) {
int crc = calculateCrc(data, 0, data.length - 2);
data[data.length - 2] = (byte) (crc & 0xFF);
data[data.length - 1] = (byte) ((crc >> 8) & 0xFF);
}
public static int calculateCrc(byte[] data, int start, int length) {
int crc = 0xFFFF;
for (int i = start; i < start + length; i++) {
crc ^= (data[i] & 0xFF);
for (int j = 0; j < 8; j++) {
if ((crc & 0x0001) != 0) {
crc >>= 1;
crc ^= 0xA001;
} else {
crc >>= 1;
}
}
}
return crc;
}
public static void sendResponse(byte[] response) {
if (_serialPortHelper == null) {
return;
}
_serialPortHelper.SendData(response);
Log.d(TAG, "Sent response: " + response.length + " bytes");
}
// 公共API方法
public static void updateHoldingRegister(int address, short value) {
if (address >= 0 && address < holdingRegisters.length) {
holdingRegisters[address] = value;
}
}
public static short getHoldingRegister(int address) {
if (address >= 0 && address < holdingRegisters.length) {
return holdingRegisters[address];
}
return 0;
}
public static void updateCoil(int address, boolean state) {
if (address >= 0 && address < coils.length) {
coils[address] = state;
}
}
public static boolean getCoil(int address) {
if (address >= 0 && address < coils.length) {
return coils[address];
}
return false;
}
}

200
app/src/main/java/com/example/fivewheel/services/ReceiivedIVHandler.java

@ -0,0 +1,200 @@
package com.example.fivewheel.services;
import android.graphics.Color;
import android.view.Gravity;
import android.widget.TextView;
import android.widget.Toast;
import com.example.fivewheel.MainActivity;
import com.example.fivewheel.models.BspIV;
import com.google.protobuf.InvalidProtocolBufferException;
public class ReceiivedIVHandler {
private static final int Buttons_Not_Reset = 0;
private static final int Not_Intialized = 1;
private static final int Move_Halt = 2;
private static final int Move_Forward = 3;
private static final int Move_Backward = 4;
private static final int Move_TurnLeft = 5;
private static final int Move_TurnRight = 6;
private static final int Emergency_Stop = 7;
private static final int Upper_Computer_TakenOver = 8;
private static final int Sbus_Not_Online = 9;
private static final int Android_Down = 10;
private static final int Cruise_Ahead = 11;
private static final int Cruise_Back = 12;
public static void midToast(String str, int showTime, MainActivity MainActivity) {
Toast toast = Toast.makeText(MainActivity, str, showTime);
toast.setGravity(Gravity.CENTER_VERTICAL | Gravity.CENTER_HORIZONTAL, 0, 0); //设置显示位置
TextView v = (TextView) toast.getView().findViewById(android.R.id.message);
v.setTextColor(Color.YELLOW); //设置字体颜色
toast.show();
}
public static com.example.fivewheel.models.BspIV.IV_struct_define _toReceiveIV = BspIV.IV_struct_define.newBuilder().build();
public static BspIV.IV_struct_define _toReceiveIV_Temp = BspIV.IV_struct_define.newBuilder().build();
public static void HandleIVData(MainActivity MainActivity, byte[] data) {
try {
if(data.length<5) return;
if ((data[0] != 0x55) && (data[1] != 0x55)) return;//开头结尾为0x55 表示PV数据
byte[] crcbytes = new byte[data.length - 2];
System.arraycopy(data, 0, crcbytes, 0, data.length - 2);
byte[] crc = ModbusCRC.calculateCRC(crcbytes);
//这里的校验和C#的校验正好反了
if (data[data.length - 2] != (byte) (crc[1] & 0xff)) return;
if (data[data.length - 1] != (byte) (crc[0] & 0xff)) return; //crc校验
// if ((data[0] != 0x55) && (data[1] != 0x55)) return;//开头结尾为0x55 表示PV数据
byte[] bytes = new byte[data.length - 4];
System.arraycopy(data, 2, bytes, 0, data.length - 4);
try {
_toReceiveIV_Temp = BspIV.IV_struct_define.parseFrom(bytes);
} catch (InvalidProtocolBufferException ex) {
return;
}
HandleIV(MainActivity, _toReceiveIV_Temp);
} catch (
Exception e) {
}
}
private static int restoreOriginalError(int errorFlag) {
return Integer.reverseBytes(errorFlag);
}
public static void HandleIV(MainActivity MainActivity, BspIV.IV_struct_define _toReceiveIV_Temp) {
if (_toReceiveIV_Temp == null) return;
//若单片机重启,则变量时间戳重置
if (_toReceiveIV_Temp.getRobotRestart() == 1) {
_toReceiveIV = _toReceiveIV.toBuilder().setTimeStamp(0).build();
//告知单片机接收到
MainActivity._toSendPV = MainActivity._toSendPV.toBuilder().setRobotRestartAccepted(1).build();
return;
}
MainActivity._toSendPV = MainActivity._toSendPV.toBuilder().setRobotRestartAccepted(0).build();
if (_toReceiveIV.getTimeStamp() > _toReceiveIV_Temp.getTimeStamp()) {
return;
}
_toReceiveIV = _toReceiveIV_Temp;
MainActivity.runOnUiThread(() -> {
MainActivity.mainBinding.rFAngleRoll.setText(String.valueOf(_toReceiveIV.getRobotAngleRoll() / 100.0));
MainActivity.mainBinding.tvRobotError.setText(String.valueOf(_toReceiveIV.getRobotError()));
MainActivity.mainBinding.tvDynamometer.setText(String.valueOf(_toReceiveIV.getRobotDynamometerValue() / 100.0));
MainActivity.mainBinding.tvRobotRightCompensation.setText(String.valueOf(_toReceiveIV.getRobotCompensationRight() / 100.0));
MainActivity.mainBinding.tvRobotLeftCompensation.setText(String.valueOf(_toReceiveIV.getRobotCompensationLeft() / 100.0));
MainActivity.mainBinding.tvForce.setText(String.valueOf(_toReceiveIV.getRobotForceValue()));
MainActivity.mainBinding.tvRobotCurrent.setText("L" + String.valueOf(_toReceiveIV.getRobotCurrentLeft() / 1000)
+ "R" + String.valueOf(_toReceiveIV.getRobotCurrentRight() / 1000));
int leftError = _toReceiveIV.getRobotErrorLeft();
int rightError = _toReceiveIV.getRobotErrorRight();
// 还原成原始 MCU 的错误值
int leftOriginal = restoreOriginalError(leftError);
int rightOriginal = restoreOriginalError(rightError);
// 左
if (leftOriginal != 0) {
StringBuilder leftBits = new StringBuilder("错误: ");
for (int i = 0; i < 32; i++) {
if (((leftOriginal >> i) & 1) == 1) {
leftBits.append(32 - i).append(" ");
}
}
MainActivity.mainBinding.tvLeftError.setText(leftBits.toString().trim());
} else {
MainActivity.mainBinding.tvLeftError.setText("正常");
}
//右
if (rightOriginal != 0) {
StringBuilder rightBits = new StringBuilder("错误: ");
for (int i = 0; i < 32; i++) {
if (((rightOriginal >> i) & 1) == 1) {
rightBits.append(32 - i).append(" ");
}
}
MainActivity.mainBinding.tvRightError.setText(rightBits.toString().trim());
} else {
MainActivity.mainBinding.tvRightError.setText("正常");
}
if (_toReceiveIV.getRobotError() != 0 && _toReceiveIV.getRobotCurrentState() != 12) {
} else {
String m = "";
switch (_toReceiveIV.getRobotCurrentState()) {
case 0:
m = "停止";
break;
case 1:
m = "前进";
break;
case 2:
m = "后退";
break;
case 3:
m = "左转";
break;
case 4:
m = "右转";
break;
case 5:
m = "自动前进";
break;
case 6:
m = "自动后退";
break;
case 7:
m = "左换道";
break;
case 8:
m = "右换道";
break;
case 9:
m = "上换道";
break;
case 10:
m = "下换道";
break;
case 11:
m = "换道完成";
break;
case 12:
m = "急停";
break;
default:
throw new IllegalStateException("Unexpected value: " + _toReceiveIV.getRobotCurrentState());
}
MainActivity.mainBinding.tvRobotError.setText(m);
}
int errorInt = _toReceiveIV.getSystemError();
String errorString = ErrorDeocdeHelper.ErrorDeocde(errorInt);
String error_to_Display = "错误:";
if (_toReceiveIV.getRobotErrorLeft() != 0) {
errorString += " \t 电机1错误码:" + String.valueOf(_toReceiveIV.getRobotErrorLeft());
}
if (_toReceiveIV.getRobotErrorRight() != 0) {
errorString += " \t 电机2错误码:" + String.valueOf(_toReceiveIV.getRobotErrorRight());
}
});
}
}

54
app/src/main/java/com/example/fivewheel/services/RobotDataHanlder.java

@ -0,0 +1,54 @@
package com.example.fivewheel.services;
import com.example.fivewheel.models.RobotData;
import com.google.protobuf.InvalidProtocolBufferException;
public class RobotDataHanlder {
public static void test()
{
//byte[] data=hexToByteArray("080110830118313A04B1CBBACF");
byte[] data=hexToByteArray("100A180A28013A32B1CBBACF00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
}
public static RobotData.DataTrans DeoodeDataFromRobot(byte[] data)
{
RobotData.DataTrans dtrans3 = null;
try
{
dtrans3 = RobotData.DataTrans.parseFrom(data);
return dtrans3;
} catch (InvalidProtocolBufferException e) {
return null;
}
}
public static byte[] hexToByteArray(String inHex){
int hexlen = inHex.length();
byte[] result;
if (hexlen % 2 == 1){
//奇数
hexlen++;
result = new byte[(hexlen/2)];
inHex="0"+inHex;
}else {
//偶数
result = new byte[(hexlen/2)];
}
int j=0;
for (int i = 0; i < hexlen; i+=2){
result[j]=hexToByte(inHex.substring(i,i+2));
j++;
}
return result;
}
public static byte hexToByte(String inHex){
return (byte)Integer.parseInt(inHex,16);
}
}

140
app/src/main/java/com/example/fivewheel/services/RtspRecorder.java

@ -0,0 +1,140 @@
//package com.example.removemarineanimals.services;
//
//import android.content.Context;
//import android.graphics.Bitmap;
//import android.graphics.Canvas;
//import android.view.View;
//import android.widget.Toast;
//
//import com.arthenica.ffmpegkit.FFmpegKit;
//import com.arthenica.ffmpegkit.FFmpegSession;
//import com.arthenica.ffmpegkit.ReturnCode;
//import com.example.removemarineanimals.MainActivity;
//
//import java.io.File;
//import java.io.FileOutputStream;
//import java.io.IOException;
//import java.text.SimpleDateFormat;
//import java.util.Date;
//
//public class RtspRecorder {
// // 用于控制录制会话
// private MainActivity MainActivity;
// private static FFmpegSession recordingSession;
//
// // 开始分段录制
// public static void startRecording(Context context, String rtspUrl)
// {
//
// String outputPath ="storage/emulated/0/DCIM/" + "/record_%Y-%m-%d_%H-%M-%S.mp4";
// //String outputPath = context.getExternalFilesDir(null) + "/record_%Y-%m-%d_%H-%M-%S.mp4";
// String command = String.format(
// "-rtsp_transport tcp -i \"%s\" -c:v copy -f segment -segment_time 30 -reset_timestamps 1 -strftime 1 \"%s\"",
// rtspUrl, outputPath
// );
//
// recordingSession = FFmpegKit.executeAsync(command, session -> {
// if (ReturnCode.isSuccess(session.getReturnCode())) {
// // 录制正常结束
// } else {
// // 录制异常终止
// }
// });
// }
//
// // 停止录制
// public static void stopRecording() {
// if (recordingSession != null) {
// FFmpegKit.cancel(recordingSession.getSessionId());
// recordingSession = null;
// }
// }
//
// // 实时截图(需手动调用)
// public static void takeSnapshot(Context context, String rtspUrl) {
// //String outputPath = context.getExternalFilesDir(null) + "/snapshot_%Y-%m-%d_%H-%M-%S.jpg";
//
// String outputPath = "storage/emulated/0/DCIM/" + "/snapshot_%Y-%m-%d_%H-%M-%S.jpg";
//
// String command = String.format(
// "-rtsp_transport tcp -i \"%s\" -frames:v 1 -strftime 1 \"%s\"",
// rtspUrl, outputPath
// );
// FFmpegSession session2 = FFmpegKit.executeAsync(command,session -> {
// if (ReturnCode.isSuccess(session.getReturnCode()))
// {
// // 截图成功
// Toast.makeText(context, "截图成功", Toast.LENGTH_SHORT).show();
//
// } else
// {
// // 截图失败
// Toast.makeText(context, "截图失败", Toast.LENGTH_SHORT).show();
// }
// });
//
////
//// if (ReturnCode.isSuccess(session.getReturnCode())) {
//// // 截图成功
//// } else {
//// // 截图失败
//// }
//
//// recordingSession = FFmpegKit.executeAsync(command, session -> {
//// if (ReturnCode.isSuccess(session.getReturnCode()))
//// {
//// // 截图成功
//// Toast.makeText(context, "截图成功", Toast.LENGTH_SHORT).show();
////
//// } else
//// {
//// // 截图失败
//// Toast.makeText(context, "截图失败", Toast.LENGTH_SHORT).show();
//// }
//// });
//
//
// }
//
// // 方法1:通过DrawingCache(适用于可见的View)
// public static Bitmap captureView(View view) {
// view.setDrawingCacheEnabled(true);
// view.buildDrawingCache();
// Bitmap bitmap = Bitmap.createBitmap(view.getDrawingCache());
// view.setDrawingCacheEnabled(false); // 释放缓存
// return bitmap;
// }
//
// // 方法2:直接绘制到Bitmap(更可靠,适用于未显示的View)
// public static Bitmap captureViewManual(View view) {
//
//// view.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
//// view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
//// view.buildDrawingCache();
//// Bitmap bitmap = view.getDrawingCache();
//
//
// Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888);
// Canvas canvas = new Canvas(bitmap);
// view.draw(canvas);
// return bitmap;
// }
//
// public static void SnapPictureByView (View view)
// {
// // 保存到文件(需权限)
// Date dNow=new Date();
// SimpleDateFormat ft = new SimpleDateFormat ("yyyy-MM-dd hh-mm-ss");
// String path = "storage/emulated/0/DCIM/" + ft.format(dNow)+ ".png";
// File file = new File(path);
// try (FileOutputStream out = new FileOutputStream(file))
// {
// // Bitmap screenshot = captureView(view);
// Bitmap screenshot = captureViewManual(view);
// screenshot.compress(Bitmap.CompressFormat.PNG, 100, out);
// } catch (IOException e) {
// e.printStackTrace();
// }
// }
//
//}

324
app/src/main/java/com/example/fivewheel/services/USBSerialPortHelper.java

@ -0,0 +1,324 @@
package com.example.fivewheel.services;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbManager;
import android.os.Build;
import android.os.CountDownTimer;
import android.os.Handler;
import android.os.Looper;
import androidx.core.content.ContextCompat;
import com.example.fivewheel.BuildConfig;
import com.example.fivewheel.models.BspIV;
import com.hoho.android.usbserial.driver.UsbSerialDriver;
import com.hoho.android.usbserial.driver.UsbSerialPort;
import com.hoho.android.usbserial.driver.UsbSerialProber;
import com.hoho.android.usbserial.util.SerialInputOutputManager;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import com.example.fivewheel.MainActivity;
public class USBSerialPortHelper implements SerialInputOutputManager.Listener {
public USBSerialPortHelper(MainActivity mainActivity, int baudRate) {
this.MainActivity = mainActivity;
this.baudRate=baudRate;
}
private MainActivity MainActivity;
private enum UsbPermission {Unknown, Requested, Granted, Denied}
private final String INTENT_ACTION_GRANT_USB = BuildConfig.APPLICATION_ID + ".GRANT_USB";
private int deviceId = 60000;
private int deviceId_test = 60000;
private int portNum;
private final int WRITE_WAIT_MILLIS = 500;
private final int READ_WAIT_MILLIS = 100;
private String PortNameContians = "SILICON";/**/
// private static String PortNameContians="FTD";
//private int baudRate = 115200;
private int baudRate = 38400;
private boolean withIoManager = true;
private BroadcastReceiver broadcastReceiver;
private Handler mainLooper;
private SerialInputOutputManager usbIoManager;
private UsbSerialPort usbSerialPort;
private UsbPermission usbPermission = UsbPermission.Unknown;
private boolean connected = false;
public void intialize() {
broadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (INTENT_ACTION_GRANT_USB.equals(intent.getAction())) {
usbPermission = intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false) ? UsbPermission.Granted : UsbPermission.Denied;
connect();
}
}
};
mainLooper = new Handler(Looper.getMainLooper());
_receiveBufferlist = new ArrayList<Byte>();
}
@Override
public void onNewData(byte[] data) {
status("new data");
mainLooper.post(() -> {
receive(data);
// receive data
});
}
@Override
public void onRunError(Exception e) {
mainLooper.post(() -> {
status("connection lost: " + e.getMessage());
disconnect();
});
}
public void connect() {
UsbDevice device = null;
UsbManager usbManager = (UsbManager) MainActivity.getSystemService(Context.USB_SERVICE);
for (UsbDevice v : usbManager.getDeviceList().values()) {
// status(v.getManufacturerName().toUpperCase());
if (v.getVendorId() == 6790) {
device = v;
break;
}
// if (v.getManufacturerName().toUpperCase().contains(PortNameContians)) {
// device = v;
// break;
// }
}
if (device == null) {
// _serialPortSwitch.setChecked(false);
status("找不到设备");
return;
}
UsbSerialDriver driver = UsbSerialProber.getDefaultProber().probeDevice(device);
if (driver == null) {
driver = CustomProber.getCustomProber().probeDevice(device);
}
if (driver == null) {
// _serialPortSwitch.setChecked(false);
status("无驱动");
return;
}
if (driver.getPorts().size() < portNum) //就是0 cp2102 或者同一个驱动,第一个
{
status("connection failed: not enough ports at device");
status("找不到设备");
return;
}
usbSerialPort = driver.getPorts().get(portNum);
UsbDeviceConnection usbConnection = usbManager.openDevice(driver.getDevice());
if (usbConnection == null && usbPermission == UsbPermission.Unknown && !usbManager.hasPermission(driver.getDevice())) {
usbPermission = UsbPermission.Requested;
int flags = Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ? PendingIntent.FLAG_MUTABLE : 0;
Intent intent = new Intent(INTENT_ACTION_GRANT_USB);
intent.setPackage(MainActivity.getPackageName());
PendingIntent usbPermissionIntent = PendingIntent.getBroadcast(MainActivity, 0, intent, flags);
usbManager.requestPermission(driver.getDevice(), usbPermissionIntent);
return;
}
if (usbConnection == null) {
if (!usbManager.hasPermission(driver.getDevice())) {
status("connection failed: permission denied");
} else {
status("connection failed: open failed");
}
return;
}
try {
usbSerialPort.open(usbConnection);
try {
usbSerialPort.setParameters(baudRate, 8, 1, UsbSerialPort.PARITY_NONE);
status("connected: ");
} catch (UnsupportedOperationException e) {
status("unsupport setparameters");
}
if (withIoManager) {
usbIoManager = new SerialInputOutputManager(usbSerialPort, this);
usbIoManager.setReadBufferSize(40960);
usbIoManager.setReadTimeout(READ_WAIT_MILLIS);
usbIoManager.start();
}
connected = true;
} catch (Exception e) {
status("connection failed: " + e.getMessage());
disconnect();
}
}
private void disconnect() {
connected = false;
if (usbIoManager != null) {
usbIoManager.setListener(null);
usbIoManager.stop();
}
usbIoManager = null;
try {
usbSerialPort.close();
} catch (IOException ignored) {
}
usbSerialPort = null;
}
List<Byte> _receiveBufferlist;
private static byte[] listTobyte(List<Byte> list) {
if (list == null || list.size() < 0) return null;
byte[] bytes = new byte[list.size()];
int i = 0;
Iterator<Byte> iterator = list.iterator();
while (iterator.hasNext()) {
bytes[i] = iterator.next();
i++;
}
return bytes;
}
boolean StartCountDown = false;
private void receive(byte[] data) {
// status("read data");
for (int i = 0; i < data.length; i++) {
_receiveBufferlist.add(data[i]);
}
//decodeRceive(data);
if (StartCountDown == false)//从收到第一个数据开始计时
{
StartCountDown = true;
new CountDownTimer(5, 5) {
public void onTick(long millisUntilFinished) {
}
public void onFinish() {
status("read finished");
decodeRceive(listTobyte(_receiveBufferlist));
_receiveBufferlist.clear();
StartCountDown = false;
}
}.start();
}
}
void status(String str) {
// SpannableStringBuilder spn = new SpannableStringBuilder(str+'\r'+'\n');
//
// // spn.append(getTime());
//
// spn.setSpan(new ForegroundColorSpan(MainActivity.getResources().getColor(R.color.colorAccent)), 0, spn.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
// receiveText.append(spn);
// mainBinding.roll.fullScroll(ScrollView.FOCUS_DOWN);
// MainActivity.mainBinding.message.setText(str);
}
int Index = 0;
private void decodeRceive(byte[] data) {
try {
MainActivity.USBSerialPortReceivedTimeCounter=0;//计算时间 归零
if (ModbusRtuSlaveService.processModbusRequest(data, data.length) == 0x03) {
Index++;
//Index=128;
//由于 System.currentTimeMillis() 会随着时间累加,所以不存在
DataExchangeHelper.setModbusPVValues( MainActivity._toSendPV);
} else if (ModbusRtuSlaveService.processModbusRequest(data, data.length) == 0x10) {
BspIV.IV_struct_define iv = DataExchangeHelper.getIVByModbus();
ReceiivedIVHandler.HandleIV(MainActivity,iv);
}
} catch (Exception e) {
int a =100;
}
}
public static String bytesToHex(byte[] bytes) {
StringBuilder result = new StringBuilder();
for (byte b : bytes) {
result.append(String.format("%02X ", b & 0xFF));
}
return result.toString();
}
public void onStart() {
ContextCompat.registerReceiver(MainActivity, broadcastReceiver, new IntentFilter(INTENT_ACTION_GRANT_USB), ContextCompat.RECEIVER_NOT_EXPORTED);
status("onStart");
}
public void onStop() {
MainActivity.unregisterReceiver(broadcastReceiver);
status("onStop");
}
public void onResume() {
if (!connected && (usbPermission == UsbPermission.Unknown || usbPermission == UsbPermission.Granted)) {
mainLooper.post(this::connect);
}
}
public void onPause() {
if (connected) {
status("串口断开");
// _serialPortSwitch.setChecked(false);
disconnect();
}
}
public void SendData(byte[] data) {
if (connected) {
try {
usbSerialPort.write(data, WRITE_WAIT_MILLIS);
} catch (IOException e) {
status("Send Failed");
connected = false;
}
} else {
status("usb serialport disconnected");
}
}
}

27
app/src/main/java/com/example/fivewheel/services/VideoPlayerHelper.java

@ -0,0 +1,27 @@
package com.example.fivewheel.services;
import cn.nodemedia.NodePlayer;
import cn.nodemedia.NodePlayerView;
public class VideoPlayerHelper {
public static void startVedio(NodePlayerView nodePlayerView, NodePlayer nodePlayer,String address ){
nodePlayerView.setRenderType(NodePlayerView.RenderType.SURFACEVIEW);//设置渲染器类型
nodePlayerView.setUIViewContentMode(NodePlayerView.UIViewContentMode.ScaleToFill);//设置视频画面缩放模式
//nodePlayer=new NodePlayer(this);
nodePlayer.setPlayerView(nodePlayerView);//设置播放视图
//设置RTSP流使用的传输协议,支持的模式有:
nodePlayer.setRtspTransport(NodePlayer.RTSP_TRANSPORT_TCP);//设置传输
nodePlayer.setInputUrl(address);
nodePlayer.setVideoEnable(true);//设置视频启用
nodePlayer.setBufferTime(100);//设置缓冲时间
nodePlayer.setHWEnable(true);
nodePlayer.setMaxBufferTime(200);//设置最大缓冲时间
nodePlayer.start();
}
}

124
app/src/main/java/com/example/fivewheel/services/ttySerialPortHelper.java

@ -0,0 +1,124 @@
package com.example.fivewheel.services;
import android.util.Log;
import com.example.fivewheel.models.BspIV;
import android_serialport_api.SerialPortFinder;
import tp.xmaihh.serialport.SerialHelper;
import tp.xmaihh.serialport.bean.ComBean;
public class ttySerialPortHelper {
public static com.example.fivewheel.MainActivity MainActivity;
private static final String TAG = "ttySerialPortHelper";
private static SerialHelper serialHelper;
private static SerialPortFinder serialPortFinder;
public static boolean IsAllButtonSendBack = false;
final String[] ports = serialPortFinder.getAllDevicesPath();
final String[] botes = new String[]{"0", "50", "75", "110", "134", "150", "200", "300", "600", "1200", "1800", "2400", "4800", "9600", "19200", "38400", "57600", "115200", "230400", "460800", "500000", "576000", "921600", "1000000", "1152000", "1500000", "2000000", "2500000", "3000000", "3500000", "4000000", "CUSTOM"};
final String[] databits = new String[]{"8", "7", "6", "5"};
final String[] paritys = new String[]{"NONE", "ODD", "EVEN", "SPACE", "MARK"};
final String[] stopbits = new String[]{"1", "2"};
final String[] flowcons = new String[]{"NONE", "RTS/CTS", "XON/XOFF"};
public static int ReceivedCounter= 0;
public static int[] decodedCH = new int[17];
public static void Open() {
try {
// serialPortFinder = new SerialPortFinder();
//serialHelper = new SerialHelper("dev/ttyHS0", 115200)//MK32
serialHelper = new SerialHelper("/dev/ttyHS3", 115200) //UR7
{
@Override
protected void onDataReceived(ComBean comBean) {
MainActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
// 更新 UI 的代码
byte[] receivedData = comBean.bRec;
if (MainActivity.AndroidMCUCommunicationMethod == CommunicationMethond.Wireless)
{
//解析单片机传来的数据
ReceiivedIVHandler.HandleIVData(MainActivity, receivedData);
return;
}
//有按钮数据传输
if (receivedData.length <= 2) {
return;
}
if (receivedData[0] != 0x55 || receivedData[1] != 0x66 || receivedData.length != 42) {
return;
}
IsAllButtonSendBack = true;
int[] decodedCH = DataExchangeHelper.getdecodedCH(receivedData);
//0 代表index,和sbus里面的数据其实不同,这里用作接收一次,添加一个
ModbusRtuSlaveService.holdingRegisters[0] += 1;
for (int i = 0; i < decodedCH.length; i++) {
ModbusRtuSlaveService.holdingRegisters[i + 1] = (short) decodedCH[i];
}
ReceivedCounter=0;
// MainActivity.mainBinding.sbusCH0.setText(String.valueOf(DataExchangeHelper.decodedCH[0]));
// MainActivity.mainBinding.sbusCH1.setText(String.valueOf(DataExchangeHelper.decodedCH[1]));
// MainActivity.mainBinding.sbusCH2.setText(String.valueOf(DataExchangeHelper.decodedCH[2]));
// MainActivity.mainBinding.sbusCH3.setText(String.valueOf(DataExchangeHelper.decodedCH[3]));
// MainActivity.mainBinding.sbusCH4.setText(String.valueOf(DataExchangeHelper.decodedCH[4]));
// MainActivity.mainBinding.sbusCH5.setText(String.valueOf(DataExchangeHelper.decodedCH[5]));
// MainActivity.mainBinding.sbusCH6.setText(String.valueOf(DataExchangeHelper.decodedCH[6]));
// MainActivity.mainBinding.sbusCH7.setText(String.valueOf(DataExchangeHelper.decodedCH[7]));
// MainActivity.mainBinding.sbusCH8.setText(String.valueOf(DataExchangeHelper.decodedCH[8]));
// MainActivity.mainBinding.sbusCH9.setText(String.valueOf(DataExchangeHelper.decodedCH[9]));
// MainActivity.mainBinding.sbusCH10.setText(String.valueOf(DataExchangeHelper.decodedCH[10]));
// MainActivity.mainBinding.sbusCH11.setText(String.valueOf(DataExchangeHelper.decodedCH[11]));
// MainActivity.mainBinding.sbusCH12.setText(String.valueOf(DataExchangeHelper.decodedCH[12]));
// MainActivity.mainBinding.sbusCH13.setText(String.valueOf(DataExchangeHelper.decodedCH[13]));
// MainActivity.mainBinding.sbusCH14.setText(String.valueOf(DataExchangeHelper.decodedCH[14]));
// MainActivity.mainBinding.sbusCH15.setText(String.valueOf(DataExchangeHelper.decodedCH[15]));
}
});
}
};
serialHelper.open();
} catch (Exception exception) {
Log.d(TAG, "Data Received");
}
}
private static int index = 0;
public static void SendData(byte[] data) {
serialHelper.send(data); // 发送byte[]
}
public static byte[] getAllChData_4Hz = new byte[]{0x55, 0x66, 0x01, 0x01, 0x00, 0x00, 0x00, 0x42, 0x02, (byte) (0xB5 & 0xff), (byte) (0xC0 & 0xff)};
public static byte[] getAllChData_5Hz = new byte[]{0x55, 0x66, 0x01, 0x01, 0x00, 0x00, 0x00, 0x42, 0x03, (byte) (0x94 & 0xff), (byte) (0xD0 & 0xff)};
public static byte[] getAllChData_10Hz = new byte[]{0x55, 0x66, 0x01, 0x01, 0x00, 0x00, 0x00, 0x42, 0x04, (byte) (0x73 & 0xff), (byte) (0xA0 & 0xff)};
public static byte[] getAllChData_20Hz = new byte[]{0x55, 0x66, 0x01, 0x01, 0x00, 0x00, 0x00, 0x42, 0x05, (byte) (0x52 & 0xff), (byte) (0xb0 & 0xff)};
public static byte[] getAllChData_50Hz = new byte[]{0x55, 0x66, 0x01, 0x01, 0x00, 0x00, 0x00, 0x42, 0x06, (byte) (0x31 & 0xff), (byte) (0x80 & 0xff)};
public static byte[] stopgetAllChData = new byte[]{0x55, 0x66, 0x01, 0x01, 0x00, 0x00, 0x00, 0x42, 0x00, (byte) (0xf7 & 0xff), (byte) (0xe0 & 0xff)};
public static void sendTxt(String sTxt) {
serialHelper.sendTxt(sTxt); // 发送byte[]
}
//serialHelper.send(byte[] bOutArray); // 发送byte[]
//serialHelper.sendHex(String sHex); // 发送Hex
//serialHelper.sendTxt(String sTxt); // 发送ASCII
public static void onDestroy() {
serialHelper.close();
}
}

67
app/src/main/java/com/example/fivewheel/viewmodels/MainViewModel.java

@ -0,0 +1,67 @@
package com.example.fivewheel.viewmodels;
import android.widget.SeekBar;
import androidx.lifecycle.ViewModel;
import com.example.fivewheel.R;
import com.example.fivewheel.databinding.ActivityMainBinding;
//import com.example.removemarineanimals.models.user;
//import com.example.removemarineanimals.services.RobotData;
//import com.example.removemarineanimals.services.VideoHelper;
public class MainViewModel extends ViewModel {
// public RobotData.DataTrans _dataTrans=new RobotData.DataTrans();
public static ActivityMainBinding mainBinding;//通过Binding可以获取界面数据
// public final MutableLiveData<user> LiveUser;
public MainViewModel()
{
// LiveUser = new MutableLiveData<user>();
//
// user u=LiveUser.getValue();
// if(u==null)
// {
// u=new user();
// u.setName("dddddd");
// LiveUser.setValue(u);
// }
}
//# region Video操作区域
int recordVideoState=0;
public void SnapVideo()
{
}
//#end region Video操作区域
void SetPage()
{
}
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
}
}

7
app/src/main/java/generate_java.bat

@ -0,0 +1,7 @@
cd /d D:\Android_studio_workspace\fw_swj\app\src\main\java
protoc --proto_path=. --java_out=. bsp_IV.proto
protoc --proto_path=. --java_out=. bsp_PV.proto
protoc --proto_path=. --java_out=. bsp_Error.proto
pause

BIN
app/src/main/java/protoc.7z

Binary file not shown.

BIN
app/src/main/java/protoc.exe

Binary file not shown.

25
app/src/main/res/drawable/background.xml

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 设置透明背景色 -->
<!-- <solid android:color="@color/gainsboro" />-->
<solid android:color="#f2f3f4" />
<!-- 设置一个黑色边框 -->
<!-- <stroke-->
<!-- android:width="4px"-->
<!-- android:color="@color/deepskyblue" />-->
<!-- 设置四个圆角的半径 -->
<corners
android:bottomLeftRadius="8dp"
android:bottomRightRadius="8dp"
android:topLeftRadius="8dp"
android:topRightRadius="8dp" />
<!-- 设置一下边距,让空间大一点 -->
<!-- <padding-->
<!-- android:bottom="5dp"-->
<!-- android:left="5dp"-->
<!-- android:right="5dp"-->
<!-- android:top="5dp" />-->
</shape>

25
app/src/main/res/drawable/blue_rounded_rectangle.xml

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 设置透明背景色 -->
<!-- <solid android:color="@color/white" />-->
<solid android:color="#d6eaf8" />
<!-- 设置一个黑色边框 -->
<!-- <stroke-->
<!-- android:width="4px"-->
<!-- android:color="@color/deepskyblue" />-->
<!-- 设置四个圆角的半径 -->
<corners
android:bottomLeftRadius="8dp"
android:bottomRightRadius="8dp"
android:topLeftRadius="8dp"
android:topRightRadius="8dp" />
<!-- 设置一下边距,让空间大一点 -->
<!-- <padding-->
<!-- android:bottom="5dp"-->
<!-- android:left="5dp"-->
<!-- android:right="5dp"-->
<!-- android:top="5dp" />-->
</shape>

10
app/src/main/res/drawable/border.xml

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<!-- 设置一个黑色边框 -->
<stroke android:width="4px" android:color="#000000"/>
<!-- 渐变 -->
<!-- 设置一下边距,让空间大一点 -->
</shape>

24
app/src/main/res/drawable/borderblue.xml

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 设置透明背景色 -->
<solid android:color="#87CEEB" />
<!-- 设置一个黑色边框 -->
<stroke
android:width="4px"
android:color="#000000" />
<!-- 设置四个圆角的半径 -->
<corners
android:bottomLeftRadius="10px"
android:bottomRightRadius="10px"
android:topLeftRadius="10px"
android:topRightRadius="10px" />
<!-- 设置一下边距,让空间大一点 -->
<!-- <padding-->
<!-- android:bottom="5dp"-->
<!-- android:left="5dp"-->
<!-- android:right="5dp"-->
<!-- android:top="5dp" />-->
</shape>

14
app/src/main/res/drawable/dash_line.xml

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="line">
<stroke
android:color="#ffffff"
android:dashWidth="10dp"
/>
<!--width:线条的高度
color:颜色
android:dashGap="8dp"
dashWidth:破折线的宽度
dashGap:破折线间空隙的宽度
如果这里设置了width,xml中android:layout_height的值必须比它大。不设置就默认为0
-->
</shape>

170
app/src/main/res/drawable/ic_launcher_background.xml

@ -0,0 +1,170 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:fillColor="#3DDC84"
android:pathData="M0,0h108v108h-108z" />
<path
android:fillColor="#00000000"
android:pathData="M9,0L9,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,0L19,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,0L29,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,0L39,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,0L49,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,0L59,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,0L69,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,0L79,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M89,0L89,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M99,0L99,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,9L108,9"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,19L108,19"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,29L108,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,39L108,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,49L108,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,59L108,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,69L108,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,79L108,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,89L108,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,99L108,99"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,29L89,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,39L89,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,49L89,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,59L89,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,69L89,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,79L89,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,19L29,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,19L39,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,19L49,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,19L59,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,19L69,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,19L79,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
</vector>

30
app/src/main/res/drawable/ic_launcher_foreground.xml

@ -0,0 +1,30 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
<aapt:attr name="android:fillColor">
<gradient
android:endX="85.84757"
android:endY="92.4963"
android:startX="42.9492"
android:startY="49.59793"
android:type="linear">
<item
android:color="#44000000"
android:offset="0.0" />
<item
android:color="#00000000"
android:offset="1.0" />
</gradient>
</aapt:attr>
</path>
<path
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
android:strokeWidth="1"
android:strokeColor="#00000000" />
</vector>

24
app/src/main/res/drawable/message_rounded_rectangle.xml

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 设置透明背景色 -->
<solid android:color="#f6ddcc" />
<!-- 设置一个黑色边框 -->
<!-- <stroke-->
<!-- android:width="4px"-->
<!-- android:color="@color/" />-->
<!-- 设置四个圆角的半径 -->
<corners
android:bottomLeftRadius="8dp"
android:bottomRightRadius="8dp"
android:topLeftRadius="8dp"
android:topRightRadius="8dp" />
<!-- 设置一下边距,让空间大一点 -->
<!-- <padding-->
<!-- android:bottom="5dp"-->
<!-- android:left="5dp"-->
<!-- android:right="5dp"-->
<!-- android:top="5dp" />-->
</shape>

BIN
app/src/main/res/drawable/squrelogo.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

760
app/src/main/res/layout/activity_main.xml

@ -0,0 +1,760 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".MainActivity">
<data>
<variable
name="vm"
type="com.example.fivewheel.viewmodels.MainViewModel" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/background"
android:orientation="vertical">
<!--medium view-->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="horizontal"
tools:ignore="UselessParent">
<!--左侧信息区域-->
<LinearLayout
android:id="@+id/messageRounded"
android:layout_width="148dp"
android:layout_height="match_parent"
android:layout_marginVertical="8dp"
android:layout_marginStart="8dp"
android:background="@drawable/message_rounded_rectangle"
android:orientation="horizontal">
<GridLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:columnCount="1"
android:orientation="vertical"
android:rowCount="9">
<!--机器人作业状态-->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_rowWeight="1"
android:gravity="center"
android:orientation="horizontal">
<TextView
android:layout_width="45dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="5dp"
android:text="状 态"
android:textColor="@color/midnightblue"
android:textSize="14sp"
android:textStyle="bold" />
<TextView
android:id="@+id/tvRobotError"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="1dp"
android:layout_weight="1"
android:gravity="center"
android:text="xxx"
android:textColor="@color/midnightblue"
android:textSize="14sp"
android:textStyle="bold" />
</LinearLayout>
<!--机器人当前角度-->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_rowWeight="1"
android:gravity="center"
android:orientation="horizontal">
<TextView
android:layout_width="45dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="5dp"
android:text="角 度"
android:textColor="@color/midnightblue"
android:textSize="14sp"
android:textStyle="bold" />
<TextView
android:id="@+id/rF_Angle_Roll"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="1dp"
android:layout_weight="1"
android:gravity="right"
android:text="0"
android:textColor="@color/midnightblue"
android:textSize="14sp"
android:textStyle="bold"
tools:ignore="RtlHardcoded" />
<TextView
android:layout_width="10dp"
android:layout_height="wrap_content"
android:layout_margin="1dp"
android:layout_weight="1"
android:gravity="left|center_horizontal"
android:text="°"
android:textColor="@color/midnightblue"
android:textSize="14sp"
android:textStyle="bold" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_rowWeight="1"
android:gravity="center"
android:orientation="horizontal">
<TextView
android:layout_width="45dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="5dp"
android:text="电 流"
android:textColor="@color/midnightblue"
android:textSize="14sp"
android:textStyle="bold" />
<TextView
android:id="@+id/tvRobotCurrent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="1dp"
android:layout_weight="1"
android:gravity="right"
android:text="0"
android:textColor="@color/midnightblue"
android:textSize="14sp"
android:textStyle="bold" />
<TextView
android:layout_width="10dp"
android:layout_height="wrap_content"
android:layout_margin="1dp"
android:layout_weight="1"
android:gravity="left|center_horizontal"
android:text="A"
android:textColor="@color/midnightblue"
android:textSize="14sp"
android:textStyle="bold" />
</LinearLayout>
<!--机器人打磨压力常数-->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_rowWeight="1"
android:gravity="center"
android:orientation="horizontal">
<TextView
android:layout_width="45dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="5dp"
android:text="压 力"
android:textColor="@color/midnightblue"
android:textSize="14sp"
android:textStyle="bold" />
<TextView
android:id="@+id/tvForce"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="1dp"
android:layout_weight="1"
android:gravity="right"
android:text="0"
android:textColor="@color/midnightblue"
android:textSize="14sp"
android:textStyle="bold" />
<TextView
android:layout_width="10dp"
android:layout_height="wrap_content"
android:layout_margin="1dp"
android:layout_weight="1"
android:gravity="left|center_horizontal"
android:text="N"
android:textColor="@color/midnightblue"
android:textSize="14sp"
android:textStyle="bold" />
</LinearLayout>
<!--机器人打磨压力常数-->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_rowWeight="1"
android:gravity="center"
android:orientation="horizontal">
<TextView
android:layout_width="45dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="5dp"
android:text="气 压"
android:textColor="@color/midnightblue"
android:textSize="14sp"
android:textStyle="bold" />
<TextView
android:id="@+id/tvDynamometer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="1dp"
android:layout_weight="1"
android:gravity="right"
android:text="0"
android:textColor="@color/midnightblue"
android:textSize="14sp"
android:textStyle="bold" />
<TextView
android:layout_width="10dp"
android:layout_height="wrap_content"
android:layout_margin="1dp"
android:layout_weight="1"
android:gravity="left|center_horizontal"
android:text="Pa"
android:textColor="@color/midnightblue"
android:textSize="14sp"
android:textStyle="bold" />
</LinearLayout>
<!--机器人左补偿-->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_rowWeight="1"
android:gravity="center"
android:orientation="horizontal">
<TextView
android:layout_width="45dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="5dp"
android:text="左补偿"
android:textColor="@color/midnightblue"
android:textSize="14sp"
android:textStyle="bold" />
<TextView
android:id="@+id/tvRobotLeftCompensation"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="1dp"
android:layout_weight="1"
android:gravity="right"
android:text="0"
android:textColor="@color/midnightblue"
android:textSize="14sp"
android:textStyle="bold"/>
<TextView
android:layout_width="10dp"
android:layout_height="wrap_content"
android:layout_margin="1dp"
android:layout_weight="1"
android:gravity="left|center_horizontal"
android:textColor="@color/midnightblue"
android:textSize="14sp"
android:text="°"
android:textStyle="bold" />
</LinearLayout>
<!--机器人右补偿-->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_rowWeight="1"
android:gravity="center"
android:orientation="horizontal">
<TextView
android:layout_width="45dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="5dp"
android:text="右补偿"
android:textColor="@color/midnightblue"
android:textSize="14sp"
android:textStyle="bold" />
<TextView
android:id="@+id/tvRobotRightCompensation"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="1dp"
android:layout_weight="1"
android:gravity="right"
android:text="0"
android:textColor="@color/midnightblue"
android:textSize="14sp"
android:textStyle="bold" />
<TextView
android:layout_width="10dp"
android:layout_height="wrap_content"
android:layout_margin="1dp"
android:layout_weight="1"
android:gravity="start|center_horizontal"
android:textColor="@color/midnightblue"
android:textSize="14sp"
android:text="°"
android:textStyle="bold" />
</LinearLayout>
<!--左电机错误信息-->
<FrameLayout
android:id="@+id/mainViewErrMessageFrameLayout"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_rowWeight="1">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="horizontal">
<TextView
android:layout_width="45dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="5dp"
android:text="左电机"
android:textColor="@color/midnightblue"
android:textSize="14sp"
android:textStyle="bold" />
<TextView
android:id="@+id/tvLeftError"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="1dp"
android:layout_weight="1"
android:gravity="center"
android:text="xxx"
android:textColor="@color/midnightblue"
android:textSize="14sp"
android:textStyle="bold" />
</LinearLayout>
</FrameLayout>
<!--右电机错误信息-->
<FrameLayout
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_rowWeight="1">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="horizontal">
<TextView
android:layout_width="45dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="5dp"
android:text="右电机"
android:textColor="@color/midnightblue"
android:textSize="14sp"
android:textStyle="bold" />
<TextView
android:id="@+id/tvRightError"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="1dp"
android:layout_weight="1"
android:gravity="center"
android:text="xxx"
android:textColor="@color/midnightblue"
android:textSize="14sp"
android:textStyle="bold" />
</LinearLayout>
</FrameLayout>
</GridLayout>
</LinearLayout>
<!--参数设定区域-->
<LinearLayout
android:id="@+id/setLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="4dp"
android:orientation="vertical"
tools:ignore="Suspicious0dp">
<!-- 第一行:左右换道 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="horizontal"
android:gravity="center"
android:layout_margin="4dp">
<Button
android:id="@+id/btnLeftLaneChange"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginHorizontal="4dp"
android:layout_weight="1"
android:gravity="center"
android:text="@string/change_left"
android:background="@drawable/blue_rounded_rectangle"
android:textColor="@color/deepskyblue"
android:textSize="30sp"
android:textStyle="bold"/>
<Button
android:id="@+id/btnRightLaneChange"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:layout_marginHorizontal="4dp"
android:text="@string/change_right"
android:background="@drawable/blue_rounded_rectangle"
android:textColor="@color/deepskyblue"
android:textSize="30sp"
android:textStyle="bold"/>
</LinearLayout>
<!--第二行:速度-->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<!--移动速度-->
<FrameLayout
android:id="@+id/mainViewRobotSpeedFrameLayout"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_gravity="center"
android:layout_margin="4dp"
android:layout_weight="1"
android:background="@drawable/blue_rounded_rectangle">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="fill"
android:orientation="horizontal">
<TextView
android:layout_width="40dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginHorizontal="8dp"
android:text="手动速度"
android:textColor="@color/midnightblue"
android:textSize="18sp"
android:textStyle="bold" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:orientation="horizontal">
<EditText
android:id="@+id/tvRobotManualSpeed"
android:layout_width="120dp"
android:layout_height="wrap_content"
android:layout_marginStart="27dp"
android:background="@null"
android:gravity="center"
android:imeOptions="actionDone"
android:inputType="numberDecimal"
android:text="10"
android:textColor="@color/deepskyblue"
android:textSize="35sp"
android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginStart="-25dp"
android:layout_weight="1"
android:gravity="center"
android:text="m/min"
android:textColor="@color/deepskyblue"
android:textSize="25sp" />
</LinearLayout>
</LinearLayout>
</FrameLayout>
<!--自动速度-->
<FrameLayout
android:id="@+id/mainViewAutoSpeedFrameLayout"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_gravity="center"
android:layout_margin="4dp"
android:layout_weight="1"
android:background="@drawable/blue_rounded_rectangle">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="fill"
android:orientation="horizontal">
<TextView
android:layout_width="40dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginHorizontal="8dp"
android:text="自动速度"
android:textColor="@color/midnightblue"
android:textSize="18sp"
android:textStyle="bold" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:orientation="horizontal">
<EditText
android:id="@+id/tvRobotAutoSpeed"
android:layout_width="120dp"
android:layout_height="match_parent"
android:layout_marginStart="27dp"
android:background="@null"
android:gravity="center"
android:imeOptions="actionDone"
android:inputType="numberDecimal"
android:text="10"
android:textColor="@color/deepskyblue"
android:textSize="35sp"
android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1"
android:layout_marginStart="-25dp"
android:gravity="center"
android:text="m/min"
android:textColor="@color/deepskyblue"
android:textSize="25sp" />
</LinearLayout>
</LinearLayout>
</FrameLayout>
</LinearLayout>
<!--第三行-->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<!--压力设定-->
<FrameLayout
android:id="@+id/mainViewEndPressureFrameLayout"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_gravity="center"
android:layout_margin="4dp"
android:layout_weight="1"
android:background="@drawable/blue_rounded_rectangle">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="fill"
android:orientation="horizontal">
<TextView
android:layout_width="40dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginHorizontal="8dp"
android:text="压力设定"
android:textColor="@color/midnightblue"
android:textSize="18sp"
android:textStyle="bold" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:orientation="horizontal">
<EditText
android:id="@+id/tvRobotForce"
android:layout_width="112dp"
android:layout_height="wrap_content"
android:layout_marginStart="40dp"
android:background="@null"
android:gravity="center"
android:imeOptions="actionDone"
android:inputType="number"
android:text="300"
android:textColor="@color/deepskyblue"
android:textSize="35sp"
android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginStart="-15dp"
android:layout_weight="1"
android:gravity="center"
android:text="N"
android:textColor="@color/deepskyblue"
android:textSize="25sp" />
</LinearLayout>
</LinearLayout>
</FrameLayout>
<!--换道幅宽-->
<FrameLayout
android:id="@+id/mainViewLaneChangeWidthFrameLayout"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_gravity="center"
android:layout_margin="4dp"
android:layout_weight="1"
android:background="@drawable/blue_rounded_rectangle">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="fill"
android:orientation="horizontal">
<TextView
android:layout_width="40dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginHorizontal="8dp"
android:text="换道幅宽"
android:textColor="@color/midnightblue"
android:textSize="18sp"
android:textStyle="bold" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:orientation="horizontal">
<EditText
android:id="@+id/tvRobotChgLength"
android:layout_width="120dp"
android:layout_height="wrap_content"
android:layout_marginStart="40dp"
android:background="@null"
android:imeOptions="actionDone"
android:inputType="number"
android:gravity="center"
android:text="40"
android:textColor="@color/deepskyblue"
android:textSize="35sp"
android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center"
android:layout_marginStart="-25dp"
android:text="mm"
android:textColor="@color/deepskyblue"
android:textSize="25sp" />
</LinearLayout>
</LinearLayout>
</FrameLayout>
</LinearLayout>
<!--第四行-->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<FrameLayout
android:id="@+id/mainViewCurrentFrameLayout"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_gravity="center"
android:layout_margin="4dp"
android:layout_weight="1"
android:background="@drawable/blue_rounded_rectangle">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="fill"
android:orientation="horizontal">
<Button
android:id="@+id/btnBindAutoWork"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginHorizontal="4dp"
android:layout_weight="1"
android:gravity="center"
android:text="绑定自动作业"
android:background="@drawable/blue_rounded_rectangle"
android:textColor="@color/deepskyblue"
android:textSize="30sp"
android:textStyle="bold"/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:orientation="horizontal">
</LinearLayout>
</LinearLayout>
</FrameLayout>
<FrameLayout
android:id="@+id/mainViewVerticalCalibrationFrameLayout"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_gravity="center"
android:layout_margin="4dp"
android:layout_weight="1"
android:background="@drawable/blue_rounded_rectangle">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="fill"
android:orientation="horizontal">
<Button
android:id="@+id/btnShowLogs"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:layout_marginHorizontal="4dp"
android:background="@drawable/blue_rounded_rectangle"
android:text="@string/log"
android:gravity="center"
android:textColor="@color/deepskyblue"
android:textSize="30sp"
android:textStyle="bold"/>
</LinearLayout>
</FrameLayout>
</LinearLayout>
</LinearLayout>
</LinearLayout>
</LinearLayout>
</layout>

15
app/src/main/res/layout/dialog_logs.xml

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp">
<TextView
android:id="@+id/tv_logs_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="14sp"
android:textColor="#000000"
android:scrollbars="vertical" />
</ScrollView>

6
app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

6
app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

BIN
app/src/main/res/mipmap-hdpi/ic_launcher.webp

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
app/src/main/res/mipmap-hdpi/ic_launcher_round.webp

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

BIN
app/src/main/res/mipmap-mdpi/ic_launcher.webp

Binary file not shown.

After

Width:  |  Height:  |  Size: 982 B

BIN
app/src/main/res/mipmap-mdpi/ic_launcher_round.webp

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
app/src/main/res/mipmap-xhdpi/ic_launcher.webp

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

BIN
app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

BIN
app/src/main/res/mipmap-xxhdpi/ic_launcher.webp

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

BIN
app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

BIN
app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

BIN
app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

16
app/src/main/res/values-night/themes.xml

@ -0,0 +1,16 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.RemoveMarineAnimals" parent="Theme.MaterialComponents.DayNight.NoActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/blue</item>
<item name="colorPrimaryVariant">@color/purple_200</item>
<item name="colorOnPrimary">@color/black</item>
<!-- Secondary brand color. -->
<item name="colorSecondary">@color/blue</item>
<item name="colorSecondaryVariant">@color/blueviolet</item>
<item name="colorOnSecondary">@color/black</item>
<!-- Status bar color. -->
<item name="android:statusBarColor">?attr/colorPrimaryVariant</item>
<!-- Customize your theme here. -->
</style>
</resources>

157
app/src/main/res/values/colors.xml

@ -0,0 +1,157 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color>
<color name="purple_200">#FFFFFFFF</color>
<color name="colorPrimary">#3F51B5</color><!--首要颜色-->
<color name="colorPrimaryDark">#303F9F</color><!--首要颜色暗色-->
<color name="colorAccent">#FF4081</color><!--色彩强调-->
<color name="snow">#fffafa</color><!--雪白色 -->
<color name="floralwhite">#fffaf0</color><!--花白色 -->
<color name="blanchedalmond">#ffebcd</color><!--杏白色 -->
<color name="ghostwhite">#f8f8ff</color><!--幽灵白 -->
<color name="whitesmoke">#f5f5f5</color><!--烟白色 -->
<color name="antiquewhite">#faebd7</color><!--古董白 -->
<color name="navajowhite">#ffdead</color><!--纳瓦白 -->
<color name="grey">#808080</color><!--灰色 -->
<color name="gainsboro">#dcdcdc</color><!--淡灰色 -->
<color name="lightgrey">#d3d3d3</color><!--亮灰色 -->
<color name="darkgrey">#a9a9a9</color><!--暗灰色 -->
<color name="dimgrey">#696969</color><!--暗灰色 -->
<color name="slategrey">#708090</color><!--灰石色 -->
<color name="lightslategrey">#778899</color><!--亮蓝灰 -->
<color name="darkslategrey">#2f4f4f</color><!--暗瓦灰色 -->
<color name="silver">#c0c0c0</color><!--银色 -->
<color name="red">#ff0000</color><!--红色 -->
<color name="darkred">#8b0000</color><!--暗红色 -->
<color name="crimson">#dc143c</color><!--暗深红色 -->
<color name="darkmagenta">#8b008b</color><!--暗洋红 -->
<color name="fuchsia">#ff00ff</color><!--紫红色 -->
<color name="tomato">#ff6347</color><!--西红柿色 -->
<color name="lightcoral">#f08080</color><!--亮珊瑚色 -->
<color name="darksalmon">#e9967a</color><!--暗肉色 -->
<color name="peachpuff">#ffdab9</color><!--桃色 -->
<color name="plum">#dda0dd</color><!--洋李色 -->
<color name="pink">#ffc0cb</color><!--粉红色 -->
<color name="lightpink">#ffb6c1</color><!--亮粉红色 -->
<color name="deeppink">#ff1493</color><!--深粉红色 -->
<color name="hotpink">#ff69b4</color><!--热粉红色 -->
<color name="lavenderblush">#fff0f5</color><!--淡紫红 -->
<color name="indianred">#cd5c5c</color><!--印第安红 -->
<color name="rosybrown">#bc8f8f</color><!--褐玫瑰红 -->
<color name="firebrick">#b22222</color><!--红砖色 -->
<color name="maroon">#800000</color><!--粟色 -->
<color name="honeydew">#f0fff0</color><!--蜜色 -->
<color name="orangered">#ff4500</color><!--红橙色 -->
<color name="orange">#ffa500</color><!--橙色 -->
<color name="limegreen">#32cd32</color><!--橙绿色 -->
<color name="lime">#00ff00</color><!--酸橙色 -->
<color name="yellow">#ffff00</color><!--黄色 -->
<color name="wheat">#f5deb3</color><!--浅黄色 -->
<color name="khaki">#f0e68c</color><!--黄褐色 -->
<color name="burlywood">#deb887</color><!--实木色 -->
<color name="bisque">#ffe4c4</color><!--桔黄色 -->
<color name="lightyellow">#ffffe0</color><!--亮黄色 -->
<color name="darkgoldenrod">#b8860b</color><!--暗金黄色 -->
<color name="darkorange">#ff8c00</color><!--暗桔黄色 -->
<color name="lightgoldenrodyellow">#fafad2</color><!--亮金黄色 -->
<color name="lemonchiffon">#fffacd</color><!--柠檬绸色 -->
<color name="cornsilk">#fff8dc</color><!--米绸色 -->
<color name="seaShell">#fff5ee</color><!--海贝色 -->
<color name="papayawhip">#ffefd5</color><!--番木色 -->
<color name="mistyrose">#ffe4e1</color><!--浅玫瑰色 -->
<color name="moccasin">#ffe4b5</color><!--鹿皮色 -->
<color name="ivory">#fffff0</color><!--象牙色 -->
<color name="gold">#ffd700</color><!--金色 -->
<color name="goldenrod">#daa520</color><!--金麒麟色 -->
<color name="lightsalmon">#ffa07a</color><!--亮肉色 -->
<color name="coral">#ff7f50</color><!--珊瑚色 -->
<color name="mintcream">#f5fffa</color><!--薄荷色 -->
<color name="beige">#f5f5dc</color><!--米色 -->
<color name="sandybrown">#f4a460</color><!--沙褐色 -->
<color name="oldlace">#fdf5e6</color><!--老花色 -->
<color name="linen">#faf0e6</color><!--亚麻色 -->
<color name="salmon">#fa8072</color><!--鲜肉色 -->
<color name="thistle">#d8bfd8</color><!--蓟色 -->
<color name="tan">#d2b48c</color><!--茶色 -->
<color name="chocolate">#d2691e</color><!--巧可力色 -->
<color name="peru">#cd853f</color><!--秘鲁色 -->
<color name="darkkhaki">#bdb76b</color><!--暗黄褐色 -->
<color name="palegoldenrod">#eee8aa</color><!--苍麒麟色 -->
<color name="brown">#a52a2a</color><!--褐色 -->
<color name="saddlebrown">#8b4513</color><!--重褐色 -->
<color name="sienna">#a0522d</color><!--赭色 -->
<color name="olive">#808000</color><!--橄榄色 -->
<color name="chartreuse">#7fff00</color><!--黄绿色 -->
<color name="greenyellow">#adff2f</color><!--黄绿色 -->
<color name="green">#008000</color><!--绿色 -->
<color name="darkgreen">#006400</color><!--暗绿色 -->
<color name="darkolivegreen">#556b2f</color><!--暗橄榄绿 -->
<color name="olivedrab">#6b8e23</color><!--深绿褐色 -->
<color name="lawngreen">#7cfc00</color><!--草绿色 -->
<color name="forestgreen">#228b22</color><!--森林绿 -->
<color name="aquamarine">#7fffd4</color><!--碧绿色 -->
<color name="paleturquoise">#afeeee</color><!--苍宝石绿 -->
<color name="palegreen">#98fb98</color><!--苍绿色 -->
<color name="mediumturquoise">#48d1cc</color><!--中绿宝石 -->
<color name="mediumaquamarine">#66cdaa</color><!--中绿色 -->
<color name="aqua">#00ffff</color><!--浅绿色 -->
<color name="springgreen">#00ff7f</color><!--春绿色 -->
<color name="mediumspringgreen">#00fa9a</color><!--中春绿色 -->
<color name="darkturquoise">#00ced1</color><!--暗宝石绿 -->
<color name="seagreen">#2e8b57</color><!--海绿色 -->
<color name="lightgreen">#90ee90</color><!--亮绿色 -->
<color name="darkseagreen">#8fbc8f</color><!--暗海兰色 -->
<color name="turquoise">#40e0d0</color><!--青绿色 -->
<color name="cyan">#00ffff</color><!--青色 -->
<color name="darkcyan">#008b8b</color><!--暗青色 -->
<color name="lightcyan">#e0ffff</color><!--亮青色 -->
<color name="teal">#008080</color><!--水鸭色 -->
<color name="indigo">#4b0082</color><!--靛青色 -->
<color name="blue">#0000ff</color><!--蓝色 -->
<color name="darkblue">#00008b</color><!--暗蓝色 -->
<color name="mediumblue">#0000cd</color><!--中兰色 -->
<color name="midnightblue">#191970</color><!--中灰兰色 -->
<color name="navy">#000080</color><!--海军色 -->
<color name="royalblue">#4169e1</color><!--皇家蓝 -->
<color name="azure">#f0ffff</color><!--天蓝色 -->
<color name="skyblue">#87ceeb</color><!--天蓝色 -->
<color name="deepskyblue">#00bfff</color><!--深天蓝色 -->
<color name="lightskyblue">#87cefa</color><!--亮天蓝色 -->
<color name="lightseagreen">#20b2aa</color><!--亮海蓝色 -->
<color name="lightblue">#add8e6</color><!--亮蓝色 -->
<color name="powderblue">#b0e0e6</color><!--粉蓝色 -->
<color name="aliceblue">#f0f8ff</color><!--艾利斯兰 -->
<color name="mediumslateblue">#7b68ee</color><!--中暗蓝色 -->
<color name="slateblue">#6a5acd</color><!--石蓝色 -->
<color name="darkslateblue">#483d8b</color><!--暗灰蓝色 -->
<color name="mediumseagreen">#3cb371</color><!--中海蓝 -->
<color name="steelblue">#4682b4</color><!--钢兰色 -->
<color name="lightsteelblue">#b0c4de</color><!--亮钢兰色 -->
<color name="cornflowerblue">#6495ed</color><!--菊兰色 -->
<color name="dodgerblue">#1e90ff</color><!--闪兰色 -->
<color name="cadetblue">#5f9ea0</color><!--军兰色 -->
<color name="blueviolet">#8a2be2</color><!--紫罗兰蓝色 -->
<color name="purple">#800080</color><!--紫色 -->
<color name="lavender">#e6e6fa</color><!--淡紫色 -->
<color name="orchid">#da70d6</color><!--淡紫色 -->
<color name="mediumpurple">#9370db</color><!--中紫色 -->
<color name="darkorchid">#9932cc</color><!--暗紫色 -->
<color name="violet">#ee82ee</color><!--紫罗兰色 -->
<color name="mediumvioletred">#c71585</color><!--中紫罗兰色 -->
<color name="palevioletred">#db7093</color><!--苍紫罗兰色 -->
<color name="darkviolet">#9400d3</color><!--暗紫罗兰色 -->
<color name="mediumorchid">#ba55d3</color><!--中粉紫色 -->
<color name="trasnparent">#00000000</color><!--中粉紫色 -->
<color name="button_normal">#4A4A4A</color>
<color name="button_active">#1E88E5</color>
<color name="button_border">#666666</color>
<!-- <color name="button_active_border">#0D47A1</color>-->
<color name="gray">#CCCCCC</color>
<color name="deep_midnightblue">#0d0d5e</color>
<color name="light_gray">#cccccc</color>
</resources>

7
app/src/main/res/values/strings.xml

@ -0,0 +1,7 @@
<resources>
<string name="app_name">五轮 251201</string>
<string name="icons">&#xe658;</string>
<string name="log">查看日志</string>
<string name="change_left">左换道</string>
<string name="change_right">右换道</string>
</resources>

25
app/src/main/res/values/themes.xml

@ -0,0 +1,25 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<!-- <style name="Theme.RemoveMarineAnimals" parent="Theme.MaterialComponents.DayNight.DarkActionBar">-->
<style name="Theme.RemoveMarineAnimals" parent="Theme.MaterialComponents.DayNight.NoActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/blue</item>
<item name="colorPrimaryVariant">@color/blue</item>
<item name="colorOnPrimary">@color/white</item>
<!-- Secondary brand color. -->
<item name="colorSecondary">@color/aliceblue</item>
<item name="colorSecondaryVariant">@color/blueviolet</item>
<item name="colorOnSecondary">@color/black</item>
<!-- Status bar color. -->
<item name="android:statusBarColor">?attr/colorPrimaryVariant</item>
<!-- Customize your theme here. -->
<item name="buttonStyle">@style/MyButtonStyle</item>
<item name="materialButtonStyle">@style/MyButtonStyle</item>
</style>
<style name="MyButtonStyle" parent="Widget.MaterialComponents.Button">
<item name="backgroundTint">@null</item> <!-- 禁用背景着色 -->
<item name="android:background">@drawable/blue_rounded_rectangle</item> <!-- 设置默认背景 -->
<item name="android:textColor">@color/white</item> <!-- 设置文本颜色 -->
</style>
</resources>

13
app/src/main/res/xml/backup_rules.xml

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?><!--
Sample backup rules file; uncomment and customize as necessary.
See https://developer.android.com/guide/topics/data/autobackup
for details.
Note: This file is ignored for devices older that API 31
See https://developer.android.com/about/versions/12/backup-restore
-->
<full-backup-content>
<!--
<include domain="sharedpref" path="."/>
<exclude domain="sharedpref" path="device.xml"/>
-->
</full-backup-content>

19
app/src/main/res/xml/data_extraction_rules.xml

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?><!--
Sample data extraction rules file; uncomment and customize as necessary.
See https://developer.android.com/about/versions/12/backup-restore#xml-changes
for details.
-->
<data-extraction-rules>
<cloud-backup>
<!-- TODO: Use <include> and <exclude> to control what is backed up.
<include .../>
<exclude .../>
-->
</cloud-backup>
<!--
<device-transfer>
<include .../>
<exclude .../>
</device-transfer>
-->
</data-extraction-rules>

38
app/src/main/res/xml/device_filter.xml

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- 0x0403 / 0x60??: FTDI -->
<usb-device vendor-id="1027" product-id="24577" /> <!-- 0x6001: FT232R -->
<usb-device vendor-id="1027" product-id="24592" /> <!-- 0x6010: FT2232H -->
<usb-device vendor-id="1027" product-id="24593" /> <!-- 0x6011: FT4232H -->
<usb-device vendor-id="1027" product-id="24596" /> <!-- 0x6014: FT232H -->
<usb-device vendor-id="1027" product-id="24597" /> <!-- 0x6015: FT230X, FT231X, FT234XD -->
<!-- 0x10C4 / 0xEA??: Silabs CP210x -->
<usb-device vendor-id="4292" product-id="60000" /> <!-- 0xea60: CP2102 and other CP210x single port devices -->
<usb-device vendor-id="4292" product-id="60016" /> <!-- 0xea70: CP2105 -->
<usb-device vendor-id="4292" product-id="60017" /> <!-- 0xea71: CP2108 -->
<!-- 0x067B / 0x23?3: Prolific PL2303x -->
<usb-device vendor-id="1659" product-id="8963" /> <!-- 0x2303: PL2303HX, HXD, TA, ... -->
<usb-device vendor-id="1659" product-id="9123" /> <!-- 0x23a3: PL2303GC -->
<usb-device vendor-id="1659" product-id="9139" /> <!-- 0x23b3: PL2303GB -->
<usb-device vendor-id="1659" product-id="9155" /> <!-- 0x23c3: PL2303GT -->
<usb-device vendor-id="1659" product-id="9171" /> <!-- 0x23d3: PL2303GL -->
<usb-device vendor-id="1659" product-id="9187" /> <!-- 0x23e3: PL2303GE -->
<usb-device vendor-id="1659" product-id="9203" /> <!-- 0x23f3: PL2303GS -->
<!-- 0x1a86 / 0x?523: Qinheng CH34x -->
<usb-device vendor-id="6790" product-id="21795" /> <!-- 0x5523: CH341A -->
<usb-device vendor-id="6790" product-id="29987" /> <!-- 0x7523: CH340 -->
<!-- CDC driver -->
<usb-device vendor-id="9025" /> <!-- 0x2341 / ......: Arduino -->
<usb-device vendor-id="5824" product-id="1155" /> <!-- 0x16C0 / 0x0483: Teensyduino -->
<usb-device vendor-id="1003" product-id="8260" /> <!-- 0x03EB / 0x2044: Atmel Lufa -->
<usb-device vendor-id="7855" product-id="4" /> <!-- 0x1eaf / 0x0004: Leaflabs Maple -->
<usb-device vendor-id="3368" product-id="516" /> <!-- 0x0d28 / 0x0204: ARM mbed -->
<usb-device vendor-id="1155" product-id="22336" /><!-- 0x0483 / 0x5740: ST CDC -->
<usb-device vendor-id="11914" product-id="5" /> <!-- 0x2E8A / 0x0005: Raspberry Pi Pico Micropython -->
<usb-device vendor-id="11914" product-id="10" /> <!-- 0x2E8A / 0x000A: Raspberry Pi Pico SDK -->
<usb-device vendor-id="6790" product-id="21972" /><!-- 0x1A86 / 0x55D4: Qinheng CH9102F -->
</resources>

17
app/src/test/java/com/example/fivewheel/ExampleUnitTest.java

@ -0,0 +1,17 @@
package com.example.fivewheel;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Example local unit test, which will execute on the development machine (host).
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
public class ExampleUnitTest {
@Test
public void addition_isCorrect() {
assertEquals(4, 2 + 2);
}
}

5
build.gradle

@ -0,0 +1,5 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
id 'com.android.application' version '8.2.2' apply false
id 'com.android.library' version '8.2.2' apply false
}

21
gradle.properties

@ -0,0 +1,21 @@
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
# AndroidX package structure to make it clearer which packages are bundled with the
# Android operating system, and which are packaged with your app's APK
# https://developer.android.com/topic/libraries/support-library/androidx-rn
android.useAndroidX=true
# Enables namespacing of each library's R class so that its R class includes only the
# resources declared in the library itself and none from the library's dependencies,
# thereby reducing the size of the R class for that library
android.nonTransitiveRClass=true

BIN
gradle/wrapper/gradle-wrapper.jar

Binary file not shown.

6
gradle/wrapper/gradle-wrapper.properties

@ -0,0 +1,6 @@
#Wed Feb 05 16:51:00 CST 2025
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

185
gradlew

@ -0,0 +1,185 @@
#!/usr/bin/env sh
#
# Copyright 2015 the original author or authors.
#
# 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
#
# https://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.
#
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=`expr $i + 1`
done
case $i in
0) set -- ;;
1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=`save "$@"`
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
exec "$JAVACMD" "$@"

89
gradlew.bat

@ -0,0 +1,89 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

363
proto/RobotData.cs

@ -0,0 +1,363 @@
// <auto-generated>
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: robot_data.proto
// </auto-generated>
#pragma warning disable 1591, 0612, 3021, 8981
#region Designer generated code
using pb = global::Google.Protobuf;
using pbc = global::Google.Protobuf.Collections;
using pbr = global::Google.Protobuf.Reflection;
using scg = global::System.Collections.Generic;
/// <summary>Holder for reflection information generated from robot_data.proto</summary>
public static partial class RobotDataReflection {
#region Descriptor
/// <summary>File descriptor for robot_data.proto</summary>
public static pbr::FileDescriptor Descriptor {
get { return descriptor; }
}
private static pbr::FileDescriptor descriptor;
static RobotDataReflection() {
byte[] descriptorData = global::System.Convert.FromBase64String(
string.Concat(
"ChByb2JvdF9kYXRhLnByb3RvImIKCURhdGFUcmFucxIVCg1SRl9BbmdsZV9S",
"b2xsGAEgASgFEhYKDlJGX0FuZ2xlX1BpdGNoGAIgASgFEhQKDFJGX0FuZ2xl",
"X1lhdxgDIAEoBRIQCghSRl9EZXB0aBgEIAEoBUIqCiZjb20uZXhhbXBsZS5y",
"ZW1vdmVtYXJpbmVhbmltYWxzLm1vZGVsc1AAYgZwcm90bzM="));
descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
new pbr::FileDescriptor[] { },
new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] {
new pbr::GeneratedClrTypeInfo(typeof(global::DataTrans), global::DataTrans.Parser, new[]{ "RFAngleRoll", "RFAnglePitch", "RFAngleYaw", "RFDepth" }, null, null, null, null)
}));
}
#endregion
}
#region Messages
[global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")]
public sealed partial class DataTrans : pb::IMessage<DataTrans>
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
, pb::IBufferMessage
#endif
{
private static readonly pb::MessageParser<DataTrans> _parser = new pb::MessageParser<DataTrans>(() => new DataTrans());
private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public static pb::MessageParser<DataTrans> Parser { get { return _parser; } }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public static pbr::MessageDescriptor Descriptor {
get { return global::RobotDataReflection.Descriptor.MessageTypes[0]; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
pbr::MessageDescriptor pb::IMessage.Descriptor {
get { return Descriptor; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public DataTrans() {
OnConstruction();
}
partial void OnConstruction();
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public DataTrans(DataTrans other) : this() {
rFAngleRoll_ = other.rFAngleRoll_;
rFAnglePitch_ = other.rFAnglePitch_;
rFAngleYaw_ = other.rFAngleYaw_;
rFDepth_ = other.rFDepth_;
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public DataTrans Clone() {
return new DataTrans(this);
}
/// <summary>Field number for the "RF_Angle_Roll" field.</summary>
public const int RFAngleRollFieldNumber = 1;
private int rFAngleRoll_;
/// <summary>
///横滚角
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public int RFAngleRoll {
get { return rFAngleRoll_; }
set {
rFAngleRoll_ = value;
}
}
/// <summary>Field number for the "RF_Angle_Pitch" field.</summary>
public const int RFAnglePitchFieldNumber = 2;
private int rFAnglePitch_;
/// <summary>
///俯仰角
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public int RFAnglePitch {
get { return rFAnglePitch_; }
set {
rFAnglePitch_ = value;
}
}
/// <summary>Field number for the "RF_Angle_Yaw" field.</summary>
public const int RFAngleYawFieldNumber = 3;
private int rFAngleYaw_;
/// <summary>
///航向角
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public int RFAngleYaw {
get { return rFAngleYaw_; }
set {
rFAngleYaw_ = value;
}
}
/// <summary>Field number for the "RF_Depth" field.</summary>
public const int RFDepthFieldNumber = 4;
private int rFDepth_;
/// <summary>
///海洋深度
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public int RFDepth {
get { return rFDepth_; }
set {
rFDepth_ = value;
}
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public override bool Equals(object other) {
return Equals(other as DataTrans);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public bool Equals(DataTrans other) {
if (ReferenceEquals(other, null)) {
return false;
}
if (ReferenceEquals(other, this)) {
return true;
}
if (RFAngleRoll != other.RFAngleRoll) return false;
if (RFAnglePitch != other.RFAnglePitch) return false;
if (RFAngleYaw != other.RFAngleYaw) return false;
if (RFDepth != other.RFDepth) return false;
return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public override int GetHashCode() {
int hash = 1;
if (RFAngleRoll != 0) hash ^= RFAngleRoll.GetHashCode();
if (RFAnglePitch != 0) hash ^= RFAnglePitch.GetHashCode();
if (RFAngleYaw != 0) hash ^= RFAngleYaw.GetHashCode();
if (RFDepth != 0) hash ^= RFDepth.GetHashCode();
if (_unknownFields != null) {
hash ^= _unknownFields.GetHashCode();
}
return hash;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public override string ToString() {
return pb::JsonFormatter.ToDiagnosticString(this);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public void WriteTo(pb::CodedOutputStream output) {
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
output.WriteRawMessage(this);
#else
if (RFAngleRoll != 0) {
output.WriteRawTag(8);
output.WriteInt32(RFAngleRoll);
}
if (RFAnglePitch != 0) {
output.WriteRawTag(16);
output.WriteInt32(RFAnglePitch);
}
if (RFAngleYaw != 0) {
output.WriteRawTag(24);
output.WriteInt32(RFAngleYaw);
}
if (RFDepth != 0) {
output.WriteRawTag(32);
output.WriteInt32(RFDepth);
}
if (_unknownFields != null) {
_unknownFields.WriteTo(output);
}
#endif
}
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
if (RFAngleRoll != 0) {
output.WriteRawTag(8);
output.WriteInt32(RFAngleRoll);
}
if (RFAnglePitch != 0) {
output.WriteRawTag(16);
output.WriteInt32(RFAnglePitch);
}
if (RFAngleYaw != 0) {
output.WriteRawTag(24);
output.WriteInt32(RFAngleYaw);
}
if (RFDepth != 0) {
output.WriteRawTag(32);
output.WriteInt32(RFDepth);
}
if (_unknownFields != null) {
_unknownFields.WriteTo(ref output);
}
}
#endif
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public int CalculateSize() {
int size = 0;
if (RFAngleRoll != 0) {
size += 1 + pb::CodedOutputStream.ComputeInt32Size(RFAngleRoll);
}
if (RFAnglePitch != 0) {
size += 1 + pb::CodedOutputStream.ComputeInt32Size(RFAnglePitch);
}
if (RFAngleYaw != 0) {
size += 1 + pb::CodedOutputStream.ComputeInt32Size(RFAngleYaw);
}
if (RFDepth != 0) {
size += 1 + pb::CodedOutputStream.ComputeInt32Size(RFDepth);
}
if (_unknownFields != null) {
size += _unknownFields.CalculateSize();
}
return size;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public void MergeFrom(DataTrans other) {
if (other == null) {
return;
}
if (other.RFAngleRoll != 0) {
RFAngleRoll = other.RFAngleRoll;
}
if (other.RFAnglePitch != 0) {
RFAnglePitch = other.RFAnglePitch;
}
if (other.RFAngleYaw != 0) {
RFAngleYaw = other.RFAngleYaw;
}
if (other.RFDepth != 0) {
RFDepth = other.RFDepth;
}
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public void MergeFrom(pb::CodedInputStream input) {
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
input.ReadRawMessage(this);
#else
uint tag;
while ((tag = input.ReadTag()) != 0) {
if ((tag & 7) == 4) {
// Abort on any end group tag.
return;
}
switch(tag) {
default:
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 8: {
RFAngleRoll = input.ReadInt32();
break;
}
case 16: {
RFAnglePitch = input.ReadInt32();
break;
}
case 24: {
RFAngleYaw = input.ReadInt32();
break;
}
case 32: {
RFDepth = input.ReadInt32();
break;
}
}
}
#endif
}
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
uint tag;
while ((tag = input.ReadTag()) != 0) {
if ((tag & 7) == 4) {
// Abort on any end group tag.
return;
}
switch(tag) {
default:
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
break;
case 8: {
RFAngleRoll = input.ReadInt32();
break;
}
case 16: {
RFAnglePitch = input.ReadInt32();
break;
}
case 24: {
RFAngleYaw = input.ReadInt32();
break;
}
case 32: {
RFDepth = input.ReadInt32();
break;
}
}
}
}
#endif
}
#endregion
#endregion Designer generated code

792
proto/com/example/removemarineanimals/models/RobotData.java

@ -0,0 +1,792 @@
// Generated by the protocol buffer compiler. DO NOT EDIT!
// NO CHECKED-IN PROTOBUF GENCODE
// source: robot_data.proto
// Protobuf Java Version: 4.27.2
package com.example.removemarineanimals.models;
public final class RobotData {
private RobotData() {}
static {
com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion(
com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC,
/* major= */ 4,
/* minor= */ 27,
/* patch= */ 2,
/* suffix= */ "",
RobotData.class.getName());
}
public static void registerAllExtensions(
com.google.protobuf.ExtensionRegistryLite registry) {
}
public static void registerAllExtensions(
com.google.protobuf.ExtensionRegistry registry) {
registerAllExtensions(
(com.google.protobuf.ExtensionRegistryLite) registry);
}
public interface DataTransOrBuilder extends
// @@protoc_insertion_point(interface_extends:DataTrans)
com.google.protobuf.MessageOrBuilder {
/**
* <pre>
* 横滚角
* </pre>
*
* <code>int32 RF_Angle_Roll = 1;</code>
* @return The rFAngleRoll.
*/
int getRFAngleRoll();
/**
* <pre>
* 俯仰角
* </pre>
*
* <code>int32 RF_Angle_Pitch = 2;</code>
* @return The rFAnglePitch.
*/
int getRFAnglePitch();
/**
* <pre>
* 航向角
* </pre>
*
* <code>int32 RF_Angle_Yaw = 3;</code>
* @return The rFAngleYaw.
*/
int getRFAngleYaw();
/**
* <pre>
* 海洋深度
* </pre>
*
* <code>int32 RF_Depth = 4;</code>
* @return The rFDepth.
*/
int getRFDepth();
}
/**
* Protobuf type {@code DataTrans}
*/
public static final class DataTrans extends
com.google.protobuf.GeneratedMessage implements
// @@protoc_insertion_point(message_implements:DataTrans)
DataTransOrBuilder {
private static final long serialVersionUID = 0L;
static {
com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion(
com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC,
/* major= */ 4,
/* minor= */ 27,
/* patch= */ 2,
/* suffix= */ "",
DataTrans.class.getName());
}
// Use DataTrans.newBuilder() to construct.
private DataTrans(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
super(builder);
}
private DataTrans() {
}
public static final com.google.protobuf.Descriptors.Descriptor
getDescriptor() {
return com.example.removemarineanimals.models.RobotData.internal_static_DataTrans_descriptor;
}
@java.lang.Override
protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
internalGetFieldAccessorTable() {
return com.example.removemarineanimals.models.RobotData.internal_static_DataTrans_fieldAccessorTable
.ensureFieldAccessorsInitialized(
com.example.removemarineanimals.models.RobotData.DataTrans.class, com.example.removemarineanimals.models.RobotData.DataTrans.Builder.class);
}
public static final int RF_ANGLE_ROLL_FIELD_NUMBER = 1;
private int rFAngleRoll_ = 0;
/**
* <pre>
* 横滚角
* </pre>
*
* <code>int32 RF_Angle_Roll = 1;</code>
* @return The rFAngleRoll.
*/
@java.lang.Override
public int getRFAngleRoll() {
return rFAngleRoll_;
}
public static final int RF_ANGLE_PITCH_FIELD_NUMBER = 2;
private int rFAnglePitch_ = 0;
/**
* <pre>
* 俯仰角
* </pre>
*
* <code>int32 RF_Angle_Pitch = 2;</code>
* @return The rFAnglePitch.
*/
@java.lang.Override
public int getRFAnglePitch() {
return rFAnglePitch_;
}
public static final int RF_ANGLE_YAW_FIELD_NUMBER = 3;
private int rFAngleYaw_ = 0;
/**
* <pre>
* 航向角
* </pre>
*
* <code>int32 RF_Angle_Yaw = 3;</code>
* @return The rFAngleYaw.
*/
@java.lang.Override
public int getRFAngleYaw() {
return rFAngleYaw_;
}
public static final int RF_DEPTH_FIELD_NUMBER = 4;
private int rFDepth_ = 0;
/**
* <pre>
* 海洋深度
* </pre>
*
* <code>int32 RF_Depth = 4;</code>
* @return The rFDepth.
*/
@java.lang.Override
public int getRFDepth() {
return rFDepth_;
}
private byte memoizedIsInitialized = -1;
@java.lang.Override
public final boolean isInitialized() {
byte isInitialized = memoizedIsInitialized;
if (isInitialized == 1) return true;
if (isInitialized == 0) return false;
memoizedIsInitialized = 1;
return true;
}
@java.lang.Override
public void writeTo(com.google.protobuf.CodedOutputStream output)
throws java.io.IOException {
if (rFAngleRoll_ != 0) {
output.writeInt32(1, rFAngleRoll_);
}
if (rFAnglePitch_ != 0) {
output.writeInt32(2, rFAnglePitch_);
}
if (rFAngleYaw_ != 0) {
output.writeInt32(3, rFAngleYaw_);
}
if (rFDepth_ != 0) {
output.writeInt32(4, rFDepth_);
}
getUnknownFields().writeTo(output);
}
@java.lang.Override
public int getSerializedSize() {
int size = memoizedSize;
if (size != -1) return size;
size = 0;
if (rFAngleRoll_ != 0) {
size += com.google.protobuf.CodedOutputStream
.computeInt32Size(1, rFAngleRoll_);
}
if (rFAnglePitch_ != 0) {
size += com.google.protobuf.CodedOutputStream
.computeInt32Size(2, rFAnglePitch_);
}
if (rFAngleYaw_ != 0) {
size += com.google.protobuf.CodedOutputStream
.computeInt32Size(3, rFAngleYaw_);
}
if (rFDepth_ != 0) {
size += com.google.protobuf.CodedOutputStream
.computeInt32Size(4, rFDepth_);
}
size += getUnknownFields().getSerializedSize();
memoizedSize = size;
return size;
}
@java.lang.Override
public boolean equals(final java.lang.Object obj) {
if (obj == this) {
return true;
}
if (!(obj instanceof com.example.removemarineanimals.models.RobotData.DataTrans)) {
return super.equals(obj);
}
com.example.removemarineanimals.models.RobotData.DataTrans other = (com.example.removemarineanimals.models.RobotData.DataTrans) obj;
if (getRFAngleRoll()
!= other.getRFAngleRoll()) return false;
if (getRFAnglePitch()
!= other.getRFAnglePitch()) return false;
if (getRFAngleYaw()
!= other.getRFAngleYaw()) return false;
if (getRFDepth()
!= other.getRFDepth()) return false;
if (!getUnknownFields().equals(other.getUnknownFields())) return false;
return true;
}
@java.lang.Override
public int hashCode() {
if (memoizedHashCode != 0) {
return memoizedHashCode;
}
int hash = 41;
hash = (19 * hash) + getDescriptor().hashCode();
hash = (37 * hash) + RF_ANGLE_ROLL_FIELD_NUMBER;
hash = (53 * hash) + getRFAngleRoll();
hash = (37 * hash) + RF_ANGLE_PITCH_FIELD_NUMBER;
hash = (53 * hash) + getRFAnglePitch();
hash = (37 * hash) + RF_ANGLE_YAW_FIELD_NUMBER;
hash = (53 * hash) + getRFAngleYaw();
hash = (37 * hash) + RF_DEPTH_FIELD_NUMBER;
hash = (53 * hash) + getRFDepth();
hash = (29 * hash) + getUnknownFields().hashCode();
memoizedHashCode = hash;
return hash;
}
public static com.example.removemarineanimals.models.RobotData.DataTrans parseFrom(
java.nio.ByteBuffer data)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data);
}
public static com.example.removemarineanimals.models.RobotData.DataTrans parseFrom(
java.nio.ByteBuffer data,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data, extensionRegistry);
}
public static com.example.removemarineanimals.models.RobotData.DataTrans parseFrom(
com.google.protobuf.ByteString data)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data);
}
public static com.example.removemarineanimals.models.RobotData.DataTrans parseFrom(
com.google.protobuf.ByteString data,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data, extensionRegistry);
}
public static com.example.removemarineanimals.models.RobotData.DataTrans parseFrom(byte[] data)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data);
}
public static com.example.removemarineanimals.models.RobotData.DataTrans parseFrom(
byte[] data,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data, extensionRegistry);
}
public static com.example.removemarineanimals.models.RobotData.DataTrans parseFrom(java.io.InputStream input)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessage
.parseWithIOException(PARSER, input);
}
public static com.example.removemarineanimals.models.RobotData.DataTrans parseFrom(
java.io.InputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessage
.parseWithIOException(PARSER, input, extensionRegistry);
}
public static com.example.removemarineanimals.models.RobotData.DataTrans parseDelimitedFrom(java.io.InputStream input)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessage
.parseDelimitedWithIOException(PARSER, input);
}
public static com.example.removemarineanimals.models.RobotData.DataTrans parseDelimitedFrom(
java.io.InputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessage
.parseDelimitedWithIOException(PARSER, input, extensionRegistry);
}
public static com.example.removemarineanimals.models.RobotData.DataTrans parseFrom(
com.google.protobuf.CodedInputStream input)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessage
.parseWithIOException(PARSER, input);
}
public static com.example.removemarineanimals.models.RobotData.DataTrans parseFrom(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessage
.parseWithIOException(PARSER, input, extensionRegistry);
}
@java.lang.Override
public Builder newBuilderForType() { return newBuilder(); }
public static Builder newBuilder() {
return DEFAULT_INSTANCE.toBuilder();
}
public static Builder newBuilder(com.example.removemarineanimals.models.RobotData.DataTrans prototype) {
return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
}
@java.lang.Override
public Builder toBuilder() {
return this == DEFAULT_INSTANCE
? new Builder() : new Builder().mergeFrom(this);
}
@java.lang.Override
protected Builder newBuilderForType(
com.google.protobuf.GeneratedMessage.BuilderParent parent) {
Builder builder = new Builder(parent);
return builder;
}
/**
* Protobuf type {@code DataTrans}
*/
public static final class Builder extends
com.google.protobuf.GeneratedMessage.Builder<Builder> implements
// @@protoc_insertion_point(builder_implements:DataTrans)
com.example.removemarineanimals.models.RobotData.DataTransOrBuilder {
public static final com.google.protobuf.Descriptors.Descriptor
getDescriptor() {
return com.example.removemarineanimals.models.RobotData.internal_static_DataTrans_descriptor;
}
@java.lang.Override
protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
internalGetFieldAccessorTable() {
return com.example.removemarineanimals.models.RobotData.internal_static_DataTrans_fieldAccessorTable
.ensureFieldAccessorsInitialized(
com.example.removemarineanimals.models.RobotData.DataTrans.class, com.example.removemarineanimals.models.RobotData.DataTrans.Builder.class);
}
// Construct using com.example.removemarineanimals.models.RobotData.DataTrans.newBuilder()
private Builder() {
}
private Builder(
com.google.protobuf.GeneratedMessage.BuilderParent parent) {
super(parent);
}
@java.lang.Override
public Builder clear() {
super.clear();
bitField0_ = 0;
rFAngleRoll_ = 0;
rFAnglePitch_ = 0;
rFAngleYaw_ = 0;
rFDepth_ = 0;
return this;
}
@java.lang.Override
public com.google.protobuf.Descriptors.Descriptor
getDescriptorForType() {
return com.example.removemarineanimals.models.RobotData.internal_static_DataTrans_descriptor;
}
@java.lang.Override
public com.example.removemarineanimals.models.RobotData.DataTrans getDefaultInstanceForType() {
return com.example.removemarineanimals.models.RobotData.DataTrans.getDefaultInstance();
}
@java.lang.Override
public com.example.removemarineanimals.models.RobotData.DataTrans build() {
com.example.removemarineanimals.models.RobotData.DataTrans result = buildPartial();
if (!result.isInitialized()) {
throw newUninitializedMessageException(result);
}
return result;
}
@java.lang.Override
public com.example.removemarineanimals.models.RobotData.DataTrans buildPartial() {
com.example.removemarineanimals.models.RobotData.DataTrans result = new com.example.removemarineanimals.models.RobotData.DataTrans(this);
if (bitField0_ != 0) { buildPartial0(result); }
onBuilt();
return result;
}
private void buildPartial0(com.example.removemarineanimals.models.RobotData.DataTrans result) {
int from_bitField0_ = bitField0_;
if (((from_bitField0_ & 0x00000001) != 0)) {
result.rFAngleRoll_ = rFAngleRoll_;
}
if (((from_bitField0_ & 0x00000002) != 0)) {
result.rFAnglePitch_ = rFAnglePitch_;
}
if (((from_bitField0_ & 0x00000004) != 0)) {
result.rFAngleYaw_ = rFAngleYaw_;
}
if (((from_bitField0_ & 0x00000008) != 0)) {
result.rFDepth_ = rFDepth_;
}
}
@java.lang.Override
public Builder mergeFrom(com.google.protobuf.Message other) {
if (other instanceof com.example.removemarineanimals.models.RobotData.DataTrans) {
return mergeFrom((com.example.removemarineanimals.models.RobotData.DataTrans)other);
} else {
super.mergeFrom(other);
return this;
}
}
public Builder mergeFrom(com.example.removemarineanimals.models.RobotData.DataTrans other) {
if (other == com.example.removemarineanimals.models.RobotData.DataTrans.getDefaultInstance()) return this;
if (other.getRFAngleRoll() != 0) {
setRFAngleRoll(other.getRFAngleRoll());
}
if (other.getRFAnglePitch() != 0) {
setRFAnglePitch(other.getRFAnglePitch());
}
if (other.getRFAngleYaw() != 0) {
setRFAngleYaw(other.getRFAngleYaw());
}
if (other.getRFDepth() != 0) {
setRFDepth(other.getRFDepth());
}
this.mergeUnknownFields(other.getUnknownFields());
onChanged();
return this;
}
@java.lang.Override
public final boolean isInitialized() {
return true;
}
@java.lang.Override
public Builder mergeFrom(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
if (extensionRegistry == null) {
throw new java.lang.NullPointerException();
}
try {
boolean done = false;
while (!done) {
int tag = input.readTag();
switch (tag) {
case 0:
done = true;
break;
case 8: {
rFAngleRoll_ = input.readInt32();
bitField0_ |= 0x00000001;
break;
} // case 8
case 16: {
rFAnglePitch_ = input.readInt32();
bitField0_ |= 0x00000002;
break;
} // case 16
case 24: {
rFAngleYaw_ = input.readInt32();
bitField0_ |= 0x00000004;
break;
} // case 24
case 32: {
rFDepth_ = input.readInt32();
bitField0_ |= 0x00000008;
break;
} // case 32
default: {
if (!super.parseUnknownField(input, extensionRegistry, tag)) {
done = true; // was an endgroup tag
}
break;
} // default:
} // switch (tag)
} // while (!done)
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
throw e.unwrapIOException();
} finally {
onChanged();
} // finally
return this;
}
private int bitField0_;
private int rFAngleRoll_ ;
/**
* <pre>
* 横滚角
* </pre>
*
* <code>int32 RF_Angle_Roll = 1;</code>
* @return The rFAngleRoll.
*/
@java.lang.Override
public int getRFAngleRoll() {
return rFAngleRoll_;
}
/**
* <pre>
* 横滚角
* </pre>
*
* <code>int32 RF_Angle_Roll = 1;</code>
* @param value The rFAngleRoll to set.
* @return This builder for chaining.
*/
public Builder setRFAngleRoll(int value) {
rFAngleRoll_ = value;
bitField0_ |= 0x00000001;
onChanged();
return this;
}
/**
* <pre>
* 横滚角
* </pre>
*
* <code>int32 RF_Angle_Roll = 1;</code>
* @return This builder for chaining.
*/
public Builder clearRFAngleRoll() {
bitField0_ = (bitField0_ & ~0x00000001);
rFAngleRoll_ = 0;
onChanged();
return this;
}
private int rFAnglePitch_ ;
/**
* <pre>
* 俯仰角
* </pre>
*
* <code>int32 RF_Angle_Pitch = 2;</code>
* @return The rFAnglePitch.
*/
@java.lang.Override
public int getRFAnglePitch() {
return rFAnglePitch_;
}
/**
* <pre>
* 俯仰角
* </pre>
*
* <code>int32 RF_Angle_Pitch = 2;</code>
* @param value The rFAnglePitch to set.
* @return This builder for chaining.
*/
public Builder setRFAnglePitch(int value) {
rFAnglePitch_ = value;
bitField0_ |= 0x00000002;
onChanged();
return this;
}
/**
* <pre>
* 俯仰角
* </pre>
*
* <code>int32 RF_Angle_Pitch = 2;</code>
* @return This builder for chaining.
*/
public Builder clearRFAnglePitch() {
bitField0_ = (bitField0_ & ~0x00000002);
rFAnglePitch_ = 0;
onChanged();
return this;
}
private int rFAngleYaw_ ;
/**
* <pre>
* 航向角
* </pre>
*
* <code>int32 RF_Angle_Yaw = 3;</code>
* @return The rFAngleYaw.
*/
@java.lang.Override
public int getRFAngleYaw() {
return rFAngleYaw_;
}
/**
* <pre>
* 航向角
* </pre>
*
* <code>int32 RF_Angle_Yaw = 3;</code>
* @param value The rFAngleYaw to set.
* @return This builder for chaining.
*/
public Builder setRFAngleYaw(int value) {
rFAngleYaw_ = value;
bitField0_ |= 0x00000004;
onChanged();
return this;
}
/**
* <pre>
* 航向角
* </pre>
*
* <code>int32 RF_Angle_Yaw = 3;</code>
* @return This builder for chaining.
*/
public Builder clearRFAngleYaw() {
bitField0_ = (bitField0_ & ~0x00000004);
rFAngleYaw_ = 0;
onChanged();
return this;
}
private int rFDepth_ ;
/**
* <pre>
* 海洋深度
* </pre>
*
* <code>int32 RF_Depth = 4;</code>
* @return The rFDepth.
*/
@java.lang.Override
public int getRFDepth() {
return rFDepth_;
}
/**
* <pre>
* 海洋深度
* </pre>
*
* <code>int32 RF_Depth = 4;</code>
* @param value The rFDepth to set.
* @return This builder for chaining.
*/
public Builder setRFDepth(int value) {
rFDepth_ = value;
bitField0_ |= 0x00000008;
onChanged();
return this;
}
/**
* <pre>
* 海洋深度
* </pre>
*
* <code>int32 RF_Depth = 4;</code>
* @return This builder for chaining.
*/
public Builder clearRFDepth() {
bitField0_ = (bitField0_ & ~0x00000008);
rFDepth_ = 0;
onChanged();
return this;
}
// @@protoc_insertion_point(builder_scope:DataTrans)
}
// @@protoc_insertion_point(class_scope:DataTrans)
private static final com.example.removemarineanimals.models.RobotData.DataTrans DEFAULT_INSTANCE;
static {
DEFAULT_INSTANCE = new com.example.removemarineanimals.models.RobotData.DataTrans();
}
public static com.example.removemarineanimals.models.RobotData.DataTrans getDefaultInstance() {
return DEFAULT_INSTANCE;
}
private static final com.google.protobuf.Parser<DataTrans>
PARSER = new com.google.protobuf.AbstractParser<DataTrans>() {
@java.lang.Override
public DataTrans parsePartialFrom(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
Builder builder = newBuilder();
try {
builder.mergeFrom(input, extensionRegistry);
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
throw e.setUnfinishedMessage(builder.buildPartial());
} catch (com.google.protobuf.UninitializedMessageException e) {
throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial());
} catch (java.io.IOException e) {
throw new com.google.protobuf.InvalidProtocolBufferException(e)
.setUnfinishedMessage(builder.buildPartial());
}
return builder.buildPartial();
}
};
public static com.google.protobuf.Parser<DataTrans> parser() {
return PARSER;
}
@java.lang.Override
public com.google.protobuf.Parser<DataTrans> getParserForType() {
return PARSER;
}
@java.lang.Override
public com.example.removemarineanimals.models.RobotData.DataTrans getDefaultInstanceForType() {
return DEFAULT_INSTANCE;
}
}
private static final com.google.protobuf.Descriptors.Descriptor
internal_static_DataTrans_descriptor;
private static final
com.google.protobuf.GeneratedMessage.FieldAccessorTable
internal_static_DataTrans_fieldAccessorTable;
public static com.google.protobuf.Descriptors.FileDescriptor
getDescriptor() {
return descriptor;
}
private static com.google.protobuf.Descriptors.FileDescriptor
descriptor;
static {
java.lang.String[] descriptorData = {
"\n\020robot_data.proto\"b\n\tDataTrans\022\025\n\rRF_An" +
"gle_Roll\030\001 \001(\005\022\026\n\016RF_Angle_Pitch\030\002 \001(\005\022\024" +
"\n\014RF_Angle_Yaw\030\003 \001(\005\022\020\n\010RF_Depth\030\004 \001(\005B*" +
"\n&com.example.removemarineanimals.models" +
"P\000b\006proto3"
};
descriptor = com.google.protobuf.Descriptors.FileDescriptor
.internalBuildGeneratedFileFrom(descriptorData,
new com.google.protobuf.Descriptors.FileDescriptor[] {
});
internal_static_DataTrans_descriptor =
getDescriptor().getMessageTypes().get(0);
internal_static_DataTrans_fieldAccessorTable = new
com.google.protobuf.GeneratedMessage.FieldAccessorTable(
internal_static_DataTrans_descriptor,
new java.lang.String[] { "RFAngleRoll", "RFAnglePitch", "RFAngleYaw", "RFDepth", });
descriptor.resolveAllFeaturesImmutable();
}
// @@protoc_insertion_point(outer_class_scope)
}

615
proto/com/example/removemarineanimals/models/RobotRMACM.java

@ -0,0 +1,615 @@
// Generated by the protocol buffer compiler. DO NOT EDIT!
// NO CHECKED-IN PROTOBUF GENCODE
// source: robot_RMACM.proto
// Protobuf Java Version: 4.27.2
package com.example.removemarineanimals.models;
public final class RobotRMACM {
private RobotRMACM() {}
static {
com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion(
com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC,
/* major= */ 4,
/* minor= */ 27,
/* patch= */ 2,
/* suffix= */ "",
RobotRMACM.class.getName());
}
public static void registerAllExtensions(
com.google.protobuf.ExtensionRegistryLite registry) {
}
public static void registerAllExtensions(
com.google.protobuf.ExtensionRegistry registry) {
registerAllExtensions(
(com.google.protobuf.ExtensionRegistryLite) registry);
}
public interface RMACMOrBuilder extends
// @@protoc_insertion_point(interface_extends:RMACM)
com.google.protobuf.MessageOrBuilder {
/**
* <pre>
* 灯光亮度
* </pre>
*
* <code>int32 LightBrightness = 1;</code>
* @return The lightBrightness.
*/
int getLightBrightness();
/**
* <pre>
* 机器人速度
* </pre>
*
* <code>int32 Robot_Speed = 2;</code>
* @return The robotSpeed.
*/
int getRobotSpeed();
}
/**
* <pre>
* Remove Marine Animal Command
* </pre>
*
* Protobuf type {@code RMACM}
*/
public static final class RMACM extends
com.google.protobuf.GeneratedMessage implements
// @@protoc_insertion_point(message_implements:RMACM)
RMACMOrBuilder {
private static final long serialVersionUID = 0L;
static {
com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion(
com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC,
/* major= */ 4,
/* minor= */ 27,
/* patch= */ 2,
/* suffix= */ "",
RMACM.class.getName());
}
// Use RMACM.newBuilder() to construct.
private RMACM(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
super(builder);
}
private RMACM() {
}
public static final com.google.protobuf.Descriptors.Descriptor
getDescriptor() {
return com.example.removemarineanimals.models.RobotRMACM.internal_static_RMACM_descriptor;
}
@java.lang.Override
protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
internalGetFieldAccessorTable() {
return com.example.removemarineanimals.models.RobotRMACM.internal_static_RMACM_fieldAccessorTable
.ensureFieldAccessorsInitialized(
com.example.removemarineanimals.models.RobotRMACM.RMACM.class, com.example.removemarineanimals.models.RobotRMACM.RMACM.Builder.class);
}
public static final int LIGHTBRIGHTNESS_FIELD_NUMBER = 1;
private int lightBrightness_ = 0;
/**
* <pre>
* 灯光亮度
* </pre>
*
* <code>int32 LightBrightness = 1;</code>
* @return The lightBrightness.
*/
@java.lang.Override
public int getLightBrightness() {
return lightBrightness_;
}
public static final int ROBOT_SPEED_FIELD_NUMBER = 2;
private int robotSpeed_ = 0;
/**
* <pre>
* 机器人速度
* </pre>
*
* <code>int32 Robot_Speed = 2;</code>
* @return The robotSpeed.
*/
@java.lang.Override
public int getRobotSpeed() {
return robotSpeed_;
}
private byte memoizedIsInitialized = -1;
@java.lang.Override
public final boolean isInitialized() {
byte isInitialized = memoizedIsInitialized;
if (isInitialized == 1) return true;
if (isInitialized == 0) return false;
memoizedIsInitialized = 1;
return true;
}
@java.lang.Override
public void writeTo(com.google.protobuf.CodedOutputStream output)
throws java.io.IOException {
if (lightBrightness_ != 0) {
output.writeInt32(1, lightBrightness_);
}
if (robotSpeed_ != 0) {
output.writeInt32(2, robotSpeed_);
}
getUnknownFields().writeTo(output);
}
@java.lang.Override
public int getSerializedSize() {
int size = memoizedSize;
if (size != -1) return size;
size = 0;
if (lightBrightness_ != 0) {
size += com.google.protobuf.CodedOutputStream
.computeInt32Size(1, lightBrightness_);
}
if (robotSpeed_ != 0) {
size += com.google.protobuf.CodedOutputStream
.computeInt32Size(2, robotSpeed_);
}
size += getUnknownFields().getSerializedSize();
memoizedSize = size;
return size;
}
@java.lang.Override
public boolean equals(final java.lang.Object obj) {
if (obj == this) {
return true;
}
if (!(obj instanceof com.example.removemarineanimals.models.RobotRMACM.RMACM)) {
return super.equals(obj);
}
com.example.removemarineanimals.models.RobotRMACM.RMACM other = (com.example.removemarineanimals.models.RobotRMACM.RMACM) obj;
if (getLightBrightness()
!= other.getLightBrightness()) return false;
if (getRobotSpeed()
!= other.getRobotSpeed()) return false;
if (!getUnknownFields().equals(other.getUnknownFields())) return false;
return true;
}
@java.lang.Override
public int hashCode() {
if (memoizedHashCode != 0) {
return memoizedHashCode;
}
int hash = 41;
hash = (19 * hash) + getDescriptor().hashCode();
hash = (37 * hash) + LIGHTBRIGHTNESS_FIELD_NUMBER;
hash = (53 * hash) + getLightBrightness();
hash = (37 * hash) + ROBOT_SPEED_FIELD_NUMBER;
hash = (53 * hash) + getRobotSpeed();
hash = (29 * hash) + getUnknownFields().hashCode();
memoizedHashCode = hash;
return hash;
}
public static com.example.removemarineanimals.models.RobotRMACM.RMACM parseFrom(
java.nio.ByteBuffer data)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data);
}
public static com.example.removemarineanimals.models.RobotRMACM.RMACM parseFrom(
java.nio.ByteBuffer data,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data, extensionRegistry);
}
public static com.example.removemarineanimals.models.RobotRMACM.RMACM parseFrom(
com.google.protobuf.ByteString data)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data);
}
public static com.example.removemarineanimals.models.RobotRMACM.RMACM parseFrom(
com.google.protobuf.ByteString data,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data, extensionRegistry);
}
public static com.example.removemarineanimals.models.RobotRMACM.RMACM parseFrom(byte[] data)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data);
}
public static com.example.removemarineanimals.models.RobotRMACM.RMACM parseFrom(
byte[] data,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data, extensionRegistry);
}
public static com.example.removemarineanimals.models.RobotRMACM.RMACM parseFrom(java.io.InputStream input)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessage
.parseWithIOException(PARSER, input);
}
public static com.example.removemarineanimals.models.RobotRMACM.RMACM parseFrom(
java.io.InputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessage
.parseWithIOException(PARSER, input, extensionRegistry);
}
public static com.example.removemarineanimals.models.RobotRMACM.RMACM parseDelimitedFrom(java.io.InputStream input)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessage
.parseDelimitedWithIOException(PARSER, input);
}
public static com.example.removemarineanimals.models.RobotRMACM.RMACM parseDelimitedFrom(
java.io.InputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessage
.parseDelimitedWithIOException(PARSER, input, extensionRegistry);
}
public static com.example.removemarineanimals.models.RobotRMACM.RMACM parseFrom(
com.google.protobuf.CodedInputStream input)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessage
.parseWithIOException(PARSER, input);
}
public static com.example.removemarineanimals.models.RobotRMACM.RMACM parseFrom(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessage
.parseWithIOException(PARSER, input, extensionRegistry);
}
@java.lang.Override
public Builder newBuilderForType() { return newBuilder(); }
public static Builder newBuilder() {
return DEFAULT_INSTANCE.toBuilder();
}
public static Builder newBuilder(com.example.removemarineanimals.models.RobotRMACM.RMACM prototype) {
return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
}
@java.lang.Override
public Builder toBuilder() {
return this == DEFAULT_INSTANCE
? new Builder() : new Builder().mergeFrom(this);
}
@java.lang.Override
protected Builder newBuilderForType(
com.google.protobuf.GeneratedMessage.BuilderParent parent) {
Builder builder = new Builder(parent);
return builder;
}
/**
* <pre>
* Remove Marine Animal Command
* </pre>
*
* Protobuf type {@code RMACM}
*/
public static final class Builder extends
com.google.protobuf.GeneratedMessage.Builder<Builder> implements
// @@protoc_insertion_point(builder_implements:RMACM)
com.example.removemarineanimals.models.RobotRMACM.RMACMOrBuilder {
public static final com.google.protobuf.Descriptors.Descriptor
getDescriptor() {
return com.example.removemarineanimals.models.RobotRMACM.internal_static_RMACM_descriptor;
}
@java.lang.Override
protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
internalGetFieldAccessorTable() {
return com.example.removemarineanimals.models.RobotRMACM.internal_static_RMACM_fieldAccessorTable
.ensureFieldAccessorsInitialized(
com.example.removemarineanimals.models.RobotRMACM.RMACM.class, com.example.removemarineanimals.models.RobotRMACM.RMACM.Builder.class);
}
// Construct using com.example.removemarineanimals.models.RobotRMACM.RMACM.newBuilder()
private Builder() {
}
private Builder(
com.google.protobuf.GeneratedMessage.BuilderParent parent) {
super(parent);
}
@java.lang.Override
public Builder clear() {
super.clear();
bitField0_ = 0;
lightBrightness_ = 0;
robotSpeed_ = 0;
return this;
}
@java.lang.Override
public com.google.protobuf.Descriptors.Descriptor
getDescriptorForType() {
return com.example.removemarineanimals.models.RobotRMACM.internal_static_RMACM_descriptor;
}
@java.lang.Override
public com.example.removemarineanimals.models.RobotRMACM.RMACM getDefaultInstanceForType() {
return com.example.removemarineanimals.models.RobotRMACM.RMACM.getDefaultInstance();
}
@java.lang.Override
public com.example.removemarineanimals.models.RobotRMACM.RMACM build() {
com.example.removemarineanimals.models.RobotRMACM.RMACM result = buildPartial();
if (!result.isInitialized()) {
throw newUninitializedMessageException(result);
}
return result;
}
@java.lang.Override
public com.example.removemarineanimals.models.RobotRMACM.RMACM buildPartial() {
com.example.removemarineanimals.models.RobotRMACM.RMACM result = new com.example.removemarineanimals.models.RobotRMACM.RMACM(this);
if (bitField0_ != 0) { buildPartial0(result); }
onBuilt();
return result;
}
private void buildPartial0(com.example.removemarineanimals.models.RobotRMACM.RMACM result) {
int from_bitField0_ = bitField0_;
if (((from_bitField0_ & 0x00000001) != 0)) {
result.lightBrightness_ = lightBrightness_;
}
if (((from_bitField0_ & 0x00000002) != 0)) {
result.robotSpeed_ = robotSpeed_;
}
}
@java.lang.Override
public Builder mergeFrom(com.google.protobuf.Message other) {
if (other instanceof com.example.removemarineanimals.models.RobotRMACM.RMACM) {
return mergeFrom((com.example.removemarineanimals.models.RobotRMACM.RMACM)other);
} else {
super.mergeFrom(other);
return this;
}
}
public Builder mergeFrom(com.example.removemarineanimals.models.RobotRMACM.RMACM other) {
if (other == com.example.removemarineanimals.models.RobotRMACM.RMACM.getDefaultInstance()) return this;
if (other.getLightBrightness() != 0) {
setLightBrightness(other.getLightBrightness());
}
if (other.getRobotSpeed() != 0) {
setRobotSpeed(other.getRobotSpeed());
}
this.mergeUnknownFields(other.getUnknownFields());
onChanged();
return this;
}
@java.lang.Override
public final boolean isInitialized() {
return true;
}
@java.lang.Override
public Builder mergeFrom(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
if (extensionRegistry == null) {
throw new java.lang.NullPointerException();
}
try {
boolean done = false;
while (!done) {
int tag = input.readTag();
switch (tag) {
case 0:
done = true;
break;
case 8: {
lightBrightness_ = input.readInt32();
bitField0_ |= 0x00000001;
break;
} // case 8
case 16: {
robotSpeed_ = input.readInt32();
bitField0_ |= 0x00000002;
break;
} // case 16
default: {
if (!super.parseUnknownField(input, extensionRegistry, tag)) {
done = true; // was an endgroup tag
}
break;
} // default:
} // switch (tag)
} // while (!done)
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
throw e.unwrapIOException();
} finally {
onChanged();
} // finally
return this;
}
private int bitField0_;
private int lightBrightness_ ;
/**
* <pre>
* 灯光亮度
* </pre>
*
* <code>int32 LightBrightness = 1;</code>
* @return The lightBrightness.
*/
@java.lang.Override
public int getLightBrightness() {
return lightBrightness_;
}
/**
* <pre>
* 灯光亮度
* </pre>
*
* <code>int32 LightBrightness = 1;</code>
* @param value The lightBrightness to set.
* @return This builder for chaining.
*/
public Builder setLightBrightness(int value) {
lightBrightness_ = value;
bitField0_ |= 0x00000001;
onChanged();
return this;
}
/**
* <pre>
* 灯光亮度
* </pre>
*
* <code>int32 LightBrightness = 1;</code>
* @return This builder for chaining.
*/
public Builder clearLightBrightness() {
bitField0_ = (bitField0_ & ~0x00000001);
lightBrightness_ = 0;
onChanged();
return this;
}
private int robotSpeed_ ;
/**
* <pre>
* 机器人速度
* </pre>
*
* <code>int32 Robot_Speed = 2;</code>
* @return The robotSpeed.
*/
@java.lang.Override
public int getRobotSpeed() {
return robotSpeed_;
}
/**
* <pre>
* 机器人速度
* </pre>
*
* <code>int32 Robot_Speed = 2;</code>
* @param value The robotSpeed to set.
* @return This builder for chaining.
*/
public Builder setRobotSpeed(int value) {
robotSpeed_ = value;
bitField0_ |= 0x00000002;
onChanged();
return this;
}
/**
* <pre>
* 机器人速度
* </pre>
*
* <code>int32 Robot_Speed = 2;</code>
* @return This builder for chaining.
*/
public Builder clearRobotSpeed() {
bitField0_ = (bitField0_ & ~0x00000002);
robotSpeed_ = 0;
onChanged();
return this;
}
// @@protoc_insertion_point(builder_scope:RMACM)
}
// @@protoc_insertion_point(class_scope:RMACM)
private static final com.example.removemarineanimals.models.RobotRMACM.RMACM DEFAULT_INSTANCE;
static {
DEFAULT_INSTANCE = new com.example.removemarineanimals.models.RobotRMACM.RMACM();
}
public static com.example.removemarineanimals.models.RobotRMACM.RMACM getDefaultInstance() {
return DEFAULT_INSTANCE;
}
private static final com.google.protobuf.Parser<RMACM>
PARSER = new com.google.protobuf.AbstractParser<RMACM>() {
@java.lang.Override
public RMACM parsePartialFrom(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
Builder builder = newBuilder();
try {
builder.mergeFrom(input, extensionRegistry);
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
throw e.setUnfinishedMessage(builder.buildPartial());
} catch (com.google.protobuf.UninitializedMessageException e) {
throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial());
} catch (java.io.IOException e) {
throw new com.google.protobuf.InvalidProtocolBufferException(e)
.setUnfinishedMessage(builder.buildPartial());
}
return builder.buildPartial();
}
};
public static com.google.protobuf.Parser<RMACM> parser() {
return PARSER;
}
@java.lang.Override
public com.google.protobuf.Parser<RMACM> getParserForType() {
return PARSER;
}
@java.lang.Override
public com.example.removemarineanimals.models.RobotRMACM.RMACM getDefaultInstanceForType() {
return DEFAULT_INSTANCE;
}
}
private static final com.google.protobuf.Descriptors.Descriptor
internal_static_RMACM_descriptor;
private static final
com.google.protobuf.GeneratedMessage.FieldAccessorTable
internal_static_RMACM_fieldAccessorTable;
public static com.google.protobuf.Descriptors.FileDescriptor
getDescriptor() {
return descriptor;
}
private static com.google.protobuf.Descriptors.FileDescriptor
descriptor;
static {
java.lang.String[] descriptorData = {
"\n\021robot_RMACM.proto\"5\n\005RMACM\022\027\n\017LightBri" +
"ghtness\030\001 \001(\005\022\023\n\013Robot_Speed\030\002 \001(\005B*\n&co" +
"m.example.removemarineanimals.modelsP\000b\006" +
"proto3"
};
descriptor = com.google.protobuf.Descriptors.FileDescriptor
.internalBuildGeneratedFileFrom(descriptorData,
new com.google.protobuf.Descriptors.FileDescriptor[] {
});
internal_static_RMACM_descriptor =
getDescriptor().getMessageTypes().get(0);
internal_static_RMACM_fieldAccessorTable = new
com.google.protobuf.GeneratedMessage.FieldAccessorTable(
internal_static_RMACM_descriptor,
new java.lang.String[] { "LightBrightness", "RobotSpeed", });
descriptor.resolveAllFeaturesImmutable();
}
// @@protoc_insertion_point(outer_class_scope)
}

1
proto/generate_c.bat

@ -0,0 +1 @@
protoc --nanopb_out=. *.proto

1
proto/generate_c.txt

@ -0,0 +1 @@
protoc --nanopb_out=. *.proto

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save