Compare commits

...

1 Commits

Author SHA1 Message Date
DESKTOP-I2SDHFF\akeguo 357c440e7c 实现有线通讯 4 weeks ago
  1. 1
      .idea/.name
  2. 1
      .idea/gradle.xml
  3. 6
      .idea/vcs.xml
  4. 14
      app/build.gradle
  5. 48
      app/src/main/java/bsp_Error.proto
  6. 37
      app/src/main/java/bsp_IV.proto
  7. 14
      app/src/main/java/bsp_PV.proto
  8. 335
      app/src/main/java/com/example/fivewheel/MainActivity - 副本.txt
  9. 298
      app/src/main/java/com/example/fivewheel/MainActivity.java
  10. 1350
      app/src/main/java/com/example/fivewheel/models/BspError.java
  11. 377
      app/src/main/java/com/example/fivewheel/models/BspIV.java
  12. 343
      app/src/main/java/com/example/fivewheel/models/BspPV.java
  13. 6
      app/src/main/java/com/example/fivewheel/services/CommunicationMethond.java
  14. 154
      app/src/main/java/com/example/fivewheel/services/DataExchangeHelper.java
  15. 66
      app/src/main/java/com/example/fivewheel/services/ErrorDeocdeHelper.java
  16. 517
      app/src/main/java/com/example/fivewheel/services/ModbusRtuSlaveService.java
  17. 200
      app/src/main/java/com/example/fivewheel/services/ReceiivedIVHandler.java
  18. 116
      app/src/main/java/com/example/fivewheel/services/USBSerialPortHelper.java
  19. 223
      app/src/main/java/com/example/fivewheel/services/ttySerialPortHelper.java
  20. 6
      app/src/main/java/generate_java.bat
  21. BIN
      app/src/main/res/drawable/background.png
  22. 24
      app/src/main/res/drawable/blue_rounded_rectangle.xml
  23. BIN
      app/src/main/res/drawable/message_rounded_rectangle.png
  24. 5
      app/src/main/res/layout/activity_main.xml
  25. 2
      app/src/main/res/values/themes.xml
  26. 2
      settings.gradle

1
.idea/.name

@ -0,0 +1 @@
fivewheel

1
.idea/gradle.xml

@ -13,6 +13,7 @@
<option value="$PROJECT_DIR$/app" />
</set>
</option>
<option name="resolveExternalAnnotations" value="false" />
</GradleProjectSettings>
</option>
</component>

6
.idea/vcs.xml

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

14
app/build.gradle

@ -3,11 +3,19 @@ plugins {
}
android {
namespace 'com.example.removemarineanimals'
namespace 'com.example.fivewheel'
compileSdk 34
viewBinding
{
enabled true
}
// //add this feature
dataBinding
{
enabled true
}
defaultConfig {
applicationId "com.example.removemarineanimals"
applicationId "com.example.fivewheel"
minSdk 24
targetSdk 34
versionCode 1

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

@ -1,28 +1,40 @@
syntax = "proto3";
option java_multiple_files = false;
option java_package = "com.example.removemarineanimals.models";
option java_package = "com.example.fivewheel.models";
message ErrorData
{
int32 Com_Error_Code=1;
int32 Left_Motor_Error_Code=2;
int32 Right_Motor_Error_Code=3;
}
message ErrorDataInfo
{
int32 Error_Value = 1;
bytes Error_Name=4;
}
enum ComError // Error Bit Define
message ErrorData
{
MK32_SBus = 0;
TL720D = 1;
Force_sensor = 2;
ZQ_LeftMotor = 3;
ZQ_RightMotor = 4;
DMAKE_1 = 5;
// DMAKE_2 = 6;
// DMAKE_3 = 7;
MK32_Serial = 6;
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

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

@ -1,23 +1,28 @@
syntax = "proto3";
option java_multiple_files = false;
option java_package = "com.example.removemarineanimals.models";
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;
//
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;
};

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

@ -1,12 +1,14 @@
syntax = "proto3";
option java_multiple_files = false;
option java_package = "com.example.removemarineanimals.models";
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;
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信号
};

335
app/src/main/java/com/example/fivewheel/MainActivity - 副本.txt

@ -1,335 +0,0 @@
package com.example.removemarineanimals;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
import androidx.databinding.DataBindingUtil;
import androidx.lifecycle.ViewModelProvider;
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.Bundle;
import com.example.removemarineanimals.databinding.ActivityMainBinding;
import com.example.removemarineanimals.services.CustomProber;
//import com.example.removemarineanimals.services.USBSerialPortHelper;
import com.example.removemarineanimals.services.VideoHelper;
import com.example.removemarineanimals.viewmodels.MainViewModel;
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 android.os.Bundle;
import android.os.CountDownTimer;
import android.os.Handler;
import android.os.Looper;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import cn.nodemedia.NodePlayer;
public class MainActivity extends AppCompatActivity implements SerialInputOutputManager.Listener {
private enum UsbPermission {Unknown, Requested, Granted, Denied}
private static final String INTENT_ACTION_GRANT_USB = BuildConfig.APPLICATION_ID + ".GRANT_USB";
private int deviceId = 60000;
private int deviceId_test = 60000;
private int portNum;
private static final int WRITE_WAIT_MILLIS = 500;
private static final int READ_WAIT_MILLIS = 1000;
private static String PortNameContians = "SILICON";/**/
private int baudRate = 57600;
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 GetControlsReferences() {
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>();
}
public static ActivityMainBinding mainBinding;//通过Binding可以获取界面数据
// public USBSerialPortHelper serialPortHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// setContentView(R.layout.activity_main);
mainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
MainViewModel vm = new ViewModelProvider(this).get(MainViewModel.class);
MainViewModel.mainBinding = mainBinding;
// vm.mainBinding=mainBinding;
mainBinding.setVm(vm);
//nodePlayer0 =new NodePlayer(this);
//nodePlayer1 =new NodePlayer(this);
VideoHelper.nodePlayerView0 = mainBinding.nodePlayerView0;
VideoHelper.nodePlayerView1 = mainBinding.nodePlayerView1;
VideoHelper.nodePlayer0 = new NodePlayer(this);
VideoHelper.nodePlayer1 = new NodePlayer(this);
VideoHelper.StatPlayVideo();
//
// serialPortHelper=new USBSerialPortHelper();
// serialPortHelper.MainActivity=this;
// serialPortHelper.intialize();
GetControlsReferences();
connect();
}
@Override
protected void onStart() {
super.onStart();
ContextCompat.registerReceiver(this, broadcastReceiver, new IntentFilter(INTENT_ACTION_GRANT_USB), ContextCompat.RECEIVER_NOT_EXPORTED);
}
@Override
public void onStop() {
this.unregisterReceiver(broadcastReceiver);
super.onStop();
}
@Override
public void onResume() {
super.onResume();
if (!connected && (usbPermission == UsbPermission.Unknown || usbPermission == UsbPermission.Granted)) {
//mainLooper.post(this::connect);
}
}
@Override
public void onPause() {
if (connected) {
status("串口断开");
// _serialPortSwitch.setChecked(false);
disconnect();
}
super.onPause();
}
@Override
public void onNewData(byte[] data) {
mainLooper.post(() ->
{
receive(data);
// receive data
});
}
@Override
public void onRunError(Exception e) {
mainLooper.post(() ->
{
status("connection lost: " + e.getMessage());
disconnect();
});
}
private void connect() {
UsbDevice device = null;
UsbManager usbManager = (UsbManager) this.getSystemService(Context.USB_SERVICE);
for (UsbDevice v : usbManager.getDeviceList().values()) {
status(v.getManufacturerName().toUpperCase());
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(this.getPackageName());
PendingIntent usbPermissionIntent = PendingIntent.getBroadcast(this, 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);
} catch (UnsupportedOperationException e) {
status("unsupport setparameters");
}
if (withIoManager) {
usbIoManager = new SerialInputOutputManager(usbSerialPort, this);
usbIoManager.setReadBufferSize(40960);
usbIoManager.setReadTimeout(READ_WAIT_MILLIS);
usbIoManager.start();
}
//status("connected");
connected = true;
// _serialPortSwitch.setChecked(true);
//switch set 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 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;
}
public int Counter = 1000;
boolean StartCountDown = false;
private void receive(byte[] data) {
for (int i = 0; i < data.length; i++) {
_receiveBufferlist.add(data[i]);
}
//decodeRceive(data);
if (StartCountDown == false) {
StartCountDown = true;
new CountDownTimer(500, 500) {
public void onTick(long millisUntilFinished) {
// Used for formatting digit to be in 2 digits only
}
// When the task is over it will print 00:00:00 there
public void onFinish() {
decodeRceive(listTobyte(_receiveBufferlist));
_receiveBufferlist.clear();
StartCountDown = false;
}
}.start();
}
}
private void decodeRceive(byte[] data) {
try {
} catch (
Exception e) {
//spn.append("exception:{e} ");
}
}
void status(String str)
{
mainBinding.message.setText(str);
// SpannableStringBuilder spn = new SpannableStringBuilder(str + '\r' + '\n');
//
// // spn.append(getTime());
//
// spn.setSpan(new ForegroundColorSpan(getResources().getColor(R.color.colorAccent)), 0, spn.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
// receiveText.append(spn);
// scrollView.fullScroll(ScrollView.FOCUS_DOWN);
}
}

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

