20 changed files with 808 additions and 356 deletions
-
8src/main/java/com/iflytop/gd/app/service/DeviceParamConfigService.java
-
6src/main/java/com/iflytop/gd/hardware/command/CommandHandler.java
-
21src/main/java/com/iflytop/gd/hardware/command/command_handler/FanHandler.java
-
2src/main/java/com/iflytop/gd/hardware/device/ServoMotor.java
-
2src/main/java/com/iflytop/gd/hardware/device/StepMotor.java
-
1src/main/java/com/iflytop/gd/hardware/drivers/WebSocketCommandBusImpl.java
-
53src/main/java/com/iflytop/gd/hardware/factory/A8kPacketFactory.java
-
227src/main/java/com/iflytop/gd/hardware/type/A8kPacket.java
-
2src/main/java/com/iflytop/gd/hardware/type/AppErrorCode.java
-
44src/main/java/com/iflytop/gd/hardware/type/CmdId.java
-
2src/main/java/com/iflytop/gd/hardware/type/CommandBus.java
-
18src/main/java/com/iflytop/gd/hardware/type/MId.java
-
2src/main/java/com/iflytop/gd/hardware/type/RegIndex.java
-
124src/main/java/com/iflytop/gd/hardware/utils/ByteArray.java
-
6src/test/java/com/iflytop/gd/infrastructure/drivers/WebSocketCommandBusImplTest.java
@ -0,0 +1,53 @@ |
|||
package com.iflytop.gd.hardware.factory; |
|||
|
|||
|
|||
|
|||
import com.iflytop.gd.hardware.type.A8kPacket; |
|||
import com.iflytop.gd.hardware.type.CmdId; |
|||
|
|||
import java.util.List; |
|||
|
|||
public class A8kPacketFactory { |
|||
|
|||
//typedef struct { |
|||
// uint8_t packetType; |
|||
// uint16_t cmdid; |
|||
// uint8_t moduleId; |
|||
// uint8_t index; |
|||
// uint8_t datalen; |
|||
// uint8_t data[]; |
|||
// /* int8_t checksum;*/ |
|||
//} zcr_cmd_header_t; |
|||
|
|||
static public A8kPacket buildPacket(Integer moduleId, int packetType, Integer cmdId, Integer[] params) { |
|||
return A8kPacket.createPacket(moduleId, packetType, cmdId, params); |
|||
} |
|||
|
|||
static public A8kPacket buildCMDPacket(Integer moduleId, Integer cmdId, Integer[] params) { |
|||
return buildPacket(moduleId, (byte) 0, cmdId, params); |
|||
} |
|||
|
|||
static public A8kPacket buildCMDPacket(Integer moduleId, Integer cmdId, List<Integer> params) { |
|||
Integer[] array = new Integer[params.size()]; |
|||
params.toArray(array); |
|||
return buildPacket(moduleId, A8kPacket.PACKET_TYPE_CMD, cmdId, array); |
|||
} |
|||
|
|||
static public A8kPacket buildReportPacket(Integer moduleId, Integer cmdId, Integer[] params) { |
|||
return buildPacket(moduleId, (byte) 3, cmdId, params); |
|||
} |
|||
|
|||
// static public A8kPacket build_event_a8000_idcard_online() { |
|||
// return buildReportPacket(MId.A8kIdCardReader.toInt(), CmdId.event_a8000_idcard_online.index, new Integer[0]); |
|||
// } |
|||
// |
|||
// static public A8kPacket build_event_a8000_idcard_offline() { |
|||
// return buildReportPacket(MId.A8kIdCardReader.toInt(), CmdId.event_a8000_idcard_offline.index, new Integer[0]); |
|||
// } |
|||
|
|||
public static void main(String[] args) { |
|||
var packet = buildCMDPacket(1, CmdId.module_get_reg.toInt(), List.of(1, 2, 3)); |
|||
System.out.println(packet.toByteString()); |
|||
} |
|||
} |
|||
|
@ -0,0 +1,227 @@ |
|||
package com.iflytop.gd.hardware.type; |
|||
|
|||
import com.iflytop.gd.hardware.utils.ByteArray; |
|||
import org.slf4j.Logger; |
|||
import org.slf4j.LoggerFactory; |
|||
import org.springframework.util.Assert; |
|||
|
|||
import java.nio.ByteBuffer; |
|||
import java.nio.ByteOrder; |
|||
|
|||
public class A8kPacket { |
|||
|
|||
//#pragma pack(push, 1) |
|||
//typedef struct { |
|||
// uint8_t packetType; |
|||
// uint16_t cmdid; |
|||
// uint8_t moduleId; |
|||
// uint16_t index; |
|||
// uint8_t datalen; |
|||
// uint8_t data[]; |
|||
// /* int8_t checksum;*/ |
|||
//} zcr_cmd_header_t; |
|||
// |
|||
//#pragma pack(pop) |
|||
//typedef enum { |
|||
// kptv2_cmd = 0xA0, |
|||
// kptv2_ack = 0xA1, |
|||
// kptv2_error_ack = 0xA2, |
|||
// kptv2_event = 0xA3, |
|||
//} zcan_cmd_packet_type_t; |
|||
// |
|||
|
|||
/** |
|||
* |
|||
* @WARNING |
|||
* 1. 修改这里时,需要注意连同createPacket一起修改 |
|||
* 2. PACKET_MIN_LEN 比Header多一个字节,是因为还有一个字节的校验位 |
|||
*/ |
|||
|
|||
public static final int PACKET_TYPE_OFFSET = 0; |
|||
public static final int CMDID_OFFSET = 1; |
|||
public static final int MODULE_ID_OFFSET = 3; |
|||
public static final int INDEX_OFFSET = 4; |
|||
public static final int DATA_LEN_OFFSET = 6; |
|||
public static final int DATA_OFFSET = 7; |
|||
|
|||
public static final int PACKET_MIN_LEN = 8;// |
|||
|
|||
public static final int CMD_OVERTIME = 1500; |
|||
|
|||
|
|||
public static final int PACKET_TYPE_CMD = 0xA0; |
|||
public static final int PACKET_TYPE_ACK = 0xA1; |
|||
public static final int PACKET_TYPE_ERROR_ACK = 0xA2; |
|||
public static final int PACKET_TYPE_EVENT = 0xA3; |
|||
|
|||
public static final Logger logger = LoggerFactory.getLogger(A8kPacket.class); |
|||
|
|||
byte[] raw; |
|||
|
|||
public A8kPacket(byte[] cmd) { |
|||
raw = new byte[cmd.length]; |
|||
System.arraycopy(cmd, 0, raw, 0, cmd.length); |
|||
} |
|||
|
|||
public void setPacketIndex(int packetIndex) { |
|||
ByteArray.setU16bit(raw, INDEX_OFFSET, packetIndex); |
|||
int checkcode = computeCheckcode(); |
|||
ByteArray.setU8(raw, raw.length - 1, checkcode); |
|||
} |
|||
|
|||
|
|||
public int getPacketIndex() { |
|||
return ByteArray.readU16bit(raw, INDEX_OFFSET); |
|||
} |
|||
|
|||
public int getCmdId() { |
|||
return ByteArray.readU16bit(raw, CMDID_OFFSET); |
|||
} |
|||
|
|||
public int getPacketType() { |
|||
return ByteArray.readU8bit(raw, PACKET_TYPE_OFFSET); |
|||
} |
|||
|
|||
public int getModuleId() { |
|||
return ByteArray.readU8bit(raw, MODULE_ID_OFFSET); |
|||
} |
|||
|
|||
public int getDataLen() { |
|||
return ByteArray.readU8bit(raw, DATA_LEN_OFFSET); |
|||
} |
|||
|
|||
public byte[] getCmdContent() { |
|||
if (raw.length < PACKET_MIN_LEN) { |
|||
return new byte[0]; |
|||
} |
|||
byte[] cmdcontent = new byte[getDataLen()]; |
|||
System.arraycopy(raw, DATA_OFFSET, cmdcontent, 0, getDataLen()); |
|||
return cmdcontent; |
|||
} |
|||
|
|||
public int getContentI32(int index) { |
|||
return ByteArray.read32bit(raw, DATA_OFFSET + index * 4); |
|||
} |
|||
|
|||
public int getCheckcode() { |
|||
return ByteArray.readU8bit(raw, raw.length - 1); |
|||
} |
|||
|
|||
public int computeCheckcode() { |
|||
int checkcode = 0; |
|||
for (int i = 0; i < raw.length - 1; i++) { |
|||
checkcode += raw[i]; |
|||
} |
|||
return checkcode & 0xFF; |
|||
} |
|||
|
|||
public String toByteString() { |
|||
return ByteArray.toByteString(raw); |
|||
} |
|||
|
|||
public String toString() { |
|||
int packetType = getPacketType(); |
|||
String ret = ""; |
|||
|
|||
CmdId cmdId = CmdId.valueOf(getCmdId()); |
|||
Assert.isTrue(cmdId != null, "cmdId is null"); |
|||
if (packetType == PACKET_TYPE_CMD) { |
|||
|
|||
if (cmdId.equals(CmdId.module_get_reg) || cmdId.equals(CmdId.module_set_reg)) { |
|||
RegIndex regIndex = RegIndex.valueOf(getContentI32(0)); |
|||
if (regIndex != null) { |
|||
ret = String.format("[CMD ] index:[%d] %s %s %s(%d) %d", getPacketIndex(), cmdId, |
|||
MId.valueOf(getModuleId()), regIndex, regIndex.index, getContentI32(1)); |
|||
} else { |
|||
ret = String.format("[CMD ] index:[%d] %s unkown_index(%d) %d", getPacketIndex(), cmdId, |
|||
getContentI32(0), getContentI32(1)); |
|||
} |
|||
} else { |
|||
if (cmdId.getCmdAttachType() == CmdId.ATTACH_IS_INT32) { |
|||
ret = String.format("[CMD ] index:[%d] (%s %s(%d) :param:[%s])", getPacketIndex(), cmdId, |
|||
MId.valueOf(getModuleId()), getModuleId(), formatInt32ATTACH(getCmdContent())); |
|||
} else { |
|||
ret = String.format("[CMD ] index:[%d] (%s %s(%d) :param:[%s])", getPacketIndex(), cmdId, |
|||
MId.valueOf(getModuleId()), getModuleId(), ByteArray.toByteString(getCmdContent())); |
|||
} |
|||
} |
|||
|
|||
} else if (packetType == PACKET_TYPE_ACK) { |
|||
if (cmdId.getReceiptAttachType() == CmdId.ATTACH_IS_INT32) { |
|||
ret = String.format("[ACK ] index:[%d] (%s :[%s])", getPacketIndex(), cmdId, |
|||
formatInt32ATTACH(getCmdContent())); |
|||
} else { |
|||
ret = String.format("[ACK ] index:[%d] (%s :[%s])", getPacketIndex(), cmdId, |
|||
ByteArray.toByteString(getCmdContent())); |
|||
} |
|||
} else if (packetType == PACKET_TYPE_ERROR_ACK) { |
|||
ret = String.format("[EACK ] index:[%d] (%s :[%s])", getPacketIndex(), cmdId, (getContentI32(0))); |
|||
} else if (packetType == PACKET_TYPE_EVENT) { |
|||
if (cmdId.getCmdAttachType() == CmdId.ATTACH_IS_INT32) { |
|||
ret = String.format("[EVENT] index:[%d] (%s %s(%d) :[%s])", getPacketIndex(), cmdId, |
|||
MId.valueOf(getModuleId()), getModuleId(), formatInt32ATTACH(getCmdContent())); |
|||
} else { |
|||
ret = String.format("[EVENT] index:[%d] (%s %s(%d) :[%s])", getPacketIndex(), cmdId, |
|||
MId.valueOf(getModuleId()), getModuleId(), ByteArray.toByteString(getCmdContent())); |
|||
} |
|||
} else { |
|||
ret = String.format("Unknown packet type: %d", packetType); |
|||
} |
|||
return ret; |
|||
} |
|||
|
|||
private String formatInt32ATTACH(byte[] attach) { |
|||
StringBuilder ret = new StringBuilder(); |
|||
for (int i = 0; i < attach.length; i += 4) { |
|||
if (i + 3 >= attach.length) |
|||
break; |
|||
if (i != 0) |
|||
ret.append(","); |
|||
ret.append(String.format("%d", ByteArray.read32bit(attach, i))); |
|||
} |
|||
return ret.toString(); |
|||
} |
|||
|
|||
public Boolean isSupportPacket() { |
|||
CmdId cmdid = CmdId.valueOf(getCmdId()); |
|||
if (cmdid == null) { |
|||
return false; |
|||
} |
|||
if (CmdId.module_get_reg.equals(cmdid) || CmdId.module_set_reg.equals(cmdid)) { |
|||
if (getPacketType() == PACKET_TYPE_CMD) { |
|||
RegIndex regIndex = RegIndex.valueOf(getContentI32(0)); |
|||
return regIndex != null; |
|||
} |
|||
} |
|||
return true; |
|||
} |
|||
|
|||
|
|||
static public A8kPacket createPacket(Integer moduleId, int packetType, Integer cmdId, Integer[] params) { |
|||
int bufferSize = A8kPacket.PACKET_MIN_LEN + 4 * params.length; |
|||
ByteBuffer buffer = ByteBuffer.allocate(bufferSize); |
|||
buffer.order(ByteOrder.LITTLE_ENDIAN); |
|||
buffer.put((byte) (packetType & 0xff)); // packetType |
|||
buffer.putShort((short) (cmdId & 0xffff)); // cmdid |
|||
buffer.put((byte) (moduleId & 0xFF)); // moduleId |
|||
buffer.put((byte) 0x4C); // index |
|||
buffer.put((byte) 0x00); // index |
|||
buffer.put((byte) (params.length * 4)); // datalen |
|||
for (int value : params) { |
|||
buffer.putInt(value); |
|||
} |
|||
// int8_t checksum; |
|||
int checksum = 0; |
|||
for (int i = 0; i < bufferSize - 1; i++) { |
|||
checksum += buffer.get(i); |
|||
} |
|||
buffer.put((byte) checksum); |
|||
return new A8kPacket(buffer.array()); |
|||
} |
|||
|
|||
public static void main(String[] args) { |
|||
var packet = createPacket(41, A8kPacket.PACKET_TYPE_CMD, CmdId.module_stop.index, new Integer[]{}); |
|||
logger.info("{}", packet.toByteString()); |
|||
} |
|||
|
|||
} |
@ -1,4 +1,4 @@ |
|||
package com.iflytop.gd.hardware.drivers; |
|||
package com.iflytop.gd.hardware.type; |
|||
|
|||
public enum AppErrorCode { |
|||
APP_OK(200, "操作成功"), |
@ -1,4 +1,4 @@ |
|||
package com.iflytop.gd.hardware.drivers; |
|||
package com.iflytop.gd.hardware.type; |
|||
|
|||
import com.iflytop.gd.common.exception.CommandExecTimeoutException; |
|||
import com.iflytop.gd.common.exception.HardwareErrorException; |
@ -1,4 +1,4 @@ |
|||
package com.iflytop.gd.hardware.drivers; |
|||
package com.iflytop.gd.hardware.type; |
|||
|
|||
/** |
|||
* @brief 寄存器索引 |
@ -0,0 +1,124 @@ |
|||
package com.iflytop.gd.hardware.utils; |
|||
|
|||
import org.springframework.lang.NonNull; |
|||
|
|||
public class ByteArray { |
|||
public ByteArray() { |
|||
} |
|||
|
|||
public static int readU8bit(byte[] code, int index) { |
|||
if (index >= code.length) |
|||
return 0; |
|||
return code[index] & 255; |
|||
} |
|||
|
|||
public static int readS8bit(byte[] code, int index) { |
|||
if (index >= code.length) |
|||
return 0; |
|||
|
|||
return code[index]; |
|||
} |
|||
|
|||
public static int readU16bit(byte[] code, int index) { |
|||
if (index + 1 >= code.length) |
|||
return 0; |
|||
return (code[index + 1] & 255) << 8 | code[index] & 255; |
|||
} |
|||
|
|||
public static void setU16bit(byte[] code, int index, int value) { |
|||
code[index + 1] = (byte) (value >> 8); |
|||
code[index] = (byte) value; |
|||
} |
|||
|
|||
public static void setU8(byte[] code, int off, int value) { |
|||
code[off] = (byte) value; |
|||
} |
|||
|
|||
public static int readS16bit(byte[] code, int index) { |
|||
if (index + 1 >= code.length) |
|||
return 0; |
|||
|
|||
return code[index + 1] << 8 | code[index] & 255; |
|||
} |
|||
|
|||
public static int read32bit(byte[] code, int index) { |
|||
if (index + 3 >= code.length) |
|||
return 0; |
|||
return code[index + 3] << 24 | (code[index + 2] & 255) << 16 | (code[index + 1] & 255) << 8 | code[index] & 255; |
|||
} |
|||
|
|||
public static Integer[] read32bitArray(byte[] code) { |
|||
int count = code.length / 4; |
|||
Integer[] array = new Integer[count]; |
|||
for (int i = 0; i < count; i++) { |
|||
array[i] = read32bit(code, i * 4); |
|||
} |
|||
return array; |
|||
} |
|||
|
|||
public static Integer[] read16bitArray(byte[] code) { |
|||
int count = code.length / 2; |
|||
Integer[] array = new Integer[count]; |
|||
for (int i = 0; i < count; i++) { |
|||
array[i] = readS16bit(code, i * 2); |
|||
} |
|||
return array; |
|||
} |
|||
|
|||
public static Integer[] readU16bitArray(byte[] code) { |
|||
int count = code.length / 2; |
|||
Integer[] array = new Integer[count]; |
|||
for (int i = 0; i < count; i++) { |
|||
array[i] = readU16bit(code, i * 2); |
|||
} |
|||
return array; |
|||
} |
|||
|
|||
|
|||
public static String toByteString(byte[] arrary) { |
|||
StringBuilder sb = new StringBuilder(); |
|||
for (byte b : arrary) { |
|||
sb.append(String.format("%02X", b)); |
|||
} |
|||
return sb.toString(); |
|||
} |
|||
|
|||
public static byte[] hexStringToBytes(@NonNull String str) { |
|||
if (str.isEmpty()) { |
|||
return new byte[0]; |
|||
} else { |
|||
byte[] byteArray = new byte[str.length() / 2]; |
|||
for (int i = 0; i < byteArray.length; i++) { |
|||
int high = Character.digit(str.charAt(i * 2), 16); |
|||
int low = Character.digit(str.charAt(i * 2 + 1), 16); |
|||
if (high == -1 || low == -1) { |
|||
return null; |
|||
} |
|||
byteArray[i] = (byte) (high * 16 + low); |
|||
} |
|||
return byteArray; |
|||
} |
|||
} |
|||
|
|||
|
|||
public static byte[] concat(byte[]... arrays) { |
|||
int length = 0; |
|||
for (byte[] array : arrays) { |
|||
length += array.length; |
|||
} |
|||
|
|||
byte[] result = new byte[length]; |
|||
int destPos = 0; |
|||
for (byte[] array : arrays) { |
|||
System.arraycopy(array, 0, result, destPos, array.length); |
|||
destPos += array.length; |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
|
|||
// public static void main(String[] args) { |
|||
// byte[] bytes = new byte[]{0x01, 0x02, 0x03, 0x04}; |
|||
// System.out.println(toByteString(bytes)); |
|||
// } |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue