Compare commits
1 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
357c440e7c | 4 weeks ago |
26 changed files with 3113 additions and 1032 deletions
@ -0,0 +1 @@ |
|||
fivewheel |
|||
@ -0,0 +1,6 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<project version="4"> |
|||
<component name="VcsDirectoryMappings"> |
|||
<mapping directory="" vcs="Git" /> |
|||
</component> |
|||
</project> |
|||
@ -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); |
|||
} |
|||
} |
|||
File diff suppressed because it is too large
@ -0,0 +1,6 @@ |
|||
package com.example.fivewheel.services; |
|||
|
|||
|
|||
public enum CommunicationMethond { |
|||
Wireless, Wired |
|||
} |
|||
@ -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; |
|||
} |
|||
} |
|||
} |
|||
@ -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; |
|||
} |
|||
|
|||
|
|||
|
|||
} |
|||
@ -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; |
|||
} |
|||
|
|||
|
|||
} |
|||
@ -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()); |
|||
} |
|||
}); |
|||
|
|||
} |
|||
|
|||
} |
|||
@ -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 |
|||
|
|||
|
|||
|
After Width: | Height: | Size: 162 KiB |
@ -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> |
|||
|
After Width: | Height: | Size: 902 KiB |
Loading…
Reference in new issue