@ -14,13 +14,18 @@ import androidx.databinding.DataBindingUtil;
import androidx.lifecycle.ViewModelProvider;
import androidx.lifecycle.ViewModelStoreOwner;
import com.example.fivewheel.databinding.ActivityMainBinding;
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.VideoPlayerHelper;
import com.example.fivewheel.services.ttySerialPortHelper;
import com.example.fivewheel.viewmodels.MainViewModel;
import com.example.fivewheel.databinding.ActivityMainBinding;
import java.util.Timer;
import java.util.TimerTask;
@ -28,56 +33,28 @@ import java.util.TimerTask;
import cn.nodemedia.NodePlayer;
public class MainActivity extends AppCompatActivity {
public ActivityMainBinding mainBinding;//通过Binding可以获取界面数据
//USB 串口服务
//public USBSerialPortHelper serialPortHelper;
private BspPV.PV_struct_define _toSendPV;
public static CommunicationMethond AndroidMCUCommunicationMethod = CommunicationMethond.Wired;//0 默认无线, 1 有线
public RobotRMACM.RMACM robotRMACM;
String RobotAutoSpeed;
String RobotManualSpeed;
String RobotChgLength;
private static final String ALLOWED_CHARS = "0123456789.-+";
/**
* 判断字符串是否是数字
*/
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;
}
}
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 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();
@ -97,7 +74,7 @@ public class MainActivity extends AppCompatActivity {
editText.setText("0");
}
}else {
} else {
// 获得焦点时再显示光标
editText.setCursorVisible(true);
}
@ -119,8 +96,14 @@ public class MainActivity extends AppCompatActivity {
// 小数输入框
private void setupDecimalEditText(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 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();
@ -138,7 +121,7 @@ public class MainActivity extends AppCompatActivity {
if (text.isEmpty()) {
editText.setText("0");
}
}else {
} else {
// 获得焦点时再显示光标
editText.setCursorVisible(true);
}
@ -177,27 +160,24 @@ public class MainActivity extends AppCompatActivity {
}
Timer timer = new Timer();
//--
public MainActivity() {
robotRMACM = RobotRMACM.RMACM.newBuilder().setRobotSpeed(0).setLightBrightness(0).build();
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 = DataBindingUtil.setContentView(this, R.layout.activity_main);
MainViewModel vm = new ViewModelProvider((ViewModelStoreOwner) this).get(MainViewModel.class);
MainViewModel.mainBinding = mainBinding;
mainBinding.setVm(vm);
// 整数输入框
setupIntegerEditText(mainBinding.tvRobotChgLength);
@ -206,7 +186,7 @@ public class MainActivity extends AppCompatActivity {
// 小数输入框
// setupDecimalEditText(mainBinding.tvRobotLeftCompensation);
// setupDecimalEditText(mainBinding.tvRobotRightCompensation);
// setupDecimalEditText(mainBinding.tvRobotRightCompensation);
// 保存数据
@ -216,31 +196,22 @@ public class MainActivity extends AppCompatActivity {
String Str_RobotManualSpeed = "8";
String Str_RobotAutoSpeed = "20";
// SharedPreferences sharedPreferences = getSharedPreferences("MyData", Context.MODE_PRIVATE);
//
// Str_RobotChgLength = sharedPreferences.getString("RobotChgLength","");
// Str_RobotLeftCompensation = sharedPreferences.getString("RobotLeftCompensation","");
// Str_RobotRightCompensation = sharedPreferences.getString("RobotRightCompensation","");
// Str_RobotManualSpeed = sharedPreferences.getString("RobotManualSpeed","");
// Str_RobotAutoSpeed = sharedPreferences.getString("RobotAutoSpeed","");
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.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));
/* USB串口 控制区域*/
ttySerialPortHelper.MainActivity = this;
ttySerialPortHelper.Open();
/* NodePlayer 播放视频区域*/
NodePlayer nodePlayer0=new NodePlayer(this);
NodePlayer nodePlayer0 = new NodePlayer(this);
// NodePlayer nodePlayer1=new NodePlayer(this);
//String address0 = "rtsp://192.168.1.168:8554/0";
@ -249,81 +220,99 @@ public class MainActivity extends AppCompatActivity {
//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.nodePlayerView0,nodePlayer0,address0);
// VideoPlayerHelper.startVedio(mainBinding.nodePlayerView1,nodePlayer1,address1);
//VideoPlayerHelper.startVedio(mainBinding.nodePlayerView1,nodePlayer1,addressTest);
timer.schedule(new TimerTask() {
@Override
public void run() {
// byte[] sendbyteArray=new byte[4];
// sendbyteArray[0]=(byte) 0xff;
// sendbyteArray[1]=(byte) 0xff;
// sendbyteArray[2]=(byte) robotRMACM.getLightBrightness();
// sendbyteArray[3]=(byte) robotRMACM.getRobotSpeed();
// mainBinding.tvRobotSpeed22.getText();
//
// ttySerialPortHelper.SendData(sendbyteArray);
_toSendPV = BspPV.PV_struct_define.newBuilder()
.setRobotChgLength(getSafeInt(mainBinding.tvRobotChgLength, 0))
.setRobotAutoSpeedBase(getSafeDouble(mainBinding.tvRobotAutoSpeed, 0.0))
.setRobotManualSpeedBase(getSafeDouble(mainBinding.tvRobotManualSpeed, 0.0))
.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);
}
}, 0, 1000); // 延迟 0 毫秒,每隔 1000 毫秒执行一次
/* USB串口 控制区域*/
serialPortHelper = new USBSerialPortHelper(this, 38400);
serialPortHelper.intialize();
serialPortHelper.connect();
ttySerialPortHelper.MainActivity = this;
ttySerialPortHelper.Open();
ModbusRtuSlaveService.ModbusRtuSlaveServiceIntialize(serialPortHelper);
}
int testCounter=0;
// Create a Timer instance
int UARTSendCount = 0;
public int USBSerialPortReceivedTimeCounter = 0;
@Override
protected void onStart() {
super.onStart();
// serialPortHelper.onStart();
serialPortHelper.onStart();
UARTSendCount = 0;
timer.schedule(new TimerTask() {
@Override
public void run() {
// 使用 Handler 或 runOnUiThread 更新 UI
runOnUiThread(new Runnable() {
@Override
public void run() {
//数据更新
_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_20Hz);
}
}
// ttySerialPortHelper.SendData(DataExchangeHelper.getSendPVBytes(_toSendPV));
}
});
}
}, 0, 250); // 延迟 0 毫秒,每隔 1000 毫秒执行一次
}
@Override
public void onStop()
{
// serialPortHelper.onStop();
//获取SharedPreferences对象
@Override
public void onStop() {
SharedPreferences sharedPreferences = getSharedPreferences("MyData", Context.MODE_PRIVATE);
SharedPreferences.Editor editor =sharedPreferences.edit();
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString("RobotChgLength", String.valueOf(mainBinding.tvRobotChgLength.getText()));
editor.putString("RobotLeftCompensation", String.valueOf(mainBinding.tvRobotLeftCompensation.getText()));
@ -332,26 +321,24 @@ public class MainActivity extends AppCompatActivity {
editor.putString("RobotAutoSpeed", String.valueOf(mainBinding.tvRobotAutoSpeed.getText()));
editor.apply();
// 保存数据
serialPortHelper.onStop();
super.onStop();
}
@Override
public void onResume()
{
public void onResume() {
super.onResume();
// serialPortHelper.onResume();
startSending();
serialPortHelper.onResume();
}
@Override
public void onPause()
{
// serialPortHelper.onPause();
public void onPause() {
serialPortHelper.onPause();
SharedPreferences sharedPreferences = getSharedPreferences("MyData", Context.MODE_PRIVATE);
SharedPreferences.Editor editor =sharedPreferences.edit();
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString("RobotChgLength", String.valueOf(mainBinding.tvRobotChgLength.getText()));
editor.putString("RobotLeftCompensation", String.valueOf(mainBinding.tvRobotLeftCompensation.getText()));
@ -362,6 +349,7 @@ public class MainActivity extends AppCompatActivity {
stopSending();
super.onPause();
}
@Override
protected void onDestroy() {
super.onDestroy();
@ -369,42 +357,9 @@ public class MainActivity extends AppCompatActivity {
timer.cancel();
}
}
private TimerTask sendTask;
private void startSending() {
if (timer == null) {
timer = new Timer();
sendTask = new TimerTask() {
@Override
public void run() {
_toSendPV = BspPV.PV_struct_define.newBuilder()
.setRobotChgLength(Integer.parseInt(mainBinding.tvRobotChgLength.getText().toString()))
.setRobotAutoSpeedBase(Double.parseDouble(mainBinding.tvRobotAutoSpeed.getText().toString()))
.setRobotManualSpeedBase(Double.parseDouble(mainBinding.tvRobotManualSpeed.getText().toString()))
.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);
private TimerTask sendTask;
ttySerialPortHelper.SendData(sendbyteArray3);
}
};
timer.schedule(sendTask, 0, 1000); // 1 秒一次
}
}
private void stopSending() {
if (timer != null) {
timer.cancel();
@ -415,17 +370,6 @@ public class MainActivity extends AppCompatActivity {
sendTask = null;
}
}
/*
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();
}
*/
}

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

File diff suppressed because it is too large

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

@ -32,6 +32,7 @@ public final class BspIV {
/**
* <pre>
* 五轮项目
* 五轮项目
* </pre>
*
* <code>int32 Robot_Move_AutoSpeed = 1;</code>
@ -116,6 +117,36 @@ public final class BspIV {
* @return The robotCompensationRight.
*/
int getRobotCompensationRight();
/**
* <code>int32 Robot_RESET = 15;</code>
* @return The robotRESET.
*/
int getRobotRESET();
/**
* <code>int64 TimeStamp = 16;</code>
* @return The timeStamp.
*/
long getTimeStamp();
/**
* <code>int32 RobotRestart = 17;</code>
* @return The robotRestart.
*/
int getRobotRestart();
/**
* <code>int32 RobotAngle = 18;</code>
* @return The robotAngle.
*/
int getRobotAngle();
/**
* <code>int32 SystemError = 19;</code>
* @return The systemError.
*/
int getSystemError();
}
/**
* Protobuf type {@code IV_struct_define}
@ -159,6 +190,7 @@ public final class BspIV {
/**
* <pre>
* 五轮项目
* 五轮项目
* </pre>
*
* <code>int32 Robot_Move_AutoSpeed = 1;</code>
@ -312,6 +344,61 @@ public final class BspIV {
return robotCompensationRight_;
}
public static final int ROBOT_RESET_FIELD_NUMBER = 15;
private int robotRESET_ = 0;
/**
* <code>int32 Robot_RESET = 15;</code>
* @return The robotRESET.
*/
@java.lang.Override
public int getRobotRESET() {
return robotRESET_;
}
public static final int TIMESTAMP_FIELD_NUMBER = 16;
private long timeStamp_ = 0L;
/**
* <code>int64 TimeStamp = 16;</code>
* @return The timeStamp.
*/
@java.lang.Override
public long getTimeStamp() {
return timeStamp_;
}
public static final int ROBOTRESTART_FIELD_NUMBER = 17;
private int robotRestart_ = 0;
/**
* <code>int32 RobotRestart = 17;</code>
* @return The robotRestart.
*/
@java.lang.Override
public int getRobotRestart() {
return robotRestart_;
}
public static final int ROBOTANGLE_FIELD_NUMBER = 18;
private int robotAngle_ = 0;
/**
* <code>int32 RobotAngle = 18;</code>
* @return The robotAngle.
*/
@java.lang.Override
public int getRobotAngle() {
return robotAngle_;
}
public static final int SYSTEMERROR_FIELD_NUMBER = 19;
private int systemError_ = 0;
/**
* <code>int32 SystemError = 19;</code>
* @return The systemError.
*/
@java.lang.Override
public int getSystemError() {
return systemError_;
}
private byte memoizedIsInitialized = -1;
@java.lang.Override
public final boolean isInitialized() {
@ -368,6 +455,21 @@ public final class BspIV {
if (robotCompensationRight_ != 0) {
output.writeInt32(14, robotCompensationRight_);
}
if (robotRESET_ != 0) {
output.writeInt32(15, robotRESET_);
}
if (timeStamp_ != 0L) {
output.writeInt64(16, timeStamp_);
}
if (robotRestart_ != 0) {
output.writeInt32(17, robotRestart_);
}
if (robotAngle_ != 0) {
output.writeInt32(18, robotAngle_);
}
if (systemError_ != 0) {
output.writeInt32(19, systemError_);
}
getUnknownFields().writeTo(output);
}
@ -433,6 +535,26 @@ public final class BspIV {
size += com.google.protobuf.CodedOutputStream
.computeInt32Size(14, robotCompensationRight_);
}
if (robotRESET_ != 0) {
size += com.google.protobuf.CodedOutputStream
.computeInt32Size(15, robotRESET_);
}
if (timeStamp_ != 0L) {
size += com.google.protobuf.CodedOutputStream
.computeInt64Size(16, timeStamp_);
}
if (robotRestart_ != 0) {
size += com.google.protobuf.CodedOutputStream
.computeInt32Size(17, robotRestart_);
}
if (robotAngle_ != 0) {
size += com.google.protobuf.CodedOutputStream
.computeInt32Size(18, robotAngle_);
}
if (systemError_ != 0) {
size += com.google.protobuf.CodedOutputStream
.computeInt32Size(19, systemError_);
}
size += getUnknownFields().getSerializedSize();
memoizedSize = size;
return size;
@ -476,6 +598,16 @@ public final class BspIV {
!= other.getRobotCompensationLeft()) return false;
if (getRobotCompensationRight()
!= other.getRobotCompensationRight()) return false;
if (getRobotRESET()
!= other.getRobotRESET()) return false;
if (getTimeStamp()
!= other.getTimeStamp()) return false;
if (getRobotRestart()
!= other.getRobotRestart()) return false;
if (getRobotAngle()
!= other.getRobotAngle()) return false;
if (getSystemError()
!= other.getSystemError()) return false;
if (!getUnknownFields().equals(other.getUnknownFields())) return false;
return true;
}
@ -515,6 +647,17 @@ public final class BspIV {
hash = (53 * hash) + getRobotCompensationLeft();
hash = (37 * hash) + ROBOT_COMPENSATION_RIGHT_FIELD_NUMBER;
hash = (53 * hash) + getRobotCompensationRight();
hash = (37 * hash) + ROBOT_RESET_FIELD_NUMBER;
hash = (53 * hash) + getRobotRESET();
hash = (37 * hash) + TIMESTAMP_FIELD_NUMBER;
hash = (53 * hash) + com.google.protobuf.Internal.hashLong(
getTimeStamp());
hash = (37 * hash) + ROBOTRESTART_FIELD_NUMBER;
hash = (53 * hash) + getRobotRestart();
hash = (37 * hash) + ROBOTANGLE_FIELD_NUMBER;
hash = (53 * hash) + getRobotAngle();
hash = (37 * hash) + SYSTEMERROR_FIELD_NUMBER;
hash = (53 * hash) + getSystemError();
hash = (29 * hash) + getUnknownFields().hashCode();
memoizedHashCode = hash;
return hash;
@ -660,6 +803,11 @@ public final class BspIV {
robotErrorRight_ = 0;
robotCompensationLeft_ = 0;
robotCompensationRight_ = 0;
robotRESET_ = 0;
timeStamp_ = 0L;
robotRestart_ = 0;
robotAngle_ = 0;
systemError_ = 0;
return this;
}
@ -735,6 +883,21 @@ public final class BspIV {
if (((from_bitField0_ & 0x00002000) != 0)) {
result.robotCompensationRight_ = robotCompensationRight_;
}
if (((from_bitField0_ & 0x00004000) != 0)) {
result.robotRESET_ = robotRESET_;
}
if (((from_bitField0_ & 0x00008000) != 0)) {
result.timeStamp_ = timeStamp_;
}
if (((from_bitField0_ & 0x00010000) != 0)) {
result.robotRestart_ = robotRestart_;
}
if (((from_bitField0_ & 0x00020000) != 0)) {
result.robotAngle_ = robotAngle_;
}
if (((from_bitField0_ & 0x00040000) != 0)) {
result.systemError_ = systemError_;
}
}
@java.lang.Override
@ -791,6 +954,21 @@ public final class BspIV {
if (other.getRobotCompensationRight() != 0) {
setRobotCompensationRight(other.getRobotCompensationRight());
}
if (other.getRobotRESET() != 0) {
setRobotRESET(other.getRobotRESET());
}
if (other.getTimeStamp() != 0L) {
setTimeStamp(other.getTimeStamp());
}
if (other.getRobotRestart() != 0) {
setRobotRestart(other.getRobotRestart());
}
if (other.getRobotAngle() != 0) {
setRobotAngle(other.getRobotAngle());
}
if (other.getSystemError() != 0) {
setSystemError(other.getSystemError());
}
this.mergeUnknownFields(other.getUnknownFields());
onChanged();
return this;
@ -887,6 +1065,31 @@ public final class BspIV {
bitField0_ |= 0x00002000;
break;
} // case 112
case 120: {
robotRESET_ = input.readInt32();
bitField0_ |= 0x00004000;
break;
} // case 120
case 128: {
timeStamp_ = input.readInt64();
bitField0_ |= 0x00008000;
break;
} // case 128
case 136: {
robotRestart_ = input.readInt32();
bitField0_ |= 0x00010000;
break;
} // case 136
case 144: {
robotAngle_ = input.readInt32();
bitField0_ |= 0x00020000;
break;
} // case 144
case 152: {
systemError_ = input.readInt32();
bitField0_ |= 0x00040000;
break;
} // case 152
default: {
if (!super.parseUnknownField(input, extensionRegistry, tag)) {
done = true; // was an endgroup tag
@ -908,6 +1111,7 @@ public final class BspIV {
/**
* <pre>
* 五轮项目
* 五轮项目
* </pre>
*
* <code>int32 Robot_Move_AutoSpeed = 1;</code>
@ -920,6 +1124,7 @@ public final class BspIV {
/**
* <pre>
* 五轮项目
* 五轮项目
* </pre>
*
* <code>int32 Robot_Move_AutoSpeed = 1;</code>
@ -936,6 +1141,7 @@ public final class BspIV {
/**
* <pre>
* 五轮项目
* 五轮项目
* </pre>
*
* <code>int32 Robot_Move_AutoSpeed = 1;</code>
@ -1364,6 +1570,166 @@ public final class BspIV {
return this;
}
private int robotRESET_ ;
/**
* <code>int32 Robot_RESET = 15;</code>
* @return The robotRESET.
*/
@java.lang.Override
public int getRobotRESET() {
return robotRESET_;
}
/**
* <code>int32 Robot_RESET = 15;</code>
* @param value The robotRESET to set.
* @return This builder for chaining.
*/
public Builder setRobotRESET(int value) {
robotRESET_ = value;
bitField0_ |= 0x00004000;
onChanged();
return this;
}
/**
* <code>int32 Robot_RESET = 15;</code>
* @return This builder for chaining.
*/
public Builder clearRobotRESET() {
bitField0_ = (bitField0_ & ~0x00004000);
robotRESET_ = 0;
onChanged();
return this;
}
private long timeStamp_ ;
/**
* <code>int64 TimeStamp = 16;</code>
* @return The timeStamp.
*/
@java.lang.Override
public long getTimeStamp() {
return timeStamp_;
}
/**
* <code>int64 TimeStamp = 16;</code>
* @param value The timeStamp to set.
* @return This builder for chaining.
*/
public Builder setTimeStamp(long value) {
timeStamp_ = value;
bitField0_ |= 0x00008000;
onChanged();
return this;
}
/**
* <code>int64 TimeStamp = 16;</code>
* @return This builder for chaining.
*/
public Builder clearTimeStamp() {
bitField0_ = (bitField0_ & ~0x00008000);
timeStamp_ = 0L;
onChanged();
return this;
}
private int robotRestart_ ;
/**
* <code>int32 RobotRestart = 17;</code>
* @return The robotRestart.
*/
@java.lang.Override
public int getRobotRestart() {
return robotRestart_;
}
/**
* <code>int32 RobotRestart = 17;</code>
* @param value The robotRestart to set.
* @return This builder for chaining.
*/
public Builder setRobotRestart(int value) {
robotRestart_ = value;
bitField0_ |= 0x00010000;
onChanged();
return this;
}
/**
* <code>int32 RobotRestart = 17;</code>
* @return This builder for chaining.
*/
public Builder clearRobotRestart() {
bitField0_ = (bitField0_ & ~0x00010000);
robotRestart_ = 0;
onChanged();
return this;
}
private int robotAngle_ ;
/**
* <code>int32 RobotAngle = 18;</code>
* @return The robotAngle.
*/
@java.lang.Override
public int getRobotAngle() {
return robotAngle_;
}
/**
* <code>int32 RobotAngle = 18;</code>
* @param value The robotAngle to set.
* @return This builder for chaining.
*/
public Builder setRobotAngle(int value) {
robotAngle_ = value;
bitField0_ |= 0x00020000;
onChanged();
return this;
}
/**
* <code>int32 RobotAngle = 18;</code>
* @return This builder for chaining.
*/
public Builder clearRobotAngle() {
bitField0_ = (bitField0_ & ~0x00020000);
robotAngle_ = 0;
onChanged();
return this;
}
private int systemError_ ;
/**
* <code>int32 SystemError = 19;</code>
* @return The systemError.
*/
@java.lang.Override
public int getSystemError() {
return systemError_;
}
/**
* <code>int32 SystemError = 19;</code>
* @param value The systemError to set.
* @return This builder for chaining.
*/
public Builder setSystemError(int value) {
systemError_ = value;
bitField0_ |= 0x00040000;
onChanged();
return this;
}
/**
* <code>int32 SystemError = 19;</code>
* @return This builder for chaining.
*/
public Builder clearSystemError() {
bitField0_ = (bitField0_ & ~0x00040000);
systemError_ = 0;
onChanged();
return this;
}
// @@protoc_insertion_point(builder_scope:IV_struct_define)
}
@ -1429,7 +1795,7 @@ public final class BspIV {
descriptor;
static {
java.lang.String[] descriptorData = {
"\n\014bsp_IV.proto\"\244\003\n\020IV_struct_define\022\034\n\024R" +
"\n\014bsp_IV.proto\"\213\004\n\020IV_struct_define\022\034\n\024R" +
"obot_Move_AutoSpeed\030\001 \001(\005\022\036\n\026Robot_Move_" +
"ManualSpeed\030\002 \001(\005\022\035\n\025Robot_CurrentPositi" +
"on\030\003 \001(\005\022\027\n\017Robot_AngleRoll\030\004 \001(\005\022\023\n\013Rob" +
@ -1439,8 +1805,11 @@ public final class BspIV {
"ft\030\t \001(\005\022\033\n\023Robot_Current_Right\030\n \001(\005\022\030\n" +
"\020Robot_Error_Left\030\013 \001(\005\022\031\n\021Robot_Error_R" +
"ight\030\014 \001(\005\022\037\n\027Robot_Compensation_Left\030\r " +
"\001(\005\022 \n\030Robot_Compensation_Right\030\016 \001(\005B \n" +
"\034com.example.fivewheel.modelsP\000b\006proto3"
"\001(\005\022 \n\030Robot_Compensation_Right\030\016 \001(\005\022\023\n" +
"\013Robot_RESET\030\017 \001(\005\022\021\n\tTimeStamp\030\020 \001(\003\022\024\n" +
"\014RobotRestart\030\021 \001(\005\022\022\n\nRobotAngle\030\022 \001(\005\022" +
"\023\n\013SystemError\030\023 \001(\005B \n\034com.example.five" +
"wheel.modelsP\000b\006proto3"
};
descriptor = com.google.protobuf.Descriptors.FileDescriptor
.internalBuildGeneratedFileFrom(descriptorData,
@ -1451,7 +1820,7 @@ public final class BspIV {
internal_static_IV_struct_define_fieldAccessorTable = new
com.google.protobuf.GeneratedMessage.FieldAccessorTable(
internal_static_IV_struct_define_descriptor,
new java.lang.String[] { "RobotMoveAutoSpeed", "RobotMoveManualSpeed", "RobotCurrentPosition", "RobotAngleRoll", "RobotError", "RobotDynamometerValue", "RobotForceValue", "RobotCurrentState", "RobotCurrentLeft", "RobotCurrentRight", "RobotErrorLeft", "RobotErrorRight", "RobotCompensationLeft", "RobotCompensationRight", });
new java.lang.String[] { "RobotMoveAutoSpeed", "RobotMoveManualSpeed", "RobotCurrentPosition", "RobotAngleRoll", "RobotError", "RobotDynamometerValue", "RobotForceValue", "RobotCurrentState", "RobotCurrentLeft", "RobotCurrentRight", "RobotErrorLeft", "RobotErrorRight", "RobotCompensationLeft", "RobotCompensationRight", "RobotRESET", "TimeStamp", "RobotRestart", "RobotAngle", "SystemError", });
descriptor.resolveAllFeaturesImmutable();
}

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

@ -46,6 +46,38 @@ public final class BspPV {
* @return The robotManualSpeedBase.
*/
double getRobotManualSpeedBase();
/**
* <code>int32 Robot_LaneChange_Direction = 4;</code>
* @return The robotLaneChangeDirection.
*/
int getRobotLaneChangeDirection();
/**
* <code>int32 Robot_Force = 5;</code>
* @return The robotForce.
*/
int getRobotForce();
/**
* <pre>
* 上位机发送下来的时间戳
* </pre>
*
* <code>int64 TimeStamp = 6;</code>
* @return The timeStamp.
*/
long getTimeStamp();
/**
* <pre>
* 上位机接收到单片机发送的Restart信号
* </pre>
*
* <code>int32 RobotRestartAccepted = 7;</code>
* @return The robotRestartAccepted.
*/
int getRobotRestartAccepted();
}
/**
* Protobuf type {@code PV_struct_define}
@ -117,6 +149,58 @@ public final class BspPV {
return robotManualSpeedBase_;
}
public static final int ROBOT_LANECHANGE_DIRECTION_FIELD_NUMBER = 4;
private int robotLaneChangeDirection_ = 0;
/**
* <code>int32 Robot_LaneChange_Direction = 4;</code>
* @return The robotLaneChangeDirection.
*/
@java.lang.Override
public int getRobotLaneChangeDirection() {
return robotLaneChangeDirection_;
}
public static final int ROBOT_FORCE_FIELD_NUMBER = 5;
private int robotForce_ = 0;
/**
* <code>int32 Robot_Force = 5;</code>
* @return The robotForce.
*/
@java.lang.Override
public int getRobotForce() {
return robotForce_;
}
public static final int TIMESTAMP_FIELD_NUMBER = 6;
private long timeStamp_ = 0L;
/**
* <pre>
* 上位机发送下来的时间戳
* </pre>
*
* <code>int64 TimeStamp = 6;</code>
* @return The timeStamp.
*/
@java.lang.Override
public long getTimeStamp() {
return timeStamp_;
}
public static final int ROBOTRESTARTACCEPTED_FIELD_NUMBER = 7;
private int robotRestartAccepted_ = 0;
/**
* <pre>
* 上位机接收到单片机发送的Restart信号
* </pre>
*
* <code>int32 RobotRestartAccepted = 7;</code>
* @return The robotRestartAccepted.
*/
@java.lang.Override
public int getRobotRestartAccepted() {
return robotRestartAccepted_;
}
private byte memoizedIsInitialized = -1;
@java.lang.Override
public final boolean isInitialized() {
@ -140,6 +224,18 @@ public final class BspPV {
if (java.lang.Double.doubleToRawLongBits(robotManualSpeedBase_) != 0) {
output.writeDouble(3, robotManualSpeedBase_);
}
if (robotLaneChangeDirection_ != 0) {
output.writeInt32(4, robotLaneChangeDirection_);
}
if (robotForce_ != 0) {
output.writeInt32(5, robotForce_);
}
if (timeStamp_ != 0L) {
output.writeInt64(6, timeStamp_);
}
if (robotRestartAccepted_ != 0) {
output.writeInt32(7, robotRestartAccepted_);
}
getUnknownFields().writeTo(output);
}
@ -161,6 +257,22 @@ public final class BspPV {
size += com.google.protobuf.CodedOutputStream
.computeDoubleSize(3, robotManualSpeedBase_);
}
if (robotLaneChangeDirection_ != 0) {
size += com.google.protobuf.CodedOutputStream
.computeInt32Size(4, robotLaneChangeDirection_);
}
if (robotForce_ != 0) {
size += com.google.protobuf.CodedOutputStream
.computeInt32Size(5, robotForce_);
}
if (timeStamp_ != 0L) {
size += com.google.protobuf.CodedOutputStream
.computeInt64Size(6, timeStamp_);
}
if (robotRestartAccepted_ != 0) {
size += com.google.protobuf.CodedOutputStream
.computeInt32Size(7, robotRestartAccepted_);
}
size += getUnknownFields().getSerializedSize();
memoizedSize = size;
return size;
@ -184,6 +296,14 @@ public final class BspPV {
if (java.lang.Double.doubleToLongBits(getRobotManualSpeedBase())
!= java.lang.Double.doubleToLongBits(
other.getRobotManualSpeedBase())) return false;
if (getRobotLaneChangeDirection()
!= other.getRobotLaneChangeDirection()) return false;
if (getRobotForce()
!= other.getRobotForce()) return false;
if (getTimeStamp()
!= other.getTimeStamp()) return false;
if (getRobotRestartAccepted()
!= other.getRobotRestartAccepted()) return false;
if (!getUnknownFields().equals(other.getUnknownFields())) return false;
return true;
}
@ -203,6 +323,15 @@ public final class BspPV {
hash = (37 * hash) + ROBOT_MANUALSPEEDBASE_FIELD_NUMBER;
hash = (53 * hash) + com.google.protobuf.Internal.hashLong(
java.lang.Double.doubleToLongBits(getRobotManualSpeedBase()));
hash = (37 * hash) + ROBOT_LANECHANGE_DIRECTION_FIELD_NUMBER;
hash = (53 * hash) + getRobotLaneChangeDirection();
hash = (37 * hash) + ROBOT_FORCE_FIELD_NUMBER;
hash = (53 * hash) + getRobotForce();
hash = (37 * hash) + TIMESTAMP_FIELD_NUMBER;
hash = (53 * hash) + com.google.protobuf.Internal.hashLong(
getTimeStamp());
hash = (37 * hash) + ROBOTRESTARTACCEPTED_FIELD_NUMBER;
hash = (53 * hash) + getRobotRestartAccepted();
hash = (29 * hash) + getUnknownFields().hashCode();
memoizedHashCode = hash;
return hash;
@ -337,6 +466,10 @@ public final class BspPV {
robotChgLength_ = 0;
robotAutoSpeedBase_ = 0D;
robotManualSpeedBase_ = 0D;
robotLaneChangeDirection_ = 0;
robotForce_ = 0;
timeStamp_ = 0L;
robotRestartAccepted_ = 0;
return this;
}
@ -379,6 +512,18 @@ public final class BspPV {
if (((from_bitField0_ & 0x00000004) != 0)) {
result.robotManualSpeedBase_ = robotManualSpeedBase_;
}
if (((from_bitField0_ & 0x00000008) != 0)) {
result.robotLaneChangeDirection_ = robotLaneChangeDirection_;
}
if (((from_bitField0_ & 0x00000010) != 0)) {
result.robotForce_ = robotForce_;
}
if (((from_bitField0_ & 0x00000020) != 0)) {
result.timeStamp_ = timeStamp_;
}
if (((from_bitField0_ & 0x00000040) != 0)) {
result.robotRestartAccepted_ = robotRestartAccepted_;
}
}
@java.lang.Override
@ -402,6 +547,18 @@ public final class BspPV {
if (other.getRobotManualSpeedBase() != 0D) {
setRobotManualSpeedBase(other.getRobotManualSpeedBase());
}
if (other.getRobotLaneChangeDirection() != 0) {
setRobotLaneChangeDirection(other.getRobotLaneChangeDirection());
}
if (other.getRobotForce() != 0) {
setRobotForce(other.getRobotForce());
}
if (other.getTimeStamp() != 0L) {
setTimeStamp(other.getTimeStamp());
}
if (other.getRobotRestartAccepted() != 0) {
setRobotRestartAccepted(other.getRobotRestartAccepted());
}
this.mergeUnknownFields(other.getUnknownFields());
onChanged();
return this;
@ -443,6 +600,26 @@ public final class BspPV {
bitField0_ |= 0x00000004;
break;
} // case 25
case 32: {
robotLaneChangeDirection_ = input.readInt32();
bitField0_ |= 0x00000008;
break;
} // case 32
case 40: {
robotForce_ = input.readInt32();
bitField0_ |= 0x00000010;
break;
} // case 40
case 48: {
timeStamp_ = input.readInt64();
bitField0_ |= 0x00000020;
break;
} // case 48
case 56: {
robotRestartAccepted_ = input.readInt32();
bitField0_ |= 0x00000040;
break;
} // case 56
default: {
if (!super.parseUnknownField(input, extensionRegistry, tag)) {
done = true; // was an endgroup tag
@ -556,6 +733,158 @@ public final class BspPV {
return this;
}
private int robotLaneChangeDirection_ ;
/**
* <code>int32 Robot_LaneChange_Direction = 4;</code>
* @return The robotLaneChangeDirection.
*/
@java.lang.Override
public int getRobotLaneChangeDirection() {
return robotLaneChangeDirection_;
}
/**
* <code>int32 Robot_LaneChange_Direction = 4;</code>
* @param value The robotLaneChangeDirection to set.
* @return This builder for chaining.
*/
public Builder setRobotLaneChangeDirection(int value) {
robotLaneChangeDirection_ = value;
bitField0_ |= 0x00000008;
onChanged();
return this;
}
/**
* <code>int32 Robot_LaneChange_Direction = 4;</code>
* @return This builder for chaining.
*/
public Builder clearRobotLaneChangeDirection() {
bitField0_ = (bitField0_ & ~0x00000008);
robotLaneChangeDirection_ = 0;
onChanged();
return this;
}
private int robotForce_ ;
/**
* <code>int32 Robot_Force = 5;</code>
* @return The robotForce.
*/
@java.lang.Override
public int getRobotForce() {
return robotForce_;
}
/**
* <code>int32 Robot_Force = 5;</code>
* @param value The robotForce to set.
* @return This builder for chaining.
*/
public Builder setRobotForce(int value) {
robotForce_ = value;
bitField0_ |= 0x00000010;
onChanged();
return this;
}
/**
* <code>int32 Robot_Force = 5;</code>
* @return This builder for chaining.
*/
public Builder clearRobotForce() {
bitField0_ = (bitField0_ & ~0x00000010);
robotForce_ = 0;
onChanged();
return this;
}
private long timeStamp_ ;
/**
* <pre>
* 上位机发送下来的时间戳
* </pre>
*
* <code>int64 TimeStamp = 6;</code>
* @return The timeStamp.
*/
@java.lang.Override
public long getTimeStamp() {
return timeStamp_;
}
/**
* <pre>
* 上位机发送下来的时间戳
* </pre>
*
* <code>int64 TimeStamp = 6;</code>
* @param value The timeStamp to set.
* @return This builder for chaining.
*/
public Builder setTimeStamp(long value) {
timeStamp_ = value;
bitField0_ |= 0x00000020;
onChanged();
return this;
}
/**
* <pre>
* 上位机发送下来的时间戳
* </pre>
*
* <code>int64 TimeStamp = 6;</code>
* @return This builder for chaining.
*/
public Builder clearTimeStamp() {
bitField0_ = (bitField0_ & ~0x00000020);
timeStamp_ = 0L;
onChanged();
return this;
}
private int robotRestartAccepted_ ;
/**
* <pre>
* 上位机接收到单片机发送的Restart信号
* </pre>
*
* <code>int32 RobotRestartAccepted = 7;</code>
* @return The robotRestartAccepted.
*/
@java.lang.Override
public int getRobotRestartAccepted() {
return robotRestartAccepted_;
}
/**
* <pre>
* 上位机接收到单片机发送的Restart信号
* </pre>
*
* <code>int32 RobotRestartAccepted = 7;</code>
* @param value The robotRestartAccepted to set.
* @return This builder for chaining.
*/
public Builder setRobotRestartAccepted(int value) {
robotRestartAccepted_ = value;
bitField0_ |= 0x00000040;
onChanged();
return this;
}
/**
* <pre>
* 上位机接收到单片机发送的Restart信号
* </pre>
*
* <code>int32 RobotRestartAccepted = 7;</code>
* @return This builder for chaining.
*/
public Builder clearRobotRestartAccepted() {
bitField0_ = (bitField0_ & ~0x00000040);
robotRestartAccepted_ = 0;
onChanged();
return this;
}
// @@protoc_insertion_point(builder_scope:PV_struct_define)
}
@ -621,11 +950,13 @@ public final class BspPV {
descriptor;
static {
java.lang.String[] descriptorData = {
"\n\014bsp_PV.proto\"g\n\020PV_struct_define\022\027\n\017Ro" +
"bot_ChgLength\030\001 \001(\005\022\033\n\023Robot_AutoSpeedBa" +
"se\030\002 \001(\001\022\035\n\025Robot_ManualSpeedBase\030\003 \001(\001B" +
" \n\034com.example.fivewheel.modelsP\000b\006proto" +
"3"
"\n\014bsp_PV.proto\"\321\001\n\020PV_struct_define\022\027\n\017R" +
"obot_ChgLength\030\001 \001(\005\022\033\n\023Robot_AutoSpeedB" +
"ase\030\002 \001(\001\022\035\n\025Robot_ManualSpeedBase\030\003 \001(\001" +
"\022\"\n\032Robot_LaneChange_Direction\030\004 \001(\005\022\023\n\013" +
"Robot_Force\030\005 \001(\005\022\021\n\tTimeStamp\030\006 \001(\003\022\034\n\024" +
"RobotRestartAccepted\030\007 \001(\005B \n\034com.exampl" +
"e.fivewheel.modelsP\000b\006proto3"
};
descriptor = com.google.protobuf.Descriptors.FileDescriptor
.internalBuildGeneratedFileFrom(descriptorData,
@ -636,7 +967,7 @@ public final class BspPV {
internal_static_PV_struct_define_fieldAccessorTable = new
com.google.protobuf.GeneratedMessage.FieldAccessorTable(
internal_static_PV_struct_define_descriptor,
new java.lang.String[] { "RobotChgLength", "RobotAutoSpeedBase", "RobotManualSpeedBase", });
new java.lang.String[] { "RobotChgLength", "RobotAutoSpeedBase", "RobotManualSpeedBase", "RobotLaneChangeDirection", "RobotForce", "TimeStamp", "RobotRestartAccepted", });
descriptor.resolveAllFeaturesImmutable();
}

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
}

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.BspIV;
import com.example.fivewheel.models.BspPV;
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[18] = (short) byteArray.length;
//将数据转为小端发送
for (int i = 0; i < modifyHoldingRegisterNum; i++) {
ModbusRtuSlaveService.holdingRegisters[19 + 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;
}
}
}

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;
}
}

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());
}
});
}
}

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

@ -1,5 +1,6 @@
package com.example.fivewheel.services;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
@ -15,10 +16,9 @@ import android.os.Looper;
import androidx.core.content.ContextCompat;
import com.example.fivewheel.BuildConfig;
import com.example.fivewheel.MainActivity;
import com.example.fivewheel.models.RobotData;
import com.example.fivewheel.viewmodels.MainViewModel;
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;
@ -28,23 +28,15 @@ 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 MainActivity MainActivity;
//sserial port part start
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";
// <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 -->
private int deviceId = 60000;
private int deviceId_test = 60000;
private int portNum;
@ -52,7 +44,8 @@ public class USBSerialPortHelper implements SerialInputOutputManager.Listener {
private final int READ_WAIT_MILLIS = 100;
private String PortNameContians = "SILICON";/**/
// private static String PortNameContians="FTD";
private int baudRate = 57600;
//private int baudRate = 115200;
private int baudRate = 38400;
private boolean withIoManager = true;
private BroadcastReceiver broadcastReceiver;
@ -77,10 +70,6 @@ public class USBSerialPortHelper implements SerialInputOutputManager.Listener {
mainLooper = new Handler(Looper.getMainLooper());
_receiveBufferlist = new ArrayList<Byte>();
}
/*
* Serial
*/
@Override
public void onNewData(byte[] data) {
status("new data");
@ -97,21 +86,21 @@ public class USBSerialPortHelper implements SerialInputOutputManager.Listener {
disconnect();
});
}
/*
* Serial + UI
*/
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.getManufacturerName().toUpperCase().contains(PortNameContians)) {
// status(v.getManufacturerName().toUpperCase());
if (v.getVendorId() == 6790) {
device = v;
break;
}
// if (v.getManufacturerName().toUpperCase().contains(PortNameContians)) {
// device = v;
// break;
// }
}
if (device == null) {
@ -153,7 +142,6 @@ public class USBSerialPortHelper implements SerialInputOutputManager.Listener {
} else {
status("connection failed: open failed");
}
return;
}
@ -172,11 +160,7 @@ public class USBSerialPortHelper implements SerialInputOutputManager.Listener {
usbIoManager.setReadTimeout(READ_WAIT_MILLIS);
usbIoManager.start();
}
//status("connected");
connected = true;
// _serialPortSwitch.setChecked(true);
//switch set true
} catch (Exception e) {
status("connection failed: " + e.getMessage());
disconnect();
@ -212,13 +196,10 @@ public class USBSerialPortHelper implements SerialInputOutputManager.Listener {
}
return bytes;
}
boolean StartCountDown = false;
// byte _receivedData
private void receive(byte[] data) {
status("read data");
// status("read data");
for (int i = 0; i < data.length; i++) {
_receiveBufferlist.add(data[i]);
}
@ -227,32 +208,19 @@ public class USBSerialPortHelper implements SerialInputOutputManager.Listener {
if (StartCountDown == false)//从收到第一个数据开始计时
{
StartCountDown = true;
new CountDownTimer(50, 10) {
new CountDownTimer(5, 5) {
public void onTick(long millisUntilFinished) {
}
public void onFinish() {
status("read finished");
try {
decodeRceive(listTobyte(_receiveBufferlist));
}
catch (Exception ignored)
{
status(ignored.getMessage());
}
decodeRceive(listTobyte(_receiveBufferlist));
_receiveBufferlist.clear();
StartCountDown = false;
}
}.start();
}
}
void status(String str) {
@ -265,41 +233,47 @@ public class USBSerialPortHelper implements SerialInputOutputManager.Listener {
// mainBinding.roll.fullScroll(ScrollView.FOCUS_DOWN);
// com.example.removemarineanimals.MainActivity.mainBinding.message.setText(str);
// MainActivity.mainBinding.message.setText(str);
}
int Index = 0;
private void decodeRceive(byte[] data) {
try {
MainActivity.USBSerialPortReceivedTimeCounter=0;//计算时间 归零
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 (ModbusRtuSlaveService.processModbusRequest(data, data.length) == 0x03) {
Index++;
//Index=128;
//由于 System.currentTimeMillis() 会随着时间累加,所以不存在
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 - 2];
System.arraycopy(data, 2, bytes, 0, data.length - 2);
RobotData.DataTrans _dataTrans = RobotDataHanlder.DeoodeDataFromRobot(bytes);
//RobotData.DataTrans _dataTrans = RobotDataHanlder.DeoodeDataFromRobot(data);
status("received data");
if (_dataTrans != null) {
DataExchangeHelper.setModbusPVValues( MainActivity._toSendPV);
} else if (ModbusRtuSlaveService.processModbusRequest(data, data.length) == 0x10) {
BspIV.IV_struct_define iv = DataExchangeHelper.getIVByModbus();
ReceiivedIVHandler.HandleIV(MainActivity,iv);
MainViewModel.mainBinding.rFAngleRoll.setText(String.valueOf(_dataTrans.getRFAngleRoll()));
}
}
} 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() {
@ -329,10 +303,8 @@ public class USBSerialPortHelper implements SerialInputOutputManager.Listener {
// _serialPortSwitch.setChecked(false);
disconnect();
}
}
public void SendData(byte[] data) {
if (connected) {
try {

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

@ -13,10 +13,8 @@ public class ttySerialPortHelper {
private static final String TAG = "ttySerialPortHelper";
private static SerialHelper serialHelper;
private static SerialPortFinder serialPortFinder;
public static boolean IsAllButtonSendBack = false;
private static int restoreOriginalError(int errorFlag) {
return Integer.reverseBytes(errorFlag);
}
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"};
@ -24,17 +22,15 @@ public class ttySerialPortHelper {
final String[] stopbits = new String[]{"1", "2"};
final String[] flowcons = new String[]{"NONE", "RTS/CTS", "XON/XOFF"};
public static int[] decodedCH=new int[17];
public static int[] decodedCH = new int[17];
public static void Open()
{
public static void Open() {
try {
// serialPortFinder = new SerialPortFinder();
// serialPortFinder = new SerialPortFinder();
//serialHelper = new SerialHelper("dev/ttyHS0", 115200)//MK32
serialHelper = new SerialHelper("/dev/ttyHS3", 115200) //UR7
{
@Override
protected void onDataReceived(ComBean comBean) {
@ -42,178 +38,79 @@ public class ttySerialPortHelper {
@Override
public void run() {
// 更新 UI 的代码
byte[] data=comBean.bRec;
// if (data[0] == 0x55 && data[1] == 0x55) {
// byte[] bytes = new byte[data.length - 2];
// System.arraycopy(data, 2, bytes, 0, data.length - 2);
// RobotData.DataTrans _dataTrans = RobotDataHanlder.DeoodeDataFromRobot(bytes);
//
// if (_dataTrans != null) {
// MainViewModel.mainBinding.rFAngleDepth.setText(String.valueOf(_dataTrans.getRFDepth()));
// MainViewModel.mainBinding.rFAnglePitch.setText(String.valueOf(_dataTrans.getRFAnglePitch()));
// MainViewModel.mainBinding.rFAngleRoll.setText(String.valueOf(_dataTrans.getRFAngleRoll()));
// MainViewModel.mainBinding.rFAngleYaw.setText(String.valueOf(_dataTrans.getRFAngleYaw()));
// }
// }
try {
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);
BspIV.IV_struct_define _toReceiveIV=BspIV.IV_struct_define.parseFrom(bytes);
if (_toReceiveIV!=null)
{
// MainActivity.mainBinding.rxRobotSpeed.setText(String.valueOf(_toReceiveIV.getRobotMoveSpeed()));
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);
}
}
}
}
} catch (Exception e) {
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];
}
// 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");
} catch (Exception exception) {
Log.d(TAG, "Data Received");
}
}
private static int index =0;
private static int index = 0;
public static void SendData(byte[] data) {
serialHelper.send( data); // 发送byte[]
serialHelper.send(data); // 发送byte[]
}
public static byte[] getAllChData=new byte[]{0x55, 0x66,0x01,0x01,0x00,0x00,0x00,0x42,0x02,(byte)(0xB5&0xff),(byte)(0xC0&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[]
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.send(byte[] bOutArray); // 发送byte[]
//serialHelper.sendHex(String sHex); // 发送Hex
//serialHelper.sendTxt(String sTxt); // 发送ASCII
public static void onDestroy() {

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

@ -1,6 +1,2 @@
cd /d D:\Android_studio_workspace\RemoveMarineAnimals\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
protoc --java_out . *.proto

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 162 KiB

24
app/src/main/res/drawable/blue_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="#00ffffff" />
<!-- 设置一个黑色边框 -->
<stroke
android:width="16px"
android:color="#ffffff" />
<!-- 设置四个圆角的半径 -->
<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>

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 902 KiB

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

@ -4,11 +4,6 @@
xmlns:tools="http://schemas.android.com/tools"
tools:context=".MainActivity">
<data>
<variable
name="vm"
type="com.example.removemarineanimals.viewmodels.MainViewModel" />
</data>
<LinearLayout
android:layout_width="match_parent"

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

@ -19,7 +19,7 @@
<style name="MyButtonStyle" parent="Widget.MaterialComponents.Button">
<item name="backgroundTint">@null</item> <!-- 禁用背景着色 -->
<item name="android:background">@drawable/blue_rounded_rectangle</item> <!-- 设置默认背景 -->
<!-- <item name="android:background">@drawable/blue_rounded_rectangle</item> &lt;!&ndash; 设置默认背景 &ndash;&gt;-->
<item name="android:textColor">@color/white</item> <!-- 设置文本颜色 -->
</style>
</resources>

2
settings.gradle

@ -16,5 +16,5 @@ dependencyResolutionManagement {
}
}
rootProject.name = "RemoveMarineAnimals"
rootProject.name = "fivewheel"
include ':app'

Loading…
Cancel
Save