25 changed files with 904 additions and 73 deletions
-
33src/main/java/com/iflytop/gd/common/notification/Notification.java
-
21src/main/java/com/iflytop/gd/infrastructure/drivers/AppErrorCode.java
-
122src/main/java/com/iflytop/gd/infrastructure/drivers/CmdId.java
-
98src/main/java/com/iflytop/gd/infrastructure/drivers/ModuleId.java
-
78src/main/java/com/iflytop/gd/infrastructure/drivers/RegIndex.java
-
98src/main/java/com/iflytop/gd/infrastructure/drivers/WebSocketCommandBusImpl.java
-
18src/main/java/com/iflytop/gd/system/constants/RotationDirection.java
-
46src/main/java/com/iflytop/gd/system/devices/BaseStepStepMotor.java
-
11src/main/java/com/iflytop/gd/system/devices/BinaryDevice.java
-
9src/main/java/com/iflytop/gd/system/devices/DoorStepMotor.java
-
2src/main/java/com/iflytop/gd/system/devices/Fan.java
-
2src/main/java/com/iflytop/gd/system/devices/Heater.java
-
2src/main/java/com/iflytop/gd/system/devices/Relay.java
-
2src/main/java/com/iflytop/gd/system/devices/ServoMotor.java
-
77src/main/java/com/iflytop/gd/system/devices/StepMotor.java
-
22src/main/java/com/iflytop/gd/system/drivers/CommandBus.java
-
34src/main/java/com/iflytop/gd/system/drivers/StepMotor.java
-
22src/main/java/com/iflytop/gd/system/exceptions/CommandExecTimeoutException.java
-
22src/main/java/com/iflytop/gd/system/exceptions/HardwareErrorException.java
-
83src/main/java/com/iflytop/gd/system/models/DataPacket.java
-
125src/main/java/com/iflytop/gd/system/utils/ByteArray.java
@ -0,0 +1,21 @@ |
|||||
|
package com.iflytop.gd.infrastructure.drivers; |
||||
|
|
||||
|
public enum AppErrorCode { |
||||
|
APP_OK(200, "操作成功"), |
||||
|
FAIL(500, "操作失败"), |
||||
|
PARAM_ERROR(400, "参数错误"); |
||||
|
|
||||
|
private int code; |
||||
|
private String msg; |
||||
|
private AppErrorCode(int code, String msg) { |
||||
|
this.code = code; |
||||
|
this.msg = msg; |
||||
|
} |
||||
|
|
||||
|
public int getCode() { |
||||
|
return code; |
||||
|
} |
||||
|
public String getMsg() { |
||||
|
return msg; |
||||
|
} |
||||
|
} |
@ -0,0 +1,122 @@ |
|||||
|
package com.iflytop.gd.infrastructure.drivers; |
||||
|
|
||||
|
|
||||
|
public enum CmdId { |
||||
|
NotSet(0xFFFF, "NOACTION"),// |
||||
|
|
||||
|
board_reset(0x0000, "复位板子"),// |
||||
|
event_bus_reg_change_report(0x0064, "寄存器修改事件"),// |
||||
|
// |
||||
|
|
||||
|
module_ping(0x0101, "MODULE_PING"), |
||||
|
module_stop(0x0102, "MODULE_STOP"), |
||||
|
|
||||
|
module_get_error(0x0110, "MODULE_GET_ERROR"), |
||||
|
module_get_detail_error(0x0111, "MODULE_GET_DETAIL_ERROR"), |
||||
|
module_clear_error(0x0112, "MODULE_CLEAR_ERROR"), |
||||
|
|
||||
|
module_set_reg(0x0120, "MODULE_SET_REG"), |
||||
|
module_get_reg(0x0121, "MODULE_GET_REG"), |
||||
|
module_reset_reg(0x0123, "MODULE_RESET_REG"), |
||||
|
|
||||
|
module_get_version(0x0130, "MODULE_GET_VERSION"), |
||||
|
module_get_type(0x0131, "MODULE_GET_TYPE"), |
||||
|
module_get_status(0x0132, "MODULE_GET_STATUS"), |
||||
|
|
||||
|
// 扩展板 |
||||
|
extboard_read_inio(0x6701, "EXTBOARD_READ_INIO"),// |
||||
|
extboard_write_outio(0x6702, "EXTBOARD_WRITE_OUTIO"),// |
||||
|
extboard_read_muti_inio(0x6703, "EXTBOARD_READ_MUTI_INIO"),// |
||||
|
extboard_read_inio_index_in_stm32(0x6704, "EXTBOARD_READ_INIO_INDEX_IN_STM32"),// |
||||
|
extboard_read_outio_index_in_stm32(0x6705, "EXTBOARD_READ_OUTIO_INDEX_IN_STM32"),// |
||||
|
extboard_read_outio(0x6706, "EXTBOARD_READ_OUTIO"),// |
||||
|
|
||||
|
// 补光灯模块 |
||||
|
module_pwm_light_on(0x0204, "MODULE_PWM_LIGHT_ON"), // 补光灯 开启 |
||||
|
module_pwm_light_off(0x0205, "MODULE_PWM_LIGHT_OFF"), // 补光灯 |
||||
|
|
||||
|
// 三色灯模块 |
||||
|
module_tricolor_light_on(0x0206, "MODULE_TRICOLOR_LIGHT_ON"), // 三色灯开启 |
||||
|
module_tricolor_light_off(0x0207, "MODULE_TRICOLOR_LIGHT_OFF"), // 三色灯 |
||||
|
|
||||
|
// IO 板卡 1 |
||||
|
module_io1_read_heat_rod_current(0x0207, "MODULE_IO_READ_HEAT_ROD_CURRENT"), // 读取加热棒电流 |
||||
|
|
||||
|
// IO 板卡 2 |
||||
|
|
||||
|
// 电机通用控制 |
||||
|
step_motor_enable(0x0201, "STEP_MOTOR_ENABLE"),// |
||||
|
step_motor_read_pos(0x020b, "STEP_MOTOR_READ_POS"),// |
||||
|
step_motor_read_enc_pos(0x020c, "STEP_MOTOR_READ_ENC_POS"),// |
||||
|
step_motor_easy_rotate(0x0211, "STEP_MOTOR_EASY_ROTATE"),// |
||||
|
step_motor_easy_move_by(0x0212, "STEP_MOTOR_EASY_MOVE_BY"),// |
||||
|
step_motor_easy_move_to(0x0213, "STEP_MOTOR_EASY_MOVE_TO"),// |
||||
|
step_motor_easy_move_to_zero(0x0214, "STEP_MOTOR_EASY_MOVE_TO_ZERO"),// |
||||
|
step_motor_easy_set_current_pos(0x0215, "STEP_MOTOR_EASY_SET_CURRENT_POS"),// |
||||
|
step_motor_easy_move_to_io(0x0216, "STEP_MOTOR_EASY_MOVE_TO_IO"),// |
||||
|
step_motor_stop(0x0228, "STEP_MOTOR_STOP"),// |
||||
|
step_motor_move_by(0x021d, "STEP_MOTOR_MOVE_BY"), // (dpos,speedlevel)->null speedlevel=0,1,2,3(default,low,mid,high) |
||||
|
step_motor_move_to(0x021e, "STEP_MOTOR_MOVE_TO"), // (pos,speedlevel)->null speedlevel=0,1,2,3(default,low,mid,high) |
||||
|
step_motor_move_to_zero_point_quick(0x021f, "STEP_MOTOR_MOVE_TO_ZERO_POINT_QUICK"), // (speedlevel)->null speedlevel=0,1,2,3(default,low,mid,high) |
||||
|
step_motor_rotate(0x0220, "STEP_MOTOR_ROTATE"), // |
||||
|
|
||||
|
step_motor_active_cfg(0x0229, "STEP_MOTOR_ACTIVE_CFG"),// |
||||
|
step_motor_read_io_state(0x022a, "STEP_MOTOR_READ_IO_STATE"),// |
||||
|
step_motor_easy_move_to_end_point(0x022c, "STEP_MOTOR_EASY_MOVE_TO_END_POINT"),// |
||||
|
step_motor_read_tmc5130_status(0x0232, "STEP_MOTOR_READ_TMC5130_STATUS"),// |
||||
|
step_motor_read_tmc5130_state(0x0233, "STEP_MOTOR_READ_TMC5130_STATE"),// |
||||
|
step_motor_read_io_index_in_stm32(0x0238, "STEP_MOTOR_READ_IO_INDEX_IN_STM32"),// |
||||
|
step_motor_set_subdevice_reg(0x0239, "STEP_MOTOR_SET_SUBDEVICE_REG"),// |
||||
|
step_motor_get_subdevice_reg(0x023a, "STEP_MOTOR_GET_SUBDEVICE_REG"),// |
||||
|
step_motor_easy_reciprocating_motion(0x022d, "STEP_MOTOR_EASY_RECIPROCATING_MOTION"),// |
||||
|
step_motor_easy_move_to_zero_point_quick(0x022e, "STEP_MOTOR_EASY_MOVE_TO_ZERO_POINT_QUICK"), |
||||
|
|
||||
|
|
||||
|
; |
||||
|
|
||||
|
public final static int ATTACH_IS_BYTES = 1; |
||||
|
public final static int ATTACH_IS_INT32 = 2; |
||||
|
public final int index; |
||||
|
public final String name; |
||||
|
|
||||
|
CmdId(int index, String chname) { |
||||
|
this.index = index; |
||||
|
this.name = chname; |
||||
|
} |
||||
|
|
||||
|
public int toInt() { |
||||
|
return index; |
||||
|
} |
||||
|
|
||||
|
public static CmdId valueOf(int val) { |
||||
|
CmdId[] values = CmdId.values(); |
||||
|
for (CmdId e : values) { |
||||
|
if (e.toInt() == val) |
||||
|
return e; |
||||
|
} |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
public static String toString(int val) { |
||||
|
CmdId[] values = CmdId.values(); |
||||
|
for (CmdId e : values) { |
||||
|
if (e.toInt() == val) { |
||||
|
return e.toString(); |
||||
|
} |
||||
|
} |
||||
|
return "unknown(" + val + ")"; |
||||
|
} |
||||
|
|
||||
|
public String getName() { |
||||
|
return name; |
||||
|
} |
||||
|
|
||||
|
public Boolean eq(Integer index) { |
||||
|
return this.index == index; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
public boolean isTrace() { |
||||
|
return true; |
||||
|
} |
||||
|
} |
@ -0,0 +1,98 @@ |
|||||
|
package com.iflytop.gd.infrastructure.drivers; |
||||
|
|
||||
|
public enum ModuleId { |
||||
|
NotSet(0, "未设置"), |
||||
|
IO1Board(10, "台面 IO 板模块"), |
||||
|
PWMLight(11, "PWM 灯"), |
||||
|
TriColorLight(12, "三色灯"), |
||||
|
|
||||
|
IO2Board(30, "台下 IO 板模块"), |
||||
|
|
||||
|
DoorBoard(80, "门电机板模块"),// |
||||
|
DoorM(81, "门电机"), |
||||
|
|
||||
|
ShakeModBoard(90, "摇匀模组板"), // |
||||
|
ShakeModShakeM(91, "加液位摇匀电机"), // |
||||
|
|
||||
|
CapStorageBoard(100, "拍子存放板模块"), // |
||||
|
CapStorageM(101, "拍子存放电机"), // |
||||
|
|
||||
|
DualRobotAxis1Board(110, "双轴机械臂1轴板模块"),// |
||||
|
DualRobotAxis1M(111, "双轴机械臂1轴电机"), |
||||
|
DualRobotAxis2Board(120, "双轴机械臂2轴板模块"),// |
||||
|
DualRobotAxis2M(121, "双轴机械臂2轴电机"), |
||||
|
|
||||
|
HBotXBoard(130, "X轴板模块"),// |
||||
|
HBotXM(131, "X轴电机"), |
||||
|
HBotYBoard(140, "Y轴板模块"),// |
||||
|
HBotYM(141, "Y轴电机"), |
||||
|
HBotZBoard(150, "Z轴板模块"),// |
||||
|
HBotZM(151, "Z轴电机"), |
||||
|
|
||||
|
Heater1Board(160, "加热1板模块"),// |
||||
|
Heater1M(161, "加热1电机"), |
||||
|
Heater2Board(170, "加热2板模块"),// |
||||
|
Heater2M(171, "加热2电机"), |
||||
|
Heater3Board(180, "加热3板模块"),// |
||||
|
Heater3M(181, "加热3电机"), |
||||
|
Heater4Board(190, "加热4板模块"),// |
||||
|
Heater4M(191, "加热4电机"), |
||||
|
Heater5Board(200, "加热5板模块"),// |
||||
|
Heater5M(201, "加热5电机"), |
||||
|
Heater6Board(210, "加热6板模块"),// |
||||
|
Heater6M(211, "加热6电机"), |
||||
|
|
||||
|
AcidPump1Board(220, "加酸泵1板模块"),// |
||||
|
AcidPump1M(221, "加酸泵1电机"), |
||||
|
AcidPump2Board(230, "加酸泵2板模块"),// |
||||
|
AcidPump2M(231, "加酸泵2电机"), |
||||
|
AcidPump3Board(240, "加酸泵3板模块"),// |
||||
|
AcidPump3M(241, "加酸泵3电机"), |
||||
|
AcidPump4Board(250, "加酸泵4板模块"),// |
||||
|
AcidPump4M(251, "加酸泵4电机"), |
||||
|
AcidPump5Board(260, "泵5板模块"),// |
||||
|
AcidPump5M(261, "泵5电机"), |
||||
|
AcidPump6Board(270, "泵6板模块"),// |
||||
|
AcidPump6M(271, "泵6电机"), |
||||
|
AcidPump7Board(280, "泵7板模块"),// |
||||
|
AcidPump7M(281, "泵7电机"), |
||||
|
AcidPump8Board(290, "泵8板模块"),// |
||||
|
AcidPump8M(291, "泵8电机"), |
||||
|
; |
||||
|
|
||||
|
final public String name; |
||||
|
final public int index; |
||||
|
|
||||
|
ModuleId(int index, String name) { |
||||
|
this.name = name; |
||||
|
this.index = index; |
||||
|
} |
||||
|
|
||||
|
public int toInt() { |
||||
|
return index; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
public static ModuleId valueOf(Integer val) { |
||||
|
return valueOf(val.intValue()); |
||||
|
} |
||||
|
|
||||
|
public static ModuleId valueOf(int val) { |
||||
|
ModuleId[] values = ModuleId.values(); |
||||
|
for (ModuleId e : values) { |
||||
|
if (e.toInt() == val) |
||||
|
return e; |
||||
|
} |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
public static String toString(int val) { |
||||
|
ModuleId[] values = ModuleId.values(); |
||||
|
for (ModuleId e : values) { |
||||
|
if (e.toInt() == val) { |
||||
|
return e.toString(); |
||||
|
} |
||||
|
} |
||||
|
return "unknown(" + val + ")"; |
||||
|
} |
||||
|
} |
@ -0,0 +1,78 @@ |
|||||
|
package com.iflytop.gd.infrastructure.drivers; |
||||
|
|
||||
|
/** |
||||
|
* @brief 寄存器索引 |
||||
|
*/ |
||||
|
public enum RegIndex { |
||||
|
|
||||
|
/*********************************************************************************************************************** |
||||
|
* 步进电机控制器 * |
||||
|
***********************************************************************************************************************/ |
||||
|
/*********************************************************************************************************************** |
||||
|
* step_motor start * |
||||
|
***********************************************************************************************************************/ |
||||
|
|
||||
|
kreg_step_motor_pos(10101), // 机器人x坐标 |
||||
|
kreg_step_motor_is_enable(10102), // 是否使能 |
||||
|
kreg_step_motor_dpos(10103), // 执行完上一条指令后的相对位移 |
||||
|
kreg_step_motor_has_move_zero(10104), // 是否回零 |
||||
|
// kreg_step_motor_shift(10150), // x偏移 |
||||
|
kreg_step_motor_shaft(10151), // x轴是否反转 |
||||
|
kreg_step_motor_one_circle_pulse(10152), // x轴一圈脉冲数 |
||||
|
kreg_step_motor_one_circle_pulse_denominator(10153), // 设置一圈脉冲数的分母 |
||||
|
kreg_step_motor_default_velocity(10154), // 默认速度 |
||||
|
kreg_step_motor_low_velocity(10155), // 低速 |
||||
|
kreg_step_motor_mid_velocity(10156), // 中速 |
||||
|
kreg_step_motor_high_velocity(10157), // 高速 |
||||
|
kreg_step_motor_ihold(10158), // 步进电机电流配置 |
||||
|
kreg_step_motor_irun(10159), // 步进电机电流配置 |
||||
|
kreg_step_motor_iholddelay(10160), // 步进电机电流配置 |
||||
|
kreg_step_motor_iglobalscaler(10161), // 步进电机电流配置 |
||||
|
kreg_step_motor_mres(10162), // 电机细分 |
||||
|
kreg_step_motor_run_to_zero_speed(10173), // 回零速度 |
||||
|
kreg_step_motor_look_zero_edge_speed(10175), // 找零边缘速度 |
||||
|
kreg_step_motor_max_d(10178), // 最大限制距离 |
||||
|
kreg_step_motor_min_d(10179), // 最小限制距离 |
||||
|
kreg_step_motor_in_debug_mode(10180), // 驱动器处于调试模式 |
||||
|
kreg_step_motor_vstart(10181), // a1起作用的速度 |
||||
|
kreg_step_motor_a1(10182), // |
||||
|
kreg_step_motor_amax(10183), // |
||||
|
kreg_step_motor_v1(10184), // |
||||
|
kreg_step_motor_dmax(10185), // |
||||
|
kreg_step_motor_d1(10186), // |
||||
|
kreg_step_motor_vstop(10187), // |
||||
|
kreg_step_motor_tzerowait(10188), // |
||||
|
kreg_step_motor_enc_resolution(10189), // 编码器分辨率 1000,1024,4000,4096,16384 |
||||
|
kreg_step_motor_enable_enc(10190), // |
||||
|
kreg_step_motor_dzero_pos(10191), // 驱动器处于调试模式 |
||||
|
kret_step_motor_pos_devi_tolerance(10192), // 位置偏差容忍度 |
||||
|
kret_step_motor_io_trigger_append_distance(10193), // 移动到io时,附加的距离 |
||||
|
|
||||
|
/*********************************************************************************************************************** |
||||
|
* step_motor end * |
||||
|
***********************************************************************************************************************/ |
||||
|
; |
||||
|
|
||||
|
public final int index; |
||||
|
public final Boolean trace; |
||||
|
|
||||
|
RegIndex(int regIndex) { |
||||
|
this.index = regIndex; |
||||
|
this.trace = true; |
||||
|
} |
||||
|
|
||||
|
RegIndex(int regIndex, Boolean trace) { |
||||
|
this.index = regIndex; |
||||
|
this.trace = trace; |
||||
|
} |
||||
|
|
||||
|
public static RegIndex valueOf(int val) { |
||||
|
RegIndex[] values = RegIndex.values(); |
||||
|
for (RegIndex regindex : values) { |
||||
|
if (regindex.index == val) { |
||||
|
return regindex; |
||||
|
} |
||||
|
} |
||||
|
return null; |
||||
|
} |
||||
|
} |
@ -0,0 +1,98 @@ |
|||||
|
package com.iflytop.gd.infrastructure.drivers; |
||||
|
|
||||
|
import cn.hutool.core.util.ObjectUtil; |
||||
|
import com.iflytop.gd.common.exception.AppException; |
||||
|
import com.iflytop.gd.system.drivers.CommandBus; |
||||
|
import com.iflytop.gd.system.exceptions.CommandExecTimeoutException; |
||||
|
import com.iflytop.gd.system.exceptions.HardwareErrorException; |
||||
|
import com.iflytop.gd.system.models.DataPacket; |
||||
|
import com.iflytop.gd.system.utils.ByteArray; |
||||
|
import jakarta.websocket.*; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.springframework.stereotype.Component; |
||||
|
import org.springframework.web.socket.client.WebSocketClient; |
||||
|
|
||||
|
import java.io.IOException; |
||||
|
import java.util.concurrent.CountDownLatch; |
||||
|
import java.util.concurrent.TimeUnit; |
||||
|
import java.util.concurrent.atomic.AtomicReference; |
||||
|
import java.util.concurrent.locks.ReentrantLock; |
||||
|
|
||||
|
|
||||
|
@Slf4j |
||||
|
@Component |
||||
|
@ClientEndpoint |
||||
|
public class WebSocketCommandBusImpl implements CommandBus { |
||||
|
private Session session; |
||||
|
private WebSocketClient webSocketClient; |
||||
|
private CountDownLatch countDownLatch; |
||||
|
private DataPacket lastDataPacket; |
||||
|
|
||||
|
|
||||
|
|
||||
|
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; |
||||
|
@Override |
||||
|
public synchronized DataPacket waitForCommandExec(DataPacket commandPacket, Integer timeout, TimeUnit unit) |
||||
|
throws CommandExecTimeoutException, HardwareErrorException, IOException, InterruptedException { |
||||
|
try { |
||||
|
this.countDownLatch = new CountDownLatch(1); |
||||
|
this.session.getBasicRemote().sendText(commandPacket.toByteString()); |
||||
|
boolean isTimeout = this.countDownLatch.await(timeout, unit); |
||||
|
// 命令返回或者超时了 |
||||
|
if (isTimeout) { |
||||
|
// TODO处理超时 |
||||
|
throw new CommandExecTimeoutException(); |
||||
|
} |
||||
|
if (this.lastDataPacket.getPacketType() == PACKET_TYPE_ERROR_ACK) { |
||||
|
log.error("moduleId={}执行command={}发送硬件错误", this.lastDataPacket.getModuleId(), this.lastDataPacket.getCmdId()); |
||||
|
throw new HardwareErrorException(); |
||||
|
} |
||||
|
return ObjectUtil.cloneByStream(this.lastDataPacket); |
||||
|
} catch (IOException e) { |
||||
|
log.error("发送指令发生异常", e); |
||||
|
throw e; |
||||
|
} catch (InterruptedException e) { |
||||
|
Thread.currentThread().getName(); |
||||
|
log.error(""); |
||||
|
throw e; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
@OnOpen |
||||
|
public void onOpen(Session session) { |
||||
|
if (this.session != null) { |
||||
|
try { |
||||
|
this.session.close(); |
||||
|
} catch (IOException e) { |
||||
|
log.error(e.getMessage(), e); |
||||
|
} |
||||
|
} |
||||
|
this.session = session; |
||||
|
} |
||||
|
|
||||
|
@OnMessage |
||||
|
public void onMessage(String message) { |
||||
|
byte[] bytes = ByteArray.hexStringToBytes(message); |
||||
|
this.lastDataPacket = new DataPacket(bytes); |
||||
|
this.countDownLatch.countDown(); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
@OnClose |
||||
|
public void onClose() { |
||||
|
if (this.countDownLatch != null) { |
||||
|
this.countDownLatch.countDown(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@OnError |
||||
|
public void onError(Session session, Throwable throwable) { |
||||
|
if (this.countDownLatch != null) { |
||||
|
this.countDownLatch.countDown(); |
||||
|
} |
||||
|
} |
||||
|
} |
@ -0,0 +1,18 @@ |
|||||
|
package com.iflytop.gd.system.constants; |
||||
|
|
||||
|
import lombok.Getter; |
||||
|
|
||||
|
/** |
||||
|
* 电机转动方向 |
||||
|
*/ |
||||
|
@Getter |
||||
|
public enum RotationDirection { |
||||
|
Forward(1),Backward(-1); |
||||
|
|
||||
|
private Integer value; |
||||
|
|
||||
|
RotationDirection(Integer value) { |
||||
|
this.value = value; |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,46 @@ |
|||||
|
package com.iflytop.gd.system.devices; |
||||
|
|
||||
|
import com.iflytop.gd.infrastructure.drivers.CmdId; |
||||
|
import com.iflytop.gd.infrastructure.drivers.ModuleId; |
||||
|
import com.iflytop.gd.system.constants.DistanceUnit; |
||||
|
import com.iflytop.gd.system.constants.SpeedUnit; |
||||
|
import com.iflytop.gd.system.drivers.CommandBus; |
||||
|
import com.iflytop.gd.system.exceptions.CommandExecTimeoutException; |
||||
|
import com.iflytop.gd.system.exceptions.HardwareErrorException; |
||||
|
import com.iflytop.gd.system.models.DataPacket; |
||||
|
|
||||
|
import java.io.IOException; |
||||
|
import java.util.concurrent.TimeUnit; |
||||
|
|
||||
|
public abstract class BaseStepStepMotor implements StepMotor { |
||||
|
protected final ModuleId moduleId; |
||||
|
protected final CommandBus commandBus; |
||||
|
protected final Integer DEFAULT_COMMAND_EXEC_TIMEOUT_SECONDS = 10; |
||||
|
|
||||
|
protected BaseStepStepMotor(ModuleId moduleId, CommandBus commandBus) { |
||||
|
this.moduleId = moduleId; |
||||
|
this.commandBus = commandBus; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
@Override |
||||
|
public void easyMoveTo(Integer value, DistanceUnit unit) { |
||||
|
DataPacket commandDataPacket = DataPacket.createCommandDataPacket(moduleId.index, CmdId.step_motor_easy_move_to.index, value); |
||||
|
try { |
||||
|
commandBus.waitForCommandExec(commandDataPacket, DEFAULT_COMMAND_EXEC_TIMEOUT_SECONDS, TimeUnit.SECONDS); |
||||
|
} catch (CommandExecTimeoutException e) { |
||||
|
throw new RuntimeException(e); |
||||
|
} catch (HardwareErrorException e) { |
||||
|
throw new RuntimeException(e); |
||||
|
} catch (IOException e) { |
||||
|
throw new RuntimeException(e); |
||||
|
} catch (InterruptedException e) { |
||||
|
throw new RuntimeException(e); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void easyMoveBy(Integer value, DistanceUnit unit) { |
||||
|
|
||||
|
} |
||||
|
} |
@ -0,0 +1,11 @@ |
|||||
|
package com.iflytop.gd.system.devices; |
||||
|
|
||||
|
/** |
||||
|
* 开关类型设备驱动定义 |
||||
|
*/ |
||||
|
public interface BinaryDevice { |
||||
|
void open(); |
||||
|
void close(); |
||||
|
boolean isOpen(); |
||||
|
boolean isClosed(); |
||||
|
} |
@ -0,0 +1,9 @@ |
|||||
|
package com.iflytop.gd.system.devices; |
||||
|
|
||||
|
/** |
||||
|
* 步进电机 |
||||
|
*/ |
||||
|
public class DoorStepMotor { |
||||
|
|
||||
|
|
||||
|
} |
@ -1,4 +1,4 @@ |
|||||
package com.iflytop.gd.system.drivers; |
|
||||
|
package com.iflytop.gd.system.devices; |
||||
|
|
||||
/** |
/** |
||||
* 风扇 |
* 风扇 |
@ -1,4 +1,4 @@ |
|||||
package com.iflytop.gd.system.drivers; |
|
||||
|
package com.iflytop.gd.system.devices; |
||||
|
|
||||
/** |
/** |
||||
* 加热器 |
* 加热器 |
@ -1,4 +1,4 @@ |
|||||
package com.iflytop.gd.system.drivers; |
|
||||
|
package com.iflytop.gd.system.devices; |
||||
|
|
||||
/** |
/** |
||||
* 继电器 |
* 继电器 |
@ -1,4 +1,4 @@ |
|||||
package com.iflytop.gd.system.drivers; |
|
||||
|
package com.iflytop.gd.system.devices; |
||||
|
|
||||
|
|
||||
/** |
/** |
@ -0,0 +1,77 @@ |
|||||
|
package com.iflytop.gd.system.devices; |
||||
|
|
||||
|
import com.iflytop.gd.system.constants.DistanceUnit; |
||||
|
import com.iflytop.gd.system.constants.RotationDirection; |
||||
|
|
||||
|
/** |
||||
|
* 电机驱动类型设备 |
||||
|
*/ |
||||
|
public interface StepMotor { |
||||
|
|
||||
|
/** |
||||
|
* 移动指定距离 |
||||
|
* @param value |
||||
|
* @param unit |
||||
|
*/ |
||||
|
void easyMoveBy(Integer value, DistanceUnit unit); |
||||
|
|
||||
|
void easyMoveTo(Integer value, DistanceUnit unit); |
||||
|
|
||||
|
void easyMoveToZero(); |
||||
|
|
||||
|
void setCurrentPosition(Integer value); |
||||
|
|
||||
|
void easyMoveToZeroPointQuick(); |
||||
|
|
||||
|
void easyMoveToEndPoint(); |
||||
|
|
||||
|
/** |
||||
|
* 使能电机 |
||||
|
*/ |
||||
|
void enable(); |
||||
|
|
||||
|
/** |
||||
|
* 读取当前位置 |
||||
|
* @return |
||||
|
*/ |
||||
|
Integer readPosition(); |
||||
|
|
||||
|
/** |
||||
|
* 读取编码器位置 |
||||
|
* @return |
||||
|
*/ |
||||
|
Integer readEncoderPosition(); |
||||
|
|
||||
|
void easyRotate(RotationDirection direction); |
||||
|
|
||||
|
void easyMoveByBlock(); |
||||
|
|
||||
|
void easyMoveToBlock(); |
||||
|
|
||||
|
void easyMoveToZeroBlock(); |
||||
|
|
||||
|
void readPositionByMoveToZeroBlock(); |
||||
|
|
||||
|
void easyMoveToZeroPointQuickBlock(); |
||||
|
|
||||
|
void stop(); |
||||
|
|
||||
|
void moveByBlock(); |
||||
|
|
||||
|
void moveTOBlock(); |
||||
|
|
||||
|
void rotate(); |
||||
|
|
||||
|
Boolean readIOState(); |
||||
|
|
||||
|
void easyReciprocatingMotion(); |
||||
|
|
||||
|
void easyReciprocatingMotionBlock(); |
||||
|
|
||||
|
Boolean isReturnToZero(); |
||||
|
|
||||
|
void setReg(); |
||||
|
|
||||
|
Integer readReg(); |
||||
|
|
||||
|
} |
@ -0,0 +1,22 @@ |
|||||
|
package com.iflytop.gd.system.drivers; |
||||
|
|
||||
|
import com.iflytop.gd.common.exception.AppException; |
||||
|
import com.iflytop.gd.system.exceptions.CommandExecTimeoutException; |
||||
|
import com.iflytop.gd.system.exceptions.HardwareErrorException; |
||||
|
import com.iflytop.gd.system.models.DataPacket; |
||||
|
|
||||
|
import java.io.IOException; |
||||
|
import java.util.concurrent.TimeUnit; |
||||
|
|
||||
|
public interface CommandBus { |
||||
|
|
||||
|
/** |
||||
|
* 发送命令数据包并等待响应 |
||||
|
* @param commandPacket 命令数据包 |
||||
|
* @param timeout 等待超时事件 |
||||
|
* @param unit 超时时间单位 |
||||
|
* @return 响应数据包 |
||||
|
* @throws Exception |
||||
|
*/ |
||||
|
DataPacket waitForCommandExec(DataPacket commandPacket, Integer timeout, TimeUnit unit) throws CommandExecTimeoutException, HardwareErrorException, IOException, InterruptedException; |
||||
|
} |
@ -1,34 +0,0 @@ |
|||||
package com.iflytop.gd.system.drivers; |
|
||||
|
|
||||
import com.iflytop.gd.system.constants.DistanceUnit; |
|
||||
import com.iflytop.gd.system.constants.SpeedUnit; |
|
||||
|
|
||||
/** |
|
||||
* 步进电机 |
|
||||
*/ |
|
||||
public interface StepMotor { |
|
||||
|
|
||||
/** |
|
||||
* 移动指定距离 |
|
||||
* @param value |
|
||||
* @param unit |
|
||||
*/ |
|
||||
void move(Integer value, DistanceUnit unit); |
|
||||
|
|
||||
/** |
|
||||
* 停止移动 |
|
||||
*/ |
|
||||
void stop(); |
|
||||
|
|
||||
/** |
|
||||
* 设置移动速度 |
|
||||
* @param value |
|
||||
* @param unit |
|
||||
*/ |
|
||||
void setSpeed(Integer value, SpeedUnit unit); |
|
||||
|
|
||||
/** |
|
||||
* 复位电机 |
|
||||
*/ |
|
||||
void reset(); |
|
||||
} |
|
@ -0,0 +1,22 @@ |
|||||
|
package com.iflytop.gd.system.exceptions; |
||||
|
|
||||
|
public class CommandExecTimeoutException extends Exception{ |
||||
|
public CommandExecTimeoutException() { |
||||
|
} |
||||
|
|
||||
|
public CommandExecTimeoutException(String message) { |
||||
|
super(message); |
||||
|
} |
||||
|
|
||||
|
public CommandExecTimeoutException(String message, Throwable cause) { |
||||
|
super(message, cause); |
||||
|
} |
||||
|
|
||||
|
public CommandExecTimeoutException(Throwable cause) { |
||||
|
super(cause); |
||||
|
} |
||||
|
|
||||
|
public CommandExecTimeoutException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { |
||||
|
super(message, cause, enableSuppression, writableStackTrace); |
||||
|
} |
||||
|
} |
@ -0,0 +1,22 @@ |
|||||
|
package com.iflytop.gd.system.exceptions; |
||||
|
|
||||
|
public class HardwareErrorException extends Exception{ |
||||
|
public HardwareErrorException() { |
||||
|
} |
||||
|
|
||||
|
public HardwareErrorException(String message) { |
||||
|
super(message); |
||||
|
} |
||||
|
|
||||
|
public HardwareErrorException(String message, Throwable cause) { |
||||
|
super(message, cause); |
||||
|
} |
||||
|
|
||||
|
public HardwareErrorException(Throwable cause) { |
||||
|
super(cause); |
||||
|
} |
||||
|
|
||||
|
public HardwareErrorException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { |
||||
|
super(message, cause, enableSuppression, writableStackTrace); |
||||
|
} |
||||
|
} |
@ -0,0 +1,83 @@ |
|||||
|
package com.iflytop.gd.system.models; |
||||
|
|
||||
|
import com.iflytop.gd.system.utils.ByteArray; |
||||
|
|
||||
|
import java.nio.ByteBuffer; |
||||
|
import java.nio.ByteOrder; |
||||
|
|
||||
|
public class DataPacket { |
||||
|
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; |
||||
|
|
||||
|
byte[] raw; |
||||
|
|
||||
|
public DataPacket(byte[] cmd) { |
||||
|
raw = new byte[cmd.length]; |
||||
|
System.arraycopy(cmd, 0, raw, 0, cmd.length); |
||||
|
} |
||||
|
|
||||
|
public String toByteString() { |
||||
|
return ByteArray.toByteString(raw); |
||||
|
} |
||||
|
|
||||
|
static public DataPacket createPacket(Integer moduleId, int packetType, Integer cmdId, Integer[] params) { |
||||
|
int bufferSize = DataPacket.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 DataPacket(buffer.array()); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
public static DataPacket createCommandDataPacket(Integer moduleId, Integer cmdId, Integer... params) { |
||||
|
return createPacket(moduleId, PACKET_TYPE_CMD, cmdId, params); |
||||
|
} |
||||
|
|
||||
|
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); |
||||
|
} |
||||
|
} |
@ -0,0 +1,125 @@ |
|||||
|
// Source code is decompiled from a .class file using FernFlower decompiler. |
||||
|
package com.iflytop.gd.system.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